Add support for cpus_allowed_policy
[fio.git] / options.c
index dc55c985cc19b0d2940642cb1cac49dc3cd1aee7..c1a8f323e956986f30155fa0c43976376c449afc 100644 (file)
--- a/options.c
+++ b/options.c
@@ -102,7 +102,7 @@ static int bssplit_ddir(struct thread_options *o, int ddir, char *str)
                } else
                        perc = -1;
 
-               if (str_to_decimal(fname, &val, 1, o)) {
+               if (str_to_decimal(fname, &val, 1, o, 0)) {
                        log_err("fio: bssplit conversion failed\n");
                        free(bssplit);
                        return 1;
@@ -336,7 +336,7 @@ static int str_rw_cb(void *data, const char *str)
        else {
                long long val;
 
-               if (str_to_decimal(nr, &val, 1, o)) {
+               if (str_to_decimal(nr, &val, 1, o, 0)) {
                        log_err("fio: rw postfix parsing failed\n");
                        free(nr);
                        return 1;
@@ -394,6 +394,21 @@ static int str_exitall_cb(void)
 }
 
 #ifdef FIO_HAVE_CPU_AFFINITY
+int fio_cpus_split(os_cpu_mask_t *mask, unsigned int cpu)
+{
+       const long max_cpu = cpus_online();
+       unsigned int i;
+
+       for (i = 0; i < max_cpu; i++) {
+               if (cpu != i) {
+                       fio_cpu_clear(mask, i);
+                       continue;
+               }
+       }
+
+       return fio_cpu_count(mask);
+}
+
 static int str_cpumask_cb(void *data, unsigned long long *val)
 {
        struct thread_data *td = data;
@@ -827,8 +842,7 @@ static int str_filename_cb(void *data, const char *input)
        while ((fname = get_next_name(&str)) != NULL) {
                if (!strlen(fname))
                        break;
-               add_file(td, fname, 0);
-               td->o.nr_files++;
+               add_file(td, fname, 0, 1);
        }
 
        free(p);
@@ -1834,6 +1848,8 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .off1   = td_var_offset(allrand_repeatable),
                .help   = "Use repeatable random numbers for everything",
                .def    = "0",
+               .category = FIO_OPT_C_IO,
+               .group  = FIO_OPT_G_RANDOM,
        },
        {
                .name   = "nrfiles",
@@ -2066,6 +2082,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .off2   = td_var_offset(start_delay_high),
                .help   = "Only start job when this period has passed",
                .def    = "0",
+               .is_seconds = 1,
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_RUNTIME,
        },
@@ -2077,6 +2094,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .off1   = td_var_offset(timeout),
                .help   = "Stop workload when this amount of time has passed",
                .def    = "0",
+               .is_seconds = 1,
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_RUNTIME,
        },
@@ -2104,6 +2122,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .type   = FIO_OPT_STR_VAL_TIME,
                .off1   = td_var_offset(ramp_time),
                .help   = "Ramp up time before measuring performance",
+               .is_seconds = 1,
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_RUNTIME,
        },
@@ -2871,6 +2890,27 @@ struct fio_option fio_options[FIO_MAX_OPTS] = {
                .category = FIO_OPT_C_GENERAL,
                .group  = FIO_OPT_G_CRED,
        },
+       {
+               .name   = "cpus_allowed_policy",
+               .lname  = "CPUs allowed distribution policy",
+               .type   = FIO_OPT_STR,
+               .off1   = td_var_offset(cpus_allowed_policy),
+               .help   = "Distribution policy for cpus_allowed",
+               .parent = "cpus_allowed",
+               .prio   = 1,
+               .posval = {
+                         { .ival = "shared",
+                           .oval = FIO_CPUS_SHARED,
+                           .help = "Mask shared between threads",
+                         },
+                         { .ival = "split",
+                           .oval = FIO_CPUS_SPLIT,
+                           .help = "Mask split between threads",
+                         },
+               },
+               .category = FIO_OPT_C_GENERAL,
+               .group  = FIO_OPT_G_CRED,
+       },
 #endif
 #ifdef CONFIG_LIBNUMA
        {
@@ -3785,6 +3825,7 @@ int fio_cmd_ioengine_option_parse(struct thread_data *td, const char *opt,
 
 void fio_fill_default_options(struct thread_data *td)
 {
+       td->o.magic = OPT_MAGIC;
        fill_default_options(td, fio_options);
 }
 
@@ -3829,7 +3870,16 @@ unsigned int fio_get_kb_base(void *data)
        struct thread_options *o = data;
        unsigned int kb_base = 0;
 
-       if (o)
+       /*
+        * This is a hack... For private options, *data is not holding
+        * a pointer to the thread_options, but to private data. This means
+        * we can't safely dereference it, but magic is first so mem wise
+        * it is valid. But this also means that if the job first sets
+        * kb_base and expects that to be honored by private options,
+        * it will be disappointed. We will return the global default
+        * for this.
+        */
+       if (o && o->magic == OPT_MAGIC)
                kb_base = o->kb_base;
        if (!kb_base)
                kb_base = 1024;