configure: update compiler probing
[fio.git] / ioengines.c
index 95013d1daaaa07d9bd26ed2899a81d7fd1b45244..9638d8043753627f60ffc223b8308ca6f61d57af 100644 (file)
@@ -123,13 +123,10 @@ static struct ioengine_ops *dlopen_ioengine(struct thread_data *td,
        return ops;
 }
 
-struct ioengine_ops *load_ioengine(struct thread_data *td, const char *name)
+static struct ioengine_ops *__load_ioengine(const char *name)
 {
-       struct ioengine_ops *ops;
        char engine[64];
 
-       dprint(FD_IO, "load ioengine %s\n", name);
-
        engine[sizeof(engine) - 1] = '\0';
        strncpy(engine, name, sizeof(engine) - 1);
 
@@ -139,10 +136,37 @@ struct ioengine_ops *load_ioengine(struct thread_data *td, const char *name)
        if (!strncmp(engine, "linuxaio", 8) || !strncmp(engine, "aio", 3))
                strcpy(engine, "libaio");
 
-       ops = find_ioengine(engine);
+       dprint(FD_IO, "load ioengine %s\n", engine);
+       return find_ioengine(engine);
+}
+
+struct ioengine_ops *load_ioengine(struct thread_data *td)
+{
+       struct ioengine_ops *ops = NULL;
+       const char *name;
+
+       /*
+        * Use ->ioengine_so_path if an external ioengine path is specified.
+        * In this case, ->ioengine is "external" which also means the prefix
+        * for external ioengines "external:" is properly used.
+        */
+       name = td->o.ioengine_so_path ?: td->o.ioengine;
+
+       /*
+        * Try to load ->ioengine first, and if failed try to dlopen(3) either
+        * ->ioengine or ->ioengine_so_path.  This is redundant for an external
+        * ioengine with prefix, and also leaves the possibility of unexpected
+        * behavior (e.g. if the "external" ioengine exists), but we do this
+        * so as not to break job files not using the prefix.
+        */
+       ops = __load_ioengine(td->o.ioengine);
        if (!ops)
                ops = dlopen_ioengine(td, name);
 
+       /*
+        * If ops is NULL, we failed to load ->ioengine, and also failed to
+        * dlopen(3) either ->ioengine or ->ioengine_so_path as a path.
+        */
        if (!ops) {
                log_err("fio: engine %s not loadable\n", name);
                return NULL;
@@ -281,7 +305,7 @@ int td_io_queue(struct thread_data *td, struct io_u *io_u)
                 */
                if (td->o.read_iolog_file)
                        memcpy(&td->last_issue, &io_u->issue_time,
-                                       sizeof(struct timeval));
+                                       sizeof(io_u->issue_time));
        }
 
        if (ddir_rw(ddir)) {
@@ -318,8 +342,8 @@ int td_io_queue(struct thread_data *td, struct io_u *io_u)
            td->o.odirect) {
 
                log_info("fio: first direct IO errored. File system may not "
-                        "support direct IO, or iomem_align= is bad. Try "
-                        "setting direct=0.\n");
+                        "support direct IO, or iomem_align= is bad, or "
+                        "invalid block size. Try setting direct=0.\n");
        }
 
        if (!td->io_ops->commit || io_u->ddir == DDIR_TRIM) {
@@ -356,7 +380,7 @@ int td_io_queue(struct thread_data *td, struct io_u *io_u)
                 */
                if (td->o.read_iolog_file)
                        memcpy(&td->last_issue, &io_u->issue_time,
-                                       sizeof(struct timeval));
+                                       sizeof(io_u->issue_time));
        }
 
        return ret;
@@ -368,17 +392,17 @@ int td_io_init(struct thread_data *td)
 
        if (td->io_ops->init) {
                ret = td->io_ops->init(td);
-               if (ret && td->o.iodepth > 1) {
-                       log_err("fio: io engine init failed. Perhaps try"
-                               " reducing io depth?\n");
-               }
+               if (ret)
+                       log_err("fio: io engine %s init failed.%s\n",
+                               td->io_ops->name,
+                               td->o.iodepth > 1 ?
+                               " Perhaps try reducing io depth?" : "");
+               else
+                       td->io_ops_init = 1;
                if (!td->error)
                        td->error = ret;
        }
 
-       if (!ret && td_ioengine_flagged(td, FIO_NOIO))
-               td->flags |= TD_F_NOIO;
-
        return ret;
 }
 
@@ -472,39 +496,32 @@ int td_io_open_file(struct thread_data *td, struct fio_file *f)
                        goto err;
                }
        }
