Add sub-option support (sort-of) and convert libaio_userspace_reap
You should now use ioengine=libaio:userspace_reap instead of
the separate option.
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
diff --git a/HOWTO b/HOWTO
index ad4e454..724b604 100644
--- a/HOWTO
+++ b/HOWTO
@@ -517,6 +517,16 @@
libaio Linux native asynchronous io. Note that Linux
may only support queued behaviour with
non-buffered IO (set direct=1 or buffered=0).
+ This engine also has a sub-option,
+ userspace_reap. To set it, use
+ ioengine=libaio:userspace_reap. Normally, with
+ the libaio engine in use, fio will use the
+ io_getevents system call to reap newly returned
+ events. With this flag turned on, the AIO ring
+ will be read directly from user-space to reap
+ events. The reaping mode is only enabled when
+ polling for a minimum of 0 events (eg when
+ iodepth_batch_complete=0).
posixaio glibc posix asynchronous io.
@@ -1187,13 +1197,6 @@
gid=int Set group ID, see uid.
-userspace_libaio_reap=bool Normally, with the libaio engine in use, fio
- will use the io_getevents system call to reap newly returned
- events. With this flag turned on, the AIO ring will be read
- directly from user-space to reap events. The reaping mode is
- only enabled when polling for a minimum of 0 events (eg when
- iodepth_batch_complete=0).
-
6.0 Interpreting the output
---------------------------
diff --git a/engines/libaio.c b/engines/libaio.c
index ea05c63..ad34d06 100644
--- a/engines/libaio.c
+++ b/engines/libaio.c
@@ -63,7 +63,7 @@
unsigned nr; /** number of io_events */
unsigned head;
unsigned tail;
-
+
unsigned magic;
unsigned compat_features;
unsigned incompat_features;
@@ -75,11 +75,11 @@
#define AIO_RING_MAGIC 0xa10a10a1
static int user_io_getevents(io_context_t aio_ctx, unsigned int max,
- struct io_event *events)
+ struct io_event *events)
{
long i = 0;
unsigned head;
- struct aio_ring *ring = (struct aio_ring*)aio_ctx;
+ struct aio_ring *ring = (struct aio_ring*) aio_ctx;
while (i < max) {
head = ring->head;
@@ -91,7 +91,7 @@
/* There is another completion to reap */
events[i] = ring->events[head];
read_barrier();
- ring->head = (head + 1) % ring->nr;
+ ring->head = (head + 1) % ring->nr;
i++;
}
}
diff --git a/fio.1 b/fio.1
index 488896c..ffc97c9 100644
--- a/fio.1
+++ b/fio.1
@@ -367,7 +367,13 @@
coalescing adjacents IOs into a single submission.
.TP
.B libaio
-Linux native asynchronous I/O.
+Linux native asynchronous I/O. This engine also has a sub-option,
+\fBuserspace_reap\fR. To set it, use \fBioengine=libaio:userspace_reap\fR.
+Normally, with the libaio engine in use, fio will use the
+\fIio_getevents\fR\|(3) system call to reap newly returned events. With this
+flag turned on, the AIO ring will be read directly from user-space to reap
+events. The reaping mode is only enabled when polling for a minimum of \fB0\fR
+events (eg when \fBiodepth_batch_complete=0\fR).
.TP
.B posixaio
POSIX asynchronous I/O using \fIaio_read\fR\|(3) and \fIaio_write\fR\|(3).
diff --git a/options.c b/options.c
index 6f7c41e..74c24d0 100644
--- a/options.c
+++ b/options.c
@@ -226,6 +226,21 @@
return 0;
}
+#ifdef FIO_HAVE_LIBAIO
+static int str_libaio_cb(void *data, const char *str)
+{
+ struct thread_data *td = data;
+
+ if (!strcmp(str, "userspace_reap")) {
+ td->o.userspace_libaio_reap = 1;
+ return 0;
+ }
+
+ log_err("fio: bad libaio sub-option: %s\n", str);
+ return 1;
+}
+#endif
+
static int str_mem_cb(void *data, const char *mem)
{
struct thread_data *td = data;
@@ -961,6 +976,7 @@
#ifdef FIO_HAVE_LIBAIO
{ .ival = "libaio",
.help = "Linux native asynchronous IO",
+ .cb = str_libaio_cb,
},
#endif
#ifdef FIO_HAVE_POSIXAIO
@@ -2069,15 +2085,6 @@
.off1 = td_var_offset(gid),
.help = "Run job with this group ID",
},
-#ifdef FIO_HAVE_LIBAIO
- {
- .name = "userspace_libaio_reap",
- .type = FIO_OPT_BOOL,
- .off1 = td_var_offset(userspace_libaio_reap),
- .help = "When using the libaio engine with iodepth_batch_complete=0, enable userspace reaping",
- .def = "0",
- },
-#endif
{
.name = NULL,
},
diff --git a/parse.c b/parse.c
index c2c5bf2..4458121 100644
--- a/parse.c
+++ b/parse.c
@@ -346,6 +346,9 @@
double uf;
char **cp;
int ret = 0, is_time = 0;
+ const struct value_pair *vp;
+ struct value_pair posval[PARSE_MAX_VP];
+ int i, all_skipped = 1;
dprint(FD_PARSE, "__handle_option=%s, type=%d, ptr=%s\n", o->name,
o->type, ptr);
@@ -359,9 +362,6 @@
case FIO_OPT_STR:
case FIO_OPT_STR_MULTI: {
fio_opt_str_fn *fn = o->cb;
- const struct value_pair *vp;
- struct value_pair posval[PARSE_MAX_VP];
- int i, all_skipped = 1;
posval_sort(o, posval);
@@ -487,19 +487,40 @@
case FIO_OPT_STR_STORE: {
fio_opt_str_fn *fn = o->cb;
- if (o->roff1)
- cp = (char **) o->roff1;
- else
- cp = td_var(data, o->off1);
+ posval_sort(o, posval);
- *cp = strdup(ptr);
- if (fn) {
- ret = fn(data, ptr);
- if (ret) {
- free(*cp);
- *cp = NULL;
+ ret = 1;
+ for (i = 0; i < PARSE_MAX_VP; i++) {
+ vp = &posval[i];
+ if (!vp->ival || vp->ival[0] == '\0')
+ continue;
+ all_skipped = 0;
+ if (!strncmp(vp->ival, ptr, opt_len(ptr))) {
+ char *rest;
+
+ ret = 0;
+ if (vp->cb)
+ fn = vp->cb;
+ if (o->roff1)
+ cp = (char **) o->roff1;
+ else
+ cp = td_var(data, o->off1);
+ *cp = strdup(ptr);
+ rest = strstr(*cp, ":");
+ if (rest) {
+ *rest = '\0';
+ ptr = rest + 1;
+ } else
+ ptr = NULL;
+ break;
}
}
+
+ if (ret && !all_skipped)
+ show_option_values(o);
+ else if (fn && ptr)
+ ret = fn(data, ptr);
+
break;
}
case FIO_OPT_RANGE: {
diff --git a/parse.h b/parse.h
index c5a7417..f2265a4 100644
--- a/parse.h
+++ b/parse.h
@@ -29,6 +29,7 @@
unsigned int oval; /* output value */
const char *help; /* help text for sub option */
int or; /* OR value */
+ void *cb; /* sub-option callback */
};
#define OPT_LEN_MAX 4096