The following changes since commit d06ab917303f70289ad8f256c6e79a1eeee4bee4: Merge branch 'master' of ssh://brick.kernel.dk/data/git/fio (2012-12-10 10:16:45 +0100) are available in the git repository at: git://git.kernel.dk/fio.git master Jens Axboe (3): file hash: don't close file fd on lookup/add race file: unify ->file_data and ->file_pos binject: fixup ->file_data breakage engines/binject.c | 16 ++++++++-------- engines/e4defrag.c | 3 --- engines/falloc.c | 3 --- engines/fusion-aw.c | 1 - engines/sync.c | 9 +++++++-- file.h | 5 ++--- filesetup.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 7 files changed, 59 insertions(+), 22 deletions(-) --- Diff of recent changes: diff --git a/engines/binject.c b/engines/binject.c index 47d40fe..f78d855 100644 --- a/engines/binject.c +++ b/engines/binject.c @@ -69,7 +69,7 @@ static unsigned int binject_read_commands(struct thread_data *td, void *p, one_more: events = 0; for_each_file(td, f, i) { - bf = f->file_data; + bf = (void *) f->engine_data; ret = read(bf->fd, p, left * sizeof(struct b_user_cmd)); if (ret < 0) { if (errno == EAGAIN) @@ -104,7 +104,7 @@ static int fio_binject_getevents(struct thread_data *td, unsigned int min, * Fill in the file descriptors */ for_each_file(td, f, i) { - bf = f->file_data; + bf = (void *) f->engine_data; /* * don't block for min events == 0 @@ -153,7 +153,7 @@ static int fio_binject_getevents(struct thread_data *td, unsigned int min, if (!min) { for_each_file(td, f, i) { - bf = f->file_data; + bf = (void *) f->engine_data; fcntl(bf->fd, F_SETFL, bd->fd_flags[i]); } } @@ -167,7 +167,7 @@ static int fio_binject_getevents(struct thread_data *td, unsigned int min, static int fio_binject_doio(struct thread_data *td, struct io_u *io_u) { struct b_user_cmd *buc = &io_u->buc; - struct binject_file *bf = io_u->file->file_data; + struct binject_file *bf = (void *) io_u->file->engine_data; int ret; ret = write(bf->fd, buc, sizeof(*buc)); @@ -181,7 +181,7 @@ static int fio_binject_prep(struct thread_data *td, struct io_u *io_u) { struct binject_data *bd = td->io_ops->data; struct b_user_cmd *buc = &io_u->buc; - struct binject_file *bf = io_u->file->file_data; + struct binject_file *bf = (void *) io_u->file->engine_data; if (io_u->xfer_buflen & (bf->bs - 1)) { log_err("read/write not sector aligned\n"); @@ -323,12 +323,12 @@ err_unmap: static int fio_binject_close_file(struct thread_data *td, struct fio_file *f) { - struct binject_file *bf = f->file_data; + struct binject_file *bf = (void *) f->engine_data; if (bf) { binject_unmap_dev(td, bf); free(bf); - f->file_data = NULL; + f->engine_data = 0; return generic_close_file(td, f); } @@ -357,7 +357,7 @@ static int fio_binject_open_file(struct thread_data *td, struct fio_file *f) bf = malloc(sizeof(*bf)); bf->bs = bs; bf->minor = bf->fd = -1; - f->file_data = bf; + f->engine_data = (uint64_t) bf; if (binject_map_dev(td, bf, f->fd)) { err_close: diff --git a/engines/e4defrag.c b/engines/e4defrag.c index e10cf36..6063e6c 100644 --- a/engines/e4defrag.c +++ b/engines/e4defrag.c @@ -161,9 +161,6 @@ static int fio_e4defrag_queue(struct thread_data *td, struct io_u *io_u) ret = ioctl(f->fd, EXT4_IOC_MOVE_EXT, &me); len = me.moved_len * ed->bsz; - if (io_u->file && len && ddir_rw(io_u->ddir)) - io_u->file->file_pos = io_u->offset + len; - if (len > io_u->xfer_buflen) len = io_u->xfer_buflen; diff --git a/engines/falloc.c b/engines/falloc.c index bc5ebd7..525a0aa 100644 --- a/engines/falloc.c +++ b/engines/falloc.c @@ -89,9 +89,6 @@ static int fio_fallocate_queue(struct thread_data *td, struct io_u *io_u) if (ret) io_u->error = errno; - if (io_u->file && ret == 0 && ddir_rw(io_u->ddir)) - io_u->file->file_pos = io_u->offset + ret; - return FIO_Q_COMPLETED; } diff --git a/engines/fusion-aw.c b/engines/fusion-aw.c index 9aac43a..118c6dd 100644 --- a/engines/fusion-aw.c +++ b/engines/fusion-aw.c @@ -88,7 +88,6 @@ static int queue(struct thread_data *td, struct io_u *io_u) goto out; } else { io_u->error = 0; - io_u->file->file_pos = io_u->offset + rc; rc = FIO_Q_COMPLETED; } diff --git a/engines/sync.c b/engines/sync.c index bd912e7..8779628 100644 --- a/engines/sync.c +++ b/engines/sync.c @@ -14,6 +14,11 @@ #include "../fio.h" +/* + * Sync engine uses engine_data to store last offset + */ +#define LAST_POS(f) ((f)->engine_data) + struct syncio_data { struct iovec *iovecs; struct io_u **io_us; @@ -33,7 +38,7 @@ static int fio_syncio_prep(struct thread_data *td, struct io_u *io_u) if (!ddir_rw(io_u->ddir)) return 0; - if (f->file_pos != -1ULL && f->file_pos == io_u->offset) + if (LAST_POS(f) != -1ULL && LAST_POS(f) == io_u->offset) return 0; if (lseek(f->fd, io_u->offset, SEEK_SET) == -1) { @@ -47,7 +52,7 @@ static int fio_syncio_prep(struct thread_data *td, struct io_u *io_u) static int fio_io_end(struct thread_data *td, struct io_u *io_u, int ret) { if (io_u->file && ret >= 0 && ddir_rw(io_u->ddir)) - io_u->file->file_pos = io_u->offset + ret; + LAST_POS(io_u->file) = io_u->offset + ret; if (ret != (int) io_u->xfer_buflen) { if (ret >= 0) { diff --git a/file.h b/file.h index 3024c54..e57bebc 100644 --- a/file.h +++ b/file.h @@ -63,8 +63,8 @@ struct fio_file { struct flist_head hash_list; enum fio_filetype filetype; - void *file_data; int fd; + int shadow_fd; #ifdef WIN32 HANDLE hFile; HANDLE ioCP; @@ -97,7 +97,7 @@ struct fio_file { /* * For use by the io engine */ - unsigned long long file_pos; + uint64_t engine_data; /* * if io is protected by a semaphore, this is set @@ -180,7 +180,6 @@ static inline void fio_file_reset(struct fio_file *f) { f->last_pos = f->file_offset; f->last_start = -1ULL; - f->file_pos = -1ULL; if (f->io_axmap) axmap_reset(f->io_axmap); } diff --git a/filesetup.c b/filesetup.c index f4e1adc..9d3e062 100644 --- a/filesetup.c +++ b/filesetup.c @@ -434,6 +434,12 @@ int generic_close_file(struct thread_data fio_unused *td, struct fio_file *f) ret = errno; f->fd = -1; + + if (f->shadow_fd != -1) { + close(f->shadow_fd); + f->shadow_fd = -1; + } + return ret; } @@ -462,6 +468,24 @@ int file_lookup_open(struct fio_file *f, int flags) return from_hash; } +static int file_close_shadow_fds(struct thread_data *td) +{ + struct fio_file *f; + int num_closed = 0; + unsigned int i; + + for_each_file(td, f, i) { + if (f->shadow_fd == -1) + continue; + + close(f->shadow_fd); + f->shadow_fd = -1; + num_closed++; + } + + return num_closed; +} + int generic_open_file(struct thread_data *td, struct fio_file *f) { int is_std = 0; @@ -536,6 +560,8 @@ open_again: flags &= ~FIO_O_NOATIME; goto open_again; } + if (__e == EMFILE && file_close_shadow_fds(td)) + goto open_again; snprintf(buf, sizeof(buf) - 1, "open(%s)", f->file_name); @@ -552,9 +578,22 @@ open_again: int fio_unused ret; /* - * OK to ignore, we haven't done anything with it + * Stash away descriptor for later close. This is to + * work-around a "feature" on Linux, where a close of + * an fd that has been opened for write will trigger + * udev to call blkid to check partitions, fs id, etc. + * That polutes the device cache, which can slow down + * unbuffered accesses. */ - ret = generic_close_file(td, f); + if (f->shadow_fd == -1) + f->shadow_fd = f->fd; + else { + /* + * OK to ignore, we haven't done anything + * with it + */ + ret = generic_close_file(td, f); + } goto open_again; } } @@ -1029,6 +1068,7 @@ int add_file(struct thread_data *td, const char *fname) } f->fd = -1; + f->shadow_fd = -1; fio_file_reset(f); if (td->files_size <= td->files_index) { -- To unsubscribe from this list: send the line "unsubscribe fio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html