From: Jens Axboe Date: Wed, 31 Aug 2011 02:43:53 +0000 (-0600) Subject: Add sub-option support (sort-of) and convert libaio_userspace_reap X-Git-Tag: fio-1.58~17 X-Git-Url: https://git.kernel.dk/?p=fio.git;a=commitdiff_plain;h=c44b1ff54402c589e8f07436ec56efb4f8b1ac23 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 --- diff --git a/HOWTO b/HOWTO index ad4e4540..724b604b 100644 --- a/HOWTO +++ b/HOWTO @@ -517,6 +517,16 @@ ioengine=str Defines how the job issues io to the file. The following 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 @@ uid=int Instead of running as the invoking user, set the user ID to 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 ea05c63c..ad34d065 100644 --- a/engines/libaio.c +++ b/engines/libaio.c @@ -63,7 +63,7 @@ struct aio_ring { unsigned nr; /** number of io_events */ unsigned head; unsigned tail; - + unsigned magic; unsigned compat_features; unsigned incompat_features; @@ -75,11 +75,11 @@ struct aio_ring { #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 @@ static int user_io_getevents(io_context_t aio_ctx, unsigned int max, /* 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 488896ce..ffc97c98 100644 --- a/fio.1 +++ b/fio.1 @@ -367,7 +367,13 @@ Basic \fIreadv\fR\|(2) or \fIwritev\fR\|(2) I/O. Will emulate queuing by 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 6f7c41ed..74c24d02 100644 --- a/options.c +++ b/options.c @@ -226,6 +226,21 @@ static int str_rw_cb(void *data, const char *str) 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 @@ static struct fio_option options[FIO_MAX_OPTS] = { #ifdef FIO_HAVE_LIBAIO { .ival = "libaio", .help = "Linux native asynchronous IO", + .cb = str_libaio_cb, }, #endif #ifdef FIO_HAVE_POSIXAIO @@ -2069,15 +2085,6 @@ static struct fio_option options[FIO_MAX_OPTS] = { .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 c2c5bf29..44581215 100644 --- a/parse.c +++ b/parse.c @@ -346,6 +346,9 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, 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 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, 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 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, 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 c5a74171..f2265a43 100644 --- a/parse.h +++ b/parse.h @@ -29,6 +29,7 @@ struct value_pair { 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