From: Jens Axboe Date: Tue, 24 Oct 2006 12:41:26 +0000 (+0200) Subject: [PATCH] Implement file syncing as data direction X-Git-Tag: fio-1.8~48 X-Git-Url: https://git.kernel.dk/?p=fio.git;a=commitdiff_plain;h=87dc1ab1b4df7b977f60e3d43533a896e2ee665b;hp=dfd7bc2c24d3a4281982eaf4f83aa1aeb09424de [PATCH] Implement file syncing as data direction Instead of defining a seperate ->sync() operation for the io engine, reuse the io_u infrastructure for committing and reaping sync events as well. It's a nice cleanup as well. Signed-off-by: Jens Axboe --- diff --git a/engines/fio-engine-libaio.c b/engines/fio-engine-libaio.c index 57daf1b6..5e394e3e 100644 --- a/engines/fio-engine-libaio.c +++ b/engines/fio-engine-libaio.c @@ -17,20 +17,18 @@ struct libaio_data { struct io_event *aio_events; }; -static int fio_libaio_sync(struct thread_data fio_unused *td, - struct fio_file *f) -{ - return fsync(f->fd); -} - static int fio_libaio_prep(struct thread_data fio_unused *td, struct io_u *io_u) { struct fio_file *f = io_u->file; if (io_u->ddir == DDIR_READ) io_prep_pread(&io_u->iocb, f->fd, io_u->buf, io_u->buflen, io_u->offset); - else + else if (io_u->ddir == DDIR_WRITE) io_prep_pwrite(&io_u->iocb, f->fd, io_u->buf, io_u->buflen, io_u->offset); + else if (io_u->ddir == DDIR_SYNC) + io_prep_fsync(&io_u->iocb, f->fd); + else + return 1; return 0; } @@ -59,7 +57,7 @@ static int fio_libaio_getevents(struct thread_data *td, int min, int max, break; } while (1); - return (int) r; + return (int) -r; } static int fio_libaio_queue(struct thread_data *td, struct io_u *io_u) @@ -82,7 +80,7 @@ static int fio_libaio_queue(struct thread_data *td, struct io_u *io_u) assert(ret); - return (int) ret; + return (int) -ret; } static int fio_libaio_cancel(struct thread_data *td, struct io_u *io_u) @@ -132,5 +130,4 @@ struct ioengine_ops ioengine = { .getevents = fio_libaio_getevents, .event = fio_libaio_event, .cleanup = fio_libaio_cleanup, - .sync = fio_libaio_sync, }; diff --git a/engines/fio-engine-mmap.c b/engines/fio-engine-mmap.c index d203d6af..c85f6617 100644 --- a/engines/fio-engine-mmap.c +++ b/engines/fio-engine-mmap.c @@ -48,8 +48,10 @@ static int fio_mmapio_queue(struct thread_data *td, struct io_u *io_u) if (io_u->ddir == DDIR_READ) memcpy(io_u->buf, f->mmap + real_off, io_u->buflen); - else + else if (io_u->ddir == DDIR_WRITE) memcpy(f->mmap + real_off, io_u->buf, io_u->buflen); + else if (io_u->ddir == DDIR_SYNC) + return msync(f->mmap, f->file_size, MS_SYNC); /* * not really direct, but should drop the pages from the cache @@ -67,12 +69,6 @@ static int fio_mmapio_queue(struct thread_data *td, struct io_u *io_u) return io_u->error; } -static int fio_mmapio_sync(struct thread_data fio_unused *td, - struct fio_file *f) -{ - return msync(f->mmap, f->file_size, MS_SYNC); -} - static void fio_mmapio_cleanup(struct thread_data *td) { if (td->io_ops->data) { @@ -98,6 +94,5 @@ struct ioengine_ops ioengine = { .getevents = fio_mmapio_getevents, .event = fio_mmapio_event, .cleanup = fio_mmapio_cleanup, - .sync = fio_mmapio_sync, .flags = FIO_SYNCIO | FIO_MMAPIO, }; diff --git a/engines/fio-engine-posixaio.c b/engines/fio-engine-posixaio.c index 260551a4..2d0fd311 100644 --- a/engines/fio-engine-posixaio.c +++ b/engines/fio-engine-posixaio.c @@ -45,12 +45,6 @@ static unsigned long long ts_utime_since_now(struct timespec *t) return sec + nsec; } -static int fio_posixaio_sync(struct thread_data fio_unused *td, - struct fio_file *f) -{ - return fsync(f->fd); -} - static int fio_posixaio_cancel(struct thread_data fio_unused *td, struct io_u *io_u) { @@ -149,8 +143,10 @@ static int fio_posixaio_queue(struct thread_data fio_unused *td, if (io_u->ddir == DDIR_READ) ret = aio_read(aiocb); - else + else if (io_u->ddir == DDIR_WRITE) ret = aio_write(aiocb); + else + ret = aio_fsync(O_SYNC, aiocb); if (ret) io_u->error = errno; @@ -189,5 +185,4 @@ struct ioengine_ops ioengine = { .getevents = fio_posixaio_getevents, .event = fio_posixaio_event, .cleanup = fio_posixaio_cleanup, - .sync = fio_posixaio_sync, }; diff --git a/engines/fio-engine-sg.c b/engines/fio-engine-sg.c index 01eba8d5..112f0278 100644 --- a/engines/fio-engine-sg.c +++ b/engines/fio-engine-sg.c @@ -151,28 +151,6 @@ static int fio_sgio_doio(struct thread_data *td, struct io_u *io_u, int sync) return fio_sgio_rw_doio(f, io_u, sync); } -static int fio_sgio_sync(struct thread_data *td, struct fio_file fio_unused *f) -{ - struct sgio_data *sd = td->io_ops->data; - struct sg_io_hdr *hdr; - struct io_u *io_u; - int ret; - - io_u = __get_io_u(td); - if (!io_u) - return ENOMEM; - - hdr = &io_u->hdr; - sgio_hdr_init(sd, hdr, io_u, 0); - hdr->dxfer_direction = SG_DXFER_NONE; - - hdr->cmdp[0] = 0x35; - - ret = fio_sgio_doio(td, io_u, 1); - put_io_u(td, io_u); - return ret; -} - static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u) { struct sg_io_hdr *hdr = &io_u->hdr; @@ -184,24 +162,34 @@ static int fio_sgio_prep(struct thread_data *td, struct io_u *io_u) return EINVAL; } - sgio_hdr_init(sd, hdr, io_u, 1); - if (io_u->ddir == DDIR_READ) { + sgio_hdr_init(sd, hdr, io_u, 1); + hdr->dxfer_direction = SG_DXFER_FROM_DEV; hdr->cmdp[0] = 0x28; - } else { + } else if (io_u->ddir == DDIR_WRITE) { + sgio_hdr_init(sd, hdr, io_u, 1); + hdr->dxfer_direction = SG_DXFER_TO_DEV; hdr->cmdp[0] = 0x2a; + } else { + sgio_hdr_init(sd, hdr, io_u, 0); + + hdr->dxfer_direction = SG_DXFER_NONE; + hdr->cmdp[0] = 0x35; + } + + if (hdr->dxfer_direction != SG_DXFER_NONE) { + nr_blocks = io_u->buflen / sd->bs; + lba = io_u->offset / sd->bs; + hdr->cmdp[2] = (lba >> 24) & 0xff; + hdr->cmdp[3] = (lba >> 16) & 0xff; + hdr->cmdp[4] = (lba >> 8) & 0xff; + hdr->cmdp[5] = lba & 0xff; + hdr->cmdp[7] = (nr_blocks >> 8) & 0xff; + hdr->cmdp[8] = nr_blocks & 0xff; } - nr_blocks = io_u->buflen / sd->bs; - lba = io_u->offset / sd->bs; - hdr->cmdp[2] = (lba >> 24) & 0xff; - hdr->cmdp[3] = (lba >> 16) & 0xff; - hdr->cmdp[4] = (lba >> 8) & 0xff; - hdr->cmdp[5] = lba & 0xff; - hdr->cmdp[7] = (nr_blocks >> 8) & 0xff; - hdr->cmdp[8] = nr_blocks & 0xff; return 0; } @@ -210,7 +198,7 @@ static int fio_sgio_queue(struct thread_data *td, struct io_u *io_u) struct sg_io_hdr *hdr = &io_u->hdr; int ret; - ret = fio_sgio_doio(td, io_u, 0); + ret = fio_sgio_doio(td, io_u, io_u->ddir == DDIR_SYNC); if (ret < 0) io_u->error = errno; @@ -324,6 +312,5 @@ struct ioengine_ops ioengine = { .getevents = fio_sgio_getevents, .event = fio_sgio_event, .cleanup = fio_sgio_cleanup, - .sync = fio_sgio_sync, .flags = FIO_SYNCIO | FIO_RAWIO, }; diff --git a/engines/fio-engine-splice.c b/engines/fio-engine-splice.c index cb39b722..3553d646 100644 --- a/engines/fio-engine-splice.c +++ b/engines/fio-engine-splice.c @@ -16,12 +16,6 @@ struct spliceio_data { int pipe[2]; }; -static int fio_spliceio_sync(struct thread_data fio_unused *td, - struct fio_file *f) -{ - return fsync(f->fd); -} - static int fio_spliceio_getevents(struct thread_data *td, int fio_unused min, int max, struct timespec fio_unused *t) { @@ -139,8 +133,10 @@ static int fio_spliceio_queue(struct thread_data *td, struct io_u *io_u) if (io_u->ddir == DDIR_READ) ret = fio_splice_read(td, io_u); - else + else if (io_u->ddir == DDIR_WRITE) ret = fio_splice_write(td, io_u); + else + ret = fsync(io_u->file->fd); if ((unsigned int) ret != io_u->buflen) { if (ret > 0) { @@ -191,6 +187,5 @@ struct ioengine_ops ioengine = { .getevents = fio_spliceio_getevents, .event = fio_spliceio_event, .cleanup = fio_spliceio_cleanup, - .sync = fio_spliceio_sync, .flags = FIO_SYNCIO, }; diff --git a/engines/fio-engine-sync.c b/engines/fio-engine-sync.c index d5be4c82..8bc990d7 100644 --- a/engines/fio-engine-sync.c +++ b/engines/fio-engine-sync.c @@ -14,12 +14,6 @@ struct syncio_data { struct io_u *last_io_u; }; -static int fio_syncio_sync(struct thread_data fio_unused *td, - struct fio_file *f) -{ - return fsync(f->fd); -} - static int fio_syncio_getevents(struct thread_data *td, int fio_unused min, int max, struct timespec fio_unused *t) { @@ -48,6 +42,9 @@ static int fio_syncio_prep(struct thread_data *td, struct io_u *io_u) { struct fio_file *f = io_u->file; + if (io_u->ddir == DDIR_SYNC) + return 0; + if (lseek(f->fd, io_u->offset, SEEK_SET) == -1) { td_verror(td, errno); return 1; @@ -64,8 +61,10 @@ static int fio_syncio_queue(struct thread_data *td, struct io_u *io_u) if (io_u->ddir == DDIR_READ) ret = read(f->fd, io_u->buf, io_u->buflen); - else + else if (io_u->ddir == DDIR_WRITE) ret = write(f->fd, io_u->buf, io_u->buflen); + else + ret = fsync(f->fd); if ((unsigned int) ret != io_u->buflen) { if (ret > 0) { @@ -107,6 +106,5 @@ struct ioengine_ops ioengine = { .getevents = fio_syncio_getevents, .event = fio_syncio_event, .cleanup = fio_syncio_cleanup, - .sync = fio_syncio_sync, .flags = FIO_SYNCIO, }; diff --git a/fio.c b/fio.c index 5673d9ef..fc653b3d 100644 --- a/fio.c +++ b/fio.c @@ -45,8 +45,6 @@ int shm_id = 0; int temp_stall_ts; char *fio_inst_prefix = _INST_PREFIX; -#define should_fsync(td) ((td_write(td) || td_rw(td)) && (!(td)->odirect || (td)->override_sync)) - static volatile int startup_sem; #define TERMINATE_ALL (-1) @@ -372,7 +370,7 @@ static void do_io(struct thread_data *td) ret = td_io_getevents(td, min_evts, td->cur_depth, timeout); if (ret < 0) { - td_verror(td, -ret); + td_verror(td, ret); break; } else if (!ret) continue; @@ -406,10 +404,6 @@ static void do_io(struct thread_data *td) if (td->thinktime) usec_sleep(td, td->thinktime); - - if (should_fsync(td) && td->fsync_blocks && - (td->io_blocks[DDIR_WRITE] % td->fsync_blocks) == 0) - td_io_sync(td, f); } if (!ret) { diff --git a/fio.h b/fio.h index 921282cc..967c42e6 100644 --- a/fio.h +++ b/fio.h @@ -113,6 +113,7 @@ struct group_run_stats { enum fio_ddir { DDIR_READ = 0, DDIR_WRITE, + DDIR_SYNC, }; /* @@ -184,6 +185,7 @@ struct thread_data { enum fio_ddir ddir; unsigned int iomix; unsigned int ioprio; + unsigned int last_was_sync; unsigned char sequential; unsigned char odirect; @@ -365,6 +367,18 @@ extern struct thread_data *threads; #define MAX_JOBS (1024) +static inline int should_fsync(struct thread_data *td) +{ + if (td->last_was_sync) + return 0; + if (td->odirect) + return 0; + if (td_write(td) || td_rw(td) || td->override_sync) + return 1; + + return 0; +} + struct disk_util_stat { unsigned ios[2]; unsigned merges[2]; @@ -554,12 +568,11 @@ struct ioengine_ops { struct io_u *(*event)(struct thread_data *, int); int (*cancel)(struct thread_data *, struct io_u *); void (*cleanup)(struct thread_data *); - int (*sync)(struct thread_data *, struct fio_file *); void *data; void *dlhandle; }; -#define FIO_IOOPS_VERSION 2 +#define FIO_IOOPS_VERSION 3 extern struct ioengine_ops *load_ioengine(struct thread_data *, char *); extern void close_ioengine(struct thread_data *); diff --git a/io_u.c b/io_u.c index 962c17a9..738f3e20 100644 --- a/io_u.c +++ b/io_u.c @@ -189,6 +189,16 @@ static int fill_io_u(struct thread_data *td, struct fio_file *f, if (td->read_iolog) return read_iolog_get(td, io_u); + /* + * see if it's time to sync + */ + if (td->fsync_blocks && !(td->io_blocks[DDIR_WRITE] % td->fsync_blocks) + && should_fsync(td)) { + io_u->ddir = DDIR_SYNC; + io_u->file = f; + return 0; + } + /* * No log, let the seq/rand engine retrieve the next position. */ @@ -260,18 +270,20 @@ struct io_u *get_io_u(struct thread_data *td, struct fio_file *f) io_u->buflen = f->file_size - io_u->offset; } - if (!io_u->buflen) { - put_io_u(td, io_u); - return NULL; - } + if (io_u->ddir != DDIR_SYNC) { + if (!io_u->buflen) { + put_io_u(td, io_u); + return NULL; + } - if (!td->read_iolog && !td->sequential) - mark_random_map(td, f, io_u); + if (!td->read_iolog && !td->sequential) + mark_random_map(td, f, io_u); - f->last_pos += io_u->buflen; + f->last_pos += io_u->buflen; - if (td->verify != VERIFY_NONE) - populate_verify_io_u(td, io_u); + if (td->verify != VERIFY_NONE) + populate_verify_io_u(td, io_u); + } if (td_io_prep(td, io_u)) { put_io_u(td, io_u); @@ -288,6 +300,13 @@ void io_completed(struct thread_data *td, struct io_u *io_u, struct timeval e; unsigned long msec; + if (io_u->ddir == DDIR_SYNC) { + td->last_was_sync = 1; + return; + } + + td->last_was_sync = 0; + gettimeofday(&e, NULL); if (!io_u->error) { diff --git a/ioengines.c b/ioengines.c index 9b1ad606..bb46c293 100644 --- a/ioengines.c +++ b/ioengines.c @@ -113,8 +113,40 @@ int td_io_prep(struct thread_data *td, struct io_u *io_u) int td_io_sync(struct thread_data *td, struct fio_file *f) { - if (td->io_ops->sync) - return td->io_ops->sync(td, f); + struct io_u *io_u = __get_io_u(td); + struct io_completion_data icd; + int ret; + + if (!io_u) + return 1; + + io_u->ddir = DDIR_SYNC; + io_u->file = f; + + if (td_io_prep(td, io_u)) { + put_io_u(td, io_u); + return 1; + } + + ret = td_io_queue(td, io_u); + if (ret) { + put_io_u(td, io_u); + td_verror(td, ret); + return 1; + } + + ret = td_io_getevents(td, 1, td->cur_depth, NULL); + if (ret < 0) { + td_verror(td, -ret); + return 1; + } + + icd.nr = ret; + ios_completed(td, &icd); + if (icd.error) { + td_verror(td, icd.error); + return 1; + } return 0; }