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;
+}
};
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 */
};
/*
unsigned int num_maps;
unsigned int last_free_lookup;
+ int references;
enum fio_file_flags flags;
};
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
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;
}
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;
}
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);
}
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;
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;
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;
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);
}
+