Add file reference counting
authorJens Axboe <jens.axboe@oracle.com>
Tue, 13 Mar 2007 10:06:45 +0000 (11:06 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Tue, 13 Mar 2007 10:06:45 +0000 (11:06 +0100)
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 <jens.axboe@oracle.com>
filesetup.c
fio.h
init.c
io_u.c
ioengines.c

index f6e9974..f3fccdb 100644 (file)
@@ -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 e451f95..5bf8c43 100644 (file)
--- 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 f3c756e..66a50b0 100644 (file)
--- 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 c16128e..477f387 100644 (file)
--- 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;
index 02455b8..185314f 100644 (file)
@@ -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);
 }
+