From df9c26b10275a631e83e7cc92d5f7384998b2c49 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 5 Mar 2009 10:13:58 +0100 Subject: [PATCH] Avoid opening files until they are used 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 --- engines/guasi.c | 1 + engines/libaio.c | 1 + engines/mmap.c | 1 + engines/posixaio.c | 1 + engines/sg.c | 1 + engines/solarisaio.c | 1 + engines/splice.c | 1 + engines/sync.c | 3 +++ engines/syslet-rw.c | 1 + filesetup.c | 59 +++++++++++--------------------------------- fio.c | 23 ++++------------- fio.h | 6 +++-- ioengines.c | 8 ++++++ 13 files changed, 43 insertions(+), 64 deletions(-) diff --git a/engines/guasi.c b/engines/guasi.c index 4ae01430..3802f2c2 100644 --- a/engines/guasi.c +++ b/engines/guasi.c @@ -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 */ diff --git a/engines/libaio.c b/engines/libaio.c index 99170b53..4f1e0ed4 100644 --- a/engines/libaio.c +++ b/engines/libaio.c @@ -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 */ diff --git a/engines/mmap.c b/engines/mmap.c index 5b55a811..dffad90b 100644 --- a/engines/mmap.c +++ b/engines/mmap.c @@ -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, }; diff --git a/engines/posixaio.c b/engines/posixaio.c index db11edb0..3ffdcb6b 100644 --- a/engines/posixaio.c +++ b/engines/posixaio.c @@ -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 */ diff --git a/engines/sg.c b/engines/sg.c index d7c0a6d5..39f99d8d 100644 --- a/engines/sg.c +++ b/engines/sg.c @@ -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, }; diff --git a/engines/solarisaio.c b/engines/solarisaio.c index d499f574..a48ec418 100644 --- a/engines/solarisaio.c +++ b/engines/solarisaio.c @@ -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 */ diff --git a/engines/splice.c b/engines/splice.c index a847f9ca..26c5c9ad 100644 --- a/engines/splice.c +++ b/engines/splice.c @@ -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, }; diff --git a/engines/sync.c b/engines/sync.c index 4ca04d5e..842c6c0b 100644 --- a/engines/sync.c +++ b/engines/sync.c @@ -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, }; diff --git a/engines/syslet-rw.c b/engines/syslet-rw.c index 2eab207c..ad9cb359 100644 --- a/engines/syslet-rw.c +++ b/engines/syslet-rw.c @@ -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 */ diff --git a/filesetup.c b/filesetup.c index 9862c7db..68516b9d 100644 --- a/filesetup.c +++ b/filesetup.c @@ -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 b4415fa7..f699951d 100644 --- 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 22fecd9e..b6ffe60b 100644 --- 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 *); diff --git a/ioengines.c b/ioengines.c index 8073d1b7..29698407 100644 --- a/ioengines.c +++ b/ioengines.c @@ -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); +} -- 2.25.1