2 * IO priority handling helper functions common to the libaio and io_uring
8 static int fio_cmdprio_bssplit_ddir(struct thread_options *to, void *cb_arg,
9 enum fio_ddir ddir, char *str, bool data)
11 struct cmdprio *cmdprio = cb_arg;
15 if (ddir == DDIR_TRIM)
18 memset(&split, 0, sizeof(split));
20 if (split_parse_ddir(to, &split, str, data, BSSPLIT_MAX))
25 cmdprio->bssplit_nr[ddir] = split.nr;
26 cmdprio->bssplit[ddir] = malloc(split.nr * sizeof(struct bssplit));
27 if (!cmdprio->bssplit[ddir])
30 for (i = 0; i < split.nr; i++) {
31 cmdprio->bssplit[ddir][i].bs = split.val1[i];
32 if (split.val2[i] == -1U) {
33 cmdprio->bssplit[ddir][i].perc = 0;
35 if (split.val2[i] > 100)
36 cmdprio->bssplit[ddir][i].perc = 100;
38 cmdprio->bssplit[ddir][i].perc = split.val2[i];
45 int fio_cmdprio_bssplit_parse(struct thread_data *td, const char *input,
46 struct cmdprio *cmdprio)
51 p = str = strdup(input);
53 strip_blank_front(&str);
56 ret = str_split_parse(td, str, fio_cmdprio_bssplit_ddir, cmdprio, false);
59 for (i = 0; i < CMDPRIO_RWDIR_CNT; i++) {
60 free(cmdprio->bssplit[i]);
61 cmdprio->bssplit[i] = NULL;
62 cmdprio->bssplit_nr[i] = 0;
70 static int fio_cmdprio_percentage(struct cmdprio *cmdprio, struct io_u *io_u)
72 enum fio_ddir ddir = io_u->ddir;
73 unsigned int p = cmdprio->percentage[ddir];
77 * If cmdprio_percentage option was specified, then use that
78 * percentage. Otherwise, use cmdprio_bssplit percentages depending
84 for (i = 0; i < cmdprio->bssplit_nr[ddir]; i++) {
85 if (cmdprio->bssplit[ddir][i].bs == io_u->buflen)
86 return cmdprio->bssplit[ddir][i].perc;
93 * fio_cmdprio_set_ioprio - Set an io_u ioprio according to cmdprio options
95 * Generates a random percentage value to determine if an io_u ioprio needs
96 * to be set. If the random percentage value is within the user specified
97 * percentage of I/Os that should use a cmdprio priority value (rather than
98 * the default priority), then this function updates the io_u with an ioprio
99 * value as defined by the cmdprio/cmdprio_class or cmdprio_bssplit options.
101 * Return true if the io_u ioprio was changed and false otherwise.
103 bool fio_cmdprio_set_ioprio(struct thread_data *td, struct cmdprio *cmdprio,
106 enum fio_ddir ddir = io_u->ddir;
107 unsigned int p = fio_cmdprio_percentage(cmdprio, io_u);
108 unsigned int cmdprio_value =
109 ioprio_value(cmdprio->class[ddir], cmdprio->level[ddir]);
111 if (p && rand_between(&td->prio_state, 0, 99) < p) {
112 io_u->ioprio = cmdprio_value;
113 if (!td->ioprio || cmdprio_value < td->ioprio) {
115 * The async IO priority is higher (has a lower value)
116 * than the default priority (which is either 0 or the
117 * value set by "prio" and "prioclass" options).
119 io_u->flags |= IO_U_F_HIGH_PRIO;
124 if (td->ioprio && td->ioprio < cmdprio_value) {
126 * The IO will be executed with the default priority (which is
127 * either 0 or the value set by "prio" and "prioclass options),
128 * and this priority is higher (has a lower value) than the
131 io_u->flags |= IO_U_F_HIGH_PRIO;
137 int fio_cmdprio_init(struct thread_data *td, struct cmdprio *cmdprio,
140 struct thread_options *to = &td->o;
141 bool has_cmdprio_percentage = false;
142 bool has_cmdprio_bssplit = false;
146 * If cmdprio_percentage/cmdprio_bssplit is set and cmdprio_class
147 * is not set, default to RT priority class.
149 for (i = 0; i < CMDPRIO_RWDIR_CNT; i++) {
150 if (cmdprio->percentage[i]) {
151 if (!cmdprio->class[i])
152 cmdprio->class[i] = IOPRIO_CLASS_RT;
153 has_cmdprio_percentage = true;
155 if (cmdprio->bssplit_nr[i]) {
156 if (!cmdprio->class[i])
157 cmdprio->class[i] = IOPRIO_CLASS_RT;
158 has_cmdprio_bssplit = true;
163 * Check for option conflicts
165 if (has_cmdprio_percentage && has_cmdprio_bssplit) {
166 log_err("%s: cmdprio_percentage and cmdprio_bssplit options "
167 "are mutually exclusive\n",
172 *has_cmdprio = has_cmdprio_percentage || has_cmdprio_bssplit;