static bool fio_io_sync(struct thread_data *td, struct fio_file *f)
{
struct io_u *io_u = __get_io_u(td);
- int ret;
+ enum fio_q_status ret;
if (!io_u)
return true;
requeue:
ret = td_io_queue(td, io_u);
- if (ret < 0) {
- td_verror(td, io_u->error, "td_io_queue");
- put_io_u(td, io_u);
- return true;
- } else if (ret == FIO_Q_QUEUED) {
- if (td_io_commit(td))
- return true;
+ switch (ret) {
+ case FIO_Q_QUEUED:
+ td_io_commit(td);
if (io_u_queued_complete(td, 1) < 0)
return true;
- } else if (ret == FIO_Q_COMPLETED) {
+ break;
+ case FIO_Q_COMPLETED:
if (io_u->error) {
td_verror(td, io_u->error, "td_io_queue");
return true;
if (io_u_sync_complete(td, io_u) < 0)
return true;
- } else if (ret == FIO_Q_BUSY) {
- if (td_io_commit(td))
- return true;
+ break;
+ case FIO_Q_BUSY:
+ td_io_commit(td);
goto requeue;
}
enum fio_ddir ddir, uint64_t *bytes_issued, int from_verify,
struct timespec *comp_time)
{
- int ret2;
-
switch (*ret) {
case FIO_Q_COMPLETED:
if (io_u->error) {
if (!from_verify)
unlog_io_piece(td, io_u);
requeue_io_u(td, &io_u);
- ret2 = td_io_commit(td);
- if (ret2 < 0)
- *ret = ret2;
+ td_io_commit(td);
break;
default:
assert(*ret < 0);
return overlap;
}
-static int io_u_submit(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status io_u_submit(struct thread_data *td, struct io_u *io_u)
{
/*
* Check for overlap if the user asked us to, and we have
};
-static int fio_cpuio_queue(struct thread_data *td, struct io_u fio_unused *io_u)
+static enum fio_q_status
+fio_cpuio_queue(struct thread_data *td, struct io_u fio_unused *io_u)
{
struct cpu_options *co = td->eo;
return 0;
}
-static int fio_devdax_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_devdax_queue(struct thread_data *td, struct io_u *io_u)
{
fio_ro_check(td, io_u);
io_u->error = 0;
}
-static int fio_e4defrag_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_e4defrag_queue(struct thread_data *td, struct io_u *io_u)
{
int ret;
#ifndef FALLOC_FL_PUNCH_HOLE
#define FALLOC_FL_PUNCH_HOLE 0x02 /* de-allocates range */
#endif
-static int fio_fallocate_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_fallocate_queue(struct thread_data *td, struct io_u *io_u)
{
struct fio_file *f = io_u->file;
int ret;
return 0;
}
-static int queue_io(struct thread_data *td, struct io_u fio_unused *io_u)
+static enum fio_q_status
+queue_io(struct thread_data *td, struct io_u fio_unused *io_u)
{
return FIO_Q_COMPLETED;
}
#include "../fio.h"
-static int fio_ftruncate_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_ftruncate_queue(struct thread_data *td, struct io_u *io_u)
{
struct fio_file *f = io_u->file;
int ret;
size_t sector_size;
};
-static int queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status queue(struct thread_data *td, struct io_u *io_u)
{
struct fas_data *d = FILE_ENG_DATA(io_u->file);
int rc;
iou->io_complete = 1;
}
-static int fio_gf_async_queue(struct thread_data fio_unused * td,
- struct io_u *io_u)
+static enum fio_q_status fio_gf_async_queue(struct thread_data fio_unused * td,
+ struct io_u *io_u)
{
struct gf_data *g = td->io_ops_data;
int r;
return 0;
}
-static int fio_gf_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status fio_gf_queue(struct thread_data *td, struct io_u *io_u)
{
struct gf_data *g = td->io_ops_data;
int ret = 0;
ret = glfs_fdatasync(g->fd);
else {
log_err("unsupported operation.\n");
- return -EINVAL;
+ io_u->error = EINVAL;
+ return FIO_Q_COMPLETED;
}
dprint(FD_FILE, "fio len %lu ret %d\n", io_u->xfer_buflen, ret);
if (io_u->file && ret >= 0 && ddir_rw(io_u->ddir))
return n;
}
-static int fio_guasi_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_guasi_queue(struct thread_data *td, struct io_u *io_u)
{
struct guasi_data *ld = td->io_ops_data;
return r < 0 ? r : events;
}
-static int fio_libaio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_libaio_queue(struct thread_data *td, struct io_u *io_u)
{
struct libaio_data *ld = td->io_ops_data;
return 0;
}
-static int fio_hdfsio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_hdfsio_queue(struct thread_data *td, struct io_u *io_u)
{
struct hdfsio_data *hd = td->io_ops_data;
struct hdfsio_options *options = td->eo;
return 0;
}
-static int fio_libpmem_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_libpmem_queue(struct thread_data *td, struct io_u *io_u)
{
fio_ro_check(td, io_u);
io_u->error = 0;
return 0;
}
-static int fio_mmapio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_mmapio_queue(struct thread_data *td, struct io_u *io_u)
{
struct fio_file *f = io_u->file;
struct fio_mmap_data *fmd = FILE_ENG_DATA(f);
return ret;
}
-static int fio_mtd_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_mtd_queue(struct thread_data *td, struct io_u *io_u)
{
struct fio_file *f = io_u->file;
struct fio_mtd_data *fmd = FILE_ENG_DATA(f);
return ret;
}
-static int __fio_netio_queue(struct thread_data *td, struct io_u *io_u,
- enum fio_ddir ddir)
+static enum fio_q_status
+__fio_netio_queue(struct thread_data *td, struct io_u *io_u, enum fio_ddir ddir)
{
struct netio_data *nd = td->io_ops_data;
struct netio_options *o = td->eo;
return FIO_Q_COMPLETED;
}
-static int fio_netio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_netio_queue(struct thread_data *td, struct io_u *io_u)
{
struct netio_options *o = td->eo;
int ret;
return 0;
}
-static int null_queue(struct thread_data *td, struct null_data *nd,
- struct io_u *io_u)
+static enum fio_q_status
+null_queue(struct thread_data *td, struct null_data *nd, struct io_u *io_u)
{
fio_ro_check(td, io_u);
return null_commit(td, td->io_ops_data);
}
-static int fio_null_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_null_queue(struct thread_data *td, struct io_u *io_u)
{
return null_queue(td, td->io_ops_data, io_u);
}
return 0;
}
-static int fio_pmemblk_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_pmemblk_queue(struct thread_data *td, struct io_u *io_u)
{
struct fio_file *f = io_u->file;
fio_pmemblk_file_t pmb = FILE_ENG_DATA(f);
return pd->aio_events[event];
}
-static int fio_posixaio_queue(struct thread_data *td,
- struct io_u *io_u)
+static enum fio_q_status fio_posixaio_queue(struct thread_data *td,
+ struct io_u *io_u)
{
struct posixaio_data *pd = td->io_ops_data;
os_aiocb_t *aiocb = &io_u->aiocb;
}
}
-static int fio_rados_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_rados_queue(struct thread_data *td, struct io_u *io_u)
{
struct rados_data *rados = td->io_ops_data;
struct fio_rados_iou *fri = io_u->engine_data;
return events;
}
-static int fio_rbd_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_rbd_queue(struct thread_data *td, struct io_u *io_u)
{
struct rbd_data *rbd = td->io_ops_data;
struct fio_rbd_iou *fri = io_u->engine_data;
return i;
}
-static int fio_rdmaio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_rdmaio_queue(struct thread_data *td, struct io_u *io_u)
{
struct rdmaio_data *rd = td->io_ops_data;
return r;
}
-static int fio_sgio_ioctl_doio(struct thread_data *td,
- struct fio_file *f, struct io_u *io_u)
+static enum fio_q_status
+fio_sgio_ioctl_doio(struct thread_data *td, struct fio_file *f,
+ struct io_u *io_u)
{
struct sgio_data *sd = td->io_ops_data;
struct sg_io_hdr *hdr = &io_u->hdr;
return 0;
}
-static int fio_sgio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_sgio_queue(struct thread_data *td, struct io_u *io_u)
{
struct sg_io_hdr *hdr = &io_u->hdr;
int ret, do_sync = 0;
* io_u->xfer_buflen. Residual data count may be set in io_u->resid
* for a short read/write.
*/
-static int fio_skeleton_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_skeleton_queue(struct thread_data *td, struct io_u *io_u)
{
/*
* Double sanity check to catch errant write on a readonly setup
return io_u->xfer_buflen;
}
-static int fio_spliceio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_spliceio_queue(struct thread_data *td, struct io_u *io_u)
{
struct spliceio_data *sd = td->io_ops_data;
int ret = 0;
}
#ifdef CONFIG_PWRITEV
-static int fio_pvsyncio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_pvsyncio_queue(struct thread_data *td, struct io_u *io_u)
{
struct syncio_data *sd = td->io_ops_data;
struct iovec *iov = &sd->iovecs[0];
#endif
#ifdef FIO_HAVE_PWRITEV2
-static int fio_pvsyncio2_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_pvsyncio2_queue(struct thread_data *td, struct io_u *io_u)
{
struct syncio_data *sd = td->io_ops_data;
struct psyncv2_options *o = td->eo;
#endif
-static int fio_psyncio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_psyncio_queue(struct thread_data *td, struct io_u *io_u)
{
struct fio_file *f = io_u->file;
int ret;
return fio_io_end(td, io_u, ret);
}
-static int fio_syncio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_syncio_queue(struct thread_data *td, struct io_u *io_u)
{
struct fio_file *f = io_u->file;
int ret;
sd->queued++;
}
-static int fio_vsyncio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_vsyncio_queue(struct thread_data *td, struct io_u *io_u)
{
struct syncio_data *sd = td->io_ops_data;
return dequeued;
}
-static int fio_windowsaio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status
+fio_windowsaio_queue(struct thread_data *td, struct io_u *io_u)
{
struct fio_overlapped *o = io_u->engine_data;
LPOVERLAPPED lpOvl = &o->o;
}
}
- if (!o->unit_base) {
+ if (o->unit_base == N2S_NONE) {
if (td_ioengine_flagged(td, FIO_BIT_BASED))
- o->unit_base = 1;
+ o->unit_base = N2S_BITPERSEC;
else
- o->unit_base = 8;
+ o->unit_base = N2S_BYTEPERSEC;
}
#ifndef FIO_HAVE_ANY_FALLOCATE
* io's that have been actually submitted to an async engine,
* and cur_depth is meaningless for sync engines.
*/
- if (td->io_u_queued || td->cur_depth) {
- int fio_unused ret;
-
- ret = td_io_commit(td);
- }
+ if (td->io_u_queued || td->cur_depth)
+ td_io_commit(td);
while (td->io_u_in_flight) {
int ret;
return r;
}
-int td_io_queue(struct thread_data *td, struct io_u *io_u)
+enum fio_q_status td_io_queue(struct thread_data *td, struct io_u *io_u)
{
const enum fio_ddir ddir = acct_ddir(io_u);
unsigned long buflen = io_u->xfer_buflen;
- int ret;
+ enum fio_q_status ret;
dprint_io_u(io_u, "queue");
fio_ro_check(td, io_u);
td->ts.total_io_u[io_u->ddir]++;
}
} else if (ret == FIO_Q_QUEUED) {
- int r;
-
td->io_u_queued++;
if (ddir_rw(io_u->ddir) || ddir_sync(io_u->ddir))
td->ts.total_io_u[io_u->ddir]++;
- if (td->io_u_queued >= td->o.iodepth_batch) {
- r = td_io_commit(td);
- if (r < 0)
- return r;
- }
+ if (td->io_u_queued >= td->o.iodepth_batch)
+ td_io_commit(td);
}
if (!td_ioengine_flagged(td, FIO_SYNCIO)) {
return ret;
}
-int td_io_commit(struct thread_data *td)
+void td_io_commit(struct thread_data *td)
{
int ret;
dprint(FD_IO, "calling ->commit(), depth %d\n", td->cur_depth);
if (!td->cur_depth || !td->io_u_queued)
- return 0;
+ return;
io_u_mark_depth(td, td->io_u_queued);
*/
td->io_u_in_flight += td->io_u_queued;
td->io_u_queued = 0;
-
- return 0;
}
int td_io_open_file(struct thread_data *td, struct fio_file *f)
#include "flist.h"
#include "io_u.h"
-#define FIO_IOOPS_VERSION 23
+#define FIO_IOOPS_VERSION 24
/*
* io_ops->queue() return values
*/
-enum {
+enum fio_q_status {
FIO_Q_COMPLETED = 0, /* completed sync */
FIO_Q_QUEUED = 1, /* queued, will complete async */
FIO_Q_BUSY = 2, /* no more room, call ->commit() */
int (*setup)(struct thread_data *);
int (*init)(struct thread_data *);
int (*prep)(struct thread_data *, struct io_u *);
- int (*queue)(struct thread_data *, struct io_u *);
+ enum fio_q_status (*queue)(struct thread_data *, struct io_u *);
int (*commit)(struct thread_data *);
int (*getevents)(struct thread_data *, unsigned int, unsigned int, const struct timespec *);
struct io_u *(*event)(struct thread_data *, int);
*/
extern int __must_check td_io_init(struct thread_data *);
extern int __must_check td_io_prep(struct thread_data *, struct io_u *);
-extern int __must_check td_io_queue(struct thread_data *, struct io_u *);
+extern enum fio_q_status __must_check td_io_queue(struct thread_data *, struct io_u *);
extern int __must_check td_io_getevents(struct thread_data *, unsigned int, unsigned int, const struct timespec *);
-extern int __must_check td_io_commit(struct thread_data *);
+extern void td_io_commit(struct thread_data *);
extern int __must_check td_io_open_file(struct thread_data *, struct fio_file *);
extern int td_io_close_file(struct thread_data *, struct fio_file *);
extern int td_io_unlink_file(struct thread_data *, struct fio_file *);
* @maxlen: max number of digits in the output string (not counting prefix and units, but counting .)
* @base: multiplier for num (e.g., if num represents Ki, use 1024)
* @pow2: select unit prefix - 0=power-of-10 decimal SI, nonzero=power-of-2 binary IEC
- * @units: select units - N2S_* macros defined in num2str.h
+ * @units: select units - N2S_* constants defined in num2str.h
* @returns a malloc'd buffer containing "number[<unit prefix>][<units>]"
*/
-char *num2str(uint64_t num, int maxlen, int base, int pow2, int units)
+char *num2str(uint64_t num, int maxlen, int base, int pow2, enum n2s_unit units)
{
const char *sistr[] = { "", "k", "M", "G", "T", "P" };
const char *iecstr[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi" };
const char **unitprefix;
- const char *unitstr[] = { "", "/s", "B", "bit", "B/s", "bit/s" };
+ static const char *const unitstr[] = {
+ [N2S_NONE] = "",
+ [N2S_PERSEC] = "/s",
+ [N2S_BYTE] = "B",
+ [N2S_BIT] = "bit",
+ [N2S_BYTEPERSEC]= "B/s",
+ [N2S_BITPERSEC] = "bit/s"
+ };
const unsigned int thousand[] = { 1000, 1024 };
unsigned int modulo;
- int unit_index = 0, post_index, carry = 0;
+ int post_index, carry = 0;
char tmp[32], fmt[32];
char *buf;
compiletime_assert(sizeof(sistr) == sizeof(iecstr), "unit prefix arrays must be identical sizes");
+ assert(units < ARRAY_SIZE(unitstr));
buf = malloc(128);
if (!buf)
base /= thousand[!!pow2];
switch (units) {
+ case N2S_NONE:
+ break;
case N2S_PERSEC:
- unit_index = 1;
break;
case N2S_BYTE:
- unit_index = 2;
break;
case N2S_BIT:
- unit_index = 3;
num *= 8;
break;
case N2S_BYTEPERSEC:
- unit_index = 4;
break;
case N2S_BITPERSEC:
- unit_index = 5;
num *= 8;
break;
}
post_index = 0;
sprintf(buf, "%llu%s%s", (unsigned long long) num,
- unitprefix[post_index], unitstr[unit_index]);
+ unitprefix[post_index], unitstr[units]);
return buf;
}
sprintf(tmp, fmt, (double)modulo / (double)thousand[!!pow2]);
sprintf(buf, "%llu.%s%s%s", (unsigned long long) num, &tmp[2],
- unitprefix[post_index], unitstr[unit_index]);
+ unitprefix[post_index], unitstr[units]);
return buf;
}
#include <inttypes.h>
-#define N2S_NONE 0
-#define N2S_BITPERSEC 1 /* match unit_base for bit rates */
-#define N2S_PERSEC 2
-#define N2S_BIT 3
-#define N2S_BYTE 4
-#define N2S_BYTEPERSEC 8 /* match unit_base for byte rates */
-
-extern char *num2str(uint64_t, int, int, int, int);
+enum n2s_unit {
+ N2S_NONE = 0,
+ N2S_PERSEC = 1,
+ N2S_BYTE = 2,
+ N2S_BIT = 3,
+ N2S_BYTEPERSEC = 4,
+ N2S_BITPERSEC = 5,
+};
+
+extern char *num2str(uint64_t, int, int, int, enum n2s_unit);
#endif
.prio = 1,
.posval = {
{ .ival = "0",
- .oval = 0,
+ .oval = N2S_NONE,
.help = "Auto-detect",
},
{ .ival = "8",
- .oval = 8,
+ .oval = N2S_BYTEPERSEC,
.help = "Normal (byte based)",
},
{ .ival = "1",
- .oval = 1,
+ .oval = N2S_BITPERSEC,
.help = "Bit based",
},
},
* To keep the terse format unaltered, add all of the ns latency
* buckets to the first us latency bucket
*/
-void stat_calc_lat_nu(struct thread_stat *ts, double *io_u_lat_u)
+static void stat_calc_lat_nu(struct thread_stat *ts, double *io_u_lat_u)
{
unsigned long ntotal = 0, total = ddir_rw_sum(ts->total_io_u);
int i;