Avoid opening files until they are used
authorJens Axboe <jens.axboe@oracle.com>
Thu, 5 Mar 2009 09:13:58 +0000 (10:13 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Thu, 5 Mar 2009 09:13:58 +0000 (10:13 +0100)
Fio still opens and creates all files, just to check the size of them. Add
a specialized IO engine op for getting the size of a file and use that
instead.

This also cleans a lot of things up. Note that the IO engine version is now
bumped to 10, meaning that external engines will have to separate the
file open from the size checking.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
13 files changed:
engines/guasi.c
engines/libaio.c
engines/mmap.c
engines/posixaio.c
engines/sg.c
engines/solarisaio.c
engines/splice.c
engines/sync.c
engines/syslet-rw.c
filesetup.c
fio.c
fio.h
ioengines.c

index 4ae014307bd88cfcd1d1c9df763fd4d34d08a568..3802f2c21e4ea4ff9a6db588a41df60e4ee36087 100644 (file)
@@ -261,6 +261,7 @@ static struct ioengine_ops ioengine = {
        .cleanup        = fio_guasi_cleanup,
        .open_file      = generic_open_file,
        .close_file     = generic_close_file,
+       .get_file_size  = generic_get_file_size,
 };
 
 #else /* FIO_HAVE_GUASI */
index 99170b5394f6952060626b1f55d4ed8db85e29a5..4f1e0ed4b739a3a62cad6322342bf285f75d2190 100644 (file)
@@ -223,6 +223,7 @@ static struct ioengine_ops ioengine = {
        .cleanup        = fio_libaio_cleanup,
        .open_file      = generic_open_file,
        .close_file     = generic_close_file,
+       .get_file_size  = generic_get_file_size,
 };
 
 #else /* FIO_HAVE_LIBAIO */
index 5b55a811511d594cc5f84c86e828da7a6157c800..dffad90bbff8b2d357f9690b16c391cce1989da2 100644 (file)
@@ -131,6 +131,7 @@ static struct ioengine_ops ioengine = {
        .queue          = fio_mmapio_queue,
        .open_file      = fio_mmapio_open,
        .close_file     = fio_mmapio_close,
+       .get_file_size  = generic_get_file_size,
        .flags          = FIO_SYNCIO | FIO_NOEXTEND,
 };
 
index db11edb04fb7b9bbfa965f05365480a462743a31..3ffdcb6bccc8d062b1be302b27c3cb004bd57d11 100644 (file)
@@ -226,6 +226,7 @@ static struct ioengine_ops ioengine = {
        .cleanup        = fio_posixaio_cleanup,
        .open_file      = generic_open_file,
        .close_file     = generic_close_file,
+       .get_file_size  = generic_get_file_size,
 };
 
 #else /* FIO_HAVE_POSIXAIO */
index d7c0a6d5dc9a69a9774fb667ddcfcf6e1edccdcc..39f99d8d0922050eb1a3aa3d60305cd865a09113 100644 (file)
@@ -404,6 +404,7 @@ static struct ioengine_ops ioengine = {
        .cleanup        = fio_sgio_cleanup,
        .open_file      = fio_sgio_open,
        .close_file     = generic_close_file,
+       .get_file_size  = generic_get_file_size,
        .flags          = FIO_SYNCIO | FIO_RAWIO,
 };
 
index d499f5749ffd7fb51e0b55e881162bc38e43fa59..a48ec41825b67ceae574682ba73cc545bcd9156e 100644 (file)
@@ -213,6 +213,7 @@ static struct ioengine_ops ioengine = {
        .cleanup        = fio_solarisaio_cleanup,
        .open_file      = generic_open_file,
        .close_file     = generic_close_file,
+       .get_file_size  = generic_get_file_size,
 };
 
 #else /* FIO_HAVE_SOLARISAIO */
index a847f9caaf7d5ca35cf08d9cadca59a50345d5bc..26c5c9ad6a8b8f3faaaf469186c03dbf421cc25b 100644 (file)
@@ -293,6 +293,7 @@ static struct ioengine_ops ioengine = {
        .cleanup        = fio_spliceio_cleanup,
        .open_file      = generic_open_file,
        .close_file     = generic_close_file,
+       .get_file_size  = generic_get_file_size,
        .flags          = FIO_SYNCIO,
 };
 
index 4ca04d5e9cbfad9c52f7c322920fc6dedde345c2..842c6c0b29a4f0bf33351bdbbc5ea18581361f5b 100644 (file)
@@ -283,6 +283,7 @@ static struct ioengine_ops ioengine_rw = {
        .queue          = fio_syncio_queue,
        .open_file      = generic_open_file,
        .close_file     = generic_close_file,
+       .get_file_size  = generic_get_file_size,
        .flags          = FIO_SYNCIO,
 };
 
@@ -292,6 +293,7 @@ static struct ioengine_ops ioengine_prw = {
        .queue          = fio_psyncio_queue,
        .open_file      = generic_open_file,
        .close_file     = generic_close_file,
+       .get_file_size  = generic_get_file_size,
        .flags          = FIO_SYNCIO,
 };
 
@@ -306,6 +308,7 @@ static struct ioengine_ops ioengine_vrw = {
        .getevents      = fio_vsyncio_getevents,
        .open_file      = generic_open_file,
        .close_file     = generic_close_file,
+       .get_file_size  = generic_get_file_size,
        .flags          = FIO_SYNCIO,
 };
 
index 2eab207cd8c7cb4c0ab175a321b3d9842fe72634..ad9cb35972c59042baa90093901f79fa9fcd0239 100644 (file)
@@ -284,6 +284,7 @@ static struct ioengine_ops ioengine = {
        .cleanup        = fio_syslet_cleanup,
        .open_file      = generic_open_file,
        .close_file     = generic_close_file,
+       .get_file_size  = generic_get_file_size,
 };
 
 #else /* FIO_HAVE_SYSLET */
index 9862c7dba06ae26f8f0a99ecf79cd75a61b8f159..68516b9d9a8141ce9c74224464b99fb13434b12e 100644 (file)
@@ -136,7 +136,7 @@ static int file_size(struct thread_data *td, struct fio_file *f)
 {
        struct stat st;
 
-       if (fstat(f->fd, &st) == -1) {
+       if (stat(f->file_name, &st) == -1) {
                td_verror(td, errno, "fstat");
                return 1;
        }
@@ -150,19 +150,28 @@ static int bdev_size(struct thread_data *td, struct fio_file *f)
        unsigned long long bytes;
        int r;
 
+       if (td->io_ops->open_file(td, f)) {
+               log_err("fio: failed opening blockdev %s for size check\n",
+                       f->file_name);
+               return 1;
+       }
+
        r = blockdev_size(f->fd, &bytes);
        if (r) {
                td_verror(td, r, "blockdev_size");
-               return 1;
+               goto err;
        }
 
        if (!bytes) {
                log_err("%s: zero sized block device?\n", f->file_name);
-               return 1;
+               goto err;
        }
 
        f->real_file_size = bytes;
        return 0;
+err:
+       td->io_ops->close_file(td, f);
+       return 1;
 }
 
 static int get_file_size(struct thread_data *td, struct fio_file *f)
@@ -355,9 +364,6 @@ open_again:
                td_verror(td, __e, buf);
        }
 
-       if (get_file_size(td, f))
-               goto err;
-
        if (!from_hash && f->fd != -1) {
                if (add_file_hash(f)) {
                        int ret;
@@ -371,43 +377,11 @@ open_again:
        }
 
        return 0;
-err:
-       close(f->fd);
-       return 1;
 }
 
-int open_files(struct thread_data *td)
+int generic_get_file_size(struct thread_data *td, struct fio_file *f)
 {
-       struct fio_file *f;
-       unsigned int i;
-       int err = 0;
-
-       dprint(FD_FILE, "open files\n");
-
-       for_each_file(td, f, i) {
-               err = td_io_open_file(td, f);
-               if (err) {
-                       if (td->error == EMFILE) {
-                               log_err("fio: limited open files to: %d\n",
-                                                       td->nr_open_files);
-                               td->o.open_files = td->nr_open_files;
-                               err = 0;
-                               clear_error(td);
-                       }
-                       break;
-               }
-
-               if (td->o.open_files == td->nr_open_files)
-                       break;
-       }
-
-       if (!err)
-               return 0;
-
-       for_each_file(td, f, i)
-               td_io_close_file(td, f);
-
-       return err;
+       return get_file_size(td, f);
 }
 
 /*
@@ -423,15 +397,12 @@ static int get_file_sizes(struct thread_data *td)
                dprint(FD_FILE, "get file size for %p/%d/%p\n", f, i,
                                                                f->file_name);
 
-               if (td->io_ops->open_file(td, f)) {
+               if (td->io_ops->get_file_size(td, f)) {
                        if (td->error != ENOENT) {
                                log_err("%s\n", td->verror);
                                err = 1;
                        }
                        clear_error(td);
-               } else {
-                       if (td->io_ops->close_file)
-                               td->io_ops->close_file(td, f);
                }
 
                if (f->real_file_size == -1ULL && td->o.size)
diff --git a/fio.c b/fio.c
index b4415fa7d942c2413018fb1f174345c9cb74c339..f699951dcf58697f87922be056bfe99191e82f96 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -897,25 +897,16 @@ void reset_all_stats(struct thread_data *td)
        memcpy(&td->start, &tv, sizeof(tv));
 }
 
-static int clear_io_state(struct thread_data *td)
+static void clear_io_state(struct thread_data *td)
 {
        struct fio_file *f;
        unsigned int i;
-       int ret;
 
        reset_io_counters(td);
 
        close_files(td);
-
-       ret = 0;
-       for_each_file(td, f, i) {
+       for_each_file(td, f, i)
                f->flags &= ~FIO_FILE_DONE;
-               ret = td_io_open_file(td, f);
-               if (ret)
-                       break;
-       }
-
-       return ret;
 }
 
 /*
@@ -1003,9 +994,6 @@ static void *thread_main(void *data)
        if (td_io_init(td))
                goto err;
 
-       if (open_files(td))
-               goto err;
-
        if (init_random_map(td))
                goto err;
 
@@ -1028,8 +1016,8 @@ static void *thread_main(void *data)
                        memcpy(&td->lastrate, &td->ts.stat_sample_time,
                                                        sizeof(td->lastrate));
 
-               if (clear_state && clear_io_state(td))
-                       break;
+               if (clear_state)
+                       clear_io_state(td);
 
                prune_io_piece_log(td);
 
@@ -1064,8 +1052,7 @@ static void *thread_main(void *data)
                    (td->io_ops->flags & FIO_UNIDIR))
                        continue;
 
-               if (clear_io_state(td))
-                       break;
+               clear_io_state(td);
 
                fio_gettime(&td->start, NULL);
 
diff --git a/fio.h b/fio.h
index 22fecd9e23c0a8bf52978e546a3c17933f8e6808..b6ffe60b900cfa0f391d9e6c030e3e217f152817 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -862,10 +862,10 @@ extern void options_mem_free(struct thread_data *);
 extern void close_files(struct thread_data *);
 extern void close_and_free_files(struct thread_data *);
 extern int __must_check setup_files(struct thread_data *);
-extern int __must_check open_files(struct thread_data *);
 extern int __must_check file_invalidate_cache(struct thread_data *, struct fio_file *);
 extern int __must_check generic_open_file(struct thread_data *, struct fio_file *);
 extern int __must_check generic_close_file(struct thread_data *, struct fio_file *);
+extern int __must_check generic_get_file_size(struct thread_data *, struct fio_file *);
 extern int add_file(struct thread_data *, const char *);
 extern void get_file(struct fio_file *);
 extern int __must_check put_file(struct thread_data *, struct fio_file *);
@@ -965,6 +965,7 @@ extern int __must_check td_io_getevents(struct thread_data *, unsigned int, unsi
 extern int __must_check td_io_commit(struct thread_data *);
 extern int __must_check td_io_open_file(struct thread_data *, struct fio_file *);
 extern int td_io_close_file(struct thread_data *, struct fio_file *);
+extern int __must_check td_io_get_file_size(struct thread_data *, struct fio_file *);
 
 /*
  * blktrace support
@@ -990,11 +991,12 @@ struct ioengine_ops {
        void (*cleanup)(struct thread_data *);
        int (*open_file)(struct thread_data *, struct fio_file *);
        int (*close_file)(struct thread_data *, struct fio_file *);
+       int (*get_file_size)(struct thread_data *, struct fio_file *);
        void *data;
        void *dlhandle;
 };
 
-#define FIO_IOOPS_VERSION      9
+#define FIO_IOOPS_VERSION      10
 
 extern struct ioengine_ops *load_ioengine(struct thread_data *, const char *);
 extern void register_ioengine(struct ioengine_ops *);
index 8073d1b74dc8ca0a815b1dc4577953b39a804506..2969840706d18f75965c083c574531d9ff2fa7e0 100644 (file)
@@ -405,3 +405,11 @@ int td_io_close_file(struct thread_data *td, struct fio_file *f)
 
        return put_file(td, f);
 }
+
+int td_io_get_file_size(struct thread_data *td, struct fio_file *f)
+{
+       if (!td->io_ops->get_file_size)
+               return 0;
+
+       return td->io_ops->get_file_size(td, f);
+}