os-linux: add initial support for IO priority hints
authorDamien Le Moal <dlemoal@kernel.org>
Fri, 21 Jul 2023 11:05:07 +0000 (20:05 +0900)
committerJens Axboe <axboe@kernel.dk>
Fri, 21 Jul 2023 20:07:28 +0000 (14:07 -0600)
Add initial support for Linux to allow specifying a hint for any
priority value. With this change, a priority value becomes the
combination of a priority class, a priority level and a hint.
The generic os.h ioprio manipulation macros, as well as the
os-dragonfly.h ioprio manipulation macros are modified to ignore this
hint.

For all other OSes that do not support priority classes, priotity hints
are ignored and always equal to 0.

Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Niklas Cassel <niklas.cassel@wdc.com>
Link: https://lore.kernel.org/r/20230721110510.44772-4-dlemoal@kernel.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
backend.c
engines/cmdprio.c
options.c
os/os-dragonfly.h
os/os-linux.h
os/os.h

index cb5844dba2391f0f9c14b20940f789511737a023..7e1c37733a862e1f54b1b814b9f14455e2f9a332 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -1800,12 +1800,13 @@ static void *thread_main(void *data)
        /* ioprio_set() has to be done before td_io_init() */
        if (fio_option_is_set(o, ioprio) ||
            fio_option_is_set(o, ioprio_class)) {
-               ret = ioprio_set(IOPRIO_WHO_PROCESS, 0, o->ioprio_class, o->ioprio);
+               ret = ioprio_set(IOPRIO_WHO_PROCESS, 0, o->ioprio_class,
+                                o->ioprio, 0);
                if (ret == -1) {
                        td_verror(td, errno, "ioprio_set");
                        goto err;
                }
-               td->ioprio = ioprio_value(o->ioprio_class, o->ioprio);
+               td->ioprio = ioprio_value(o->ioprio_class, o->ioprio, 0);
                td->ts.ioprio = td->ioprio;
        }
 
index 979a81b6c3c32076385a9bedcbd8fb5a2b6b0044..e6ff1fc2f18e488b1a8b881816e56d3d1e0843da 100644 (file)
@@ -342,7 +342,7 @@ static int fio_cmdprio_gen_perc(struct thread_data *td, struct cmdprio *cmdprio)
                prio = &cmdprio->perc_entry[ddir];
                prio->perc = options->percentage[ddir];
                prio->prio = ioprio_value(options->class[ddir],
-                                         options->level[ddir]);
+                                         options->level[ddir], 0);
                assign_clat_prio_index(prio, &values[ddir]);
 
                ret = init_ts_clat_prio(ts, ddir, &values[ddir]);
