Ignore pre-read for character devices
[fio.git] / filesetup.c
index ae7f8171305507d9a28417cb5afb74181cc4c655..612e79474dc4b43c0707d6a43dccf3d98a2f9e8f 100644 (file)
@@ -24,6 +24,14 @@ static int root_warn;
 
 static FLIST_HEAD(filename_list);
 
+/*
+ * List entry for filename_list
+ */
+struct file_name {
+       struct flist_head list;
+       char *filename;
+};
+
 static inline void clear_error(struct thread_data *td)
 {
        td->error = 0;
@@ -151,11 +159,18 @@ static int extend_file(struct thread_data *td, struct fio_file *f)
                }
        }
 
-       b = malloc(td->o.max_bs[DDIR_WRITE]);
-
        left = f->real_file_size;
+       bs = td->o.max_bs[DDIR_WRITE];
+       if (bs > left)
+               bs = left;
+
+       b = malloc(bs);
+       if (!b) {
+               td_verror(td, errno, "malloc");
+               goto err;
+       }
+
        while (left && !td->terminate) {
-               bs = td->o.max_bs[DDIR_WRITE];
                if (bs > left)
                        bs = left;
 
@@ -220,7 +235,11 @@ static int pre_read_file(struct thread_data *td, struct fio_file *f)
        unsigned int bs;
        char *b;
 
-       if (td_ioengine_flagged(td, FIO_PIPEIO))
+       if (td_ioengine_flagged(td, FIO_PIPEIO) ||
+           td_ioengine_flagged(td, FIO_NOIO))
+               return 0;
+
+       if (f->filetype == FIO_TYPE_CHAR)
                return 0;
 
        if (!fio_file_open(f)) {
@@ -233,8 +252,17 @@ static int pre_read_file(struct thread_data *td, struct fio_file *f)
 
        old_runstate = td_bump_runstate(td, TD_PRE_READING);
 
+       left = f->io_size;
        bs = td->o.max_bs[DDIR_READ];
+       if (bs > left)
+               bs = left;
+
        b = malloc(bs);
+       if (!b) {
+               td_verror(td, errno, "malloc");
+               ret = 1;
+               goto error;
+       }
        memset(b, 0, bs);
 
        if (lseek(f->fd, f->file_offset, SEEK_SET) < 0) {
@@ -244,8 +272,6 @@ static int pre_read_file(struct thread_data *td, struct fio_file *f)
                goto error;
        }
 
-       left = f->io_size;
-
        while (left && !td->terminate) {
                if (bs > left)
                        bs = left;
@@ -434,20 +460,22 @@ static int __file_invalidate_cache(struct thread_data *td, struct fio_file *f,
        if (len == -1ULL || off == -1ULL)
                return 0;
 
-       dprint(FD_IO, "invalidate cache %s: %llu/%llu\n", f->file_name, off,
-                                                               len);
-
        if (td->io_ops->invalidate) {
+               dprint(FD_IO, "invalidate %s cache %s\n", td->io_ops->name,
+                       f->file_name);
                ret = td->io_ops->invalidate(td, f);
                if (ret < 0)
-                       errval = ret;
+                       errval = -ret;
        } else if (f->filetype == FIO_TYPE_FILE) {
+               dprint(FD_IO, "declare unneeded cache %s: %llu/%llu\n",
+                       f->file_name, off, len);
                ret = posix_fadvise(f->fd, off, len, POSIX_FADV_DONTNEED);
                if (ret)
                        errval = ret;
        } else if (f->filetype == FIO_TYPE_BLOCK) {
                int retry_count = 0;
 
+               dprint(FD_IO, "drop page cache %s\n", f->file_name);
                ret = blockdev_invalidate_cache(f);
                while (ret < 0 && errno == EAGAIN && retry_count++ < 25) {
                        /*
@@ -469,8 +497,13 @@ static int __file_invalidate_cache(struct thread_data *td, struct fio_file *f,
                }
                if (ret < 0)
                        errval = errno;
-       } else if (f->filetype == FIO_TYPE_CHAR || f->filetype == FIO_TYPE_PIPE)
+               else if (ret) /* probably not supported */
+                       errval = ret;
+       } else if (f->filetype == FIO_TYPE_CHAR ||
+                  f->filetype == FIO_TYPE_PIPE) {
+               dprint(FD_IO, "invalidate not supported %s\n", f->file_name);
                ret = 0;
+       }
 
        /*
         * Cache flushing isn't a fatal condition, and we know it will
@@ -479,7 +512,8 @@ static int __file_invalidate_cache(struct thread_data *td, struct fio_file *f,
         * continue on our way.
         */
        if (errval)
-               log_info("fio: cache invalidation of %s failed: %s\n", f->file_name, strerror(errval));
+               log_info("fio: cache invalidation of %s failed: %s\n",
+                        f->file_name, strerror(errval));
 
        return 0;
 
@@ -511,7 +545,7 @@ int generic_close_file(struct thread_data fio_unused *td, struct fio_file *f)
                f->shadow_fd = -1;
        }
 
-       f->engine_data = 0;
+       f->engine_pos = 0;
        return ret;
 }
 
@@ -619,7 +653,8 @@ open_again:
                        f->fd = dup(STDIN_FILENO);
                else
                        from_hash = file_lookup_open(f, flags);
-       } else { //td trim
+       } else if (td_trim(td)) {
+               assert(!td_rw(td)); /* should have matched above */
                flags |= O_RDWR;
                from_hash = file_lookup_open(f, flags);
        }
@@ -904,8 +939,7 @@ int setup_files(struct thread_data *td)
                if (!o->file_size_low) {
                        /*
                         * no file size or range given, file size is equal to
-                        * total size divided by number of files. If that is
-                        * zero, set it to the real file size. If the size
+                        * total size divided by number of files. If the size
                         * doesn't divide nicely with the min blocksize,
                         * make the first files bigger.
                         */
@@ -915,8 +949,22 @@ int setup_files(struct thread_data *td)
                                f->io_size += bs;
                        }
 
-                       if (!f->io_size)
+                       /*
+                        * We normally don't come here for regular files, but
+                        * if the result is 0 for a regular file, set it to the
+                        * real file size. This could be size of the existing
+                        * one if it already exists, but otherwise will be set
+                        * to 0. A new file won't be created because
+                        * ->io_size + ->file_offset equals ->real_file_size.
+                        */
+                       if (!f->io_size) {
+                               if (f->file_offset > f->real_file_size)
+                                       goto err_offset;
                                f->io_size = f->real_file_size - f->file_offset;
+                               if (!f->io_size)
+                                       log_info("fio: file %s may be ignored\n",
+                                               f->file_name);
+                       }
                } else if (f->real_file_size < o->file_size_low ||
                           f->real_file_size > o->file_size_high) {
                        if (f->file_offset > o->file_size_low)
@@ -950,9 +998,9 @@ int setup_files(struct thread_data *td)
                        if (!o->create_on_open) {
                                need_extend++;
                                extend_size += (f->io_size + f->file_offset);
+                               fio_file_set_extend(f);
                        } else
                                f->real_file_size = f->io_size + f->file_offset;
-                       fio_file_set_extend(f);
                }
        }
 
