summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kuzmin <andrey.v.kuzmin@gmail.com>2015-12-22 09:21:25 -0700
committerJens Axboe <axboe@fb.com>2015-12-22 09:21:25 -0700
commit9cc8cb91d355d7e47d5b930b352087ec71f85f85 (patch)
tree3bd0e2fa8123e6c604784fe61b4300278dc1d0e8
parentb5f4ef37543b46f9ef44cabf691a92d6592fb286 (diff)
Add support for waiting for other jobs by name
We have stonewall to barrier against previous jobs before a new job runs. This adds support for 'wait_for', which allows the user to explicitly wait for a given job before starting. Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--HOWTO10
-rw-r--r--backend.c32
-rw-r--r--cconv.c3
-rw-r--r--examples/waitfor.fio35
-rw-r--r--fio.18
-rw-r--r--fio.h1
-rw-r--r--init.c49
-rw-r--r--libfio.c2
-rw-r--r--options.c9
-rw-r--r--server.h2
-rw-r--r--thread_options.h2
11 files changed, 151 insertions, 2 deletions
diff --git a/HOWTO b/HOWTO
index 482d696..7c24c1b 100644
--- a/HOWTO
+++ b/HOWTO
@@ -305,6 +305,16 @@ name=str ASCII name of the job. This may be used to override the
special purpose of also signaling the start of a new
job.
+wait_for=str Specifies the name of the already defined job to wait
+ for. Single waitee name only may be specified. If set, the job
+ won't be started until all workers of the waitee job are done.
+
+ Wait_for operates on the job name basis, so there are a few
+ limitations. First, the waitee must be defined prior to the
+ waiter job (meaning no forward references). Second, if a job
+ is being referenced as a waitee, it must have a unique name
+ (no duplicate waitees).
+
description=str Text description of the job. Doesn't do anything except
dump this text description when this job is run. It's
not parsed.
diff --git a/backend.c b/backend.c
index 9920e63..edc0644 100644
--- a/backend.c
+++ b/backend.c
@@ -1978,6 +1978,32 @@ mounted:
return true;
}
+static bool waitee_running(struct thread_data *me)
+{
+ const char *waitee = me->o.wait_for;
+ const char *self = me->o.name;
+ struct thread_data *td;
+ int i;
+
+ if (!waitee)
+ return false;
+
+ for_each_td(td, i) {
+ if (!strcmp(td->o.name, self) || strcmp(td->o.name, waitee))
+ continue;
+
+ if (td->runstate < TD_EXITED) {
+ dprint(FD_PROCESS, "%s fenced by %s(%s)\n",
+ self, td->o.name,
+ runstate_to_name(td->runstate));
+ return true;
+ }
+ }
+
+ dprint(FD_PROCESS, "%s: %s completed, can run\n", self, waitee);
+ return false;
+}
+
/*
* Main function for kicking off and reaping jobs, as needed.
*/
@@ -2101,6 +2127,12 @@ reap:
break;
}
+ if (waitee_running(td)) {
+ dprint(FD_PROCESS, "%s: waiting for %s\n",
+ td->o.name, td->o.wait_for);
+ break;
+ }
+
init_disk_util(td);
td->rusage_sem = fio_mutex_init(FIO_MUTEX_LOCKED);
diff --git a/cconv.c b/cconv.c
index a476aad..6d8d0b3 100644
--- a/cconv.c
+++ b/cconv.c
@@ -25,6 +25,7 @@ static void free_thread_options_to_cpu(struct thread_options *o)
{
free(o->description);
free(o->name);
+ free(o->wait_for);
free(o->directory);
free(o->filename);
free(o->filename_format);
@@ -54,6 +55,7 @@ void convert_thread_options_to_cpu(struct thread_options *o,
string_to_cpu(&o->description, top->description);
string_to_cpu(&o->name, top->name);
+ string_to_cpu(&o->wait_for, top->wait_for);
string_to_cpu(&o->directory, top->directory);
string_to_cpu(&o->filename, top->filename);
string_to_cpu(&o->filename_format, top->filename_format);
@@ -276,6 +278,7 @@ void convert_thread_options_to_net(struct thread_options_pack *top,
string_to_net(top->description, o->description);
string_to_net(top->name, o->name);
+ string_to_net(top->wait_for, o->wait_for);
string_to_net(top->directory, o->directory);
string_to_net(top->filename, o->filename);
string_to_net(top->filename_format, o->filename_format);
diff --git a/examples/waitfor.fio b/examples/waitfor.fio
new file mode 100644
index 0000000..95fad00
--- /dev/null
+++ b/examples/waitfor.fio
@@ -0,0 +1,35 @@
+[global]
+threads=1
+group_reporting=1
+filename=/tmp/data
+filesize=128m
+
+[writers]
+rw=write
+bs=128k
+numjobs=4
+runtime=10
+
+[readers]
+new_group
+wait_for=writers
+rw=randread
+bs=4k
+numjobs=4
+runtime=10
+
+[writers2]
+new_group
+wait_for=readers
+rw=randwrite
+bs=4k
+numjobs=4
+runtime=10
+
+[readers2]
+new_group
+wait_for=writers2
+rw=randread
+bs=4k
+numjobs=4
+runtime=10
diff --git a/fio.1 b/fio.1
index 4fe1be2..7bdfea3 100644
--- a/fio.1
+++ b/fio.1
@@ -180,6 +180,14 @@ a ':' character.
May be used to override the job name. On the command line, this parameter
has the special purpose of signalling the start of a new job.
.TP
+.BI wait_for \fR=\fPstr
+Specifies the name of the already defined job to wait for. Single waitee name
+only may be specified. If set, the job won't be started until all workers of
+the waitee job are done. Wait_for operates on the job name basis, so there are
+a few limitations. First, the waitee must be defined prior to the waiter job
+(meaning no forward references). Second, if a job is being referenced as a
+waitee, it must have a unique name (no duplicate waitees).
+.TP
.BI description \fR=\fPstr
Human-readable description of the job. It is printed when the job is run, but
otherwise has no special purpose.
diff --git a/fio.h b/fio.h
index ddc29db..66211e9 100644
--- a/fio.h
+++ b/fio.h
@@ -542,6 +542,7 @@ enum {
extern void td_set_runstate(struct thread_data *, int);
extern int td_bump_runstate(struct thread_data *, int);
extern void td_restore_runstate(struct thread_data *, int);
+extern const char *runstate_to_name(int runstate);
/*
* Allow 60 seconds for a job to quit on its own, otherwise reap with
diff --git a/init.c b/init.c
index 8773138..991fa1c 100644
--- a/init.c
+++ b/init.c
@@ -1217,6 +1217,49 @@ static void gen_log_name(char *name, size_t size, const char *logtype,
snprintf(name, size, "%s_%s.%s", logname, logtype, suf);
}
+static int check_waitees(char *waitee)
+{
+ struct thread_data *td;
+ int i, ret = 0;
+
+ for_each_td(td, i) {
+ if (td->subjob_number)
+ continue;
+
+ ret += !strcmp(td->o.name, waitee);
+ }
+
+ return ret;
+}
+
+static bool wait_for_ok(const char *jobname, struct thread_options *o)
+{
+ int nw;
+
+ if (!o->wait_for)
+ return true;
+
+ if (!strcmp(jobname, o->wait_for)) {
+ log_err("%s: a job cannot wait for itself (wait_for=%s).\n",
+ jobname, o->wait_for);
+ return false;
+ }
+
+ if (!(nw = check_waitees(o->wait_for))) {
+ log_err("%s: waitee job %s unknown.\n", jobname, o->wait_for);
+ return false;
+ }
+
+ if (nw > 1) {
+ log_err("%s: multiple waitees %s found,\n"
+ "please avoid duplicates when using wait_for option.\n",
+ jobname, o->wait_for);
+ return false;
+ }
+
+ return true;
+}
+
/*
* Adds a job to the list of things todo. Sanitizes the various options
* to make sure we don't have conflicts, and initializes various
@@ -1273,6 +1316,12 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num,
if (fixup_options(td))
goto err;
+ /*
+ * Belongs to fixup_options, but o->name is not necessarily set as yet
+ */
+ if (!wait_for_ok(jobname, o))
+ goto err;
+
flow_init_job(td);
/*
diff --git a/libfio.c b/libfio.c
index 6c74852..c626d15 100644
--- a/libfio.c
+++ b/libfio.c
@@ -190,7 +190,7 @@ static const char *td_runstates[] = {
"REAPED",
};
-static const char *runstate_to_name(int runstate)
+const char *runstate_to_name(int runstate)
{
compiletime_assert(TD_LAST == 12, "td runstate list");
if (runstate >= 0 && runstate < TD_LAST)
diff --git a/options.c b/options.c
index 8494713..49d6600 100644
--- a/options.c
+++ b/options.c
@@ -1229,6 +1229,15 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
.group = FIO_OPT_G_DESC,
},
{
+ .name = "wait_for",
+ .lname = "Waitee name",
+ .type = FIO_OPT_STR_STORE,
+ .off1 = td_var_offset(wait_for),
+ .help = "Name of the job this one wants to wait for before starting",
+ .category = FIO_OPT_C_GENERAL,
+ .group = FIO_OPT_G_DESC,
+ },
+ {
.name = "filename",
.lname = "Filename(s)",
.type = FIO_OPT_STR_STORE,
diff --git a/server.h b/server.h
index 5a59d07..9205ae6 100644
--- a/server.h
+++ b/server.h
@@ -38,7 +38,7 @@ struct fio_net_cmd_reply {
};
enum {
- FIO_SERVER_VER = 50,
+ FIO_SERVER_VER = 51,
FIO_SERVER_MAX_FRAGMENT_PDU = 1024,
FIO_SERVER_MAX_CMD_MB = 2048,
diff --git a/thread_options.h b/thread_options.h
index 6ae0335..858f307 100644
--- a/thread_options.h
+++ b/thread_options.h
@@ -40,6 +40,7 @@ struct thread_options {
uint64_t set_options[NR_OPTS_SZ];
char *description;
char *name;
+ char *wait_for;
char *directory;
char *filename;
char *filename_format;
@@ -289,6 +290,7 @@ struct thread_options_pack {
uint64_t set_options[NR_OPTS_SZ];
uint8_t description[FIO_TOP_STR_MAX];
uint8_t name[FIO_TOP_STR_MAX];
+ uint8_t wait_for[FIO_TOP_STR_MAX];
uint8_t directory[FIO_TOP_STR_MAX];
uint8_t filename[FIO_TOP_STR_MAX];
uint8_t filename_format[FIO_TOP_STR_MAX];