X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=engines%2Fpmemblk.c;h=45f6fb6501a216b78dbfdae34f7ef3807aa77669;hp=ab4b7697dcc3f61421392e4cbff7b3b9286eb9cc;hb=01bf5128d0581e267383f280c6a1dcd26517240f;hpb=b5b603f474a069eb63839af05db1571a9c122b56 diff --git a/engines/pmemblk.c b/engines/pmemblk.c index ab4b7697..45f6fb65 100644 --- a/engines/pmemblk.c +++ b/engines/pmemblk.c @@ -1,5 +1,5 @@ /* - * pmemblk: IO engine that uses NVML libpmemblk to read and write data + * pmemblk: IO engine that uses PMDK libpmemblk to read and write data * * Copyright (C) 2016 Hewlett Packard Enterprise Development LP * @@ -14,8 +14,8 @@ * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. */ /* @@ -27,11 +27,11 @@ * ioengine=pmemblk * * Other relevant settings: + * thread=1 REQUIRED * iodepth=1 * direct=1 - * thread=1 REQUIRED * unlink=1 - * filename=/pmem0/fiotestfile,BSIZE,FSIZEMB + * filename=/mnt/pmem0/fiotestfile,BSIZE,FSIZEMiB * * thread must be set to 1 for pmemblk as multiple processes cannot * open the same block pool file. @@ -39,23 +39,26 @@ * iodepth should be set to 1 as pmemblk is always synchronous. * Use numjobs to scale up. * - * direct=1 is implied as pmemblk is always direct. + * direct=1 is implied as pmemblk is always direct. A warning message + * is printed if this is not specified. + * + * unlink=1 removes the block pool file after testing, and is optional. * - * Can set unlink to 1 to remove the block pool file after testing. + * The pmem device must have a DAX-capable filesystem and be mounted + * with DAX enabled. filename must point to a file on that filesystem. + * + * Example: + * mkfs.xfs /dev/pmem0 + * mkdir /mnt/pmem0 + * mount -o dax /dev/pmem0 /mnt/pmem0 * * When specifying the filename, if the block pool file does not already - * exist, then the pmemblk engine can create the pool file if you specify + * exist, then the pmemblk engine creates the pool file if you specify * the block and file sizes. BSIZE is the block size in bytes. - * FSIZEMB is the pool file size in MB. + * FSIZEMB is the pool file size in MiB. * * See examples/pmemblk.fio for more. * - * libpmemblk.so - * By default, the pmemblk engine will let the system find the libpmemblk.so - * that it uses. You can use an alternative libpmemblk by setting the - * FIO_PMEMBLK_LIB environment variable to the full path to the desired - * libpmemblk.so. - * */ #include @@ -64,63 +67,17 @@ #include #include #include -#include #include +#include +#include #include "../fio.h" /* * libpmemblk */ -struct PMEMblkpool_s; -typedef struct PMEMblkpool_s PMEMblkpool; - -PMEMblkpool *(*pmemblk_create) (const char *, size_t, size_t, mode_t) = NULL; -PMEMblkpool *(*pmemblk_open) (const char *, size_t) = NULL; -void (*pmemblk_close) (PMEMblkpool *) = NULL; -size_t(*pmemblk_nblock) (PMEMblkpool *) = NULL; -size_t(*pmemblk_bsize) (PMEMblkpool *) = NULL; -int (*pmemblk_read) (PMEMblkpool *, void *, off_t) = NULL; -int (*pmemblk_write) (PMEMblkpool *, const void *, off_t) = NULL; - -int load_libpmemblk(const char *path) -{ - void *dl; - - if (NULL == path) - path = "libpmemblk.so"; - - dl = dlopen(path, RTLD_NOW | RTLD_NODELETE); - if (NULL == dl) - goto errorout; - - if (NULL == (pmemblk_create = dlsym(dl, "pmemblk_create"))) - goto errorout; - if (NULL == (pmemblk_open = dlsym(dl, "pmemblk_open"))) - goto errorout; - if (NULL == (pmemblk_close = dlsym(dl, "pmemblk_close"))) - goto errorout; - if (NULL == (pmemblk_nblock = dlsym(dl, "pmemblk_nblock"))) - goto errorout; - if (NULL == (pmemblk_bsize = dlsym(dl, "pmemblk_bsize"))) - goto errorout; - if (NULL == (pmemblk_read = dlsym(dl, "pmemblk_read"))) - goto errorout; - if (NULL == (pmemblk_write = dlsym(dl, "pmemblk_write"))) - goto errorout; - - return 0; - -errorout: - log_err("fio: unable to load libpmemblk: %s\n", dlerror()); - if (NULL != dl) - dlclose(dl); - - return (-1); - -} /* load_libpmemblk() */ - typedef struct fio_pmemblk_file *fio_pmemblk_file_t; + struct fio_pmemblk_file { fio_pmemblk_file_t pmb_next; char *pmb_filename; @@ -129,12 +86,8 @@ struct fio_pmemblk_file { size_t pmb_bsize; size_t pmb_nblocks; }; -#define FIOFILEPMBSET(_f, _v) do { \ - (_f)->engine_data = (uint64_t)(uintptr_t)(_v); \ -} while(0) -#define FIOFILEPMBGET(_f) ((fio_pmemblk_file_t)((_f)->engine_data)) -static fio_pmemblk_file_t Cache = NULL; +static fio_pmemblk_file_t Cache; static pthread_mutex_t CacheLock = PTHREAD_MUTEX_INITIALIZER; @@ -145,21 +98,17 @@ fio_pmemblk_file_t fio_pmemblk_cache_lookup(const char *filename) fio_pmemblk_file_t i; for (i = Cache; i != NULL; i = i->pmb_next) - if (0 == strcmp(filename, i->pmb_filename)) + if (!strcmp(filename, i->pmb_filename)) return i; return NULL; - -} /* fio_pmemblk_cache_lookup() */ +} static void fio_pmemblk_cache_insert(fio_pmemblk_file_t pmb) { pmb->pmb_next = Cache; Cache = pmb; - - return; - -} /* fio_pmemblk_cache_insert() */ +} static void fio_pmemblk_cache_remove(fio_pmemblk_file_t pmb) { @@ -177,17 +126,14 @@ static void fio_pmemblk_cache_remove(fio_pmemblk_file_t pmb) pmb->pmb_next = NULL; return; } - - return; - -} /* fio_pmemblk_cache_remove() */ +} /* * to control block size and gross file size at the libpmemblk * level, we allow the block size and file size to be appended * to the file name: * - * path[,bsize,fsizemb] + * path[,bsize,fsizemib] * * note that we do not use the fio option "filesize" to dictate * the file size because we can only give libpmemblk the gross @@ -197,34 +143,33 @@ static void fio_pmemblk_cache_remove(fio_pmemblk_file_t pmb) * the final path without the parameters is returned in ppath. * the block size and file size are returned in pbsize and fsize. * - * note that the user should specify the file size in MiB, but + * note that the user specifies the file size in MiB, but * we return bytes from here. */ -static void -pmb_parse_path(const char *pathspec, - char **ppath, uint64_t * pbsize, uint64_t * pfsize) +static void pmb_parse_path(const char *pathspec, char **ppath, uint64_t *pbsize, + uint64_t *pfsize) { char *path; char *s; uint64_t bsize; - uint64_t fsizemb; + uint64_t fsizemib; path = strdup(pathspec); - if (NULL == path) { + if (!path) { *ppath = NULL; return; } /* extract sizes, if given */ s = strrchr(path, ','); - if (s && (fsizemb = strtoull(s + 1, NULL, 10))) { + if (s && (fsizemib = strtoull(s + 1, NULL, 10))) { *s = 0; s = strrchr(path, ','); if (s && (bsize = strtoull(s + 1, NULL, 10))) { *s = 0; *ppath = path; *pbsize = bsize; - *pfsize = fsizemb << 20; + *pfsize = fsizemib << 20; return; } } @@ -234,12 +179,9 @@ pmb_parse_path(const char *pathspec, *ppath = path; *pbsize = 0; *pfsize = 0; - return; - -} /* pmb_parse_path() */ +} -static - fio_pmemblk_file_t pmb_open(const char *pathspec, int flags) +static fio_pmemblk_file_t pmb_open(const char *pathspec, int flags) { fio_pmemblk_file_t pmb; char *path = NULL; @@ -247,35 +189,27 @@ static uint64_t fsize = 0; pmb_parse_path(pathspec, &path, &bsize, &fsize); - if (NULL == path) + if (!path) return NULL; pthread_mutex_lock(&CacheLock); pmb = fio_pmemblk_cache_lookup(path); - - if (NULL == pmb) { - /* load libpmemblk if needed */ - if (NULL == pmemblk_open) - if (0 != load_libpmemblk(getenv("FIO_PMEMBLK_LIB"))) - goto error; - + if (!pmb) { pmb = malloc(sizeof(*pmb)); - if (NULL == pmb) + if (!pmb) goto error; /* try opening existing first, create it if needed */ pmb->pmb_pool = pmemblk_open(path, bsize); - if ((NULL == pmb->pmb_pool) && - (ENOENT == errno) && + if (!pmb->pmb_pool && (errno == ENOENT) && (flags & PMB_CREATE) && (0 < fsize) && (0 < bsize)) { pmb->pmb_pool = pmemblk_create(path, bsize, fsize, 0644); } - if (NULL == pmb->pmb_pool) { - log_err - ("fio: enable to open pmemblk pool file (errno %d)\n", - errno); + if (!pmb->pmb_pool) { + log_err("pmemblk: unable to open pmemblk pool file %s (%s)\n", + path, strerror(errno)); goto error; } @@ -295,28 +229,27 @@ static return pmb; error: - if (NULL != pmb) { - if (NULL != pmb->pmb_pool) + if (pmb) { + if (pmb->pmb_pool) pmemblk_close(pmb->pmb_pool); pmb->pmb_pool = NULL; pmb->pmb_filename = NULL; free(pmb); } - if (NULL != path) + if (path) free(path); pthread_mutex_unlock(&CacheLock); return NULL; +} -} /* pmb_open() */ - -static void pmb_close(fio_pmemblk_file_t pmb, const int keep) +static void pmb_close(fio_pmemblk_file_t pmb, const bool keep) { pthread_mutex_lock(&CacheLock); pmb->pmb_refcnt--; - if (!keep && (0 == pmb->pmb_refcnt)) { + if (!keep && !pmb->pmb_refcnt) { pmemblk_close(pmb->pmb_pool); pmb->pmb_pool = NULL; free(pmb->pmb_filename); @@ -326,10 +259,9 @@ static void pmb_close(fio_pmemblk_file_t pmb, const int keep) } pthread_mutex_unlock(&CacheLock); +} -} /* pmb_close() */ - -static int pmb_get_flags(struct thread_data *td, uint64_t * pflags) +static int pmb_get_flags(struct thread_data *td, uint64_t *pflags) { static int thread_warned = 0; static int odirect_warned = 0; @@ -339,14 +271,14 @@ static int pmb_get_flags(struct thread_data *td, uint64_t * pflags) if (!td->o.use_thread) { if (!thread_warned) { thread_warned = 1; - log_err("fio: must set thread=1 for pmemblk engine\n"); + log_err("pmemblk: must set thread=1 for pmemblk engine\n"); } return 1; } if (!td->o.odirect && !odirect_warned) { odirect_warned = 1; - log_info("fio: direct == 0, but pmemblk is always direct\n"); + log_info("pmemblk: direct == 0, but pmemblk is always direct\n"); } if (td->o.allow_create) @@ -354,54 +286,49 @@ static int pmb_get_flags(struct thread_data *td, uint64_t * pflags) (*pflags) = flags; return 0; - -} /* pmb_get_flags() */ +} static int fio_pmemblk_open_file(struct thread_data *td, struct fio_file *f) { uint64_t flags = 0; fio_pmemblk_file_t pmb; - if (0 != pmb_get_flags(td, &flags)) + if (pmb_get_flags(td, &flags)) return 1; pmb = pmb_open(f->file_name, flags); - if (NULL == pmb) + if (!pmb) return 1; - FIOFILEPMBSET(f, pmb); - + FILE_SET_ENG_DATA(f, pmb); return 0; +} -} /* fio_pmemblk_open_file() */ - -static int -fio_pmemblk_close_file(struct thread_data fio_unused * td, struct fio_file *f) +static int fio_pmemblk_close_file(struct thread_data fio_unused *td, + struct fio_file *f) { - fio_pmemblk_file_t pmb = FIOFILEPMBGET(f); + fio_pmemblk_file_t pmb = FILE_ENG_DATA(f); if (pmb) - pmb_close(pmb, 0); - - FIOFILEPMBSET(f, NULL); + pmb_close(pmb, false); + FILE_SET_ENG_DATA(f, NULL); return 0; - -} /* fio_pmemblk_close_file() */ +} static int fio_pmemblk_get_file_size(struct thread_data *td, struct fio_file *f) { uint64_t flags = 0; - fio_pmemblk_file_t pmb = FIOFILEPMBGET(f); + fio_pmemblk_file_t pmb = FILE_ENG_DATA(f); if (fio_file_size_known(f)) return 0; - if (NULL == pmb) { - if (0 != pmb_get_flags(td, &flags)) + if (!pmb) { + if (pmb_get_flags(td, &flags)) return 1; pmb = pmb_open(f->file_name, flags); - if (NULL == pmb) + if (!pmb) return 1; } @@ -409,37 +336,34 @@ static int fio_pmemblk_get_file_size(struct thread_data *td, struct fio_file *f) fio_file_set_size_known(f); - if (NULL == FIOFILEPMBGET(f)) - pmb_close(pmb, 1); + if (!FILE_ENG_DATA(f)) + pmb_close(pmb, true); return 0; +} -} /* fio_pmemblk_get_file_size() */ - -static int fio_pmemblk_queue(struct thread_data *td, struct io_u *io_u) +static enum fio_q_status fio_pmemblk_queue(struct thread_data *td, + struct io_u *io_u) { struct fio_file *f = io_u->file; - fio_pmemblk_file_t pmb = FIOFILEPMBGET(f); + fio_pmemblk_file_t pmb = FILE_ENG_DATA(f); unsigned long long off; unsigned long len; void *buf; - int (*blkop) (PMEMblkpool *, void *, off_t) = (void *)pmemblk_write; fio_ro_check(td, io_u); switch (io_u->ddir) { case DDIR_READ: - blkop = pmemblk_read; - /* fall through */ case DDIR_WRITE: off = io_u->offset; len = io_u->xfer_buflen; io_u->error = EINVAL; - if (0 != (off % pmb->pmb_bsize)) + if (off % pmb->pmb_bsize) break; - if (0 != (len % pmb->pmb_bsize)) + if (len % pmb->pmb_bsize) break; if ((off + len) / pmb->pmb_bsize > pmb->pmb_nblocks) break; @@ -449,7 +373,11 @@ static int fio_pmemblk_queue(struct thread_data *td, struct io_u *io_u) off /= pmb->pmb_bsize; len /= pmb->pmb_bsize; while (0 < len) { - if (0 != blkop(pmb->pmb_pool, buf, off)) { + if (io_u->ddir == DDIR_READ && + 0 != pmemblk_read(pmb->pmb_pool, buf, off)) { + io_u->error = errno; + break; + } else if (0 != pmemblk_write(pmb->pmb_pool, buf, off)) { io_u->error = errno; break; } @@ -473,8 +401,7 @@ static int fio_pmemblk_queue(struct thread_data *td, struct io_u *io_u) } return FIO_Q_COMPLETED; - -} /* fio_pmemblk_queue() */ +} static int fio_pmemblk_unlink_file(struct thread_data *td, struct fio_file *f) { @@ -489,17 +416,15 @@ static int fio_pmemblk_unlink_file(struct thread_data *td, struct fio_file *f) */ pmb_parse_path(f->file_name, &path, &bsize, &fsize); - if (NULL == path) - return 1; + if (!path) + return ENOENT; unlink(path); free(path); - return 0; +} -} /* fio_pmemblk_unlink_file() */ - -struct ioengine_ops ioengine = { +static struct ioengine_ops ioengine = { .name = "pmemblk", .version = FIO_IOOPS_VERSION, .queue = fio_pmemblk_queue, @@ -510,14 +435,12 @@ struct ioengine_ops ioengine = { .flags = FIO_SYNCIO | FIO_DISKLESSIO | FIO_NOEXTEND | FIO_NODISKUTIL, }; -static void -fio_init fio_pmemblk_register(void) +static void fio_init fio_pmemblk_register(void) { register_ioengine(&ioengine); } -static void -fio_exit fio_pmemblk_unregister(void) +static void fio_exit fio_pmemblk_unregister(void) { unregister_ioengine(&ioengine); }