[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 <jens.axboe@oracle.com>
diff --git a/engines/fio-engine-libaio.c b/engines/fio-engine-libaio.c
index 57daf1b..5e394e3 100644
--- a/engines/fio-engine-libaio.c
+++ b/engines/fio-engine-libaio.c
@@ -17,20 +17,18 @@
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 @@
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 @@
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 @@
.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 d203d6a..c85f661 100644
--- a/engines/fio-engine-mmap.c
+++ b/engines/fio-engine-mmap.c
@@ -48,8 +48,10 @@
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 @@
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 @@
.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 260551a..2d0fd31 100644
--- a/engines/fio-engine-posixaio.c
+++ b/engines/fio-engine-posixaio.c
@@ -45,12 +45,6 @@
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 @@
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 @@
.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 01eba8d..112f027 100644
--- a/engines/fio-engine-sg.c
+++ b/engines/fio-engine-sg.c
@@ -151,28 +151,6 @@
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 @@
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;
}
- 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;
+ 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;
+ }
+
return 0;
}
@@ -210,7 +198,7 @@
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 @@
.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 cb39b72..3553d64 100644
--- a/engines/fio-engine-splice.c
+++ b/engines/fio-engine-splice.c
@@ -16,12 +16,6 @@
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 @@
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 @@
.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 d5be4c8..8bc990d 100644
--- a/engines/fio-engine-sync.c
+++ b/engines/fio-engine-sync.c
@@ -14,12 +14,6 @@
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 @@
{
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 @@
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 @@
.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 5673d9e..fc653b3 100644
--- a/fio.c
+++ b/fio.c
@@ -45,8 +45,6 @@
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 @@
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 @@
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 921282c..967c42e 100644
--- a/fio.h
+++ b/fio.h
@@ -113,6 +113,7 @@
enum fio_ddir {
DDIR_READ = 0,
DDIR_WRITE,
+ DDIR_SYNC,
};
/*
@@ -184,6 +185,7 @@
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 @@
#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 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 962c17a..738f3e2 100644
--- a/io_u.c
+++ b/io_u.c
@@ -190,6 +190,16 @@
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.
*/
if (!get_next_offset(td, f, &io_u->offset)) {
@@ -260,19 +270,21 @@
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);
+
+ f->last_pos += io_u->buflen;
+
+ if (td->verify != VERIFY_NONE)
+ populate_verify_io_u(td, io_u);
}
- if (!td->read_iolog && !td->sequential)
- mark_random_map(td, f, io_u);
-
- f->last_pos += io_u->buflen;
-
- 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);
return NULL;
@@ -288,6 +300,13 @@
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 9b1ad60..bb46c29 100644
--- a/ioengines.c
+++ b/ioengines.c
@@ -113,8 +113,40 @@
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;
}