X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=ioengines.c;h=5dd4355d29467f1156c71014323f4160987032e3;hb=2e976800fe74a58fadbbd9b069c01120b48cf9f0;hp=dcc9496dd4ddab6fe0c79612e13684e7b790441f;hpb=f6931a1dd35896433c8cc2e10de51372a2c496c4;p=fio.git diff --git a/ioengines.c b/ioengines.c index dcc9496d..5dd4355d 100644 --- a/ioengines.c +++ b/ioengines.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "fio.h" #include "diskutil.h" @@ -24,6 +25,13 @@ static FLIST_HEAD(engine_list); +static inline bool async_ioengine_sync_trim(struct thread_data *td, + struct io_u *io_u) +{ + return td_ioengine_flagged(td, FIO_ASYNCIO_SYNC_TRIM) && + io_u->ddir == DDIR_TRIM; +} + static bool check_engine_ops(struct thread_data *td, struct ioengine_ops *ops) { if (ops->version != FIO_IOOPS_VERSION) { @@ -95,6 +103,7 @@ static void *dlopen_external(struct thread_data *td, const char *engine) sprintf(engine_path, "%s/fio-%s.so", FIO_EXT_ENG_DIR, engine); + dprint(FD_IO, "dlopen external %s\n", engine_path); dlhandle = dlopen(engine_path, RTLD_LAZY); if (!dlhandle) log_info("Engine %s not found; Either name is invalid, was not built, or fio-engine-%s package is missing.\n", @@ -116,7 +125,7 @@ static struct ioengine_ops *dlopen_ioengine(struct thread_data *td, !strncmp(engine_lib, "aio", 3)) engine_lib = "libaio"; - dprint(FD_IO, "dload engine %s\n", engine_lib); + dprint(FD_IO, "dlopen engine %s\n", engine_lib); dlerror(); dlhandle = dlopen(engine_lib, RTLD_LAZY); @@ -194,7 +203,9 @@ struct ioengine_ops *load_ioengine(struct thread_data *td) * so as not to break job files not using the prefix. */ ops = __load_ioengine(td->o.ioengine); - if (!ops) + + /* We do re-dlopen existing handles, for reference counting */ + if (!ops || ops->dlhandle) ops = dlopen_ioengine(td, name); /* @@ -220,6 +231,8 @@ struct ioengine_ops *load_ioengine(struct thread_data *td) */ void free_ioengine(struct thread_data *td) { + assert(td != NULL && td->io_ops != NULL); + dprint(FD_IO, "free ioengine %s\n", td->io_ops->name); if (td->eo && td->io_ops->options) { @@ -229,8 +242,8 @@ void free_ioengine(struct thread_data *td) } if (td->io_ops->dlhandle) { + dprint(FD_IO, "dlclose ioengine %s\n", td->io_ops->name); dlclose(td->io_ops->dlhandle); - td->io_ops->dlhandle = NULL; } td->io_ops = NULL; @@ -330,8 +343,13 @@ enum fio_q_status td_io_queue(struct thread_data *td, struct io_u *io_u) * flag is now set */ if (td_offload_overlap(td)) { - int res = pthread_mutex_unlock(&overlap_check); - assert(res == 0); + int res; + + res = pthread_mutex_unlock(&overlap_check); + if (fio_unlikely(res != 0)) { + log_err("failed to unlock overlap check mutex, err: %i:%s", errno, strerror(errno)); + abort(); + } } assert(fio_file_open(io_u->file)); @@ -345,17 +363,17 @@ enum fio_q_status td_io_queue(struct thread_data *td, struct io_u *io_u) io_u->resid = 0; if (td_ioengine_flagged(td, FIO_SYNCIO) || - (td_ioengine_flagged(td, FIO_ASYNCIO_SYNC_TRIM) && - io_u->ddir == DDIR_TRIM)) { - if (fio_fill_issue_time(td)) + async_ioengine_sync_trim(td, io_u)) { + if (fio_fill_issue_time(td)) { fio_gettime(&io_u->issue_time, NULL); - /* - * only used for iolog - */ - if (td->o.read_iolog_file) - memcpy(&td->last_issue, &io_u->issue_time, - sizeof(io_u->issue_time)); + /* + * only used for iolog + */ + if (td->o.read_iolog_file) + memcpy(&td->last_issue, &io_u->issue_time, + sizeof(io_u->issue_time)); + } } @@ -395,7 +413,7 @@ enum fio_q_status td_io_queue(struct thread_data *td, struct io_u *io_u) if (io_u->error == EINVAL && td->io_issues[io_u->ddir & 1] == 1 && td->o.odirect) { - log_info("fio: first direct IO errored. File system may not " + log_err("fio: first direct IO errored. File system may not " "support direct IO, or iomem_align= is bad, or " "invalid block size. Try setting direct=0.\n"); } @@ -403,14 +421,13 @@ enum fio_q_status td_io_queue(struct thread_data *td, struct io_u *io_u) if (zbd_unaligned_write(io_u->error) && td->io_issues[io_u->ddir & 1] == 1 && td->o.zone_mode != ZONE_MODE_ZBD) { - log_info("fio: first I/O failed. If %s is a zoned block device, consider --zonemode=zbd\n", + log_err("fio: first I/O failed. If %s is a zoned block device, consider --zonemode=zbd\n", io_u->file->file_name); } if (!td->io_ops->commit) { io_u_mark_submit(td, 1); io_u_mark_complete(td, 1); - zbd_put_io_u(td, io_u); } if (ret == FIO_Q_COMPLETED) { @@ -431,17 +448,18 @@ enum fio_q_status td_io_queue(struct thread_data *td, struct io_u *io_u) } if (!td_ioengine_flagged(td, FIO_SYNCIO) && - (!td_ioengine_flagged(td, FIO_ASYNCIO_SYNC_TRIM) || - io_u->ddir != DDIR_TRIM)) { - if (fio_fill_issue_time(td)) + !async_ioengine_sync_trim(td, io_u)) { + if (fio_fill_issue_time(td) && + !td_ioengine_flagged(td, FIO_ASYNCIO_SETS_ISSUE_TIME)) { fio_gettime(&io_u->issue_time, NULL); - /* - * only used for iolog - */ - if (td->o.read_iolog_file) - memcpy(&td->last_issue, &io_u->issue_time, - sizeof(io_u->issue_time)); + /* + * only used for iolog + */ + if (td->o.read_iolog_file) + memcpy(&td->last_issue, &io_u->issue_time, + sizeof(io_u->issue_time)); + } } return ret; @@ -553,6 +571,10 @@ int td_io_open_file(struct thread_data *td, struct fio_file *f) flags = POSIX_FADV_RANDOM; else if (td->o.fadvise_hint == F_ADV_SEQUENTIAL) flags = POSIX_FADV_SEQUENTIAL; +#ifdef POSIX_FADV_NOREUSE + else if (td->o.fadvise_hint == F_ADV_NOREUSE) + flags = POSIX_FADV_NOREUSE; +#endif else { log_err("fio: unknown fadvise type %d\n", td->o.fadvise_hint); @@ -568,19 +590,21 @@ int td_io_open_file(struct thread_data *td, struct fio_file *f) if (fio_option_is_set(&td->o, write_hint) && (f->filetype == FIO_TYPE_BLOCK || f->filetype == FIO_TYPE_FILE)) { uint64_t hint = td->o.write_hint; - int cmd; + int res; /* - * For direct IO, we just need/want to set the hint on - * the file descriptor. For buffered IO, we need to set - * it on the inode. + * For direct IO, set the hint on the file descriptor if that is + * supported. Otherwise set it on the inode. For buffered IO, we + * need to set it on the inode. */ - if (td->o.odirect) - cmd = F_SET_FILE_RW_HINT; - else - cmd = F_SET_RW_HINT; - - if (fcntl(f->fd, cmd, &hint) < 0) { + if (td->o.odirect) { + res = fcntl(f->fd, F_SET_FILE_RW_HINT, &hint); + if (res < 0) + res = fcntl(f->fd, F_SET_RW_HINT, &hint); + } else { + res = fcntl(f->fd, F_SET_RW_HINT, &hint); + } + if (res < 0) { td_verror(td, errno, "fcntl write hint"); goto err; } @@ -690,17 +714,17 @@ int fio_show_ioengine_help(const char *engine) } td.o.ioengine = (char *)engine; - io_ops = load_ioengine(&td); + td.io_ops = load_ioengine(&td); - if (!io_ops) { + if (!td.io_ops) { log_info("IO engine %s not found\n", engine); return 1; } - if (io_ops->options) - ret = show_cmd_help(io_ops->options, sep); + if (td.io_ops->options) + ret = show_cmd_help(td.io_ops->options, sep); else - log_info("IO engine %s has no options\n", io_ops->name); + log_info("IO engine %s has no options\n", td.io_ops->name); free_ioengine(&td); return ret;