-/*
- * Map of job/command line options
- */
-static struct fio_option options[] = {
- {
- .name = "description",
- .type = FIO_OPT_STR_STORE,
- .off1 = td_var_offset(description),
- .help = "Text job description",
- },
- {
- .name = "name",
- .type = FIO_OPT_STR_STORE,
- .off1 = td_var_offset(name),
- .help = "Name of this job",
- },
- {
- .name = "directory",
- .type = FIO_OPT_STR_STORE,
- .off1 = td_var_offset(directory),
- .cb = str_directory_cb,
- .help = "Directory to store files in",
- },
- {
- .name = "filename",
- .type = FIO_OPT_STR_STORE,
- .off1 = td_var_offset(filename),
- .cb = str_filename_cb,
- .help = "File(s) to use for the workload",
- },
- {
- .name = "opendir",
- .type = FIO_OPT_STR_STORE,
- .off1 = td_var_offset(opendir),
- .cb = str_opendir_cb,
- .help = "Recursively add files from this directory and down",
- },
- {
- .name = "rw",
- .alias = "readwrite",
- .type = FIO_OPT_STR,
- .cb = str_rw_cb,
- .off1 = td_var_offset(td_ddir),
- .help = "IO direction",
- .def = "read",
+ td->o.lockfile_batch = 1;
+ if (nr) {
+ td->o.lockfile_batch = atoi(nr);
+ free(nr);
+ }
+
+ return 0;
+}
+
+static int str_write_bw_log_cb(void *data, const char *str)
+{
+ struct thread_data *td = data;
+
+ if (str)
+ td->o.bw_log_file = strdup(str);
+
+ td->o.write_bw_log = 1;
+ return 0;
+}
+
+static int str_write_lat_log_cb(void *data, const char *str)
+{
+ struct thread_data *td = data;
+
+ if (str)
+ td->o.lat_log_file = strdup(str);
+
+ td->o.write_lat_log = 1;
+ return 0;
+}
+
+static int str_write_iops_log_cb(void *data, const char *str)
+{
+ struct thread_data *td = data;
+
+ if (str)
+ td->o.iops_log_file = strdup(str);
+
+ td->o.write_iops_log = 1;
+ return 0;
+}
+
+static int str_gtod_reduce_cb(void *data, int *il)
+{
+ struct thread_data *td = data;
+ int val = *il;
+
+ td->o.disable_lat = !!val;
+ td->o.disable_clat = !!val;
+ td->o.disable_slat = !!val;
+ td->o.disable_bw = !!val;
+ td->o.clat_percentiles = !val;
+ if (val)
+ td->tv_cache_mask = 63;
+
+ return 0;
+}
+
+static int str_gtod_cpu_cb(void *data, long long *il)
+{
+ struct thread_data *td = data;
+ int val = *il;
+
+ td->o.gtod_cpu = val;
+ td->o.gtod_offload = 1;
+ return 0;
+}
+
+static int str_size_cb(void *data, unsigned long long *__val)
+{
+ struct thread_data *td = data;
+ unsigned long long v = *__val;
+
+ if (parse_is_percent(v)) {
+ td->o.size = 0;
+ td->o.size_percent = -1ULL - v;
+ } else
+ td->o.size = v;
+
+ return 0;
+}
+
+static int rw_verify(struct fio_option *o, void *data)
+{
+ struct thread_data *td = data;
+
+ if (read_only && td_write(td)) {
+ log_err("fio: job <%s> has write bit set, but fio is in"
+ " read-only mode\n", td->o.name);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int gtod_cpu_verify(struct fio_option *o, void *data)
+{
+#ifndef FIO_HAVE_CPU_AFFINITY
+ struct thread_data *td = data;
+
+ if (td->o.gtod_cpu) {
+ log_err("fio: platform must support CPU affinity for"
+ "gettimeofday() offloading\n");
+ return 1;
+ }
+#endif
+
+ return 0;
+}
+
+static int kb_base_verify(struct fio_option *o, void *data)
+{
+ struct thread_data *td = data;
+
+ if (td->o.kb_base != 1024 && td->o.kb_base != 1000) {
+ log_err("fio: kb_base set to nonsensical value: %u\n",
+ td->o.kb_base);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Option grouping
+ */
+static struct opt_group fio_opt_groups[] = {
+ {
+ .name = "Description",
+ .mask = FIO_OPT_G_DESC,
+ },
+ {
+ .name = "File",
+ .mask = FIO_OPT_G_FILE,
+ },
+ {
+ .name = "Misc",
+ .mask = FIO_OPT_G_MISC,
+ },
+ {
+ .name = "IO (main)",
+ .mask = FIO_OPT_G_IO,
+ },
+ {
+ .name = "IO direction",
+ .mask = FIO_OPT_G_IO_DDIR,
+ },
+ {
+ .name = "IO buffer",
+ .mask = FIO_OPT_G_IO_BUF,
+ },
+ {
+ .name = "Random",
+ .mask = FIO_OPT_G_RAND,
+ },
+ {
+ .name = "OS",
+ .mask = FIO_OPT_G_OS,
+ },
+ {
+ .name = "Memory",
+ .mask = FIO_OPT_G_MEM,
+ },
+ {
+ .name = "Verify",
+ .mask = FIO_OPT_G_VERIFY,
+ },
+ {
+ .name = "CPU",
+ .mask = FIO_OPT_G_CPU,
+ },
+ {
+ .name = "Log",
+ .mask = FIO_OPT_G_LOG,
+ },
+ {
+ .name = "Zone",
+ .mask = FIO_OPT_G_ZONE,
+ },
+ {
+ .name = "Cache",
+ .mask = FIO_OPT_G_CACHE,
+ },
+ {
+ .name = "Stat",
+ .mask = FIO_OPT_G_STAT,
+ },
+ {
+ .name = "Error",
+ .mask = FIO_OPT_G_ERR,
+ },
+ {
+ .name = "Job",
+ .mask = FIO_OPT_G_JOB,
+ },
+ {
+ .name = NULL,
+ },
+};
+
+struct opt_group *opt_group_from_mask(unsigned int *mask)
+{
+ struct opt_group *og;
+ int i;
+
+ if (*mask == FIO_OPT_G_INVALID)
+ return NULL;
+
+ for (i = 0; fio_opt_groups[i].name; i++) {
+ og = &fio_opt_groups[i];
+
+ if (*mask & og->mask) {
+ *mask &= ~(og->mask);
+ return og;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Map of job/command line options
+ */
+struct fio_option fio_options[FIO_MAX_OPTS] = {
+ {
+ .name = "description",
+ .type = FIO_OPT_STR_STORE,
+ .off1 = td_var_offset(description),
+ .help = "Text job description",
+ .category = FIO_OPT_G_DESC,
+ },
+ {
+ .name = "name",
+ .type = FIO_OPT_STR_STORE,
+ .off1 = td_var_offset(name),
+ .help = "Name of this job",
+ .category = FIO_OPT_G_DESC,
+ },
+ {
+ .name = "directory",
+ .type = FIO_OPT_STR_STORE,
+ .off1 = td_var_offset(directory),
+ .cb = str_directory_cb,
+ .help = "Directory to store files in",
+ .category = FIO_OPT_G_FILE,
+ },
+ {
+ .name = "filename",
+ .type = FIO_OPT_STR_STORE,
+ .off1 = td_var_offset(filename),
+ .cb = str_filename_cb,
+ .prio = -1, /* must come after "directory" */
+ .help = "File(s) to use for the workload",
+ .category = FIO_OPT_G_FILE,
+ },
+ {
+ .name = "kb_base",
+ .type = FIO_OPT_INT,
+ .off1 = td_var_offset(kb_base),
+ .verify = kb_base_verify,
+ .prio = 1,
+ .def = "1024",
+ .help = "How many bytes per KB for reporting (1000 or 1024)",
+ .category = FIO_OPT_G_MISC,
+ },
+ {
+ .name = "lockfile",
+ .type = FIO_OPT_STR,
+ .cb = str_lockfile_cb,
+ .off1 = td_var_offset(file_lock_mode),
+ .help = "Lock file when doing IO to it",
+ .parent = "filename",
+ .def = "none",
+ .category = FIO_OPT_G_FILE,
+ .posval = {
+ { .ival = "none",
+ .oval = FILE_LOCK_NONE,
+ .help = "No file locking",
+ },
+ { .ival = "exclusive",
+ .oval = FILE_LOCK_EXCLUSIVE,
+ .help = "Exclusive file lock",
+ },
+ {
+ .ival = "readwrite",
+ .oval = FILE_LOCK_READWRITE,
+ .help = "Read vs write lock",
+ },
+ },
+ },
+ {
+ .name = "opendir",
+ .type = FIO_OPT_STR_STORE,
+ .off1 = td_var_offset(opendir),
+ .cb = str_opendir_cb,
+ .help = "Recursively add files from this directory and down",
+ .category = FIO_OPT_G_FILE,
+ },
+ {
+ .name = "rw",
+ .alias = "readwrite",
+ .type = FIO_OPT_STR,
+ .cb = str_rw_cb,
+ .off1 = td_var_offset(td_ddir),
+ .help = "IO direction",
+ .def = "read",
+ .verify = rw_verify,
+ .category = FIO_OPT_G_IO_DDIR,