Add support for waiting for other jobs by name
[fio.git] / init.c
diff --git a/init.c b/init.c
index fb8c9cfb7a085a7b1b1679d4add329efc9dca3db..991fa1ce3f46f8880345798425018d167568f2b3 100644 (file)
--- a/init.c
+++ b/init.c
@@ -426,6 +426,27 @@ static void fio_dump_options_free(struct thread_data *td)
        }
 }
 
+static void copy_opt_list(struct thread_data *dst, struct thread_data *src)
+{
+       struct flist_head *entry;
+
+       if (flist_empty(&src->opt_list))
+               return;
+
+       flist_for_each(entry, &src->opt_list) {
+               struct print_option *srcp, *dstp;
+
+               srcp = flist_entry(entry, struct print_option, list);
+               dstp = malloc(sizeof(*dstp));
+               dstp->name = strdup(srcp->name);
+               if (srcp->value)
+                       dstp->value = strdup(srcp->value);
+               else
+                       dstp->value = NULL;
+               flist_add_tail(&dstp->list, &dst->opt_list);
+       }
+}
+
 /*
  * Return a free job structure.
  */
@@ -452,6 +473,8 @@ static struct thread_data *get_new_job(int global, struct thread_data *parent,
        *td = *parent;
 
        INIT_FLIST_HEAD(&td->opt_list);
+       if (parent != &def_thread)
+               copy_opt_list(td, parent);
 
        td->io_ops = NULL;
        if (!preserve_eo)
@@ -1194,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
@@ -1250,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);
 
        /*
@@ -1774,6 +1846,7 @@ int parse_jobs_ini(char *file, int is_buf, int stonewall_flag, int type)
 static int fill_def_thread(void)
 {
        memset(&def_thread, 0, sizeof(def_thread));
+       INIT_FLIST_HEAD(&def_thread.opt_list);
 
        fio_getaffinity(getpid(), &def_thread.o.cpumask);
        def_thread.o.error_dump = 1;
@@ -2633,7 +2706,7 @@ void options_default_fill(struct thread_options *o)
        memcpy(o, &def_thread.o, sizeof(*o));
 }
 
-bool is_def_thread(struct thread_data *td)
+struct thread_data *get_global_options(void)
 {
-       return td == &def_thread;
+       return &def_thread;
 }