-#ifdef FIO_HAVE_STREAMID
-       if (td->o.fadvise_stream &&
+#ifdef FIO_HAVE_WRITE_HINT
+       if (fio_option_is_set(&td->o, write_hint) &&
            (f->filetype == FIO_TYPE_BLOCK || f->filetype == FIO_TYPE_FILE)) {
-               off_t stream = td->o.fadvise_stream;
-
-               if (posix_fadvise(f->fd, stream, f->io_size, POSIX_FADV_STREAMID) < 0) {
-                       td_verror(td, errno, "fadvise streamid");
-                       goto err;
-               }
-       }
-#endif
-
-#ifdef FIO_OS_DIRECTIO
-       /*
-        * Some OS's have a distinct call to mark the file non-buffered,
-        * instead of using O_DIRECT (Solaris)
-        */
-       if (td->o.odirect) {
-               int ret = fio_set_odirect(f->fd);
+               uint64_t hint = td->o.write_hint;
+               int cmd;
 
-               if (ret) {
-                       td_verror(td, ret, "fio_set_odirect");
-                       if (ret == ENOTTY) { /* ENOTTY suggests RAW device or ZFS */
-                               log_err("fio: doing directIO to RAW devices or ZFS not supported\n");
-                       } else {
-                               log_err("fio: the file system does not seem to support direct IO\n");
-                       }
+               /*
+                * 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.
+                */
+               if (td->o.odirect)
+                       cmd = F_SET_FILE_RW_HINT;
+               else
+                       cmd = F_SET_RW_HINT;
 
+               if (fcntl(f->fd, cmd, &hint) < 0) {
+                       td_verror(td, errno, "fcntl write hint");
                        goto err;
                }
        }
 #endif
 
+       if (td->o.odirect && !OS_O_DIRECT && fio_set_directio(td, f))
+               goto err;
+
 done:
        log_file(td, f, FIO_LOG_OPEN_FILE);
        return 0;
@@ -556,68 +573,9 @@ int td_io_get_file_size(struct thread_data *td, struct fio_file *f)
        return td->io_ops->get_file_size(td, f);
 }
 
-static int do_sync_file_range(const struct thread_data *td,
-                             struct fio_file *f)
-{
-       off64_t offset, nbytes;
-
-       offset = f->first_write;
-       nbytes = f->last_write - f->first_write;
-
-       if (!nbytes)
-               return 0;
-
-       return sync_file_range(f->fd, offset, nbytes, td->o.sync_file_range);
-}
-
-int do_io_u_sync(const struct thread_data *td, struct io_u *io_u)
-{
-       int ret;
-
-       if (io_u->ddir == DDIR_SYNC) {
-               ret = fsync(io_u->file->fd);
-       } else if (io_u->ddir == DDIR_DATASYNC) {
-#ifdef CONFIG_FDATASYNC
-               ret = fdatasync(io_u->file->fd);
-#else
-               ret = io_u->xfer_buflen;
-               io_u->error = EINVAL;
-#endif
-       } else if (io_u->ddir == DDIR_SYNC_FILE_RANGE)
-               ret = do_sync_file_range(td, io_u->file);
-       else {
-               ret = io_u->xfer_buflen;
-               io_u->error = EINVAL;
-       }
-
-       if (ret < 0)
-               io_u->error = errno;
-
-       return ret;
-}
-
-int do_io_u_trim(const struct thread_data *td, struct io_u *io_u)
-{
-#ifndef FIO_HAVE_TRIM
-       io_u->error = EINVAL;
-       return 0;
-#else
-       struct fio_file *f = io_u->file;
-       int ret;
-
-       ret = os_trim(f->fd, io_u->offset, io_u->xfer_buflen);
-       if (!ret)
-               return io_u->xfer_buflen;
-
-       io_u->error = ret;
-       return 0;
-#endif
-}
-
 int fio_show_ioengine_help(const char *engine)
 {
        struct flist_head *entry;
-       struct thread_data td;
        struct ioengine_ops *io_ops;
        char *sep;
        int ret = 1;
@@ -636,9 +594,7 @@ int fio_show_ioengine_help(const char *engine)
                sep++;
        }
 
-       memset(&td, 0, sizeof(td));
-
-       io_ops = load_ioengine(&td, engine);
+       io_ops = __load_ioengine(engine);
        if (!io_ops) {
                log_info("IO engine %s not found\n", engine);
                return 1;
@@ -649,7 +605,5 @@ int fio_show_ioengine_help(const char *engine)
        else
                log_info("IO engine %s has no options\n", io_ops->name);
 
-       free_ioengine(&td);
-
        return ret;
 }