The following changes since commit 397dddce43664df92101350f1fe5cd4c9cd2a2c7: Merge branch 'travis-xcode11.2-python' of https://github.com/vincentkfu/fio (2019-12-16 16:08:35 -0700) are available in the Git repository at: git://git.kernel.dk/fio.git master for you to fetch changes up to 8d853d0bbf4487af9445f7253c1951970ce75200: Merge branch 'mine/patch-2' of https://github.com/hannesweisbach/fio (2019-12-19 05:38:30 -0700) ---------------------------------------------------------------- Hannes Weisbach (2): Expand choices for exitall Add example job file for exit_what Jens Axboe (4): Merge branch 'cygwin-build-error' of https://github.com/vincentkfu/fio Merge branch 'issue-878' of https://github.com/vincentkfu/fio Merge branch 'windows_mkdir' of https://github.com/sitsofe/fio Merge branch 'mine/patch-2' of https://github.com/hannesweisbach/fio Sitsofe Wheeler (1): filesetup: fix directory creation issues Vincent Fu (2): Makefile: add libssp for Windows client/server: add missing fsync data structures HOWTO | 18 ++++++++++++++--- Makefile | 4 ++-- backend.c | 12 +++++------ cconv.c | 6 ++++-- client.c | 8 +++++++- configure | 19 ----------------- examples/exitwhat.fio | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++ filesetup.c | 22 +++++++------------- fio.1 | 17 +++++++++++++--- fio.h | 10 +++++++-- libfio.c | 7 +++++-- options.c | 27 ++++++++++++++++++++++++- os/os-windows.h | 19 +++++++++++++++++ os/os.h | 4 ++++ server.c | 12 ++++++++--- thread_options.h | 6 ++++-- 16 files changed, 186 insertions(+), 61 deletions(-) create mode 100644 examples/exitwhat.fio --- Diff of recent changes: diff --git a/HOWTO b/HOWTO index 88dbb03f..41a667af 100644 --- a/HOWTO +++ b/HOWTO @@ -2814,9 +2814,21 @@ Threads, processes and job synchronization .. option:: exitall - By default, fio will continue running all other jobs when one job finishes - but sometimes this is not the desired action. Setting ``exitall`` will - instead make fio terminate all other jobs when one job finishes. + By default, fio will continue running all other jobs when one job finishes. + Sometimes this is not the desired action. Setting ``exitall`` will instead + make fio terminate all jobs in the same group, as soon as one job of that + group finishes. + +.. option:: exit_what + + By default, fio will continue running all other jobs when one job finishes. + Sometimes this is not the desired action. Setting ``exit_all`` will + instead make fio terminate all jobs in the same group. The option + ``exit_what`` allows to control which jobs get terminated when ``exitall`` is + enabled. The default is ``group`` and does not change the behaviour of + ``exitall``. The setting ``all`` terminates all jobs. The setting ``stonewall`` + terminates all currently running jobs across all groups and continues execution + with the next stonewalled group. .. option:: exec_prerun=str diff --git a/Makefile b/Makefile index 7aab6abd..4a07fab3 100644 --- a/Makefile +++ b/Makefile @@ -209,7 +209,7 @@ ifeq ($(CONFIG_TARGET_OS), Darwin) endif ifneq (,$(findstring CYGWIN,$(CONFIG_TARGET_OS))) SOURCE += os/windows/posix.c - LIBS += -lpthread -lpsapi -lws2_32 + LIBS += -lpthread -lpsapi -lws2_32 -lssp CFLAGS += -DPSAPI_VERSION=1 -Ios/windows/posix/include -Wno-format endif @@ -506,7 +506,7 @@ t/time-test: $(T_TT_OBJS) ifdef CONFIG_HAVE_CUNIT unittests/unittest: $(UT_OBJS) $(UT_TARGET_OBJS) - $(QUIET_LINK)$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(UT_OBJS) $(UT_TARGET_OBJS) -lcunit + $(QUIET_LINK)$(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(UT_OBJS) $(UT_TARGET_OBJS) -lcunit $(LIBS) endif clean: FORCE diff --git a/backend.c b/backend.c index 1c339408..d0d691b3 100644 --- a/backend.c +++ b/backend.c @@ -81,7 +81,7 @@ static void sig_int(int sig) exit_value = 128; } - fio_terminate_threads(TERMINATE_ALL); + fio_terminate_threads(TERMINATE_ALL, TERMINATE_ALL); } } @@ -1091,7 +1091,7 @@ reap: if (!in_ramp_time(td) && should_check_rate(td)) { if (check_min_rate(td, &comp_time)) { if (exitall_on_terminate || td->o.exitall_error) - fio_terminate_threads(td->groupid); + fio_terminate_threads(td->groupid, td->o.exit_what); td_verror(td, EIO, "check_min_rate"); break; } @@ -1898,7 +1898,7 @@ static void *thread_main(void *data) exec_string(o, o->exec_postrun, (const char *)"postrun"); if (exitall_on_terminate || (o->exitall_error && td->error)) - fio_terminate_threads(td->groupid); + fio_terminate_threads(td->groupid, td->o.exit_what); err: if (td->error) @@ -2050,7 +2050,7 @@ reaped: } if (*nr_running == cputhreads && !pending && realthreads) - fio_terminate_threads(TERMINATE_ALL); + fio_terminate_threads(TERMINATE_ALL, TERMINATE_ALL); } static bool __check_trigger_file(void) @@ -2100,7 +2100,7 @@ void check_trigger_file(void) fio_clients_send_trigger(trigger_remote_cmd); else { verify_save_state(IO_LIST_ALL); - fio_terminate_threads(TERMINATE_ALL); + fio_terminate_threads(TERMINATE_ALL, TERMINATE_ALL); exec_trigger(trigger_cmd); } } @@ -2373,7 +2373,7 @@ reap: dprint(FD_MUTEX, "wait on startup_sem\n"); if (fio_sem_down_timeout(startup_sem, 10000)) { log_err("fio: job startup hung? exiting.\n"); - fio_terminate_threads(TERMINATE_ALL); + fio_terminate_threads(TERMINATE_ALL, TERMINATE_ALL); fio_abort = true; nr_started--; free(fd); diff --git a/cconv.c b/cconv.c index bff5e34f..04854b0e 100644 --- a/cconv.c +++ b/cconv.c @@ -236,7 +236,8 @@ void convert_thread_options_to_cpu(struct thread_options *o, o->loops = le32_to_cpu(top->loops); o->mem_type = le32_to_cpu(top->mem_type); o->mem_align = le32_to_cpu(top->mem_align); - o->stonewall = le32_to_cpu(top->stonewall); + o->exit_what = le16_to_cpu(top->exit_what); + o->stonewall = le16_to_cpu(top->stonewall); o->new_group = le32_to_cpu(top->new_group); o->numjobs = le32_to_cpu(top->numjobs); o->cpus_allowed_policy = le32_to_cpu(top->cpus_allowed_policy); @@ -433,7 +434,8 @@ void convert_thread_options_to_net(struct thread_options_pack *top, top->loops = cpu_to_le32(o->loops); top->mem_type = cpu_to_le32(o->mem_type); top->mem_align = cpu_to_le32(o->mem_align); - top->stonewall = cpu_to_le32(o->stonewall); + top->exit_what = cpu_to_le16(o->exit_what); + top->stonewall = cpu_to_le16(o->stonewall); top->new_group = cpu_to_le32(o->new_group); top->numjobs = cpu_to_le32(o->numjobs); top->cpus_allowed_policy = cpu_to_le32(o->cpus_allowed_policy); diff --git a/client.c b/client.c index e0047af0..55d89a0e 100644 --- a/client.c +++ b/client.c @@ -960,6 +960,7 @@ static void convert_ts(struct thread_stat *dst, struct thread_stat *src) convert_io_stat(&dst->bw_stat[i], &src->bw_stat[i]); convert_io_stat(&dst->iops_stat[i], &src->iops_stat[i]); } + convert_io_stat(&dst->sync_stat, &src->sync_stat); dst->usr_time = le64_to_cpu(src->usr_time); dst->sys_time = le64_to_cpu(src->sys_time); @@ -994,8 +995,13 @@ static void convert_ts(struct thread_stat *dst, struct thread_stat *src) for (j = 0; j < FIO_IO_U_PLAT_NR; j++) dst->io_u_plat[i][j] = le64_to_cpu(src->io_u_plat[i][j]); - for (i = 0; i < DDIR_RWDIR_CNT; i++) { + for (j = 0; j < FIO_IO_U_PLAT_NR; j++) + dst->io_u_sync_plat[j] = le64_to_cpu(src->io_u_sync_plat[j]); + + for (i = 0; i < DDIR_RWDIR_SYNC_CNT; i++) dst->total_io_u[i] = le64_to_cpu(src->total_io_u[i]); + + for (i = 0; i < DDIR_RWDIR_CNT; i++) { dst->short_io_u[i] = le64_to_cpu(src->short_io_u[i]); dst->drop_io_u[i] = le64_to_cpu(src->drop_io_u[i]); } diff --git a/configure b/configure index e32d5dcf..a1279693 100755 --- a/configure +++ b/configure @@ -2316,22 +2316,6 @@ if test "$enable_cuda" = "yes" && compile_prog "" "-lcuda" "cuda"; then fi print_config "cuda" "$cuda" -########################################## -# mkdir() probe. mingw apparently has a one-argument mkdir :/ -mkdir_two="no" -cat > $TMPC << EOF -#include <sys/stat.h> -#include <sys/types.h> -int main(int argc, char **argv) -{ - return mkdir("/tmp/bla", 0600); -} -EOF -if compile_prog "" "" "mkdir(a, b)"; then - mkdir_two="yes" -fi -print_config "mkdir(a, b)" "$mkdir_two" - ########################################## # check for cc -march=native build_native="no" @@ -2705,9 +2689,6 @@ fi if test "$cuda" = "yes" ; then output_sym "CONFIG_CUDA" fi -if test "$mkdir_two" = "yes" ; then - output_sym "CONFIG_HAVE_MKDIR_TWO" -fi if test "$march_set" = "no" && test "$build_native" = "yes" ; then output_sym "CONFIG_BUILD_NATIVE" fi diff --git a/examples/exitwhat.fio b/examples/exitwhat.fio new file mode 100644 index 00000000..a1099f0f --- /dev/null +++ b/examples/exitwhat.fio @@ -0,0 +1,56 @@ +# We want to run fast1 as long as slow1 is running, but also have a cumulative +# report of fast1 (group_reporting=1/new_group=1). exitall=1 would not cause +# fast1 to stop after slow1 is done. Setting exit_what=stonewall will cause +# alls jobs up until the next stonewall=1 setting to be stopped, when job slow1 +# finishes. +# In this example skipping forward to slow2/fast2. slow2 has exit_what=all set, +# which means all jobs will be cancelled when slow2 finishes. In particular, +# runsnever will never run. + +[global] +filename=/tmp/test +filesize=1G +blocksize=4096 +group_reporting=1 +exitall=1 + +[slow1] +rw=r +numjobs=1 +ioengine=sync +new_group=1 +thinktime=2000 +number_ios=1000 +exit_what=stonewall + +[fast1] +new_group=1 +rw=randrw +numjobs=3 +ioengine=libaio +iodepth=32 +rate=300,300,300 + +[slow2] +stonewall=1 +rw=w +numjobs=1 +ioengine=sync +new_group=1 +thinktime=2000 +number_ios=1000 +exit_what=all + +[fast2] +rw=randrw +numjobs=3 +ioengine=libaio +iodepth=32 +rate=300,300,300 + +[runsnever] +rw=randrw +numjobs=3 +ioengine=libaio +iodepth=32 +rate=300,300,300 diff --git a/filesetup.c b/filesetup.c index ed3646a4..b45a5826 100644 --- a/filesetup.c +++ b/filesetup.c @@ -918,26 +918,18 @@ static bool create_work_dirs(struct thread_data *td, const char *fname) char path[PATH_MAX]; char *start, *end; - if (td->o.directory) { - snprintf(path, PATH_MAX, "%s%c%s", td->o.directory, - FIO_OS_PATH_SEPARATOR, fname); - start = strstr(path, fname); - } else { - snprintf(path, PATH_MAX, "%s", fname); - start = path; - } + snprintf(path, PATH_MAX, "%s", fname); + start = path; end = start; while ((end = strchr(end, FIO_OS_PATH_SEPARATOR)) != NULL) { - if (end == start) - break; + if (end == start) { + end++; + continue; + } *end = '\0'; errno = 0; -#ifdef CONFIG_HAVE_MKDIR_TWO - if (mkdir(path, 0600) && errno != EEXIST) { -#else - if (mkdir(path) && errno != EEXIST) { -#endif + if (fio_mkdir(path, 0700) && errno != EEXIST) { log_err("fio: failed to create dir (%s): %d\n", start, errno); return false; diff --git a/fio.1 b/fio.1 index 14569e9f..a60863f6 100644 --- a/fio.1 +++ b/fio.1 @@ -2509,9 +2509,20 @@ wall also implies starting a new reporting group, see \fBgroup_reporting\fR. .TP .BI exitall -By default, fio will continue running all other jobs when one job finishes -but sometimes this is not the desired action. Setting \fBexitall\fR will -instead make fio terminate all other jobs when one job finishes. +By default, fio will continue running all other jobs when one job finishes. +Sometimes this is not the desired action. Setting \fBexitall\fR will instead +make fio terminate all jobs in the same group, as soon as one job of that +group finishes. +.TP +.BI exit_what +By default, fio will continue running all other jobs when one job finishes. +Sometimes this is not the desired action. Setting \fBexit_all\fR will instead +make fio terminate all jobs in the same group. The option \fBexit_what\fR +allows to control which jobs get terminated when \fBexitall\fR is enabled. The +default is \fBgroup\fR and does not change the behaviour of \fBexitall\fR. The +setting \fBall\fR terminates all jobs. The setting \fBstonewall\fR terminates +all currently running jobs across all groups and continues execution with the +next stonewalled group. .TP .BI exec_prerun \fR=\fPstr Before running this job, issue the command specified through diff --git a/fio.h b/fio.h index 2094d30b..e943ad16 100644 --- a/fio.h +++ b/fio.h @@ -660,8 +660,14 @@ extern const char *runstate_to_name(int runstate); */ #define FIO_REAP_TIMEOUT 300 -#define TERMINATE_ALL (-1U) -extern void fio_terminate_threads(unsigned int); +enum { + TERMINATE_NONE = 0, + TERMINATE_GROUP = 1, + TERMINATE_STONEWALL = 2, + TERMINATE_ALL = -1, +}; + +extern void fio_terminate_threads(unsigned int, unsigned int); extern void fio_mark_td_terminate(struct thread_data *); /* diff --git a/libfio.c b/libfio.c index 674bc1dc..7348b164 100644 --- a/libfio.c +++ b/libfio.c @@ -233,7 +233,7 @@ void fio_mark_td_terminate(struct thread_data *td) td->terminate = true; } -void fio_terminate_threads(unsigned int group_id) +void fio_terminate_threads(unsigned int group_id, unsigned int terminate) { struct thread_data *td; pid_t pid = getpid(); @@ -242,7 +242,10 @@ void fio_terminate_threads(unsigned int group_id) dprint(FD_PROCESS, "terminate group_id=%d\n", group_id); for_each_td(td, i) { - if (group_id == TERMINATE_ALL || group_id == td->groupid) { + if ((terminate == TERMINATE_GROUP && group_id == TERMINATE_ALL) || + (terminate == TERMINATE_GROUP && group_id == td->groupid) || + (terminate == TERMINATE_STONEWALL && td->runstate >= TD_RUNNING) || + (terminate == TERMINATE_ALL)) { dprint(FD_PROCESS, "setting terminate on %s/%d\n", td->o.name, (int) td->pid); diff --git a/options.c b/options.c index fad1857e..287f0435 100644 --- a/options.c +++ b/options.c @@ -1235,7 +1235,8 @@ int set_name_idx(char *target, size_t tlen, char *input, int index, len = snprintf(target, tlen, "%s/%s.", fname, client_sockaddr_str); } else - len = snprintf(target, tlen, "%s/", fname); + len = snprintf(target, tlen, "%s%c", fname, + FIO_OS_PATH_SEPARATOR); target[tlen - 1] = '\0'; free(p); @@ -3940,6 +3941,30 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_GENERAL, .group = FIO_OPT_G_PROCESS, }, + { + .name = "exit_what", + .lname = "What jobs to quit on terminate", + .type = FIO_OPT_STR, + .off1 = offsetof(struct thread_options, exit_what), + .help = "Fine-grained control for exitall", + .def = "group", + .category = FIO_OPT_C_GENERAL, + .group = FIO_OPT_G_PROCESS, + .posval = { + { .ival = "group", + .oval = TERMINATE_GROUP, + .help = "exit_all=1 default behaviour", + }, + { .ival = "stonewall", + .oval = TERMINATE_STONEWALL, + .help = "quit all currently running jobs; continue with next stonewall", + }, + { .ival = "all", + .oval = TERMINATE_ALL, + .help = "Quit everything", + }, + }, + }, { .name = "exitall_on_error", .lname = "Exit-all on terminate in error", diff --git a/os/os-windows.h b/os/os-windows.h index 3e9f7341..6061d8c7 100644 --- a/os/os-windows.h +++ b/os/os-windows.h @@ -35,6 +35,7 @@ int rand_r(unsigned *); #define FIO_HAVE_CPU_AFFINITY #define FIO_HAVE_CHARDEV_SIZE #define FIO_HAVE_GETTID +#define FIO_EMULATED_MKDIR_TWO #define FIO_PREFERRED_ENGINE "windowsaio" #define FIO_PREFERRED_CLOCK_SOURCE CS_CGETTIME @@ -197,6 +198,24 @@ static inline int fio_set_sched_idle(void) return (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE))? 0 : -1; } +static inline int fio_mkdir(const char *path, mode_t mode) { + DWORD dwAttr = GetFileAttributesA(path); + + if (dwAttr != INVALID_FILE_ATTRIBUTES && + (dwAttr & FILE_ATTRIBUTE_DIRECTORY)) { + errno = EEXIST; + return -1; + } + + if (CreateDirectoryA(path, NULL) == 0) { + log_err("CreateDirectoryA = %d\n", GetLastError()); + errno = win_to_posix_error(GetLastError()); + return -1; + } + + return 0; +} + #ifdef CONFIG_WINDOWS_XP #include "os-windows-xp.h" #else diff --git a/os/os.h b/os/os.h index dadcd87b..9a280e54 100644 --- a/os/os.h +++ b/os/os.h @@ -407,4 +407,8 @@ static inline bool os_cpu_has(cpu_features feature) } #endif +#ifndef FIO_EMULATED_MKDIR_TWO +# define fio_mkdir(path, mode) mkdir(path, mode) #endif + +#endif /* FIO_OS_H */ diff --git a/server.c b/server.c index e7846227..b7347b43 100644 --- a/server.c +++ b/server.c @@ -975,7 +975,7 @@ static int handle_trigger_cmd(struct fio_net_cmd *cmd, struct flist_head *job_li } else fio_net_queue_cmd(FIO_NET_CMD_VTRIGGER, rep, sz, NULL, SK_F_FREE | SK_F_INLINE); - fio_terminate_threads(TERMINATE_ALL); + fio_terminate_threads(TERMINATE_ALL, TERMINATE_ALL); fio_server_check_jobs(job_list); exec_trigger(buf); return 0; @@ -992,7 +992,7 @@ static int handle_command(struct sk_out *sk_out, struct flist_head *job_list, switch (cmd->opcode) { case FIO_NET_CMD_QUIT: - fio_terminate_threads(TERMINATE_ALL); + fio_terminate_threads(TERMINATE_ALL, TERMINATE_ALL); ret = 0; break; case FIO_NET_CMD_EXIT: @@ -1490,6 +1490,7 @@ void fio_server_send_ts(struct thread_stat *ts, struct group_run_stats *rs) convert_io_stat(&p.ts.bw_stat[i], &ts->bw_stat[i]); convert_io_stat(&p.ts.iops_stat[i], &ts->iops_stat[i]); } + convert_io_stat(&p.ts.sync_stat, &ts->sync_stat); p.ts.usr_time = cpu_to_le64(ts->usr_time); p.ts.sys_time = cpu_to_le64(ts->sys_time); @@ -1524,8 +1525,13 @@ void fio_server_send_ts(struct thread_stat *ts, struct group_run_stats *rs) for (j = 0; j < FIO_IO_U_PLAT_NR; j++) p.ts.io_u_plat[i][j] = cpu_to_le64(ts->io_u_plat[i][j]); - for (i = 0; i < DDIR_RWDIR_CNT; i++) { + for (j = 0; j < FIO_IO_U_PLAT_NR; j++) + p.ts.io_u_sync_plat[j] = cpu_to_le64(ts->io_u_sync_plat[j]); + + for (i = 0; i < DDIR_RWDIR_SYNC_CNT; i++) p.ts.total_io_u[i] = cpu_to_le64(ts->total_io_u[i]); + + for (i = 0; i < DDIR_RWDIR_CNT; i++) { p.ts.short_io_u[i] = cpu_to_le64(ts->short_io_u[i]); p.ts.drop_io_u[i] = cpu_to_le64(ts->drop_io_u[i]); } diff --git a/thread_options.h b/thread_options.h index ee6e4d6d..4b131bda 100644 --- a/thread_options.h +++ b/thread_options.h @@ -201,7 +201,8 @@ struct thread_options { unsigned long long max_latency; - unsigned int stonewall; + unsigned short exit_what; + unsigned short stonewall; unsigned int new_group; unsigned int numjobs; os_cpu_mask_t cpumask; @@ -489,7 +490,8 @@ struct thread_options_pack { uint32_t mem_type; uint32_t mem_align; - uint32_t stonewall; + uint16_t exit_what; + uint16_t stonewall; uint32_t new_group; uint32_t numjobs; /*