#include "idletime.h"
#include "filelock.h"
-#include "lib/getopt.h"
+#include "oslib/getopt.h"
#include "oslib/strcasestr.h"
#include "crc/test.h"
}
}
+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.
*/
*td = *parent;
INIT_FLIST_HEAD(&td->opt_list);
+ if (parent != &def_thread)
+ copy_opt_list(td, parent);
td->io_ops = NULL;
if (!preserve_eo)
if (jobname)
td->o.name = strdup(jobname);
- if (!parent->o.group_reporting)
+ if (!parent->o.group_reporting || parent == &def_thread)
stat_number++;
set_cmd_options(td);
frand_copy(&td->buf_state_prev, &td->buf_state);
init_rand_seed(&td->dedupe_state, td->rand_seeds[FIO_DEDUPE_OFF], use64);
+ init_rand_seed(&td->zone_state, td->rand_seeds[FIO_RAND_ZONE_OFF], use64);
}
/*
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
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);
/*
strip_blank_end(p);
if (!strncmp(p, "include", strlen("include"))) {
- char *filename = p + strlen("include") + 1;
+ char *filename = p + strlen("include") + 1,
+ *ts, *full_fn = NULL;
+
+ /*
+ * Allow for the include filename
+ * specification to be relative.
+ */
+ if (access(filename, F_OK) &&
+ (ts = strrchr(file, '/'))) {
+ int len = ts - file +
+ strlen(filename) + 2;
+
+ if (!(full_fn = calloc(1, len))) {
+ ret = ENOMEM;
+ break;
+ }
+
+ strncpy(full_fn,
+ file, (ts - file) + 1);
+ strncpy(full_fn + (ts - file) + 1,
+ filename, strlen(filename));
+ full_fn[len - 1] = 0;
+ filename = full_fn;
+ }
- if ((ret = __parse_jobs_ini(td, filename,
- is_buf, stonewall_flag, type, 1,
- name, &opts, &alloc_opts, &num_opts))) {
- log_err("Error %d while parsing include file %s\n",
+ ret = __parse_jobs_ini(td, filename, is_buf,
+ stonewall_flag, type, 1,
+ name, &opts,
+ &alloc_opts, &num_opts);
+
+ if (ret) {
+ log_err("Error %d while parsing "
+ "include file %s\n",
ret, filename);
- break;
}
+
+ if (full_fn)
+ free(full_fn);
+
+ if (ret)
+ break;
+
continue;
}
static void show_debug_categories(void)
{
+#ifdef FIO_INC_DEBUG
struct debug_level *dl = &debug_levels[0];
int curlen, first = 1;
first = 0;
}
printf("\n");
+#endif
}
static void usage(const char *name)