From 0ad920e7f85db1fdc26649be6bc7e584e8c7fdc9 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 13 Mar 2007 11:06:45 +0100 Subject: [PATCH] Add file reference counting We must not close a file, while io is in progress to it. That will make the queuing engines barf. Signed-off-by: Jens Axboe --- filesetup.c | 20 ++++++++++++++++++++ fio.h | 8 ++++++-- init.c | 9 +++++++-- io_u.c | 8 ++++++-- ioengines.c | 18 ++++++++++++------ 5 files changed, 51 insertions(+), 12 deletions(-) diff --git a/filesetup.c b/filesetup.c index f6e99743..f3fccdbe 100644 --- a/filesetup.c +++ b/filesetup.c @@ -445,3 +445,23 @@ void add_file(struct thread_data *td, const char *fname) td->open_files++; td->nr_uniq_files = td->open_files; } + +void get_file(struct fio_file *f) +{ + f->references++; +} + +void put_file(struct thread_data *td, struct fio_file *f) +{ + if (!(f->flags & FIO_FILE_OPEN)) + return; + + assert(f->references); + if (--f->references) + return; + + if (td->io_ops->close_file) + td->io_ops->close_file(td, f); + td->nr_open_files--; + f->flags &= ~FIO_FILE_OPEN; +} diff --git a/fio.h b/fio.h index e451f955..5bf8c43d 100644 --- a/fio.h +++ b/fio.h @@ -219,8 +219,9 @@ enum fio_ioengine_flags { }; enum fio_file_flags { - FIO_FILE_OPEN = 1 << 0, - FIO_FILE_UNLINK = 1 << 1, + FIO_FILE_OPEN = 1 << 0, /* file is open */ + FIO_FILE_UNLINK = 1 << 1, /* unlink on close */ + FIO_FILE_CLOSING = 1 << 2, /* file being closed */ }; /* @@ -252,6 +253,7 @@ struct fio_file { unsigned int num_maps; unsigned int last_free_lookup; + int references; enum fio_file_flags flags; }; @@ -654,6 +656,8 @@ extern int __must_check file_invalidate_cache(struct thread_data *, struct fio_f extern int __must_check generic_open_file(struct thread_data *, struct fio_file *); extern void generic_close_file(struct thread_data *, struct fio_file *); extern void add_file(struct thread_data *, const char *); +extern void get_file(struct fio_file *); +extern void put_file(struct thread_data *, struct fio_file *); /* * ETA/status stuff diff --git a/init.c b/init.c index f3c756e9..66a50b03 100644 --- a/init.c +++ b/init.c @@ -752,7 +752,9 @@ static void fixup_options(struct thread_data *td) if (td->iodepth_batch > td->iodepth || !td->iodepth_batch) td->iodepth_batch = td->iodepth; - if (td->open_files > td->nr_files || !td->open_files) + if (!td->nr_files) + td->nr_files = td->open_files; + else if (td->open_files > td->nr_files || !td->open_files) td->open_files = td->nr_files; } @@ -1103,9 +1105,12 @@ static int str_filename_cb(void *data, const char *input) struct thread_data *td = data; char *fname, *str; + td->nr_files = 0; str = strdup(input); - while ((fname = strsep(&str, ":")) != NULL) + while ((fname = strsep(&str, ":")) != NULL) { add_file(td, fname); + td->nr_files++; + } return 0; } diff --git a/io_u.c b/io_u.c index c16128e9..477f3877 100644 --- a/io_u.c +++ b/io_u.c @@ -340,7 +340,8 @@ static struct fio_file *get_next_file_rand(struct thread_data *td) fileno = (unsigned int) ((double) (td->open_files * r) / (RAND_MAX + 1.0)); f = &td->files[fileno]; - if (f->flags & FIO_FILE_OPEN) + if ((f->flags & FIO_FILE_OPEN) && + !(f->flags & FIO_FILE_CLOSING)) return f; } while (1); } @@ -360,7 +361,8 @@ static struct fio_file *get_next_file_rr(struct thread_data *td) if (td->next_file >= td->open_files) td->next_file = 0; - if (f->flags & FIO_FILE_OPEN) + if ((f->flags & FIO_FILE_OPEN) && + !(f->flags & FIO_FILE_CLOSING)) break; f = NULL; @@ -537,6 +539,8 @@ static void io_completed(struct thread_data *td, struct io_u *io_u, assert(io_u->flags & IO_U_F_FLIGHT); io_u->flags &= ~IO_U_F_FLIGHT; + put_file(td, io_u->file); + if (io_u->ddir == DDIR_SYNC) { td->last_was_sync = 1; return; diff --git a/ioengines.c b/ioengines.c index 02455b85..185314f0 100644 --- a/ioengines.c +++ b/ioengines.c @@ -206,6 +206,9 @@ int td_io_queue(struct thread_data *td, struct io_u *io_u) ret = td->io_ops->queue(td, io_u); + if (ret == FIO_Q_QUEUED || ret == FIO_Q_COMPLETED) + get_file(io_u->file); + if (ret == FIO_Q_QUEUED) { int r; @@ -260,20 +263,23 @@ int td_io_open_file(struct thread_data *td, struct fio_file *f) f->last_completed_pos = 0; f->last_pos = 0; f->flags |= FIO_FILE_OPEN; + f->flags &= ~FIO_FILE_CLOSING; if (f->file_map) memset(f->file_map, 0, f->num_maps * sizeof(long)); td->nr_open_files++; + get_file(f); return 0; } void td_io_close_file(struct thread_data *td, struct fio_file *f) { - if (f->flags & FIO_FILE_OPEN) { - if (td->io_ops->close_file) - td->io_ops->close_file(td, f); - td->nr_open_files--; - f->flags &= ~FIO_FILE_OPEN; - } + /* + * mark as closing, do real close when last io on it has completed + */ + f->flags |= FIO_FILE_CLOSING; + + put_file(td, f); } + -- 2.25.1