@@ -400,7 +400,7 @@ static int fio_cmdprio_parse_and_gen_bssplit(struct thread_data *td,
                        goto err;
 
                implicit_cmdprio = ioprio_value(options->class[ddir],
-                                               options->level[ddir]);
+                                               options->level[ddir], 0);
 
                ret = fio_cmdprio_generate_bsprio_desc(&cmdprio->bsprio_desc[ddir],
                                                       &parse_res[ddir],
index 0f739317248cb95ada08ef1219dc8472bb8946c1..143d358384f8e827b56e1b9fddf4f83daf647be5 100644 (file)
--- a/options.c
+++ b/options.c
@@ -344,7 +344,7 @@ static int parse_cmdprio_bssplit_entry(struct thread_options *o,
        case 4: /* bs/perc/class/level case */
                class = min(class, (unsigned int) IOPRIO_MAX_PRIO_CLASS);
                level = min(level, (unsigned int) IOPRIO_MAX_PRIO);
-               entry->prio = ioprio_value(class, level);
+               entry->prio = ioprio_value(class, level, 0);
                break;
        default:
                log_err("fio: invalid cmdprio_bssplit format\n");
index bde39101b536e1ce3a63aa493b8cd661574fe194..4ce7253956a3ca27d90275d132ec9f405cf63227 100644 (file)
@@ -171,8 +171,8 @@ static inline int fio_getaffinity(int pid, os_cpu_mask_t *mask)
  * ioprio_set() with 4 arguments, so define fio's ioprio_set() as a macro.
  * Note that there is no idea of class within ioprio_set(2) unlike Linux.
  */
-#define ioprio_value(ioprio_class, ioprio)     (ioprio)
-#define ioprio_set(which, who, ioprio_class, ioprio)   \
+#define ioprio_value(ioprio_class, ioprio, ioprio_hint)        (ioprio)
+#define ioprio_set(which, who, ioprio_class, ioprio, ioprio_hint)      \
        ioprio_set(which, who, ioprio)
 
 #define ioprio(ioprio)         (ioprio)
index 72727ac3b61b30db9c2d16c35fe6edcd17d36f05..c5cd6515813146d4f63e0d17427a1b8ee2d9efe1 100644 (file)
@@ -125,16 +125,24 @@ enum {
 #define IOPRIO_BITS            16
 #define IOPRIO_CLASS_SHIFT     13
 
+#define IOPRIO_HINT_BITS       10
+#define IOPRIO_HINT_SHIFT      3
+
 #define IOPRIO_MIN_PRIO                0       /* highest priority */
 #define IOPRIO_MAX_PRIO                7       /* lowest priority */
 
 #define IOPRIO_MIN_PRIO_CLASS  0
 #define IOPRIO_MAX_PRIO_CLASS  3
 
+#define IOPRIO_MIN_PRIO_HINT   0
+#define IOPRIO_MAX_PRIO_HINT   ((1 << IOPRIO_HINT_BITS) - 1)
+
 #define ioprio_class(ioprio)   ((ioprio) >> IOPRIO_CLASS_SHIFT)
 #define ioprio(ioprio)         ((ioprio) & IOPRIO_MAX_PRIO)
+#define ioprio_hint(ioprio)    \
+       (((ioprio) >> IOPRIO_HINT_SHIFT) & IOPRIO_MAX_PRIO_HINT)
 
-static inline int ioprio_value(int ioprio_class, int ioprio)
+static inline int ioprio_value(int ioprio_class, int ioprio, int ioprio_hint)
 {
        /*
         * If no class is set, assume BE
@@ -142,7 +150,9 @@ static inline int ioprio_value(int ioprio_class, int ioprio)
         if (!ioprio_class)
                 ioprio_class = IOPRIO_CLASS_BE;
 
-       return (ioprio_class << IOPRIO_CLASS_SHIFT) | ioprio;
+       return (ioprio_class << IOPRIO_CLASS_SHIFT) |
+               (ioprio_hint << IOPRIO_HINT_SHIFT) |
+               ioprio;
 }
 
 static inline bool ioprio_value_is_class_rt(unsigned int priority)
@@ -150,10 +160,11 @@ static inline bool ioprio_value_is_class_rt(unsigned int priority)
        return ioprio_class(priority) == IOPRIO_CLASS_RT;
 }
 
-static inline int ioprio_set(int which, int who, int ioprio_class, int ioprio)
+static inline int ioprio_set(int which, int who, int ioprio_class, int ioprio,
+                            int ioprio_hint)
 {
        return syscall(__NR_ioprio_set, which, who,
-                      ioprio_value(ioprio_class, ioprio));
+                      ioprio_value(ioprio_class, ioprio, ioprio_hint));
 }
 
 #ifndef CONFIG_HAVE_GETTID
diff --git a/os/os.h b/os/os.h
index 036fc233fe2e3a44931b7e8f618b6d9539228518..0f1823240faa9f11e638b95c2207f03f5480b4ff 100644 (file)
--- a/os/os.h
+++ b/os/os.h
@@ -120,11 +120,14 @@ extern int fio_cpus_split(os_cpu_mask_t *mask, unsigned int cpu);
 #define ioprio_value_is_class_rt(prio) (false)
 #define IOPRIO_MIN_PRIO_CLASS          0
 #define IOPRIO_MAX_PRIO_CLASS          0
+#define ioprio_hint(prio)              0
+#define IOPRIO_MIN_PRIO_HINT           0
+#define IOPRIO_MAX_PRIO_HINT           0
 #endif
 #ifndef FIO_HAVE_IOPRIO
-#define ioprio_value(prioclass, prio)  (0)
+#define ioprio_value(prioclass, prio, priohint)        (0)
 #define ioprio(ioprio)                 0
-#define ioprio_set(which, who, prioclass, prio)        (0)
+#define ioprio_set(which, who, prioclass, prio, priohint) (0)
 #define IOPRIO_MIN_PRIO                        0
 #define IOPRIO_MAX_PRIO                        0
 #endif