Commit | Line | Data |
---|---|---|
e27b9ff0 NC |
1 | /* |
2 | * IO priority handling helper functions common to the libaio and io_uring | |
3 | * engines. | |
4 | */ | |
5 | ||
6 | #include "cmdprio.h" | |
7 | ||
8 | static int fio_cmdprio_bssplit_ddir(struct thread_options *to, void *cb_arg, | |
9 | enum fio_ddir ddir, char *str, bool data) | |
10 | { | |
11 | struct cmdprio *cmdprio = cb_arg; | |
12 | struct split split; | |
13 | unsigned int i; | |
14 | ||
15 | if (ddir == DDIR_TRIM) | |
16 | return 0; | |
17 | ||
18 | memset(&split, 0, sizeof(split)); | |
19 | ||
20 | if (split_parse_ddir(to, &split, str, data, BSSPLIT_MAX)) | |
21 | return 1; | |
22 | if (!split.nr) | |
23 | return 0; | |
24 | ||
25 | cmdprio->bssplit_nr[ddir] = split.nr; | |
26 | cmdprio->bssplit[ddir] = malloc(split.nr * sizeof(struct bssplit)); | |
27 | if (!cmdprio->bssplit[ddir]) | |
28 | return 1; | |
29 | ||
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; | |
34 | } else { | |
35 | if (split.val2[i] > 100) | |
36 | cmdprio->bssplit[ddir][i].perc = 100; | |
37 | else | |
38 | cmdprio->bssplit[ddir][i].perc = split.val2[i]; | |
39 | } | |
40 | } | |
41 | ||
42 | return 0; | |
43 | } | |
44 | ||
45 | int fio_cmdprio_bssplit_parse(struct thread_data *td, const char *input, | |
46 | struct cmdprio *cmdprio) | |
47 | { | |
48 | char *str, *p; | |
49 | int i, ret = 0; | |
50 | ||
51 | p = str = strdup(input); | |
52 | ||
53 | strip_blank_front(&str); | |
54 | strip_blank_end(str); | |
55 | ||
56 | ret = str_split_parse(td, str, fio_cmdprio_bssplit_ddir, cmdprio, false); | |
57 | ||
58 | if (parse_dryrun()) { | |
a5af2a8b | 59 | for (i = 0; i < CMDPRIO_RWDIR_CNT; i++) { |
e27b9ff0 NC |
60 | free(cmdprio->bssplit[i]); |
61 | cmdprio->bssplit[i] = NULL; | |
62 | cmdprio->bssplit_nr[i] = 0; | |
63 | } | |
64 | } | |
65 | ||
66 | free(p); | |
67 | return ret; | |
68 | } | |
69 | ||
127715b6 | 70 | static int fio_cmdprio_percentage(struct cmdprio *cmdprio, struct io_u *io_u) |
e27b9ff0 NC |
71 | { |
72 | enum fio_ddir ddir = io_u->ddir; | |
e27b9ff0 NC |
73 | int i; |
74 | ||
97f2d484 NC |
75 | switch (cmdprio->mode) { |
76 | case CMDPRIO_MODE_PERC: | |
77 | return cmdprio->percentage[ddir]; | |
78 | case CMDPRIO_MODE_BSSPLIT: | |
79 | for (i = 0; i < cmdprio->bssplit_nr[ddir]; i++) { | |
80 | if (cmdprio->bssplit[ddir][i].bs == io_u->buflen) | |
81 | return cmdprio->bssplit[ddir][i].perc; | |
82 | } | |
83 | break; | |
84 | default: | |
85 | /* | |
86 | * An I/O engine should never call this function if cmdprio | |
87 | * is not is use. | |
88 | */ | |
89 | assert(0); | |
e27b9ff0 NC |
90 | } |
91 | ||
92 | return 0; | |
93 | } | |
94 | ||
127715b6 NC |
95 | /** |
96 | * fio_cmdprio_set_ioprio - Set an io_u ioprio according to cmdprio options | |
97 | * | |
98 | * Generates a random percentage value to determine if an io_u ioprio needs | |
99 | * to be set. If the random percentage value is within the user specified | |
100 | * percentage of I/Os that should use a cmdprio priority value (rather than | |
101 | * the default priority), then this function updates the io_u with an ioprio | |
102 | * value as defined by the cmdprio/cmdprio_class or cmdprio_bssplit options. | |
103 | * | |
104 | * Return true if the io_u ioprio was changed and false otherwise. | |
105 | */ | |
106 | bool fio_cmdprio_set_ioprio(struct thread_data *td, struct cmdprio *cmdprio, | |
107 | struct io_u *io_u) | |
108 | { | |
109 | enum fio_ddir ddir = io_u->ddir; | |
97f2d484 | 110 | unsigned int p; |
127715b6 NC |
111 | unsigned int cmdprio_value = |
112 | ioprio_value(cmdprio->class[ddir], cmdprio->level[ddir]); | |
113 | ||
97f2d484 | 114 | p = fio_cmdprio_percentage(cmdprio, io_u); |
127715b6 NC |
115 | if (p && rand_between(&td->prio_state, 0, 99) < p) { |
116 | io_u->ioprio = cmdprio_value; | |
117 | if (!td->ioprio || cmdprio_value < td->ioprio) { | |
118 | /* | |
119 | * The async IO priority is higher (has a lower value) | |
120 | * than the default priority (which is either 0 or the | |
121 | * value set by "prio" and "prioclass" options). | |
122 | */ | |
123 | io_u->flags |= IO_U_F_HIGH_PRIO; | |
124 | } | |
125 | return true; | |
126 | } | |
127 | ||
128 | if (td->ioprio && td->ioprio < cmdprio_value) { | |
129 | /* | |
130 | * The IO will be executed with the default priority (which is | |
131 | * either 0 or the value set by "prio" and "prioclass options), | |
132 | * and this priority is higher (has a lower value) than the | |
133 | * async IO priority. | |
134 | */ | |
135 | io_u->flags |= IO_U_F_HIGH_PRIO; | |
136 | } | |
137 | ||
138 | return false; | |
139 | } | |
140 | ||
97f2d484 | 141 | int fio_cmdprio_init(struct thread_data *td, struct cmdprio *cmdprio) |
e27b9ff0 NC |
142 | { |
143 | struct thread_options *to = &td->o; | |
144 | bool has_cmdprio_percentage = false; | |
145 | bool has_cmdprio_bssplit = false; | |
146 | int i; | |
147 | ||
148 | /* | |
149 | * If cmdprio_percentage/cmdprio_bssplit is set and cmdprio_class | |
150 | * is not set, default to RT priority class. | |
151 | */ | |
a5af2a8b | 152 | for (i = 0; i < CMDPRIO_RWDIR_CNT; i++) { |
e27b9ff0 NC |
153 | if (cmdprio->percentage[i]) { |
154 | if (!cmdprio->class[i]) | |
155 | cmdprio->class[i] = IOPRIO_CLASS_RT; | |
156 | has_cmdprio_percentage = true; | |
157 | } | |
158 | if (cmdprio->bssplit_nr[i]) { | |
159 | if (!cmdprio->class[i]) | |
160 | cmdprio->class[i] = IOPRIO_CLASS_RT; | |
161 | has_cmdprio_bssplit = true; | |
162 | } | |
163 | } | |
164 | ||
165 | /* | |
166 | * Check for option conflicts | |
167 | */ | |
168 | if (has_cmdprio_percentage && has_cmdprio_bssplit) { | |
169 | log_err("%s: cmdprio_percentage and cmdprio_bssplit options " | |
170 | "are mutually exclusive\n", | |
171 | to->name); | |
172 | return 1; | |
173 | } | |
174 | ||
97f2d484 NC |
175 | if (has_cmdprio_bssplit) |
176 | cmdprio->mode = CMDPRIO_MODE_BSSPLIT; | |
177 | else if (has_cmdprio_percentage) | |
178 | cmdprio->mode = CMDPRIO_MODE_PERC; | |
179 | else | |
180 | cmdprio->mode = CMDPRIO_MODE_NONE; | |
e27b9ff0 NC |
181 | |
182 | return 0; | |
183 | } |