diff --git a/cmd/zpios/zpios.h b/cmd/zpios/zpios.h index 88c7c2fee9..79fdf8be1e 100644 --- a/cmd/zpios/zpios.h +++ b/cmd/zpios/zpios.h @@ -57,6 +57,8 @@ #define GB (MB * 1024) #define TB (GB * 1024) +#define KMGT_SIZE 16 + /* All offsets, sizes and counts can be passed to the application in * multiple ways. * 1. a value (stored in val[0], val_count will be 1) diff --git a/cmd/zpios/zpios_main.c b/cmd/zpios/zpios_main.c index fbaf8eeefd..fca2fb63c0 100644 --- a/cmd/zpios/zpios_main.c +++ b/cmd/zpios/zpios_main.c @@ -45,7 +45,7 @@ #include "zpios.h" static const char short_opt[] = "t:l:h:e:n:i:j:k:c:u:a:b:g:L:P:R:I:" - "G:T:Vzs:A:B:C:o:m:q:r:fwxdp:v?"; + "G:T:N:VHzOs:A:B:C:o:m:q:r:fwxdp:v?"; static const struct option long_opt[] = { {"chunksize", required_argument, 0, 'c' }, {"chunksize_low", required_argument, 0, 'a' }, @@ -70,6 +70,7 @@ static const struct option long_opt[] = { {"cleanup", no_argument, 0, 'x' }, {"verify", no_argument, 0, 'V' }, {"zerocopy", no_argument, 0, 'z' }, + {"nowait", no_argument, 0, 'O' }, {"threaddelay", required_argument, 0, 'T' }, {"regionnoise", required_argument, 0, 'I' }, {"chunknoise", required_argument, 0, 'N' }, @@ -118,6 +119,7 @@ usage(void) " --cleanup -x\n" " --verify -V\n" " --zerocopy -z\n" + " --nowait -O\n" " --threaddelay -T =jiffies\n" " --regionnoise -I =shift\n" " --chunknoise -N =bytes\n" @@ -166,9 +168,6 @@ args_init(int argc, char **argv) rc = 0; switch (c) { - case 'v': /* --verbose */ - args->verbose++; - break; case 't': /* --thread count */ rc = set_count(REGEX_NUMBERS, REGEX_NUMBERS_COMMA, &args->T, optarg, &fl_th, "threadcount"); @@ -279,12 +278,18 @@ args_init(int argc, char **argv) case 'V': /* --verify */ args->flags |= DMU_VERIFY; break; - case 'z': /* --verify */ + case 'z': /* --zerocopy */ args->flags |= (DMU_WRITE_ZC | DMU_READ_ZC); break; - case 'H': + case 'O': /* --nowait */ + args->flags |= DMU_WRITE_NOWAIT; + break; + case 'H': /* --human-readable */ args->human_readable = 1; break; + case 'v': /* --verbose */ + args->verbose++; + break; case '?': rc = 1; break; diff --git a/cmd/zpios/zpios_util.c b/cmd/zpios/zpios_util.c index 14150d7289..c923673702 100644 --- a/cmd/zpios/zpios_util.c +++ b/cmd/zpios/zpios_util.c @@ -87,10 +87,10 @@ uint64_to_kmgt(char *str, uint64_t val) } if (i >= 4) - sprintf(str, "inf"); + (void)snprintf(str, KMGT_SIZE-1, "inf"); else - sprintf(str, "%lu%c", (unsigned long)val, - (i == -1) ? '\0' : postfix[i]); + (void)snprintf(str, KMGT_SIZE-1, "%lu%c", (unsigned long)val, + (i == -1) ? '\0' : postfix[i]); return str; } @@ -108,10 +108,10 @@ kmgt_per_sec(char *str, uint64_t v, double t) } if (i >= 4) - sprintf(str, "inf"); + (void)snprintf(str, KMGT_SIZE-1, "inf"); else - sprintf(str, "%.2f%c", val, - (i == -1) ? '\0' : postfix[i]); + (void)snprintf(str, KMGT_SIZE-1, "%.2f%c", val, + (i == -1) ? '\0' : postfix[i]); return str; } @@ -125,7 +125,8 @@ print_flags(char *str, uint32_t flags) str[3] = (flags & DMU_REMOVE) ? 'c' : '-'; str[4] = (flags & DMU_FPP) ? 'p' : 's'; str[5] = (flags & (DMU_WRITE_ZC | DMU_READ_ZC)) ? 'z' : '-'; - str[6] = '\0'; + str[6] = (flags & DMU_WRITE_NOWAIT) ? 'O' : '-'; + str[7] = '\0'; return str; } @@ -140,7 +141,7 @@ timespec_to_double(struct timespec t) static int regex_match(const char *string, char *pattern) { - regex_t re; + regex_t re = { 0 }; int rc; rc = regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB | REG_ICASE); @@ -327,7 +328,7 @@ print_stats_human_readable(cmd_args_t *args, zpios_cmd_t *cmd) { zpios_stats_t *summary_stats; double t_time, wr_time, rd_time, cr_time, rm_time; - char str[16]; + char str[KMGT_SIZE]; if (args->rc) printf("FAILED: %3d ", args->rc); diff --git a/module/zpios/include/zpios-ctl.h b/module/zpios/include/zpios-ctl.h index 79cbfa3ac6..767fdfdb15 100644 --- a/module/zpios/include/zpios-ctl.h +++ b/module/zpios/include/zpios-ctl.h @@ -53,6 +53,7 @@ #define DMU_FPP 0x10 #define DMU_WRITE_ZC 0x20 /* Incompatible with DMU_VERIFY */ #define DMU_READ_ZC 0x40 /* Incompatible with DMU_VERIFY */ +#define DMU_WRITE_NOWAIT 0x80 #define ZPIOS_NAME_SIZE 16 #define ZPIOS_PATH_SIZE 128 diff --git a/module/zpios/zpios.c b/module/zpios/zpios.c index 4b1c4dbbc3..5b447d4f5b 100644 --- a/module/zpios/zpios.c +++ b/module/zpios/zpios.c @@ -426,6 +426,9 @@ zpios_dmu_write(run_args_t *run_args, objset_t *os, uint64_t object, int rc, how = TXG_WAIT; int flags = 0; + if (run_args->flags & DMU_WRITE_NOWAIT) + how = TXG_NOWAIT; + while (1) { tx = dmu_tx_create(os); dmu_tx_hold_write(tx, object, offset, size); @@ -661,13 +664,12 @@ zpios_thread_done(run_args_t *run_args) static int zpios_threads_run(run_args_t *run_args) { - struct task_struct *tsk, **tsks; + struct task_struct *tsk, **tsks; thread_data_t *thr = NULL; zpios_time_t *tt = &(run_args->stats.total_time); zpios_time_t *tw = &(run_args->stats.wr_time); zpios_time_t *tr = &(run_args->stats.rd_time); - int i, rc = 0, tc = run_args->thread_count; - DEFINE_WAIT(wait); + int i, rc = 0, tc = run_args->thread_count; zpios_upcall(run_args->pre, PHASE_PRE, run_args, 0); @@ -697,32 +699,32 @@ zpios_threads_run(run_args_t *run_args) thr->thread_no = i; thr->run_args = run_args; thr->rc = 0; - mutex_init(&thr->lock, NULL, MUTEX_DEFAULT, NULL); + mutex_init(&thr->lock, NULL, MUTEX_DEFAULT, NULL); run_args->threads[i] = thr; - tsk = kthread_create(zpios_thread_main, (void *)thr, - "%s/%d", "zpios_io", i); - if (IS_ERR(tsk)) { + tsk = kthread_create(zpios_thread_main, (void *)thr, + "%s/%d", "zpios_io", i); + if (IS_ERR(tsk)) { rc = -EINVAL; goto taskerr; } tsks[i] = tsk; - } + } - tt->start = current_kernel_time(); + tt->start = current_kernel_time(); /* Wake up all threads for write phase */ zpios_upcall(run_args->pre, PHASE_WRITE, run_args, 0); - for (i = 0; i < tc; i++) + for (i = 0; i < tc; i++) wake_up_process(tsks[i]); /* Wait for write phase to complete */ - tw->start = current_kernel_time(); - wait_event(run_args->waitq, zpios_thread_done(run_args)); - tw->stop = current_kernel_time(); + tw->start = current_kernel_time(); + wait_event(run_args->waitq, zpios_thread_done(run_args)); + tw->stop = current_kernel_time(); - for (i = 0; i < tc; i++) { + for (i = 0; i < tc; i++) { thr = run_args->threads[i]; mutex_enter(&thr->lock); @@ -759,11 +761,11 @@ zpios_threads_run(run_args_t *run_args) wake_up_process(tsks[i]); /* Wait for read phase to complete */ - tr->start = current_kernel_time(); - wait_event(run_args->waitq, zpios_thread_done(run_args)); - tr->stop = current_kernel_time(); + tr->start = current_kernel_time(); + wait_event(run_args->waitq, zpios_thread_done(run_args)); + tr->stop = current_kernel_time(); - for (i = 0; i < tc; i++) { + for (i = 0; i < tc; i++) { thr = run_args->threads[i]; mutex_enter(&thr->lock); @@ -778,7 +780,7 @@ zpios_threads_run(run_args_t *run_args) zpios_upcall(run_args->post, PHASE_READ, run_args, rc); out: - tt->stop = current_kernel_time(); + tt->stop = current_kernel_time(); tt->delta = timespec_sub(tt->stop, tt->start); tw->delta = timespec_sub(tw->stop, tw->start); tr->delta = timespec_sub(tr->stop, tr->start); @@ -804,7 +806,7 @@ static int zpios_do_one_run(struct file *file, zpios_cmd_t *kcmd, int data_size, void *data) { - run_args_t *run_args; + run_args_t *run_args; zpios_stats_t *stats = (zpios_stats_t *)data; int i, n, m, size, rc; @@ -848,7 +850,7 @@ zpios_do_one_run(struct file *file, zpios_cmd_t *kcmd, return -ENOSPC; } - rc = zpios_setup_run(&run_args, kcmd, file); + rc = zpios_setup_run(&run_args, kcmd, file); if (rc) return rc;