@@ -992,9 +1040,15 @@ int setup_files(struct thread_data *td)
         */
        if (need_extend) {
                temp_stall_ts = 1;
-               if (output_format & FIO_OUTPUT_NORMAL)
-                       log_info("%s: Laying out IO file(s) (%u file(s) / %lluMiB)\n",
-                                o->name, need_extend, extend_size >> 20);
+               if (output_format & FIO_OUTPUT_NORMAL) {
+                       log_info("%s: Laying out IO file%s (%u file%s / %s%lluMiB)\n",
+                                o->name,
+                                need_extend > 1 ? "s" : "",
+                                need_extend,
+                                need_extend > 1 ? "s" : "",
+                                need_extend > 1 ? "total " : "",
+                                extend_size >> 20);
+               }
 
                for_each_file(td, f, i) {
                        unsigned long long old_len = -1ULL, extend_len = -1ULL;
@@ -1068,10 +1122,11 @@ int pre_read_files(struct thread_data *td)
        dprint(FD_FILE, "pre_read files\n");
 
        for_each_file(td, f, i) {
-               pre_read_file(td, f);
+               if (pre_read_file(td, f))
+                       return -1;
        }
 
-       return 1;
+       return 0;
 }
 
 static int __init_rand_distribution(struct thread_data *td, struct fio_file *f)