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;
}
break;
} while (1);
- return (int) r;
+ return (int) -r;
}
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)
.getevents = fio_libaio_getevents,
.event = fio_libaio_event,
.cleanup = fio_libaio_cleanup,
- .sync = fio_libaio_sync,
};
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
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) {
.getevents = fio_mmapio_getevents,
.event = fio_mmapio_event,
.cleanup = fio_mmapio_cleanup,
- .sync = fio_mmapio_sync,
.flags = FIO_SYNCIO | FIO_MMAPIO,
};
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)
{
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;
.getevents = fio_posixaio_getevents,
.event = fio_posixaio_event,
.cleanup = fio_posixaio_cleanup,
- .sync = fio_posixaio_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;
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;
}
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;
.getevents = fio_sgio_getevents,
.event = fio_sgio_event,
.cleanup = fio_sgio_cleanup,
- .sync = fio_sgio_sync,
.flags = FIO_SYNCIO | FIO_RAWIO,
};
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)
{
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) {
.getevents = fio_spliceio_getevents,
.event = fio_spliceio_event,
.cleanup = fio_spliceio_cleanup,
- .sync = fio_spliceio_sync,
.flags = FIO_SYNCIO,
};
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)
{
{
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;
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) {
.getevents = fio_syncio_getevents,
.event = fio_syncio_event,
.cleanup = fio_syncio_cleanup,
- .sync = fio_syncio_sync,
.flags = FIO_SYNCIO,
};
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)
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;
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) {
enum fio_ddir {
DDIR_READ = 0,
DDIR_WRITE,
+ DDIR_SYNC,
};
/*
enum fio_ddir ddir;
unsigned int iomix;
unsigned int ioprio;
+ unsigned int last_was_sync;
unsigned char sequential;
unsigned char odirect;
#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];
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 *);
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.
*/
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);
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) {
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;
}