Merge branch 'security-token' of https://github.com/sfc-gh-rnarubin/fio
[fio.git] / dataplacement.c
CommitLineData
a7e8aae0
KB
1/*
2 * Note: This is similar to a very basic setup
3 * of ZBD devices
4 *
5 * Specify fdp=1 (With char devices /dev/ng0n1)
6 */
7
8#include <errno.h>
9#include <string.h>
10#include <stdlib.h>
11#include <unistd.h>
a7e8aae0 12#include "fio.h"
7d352b12 13#include "file.h"
a7e8aae0
KB
14
15#include "pshared.h"
c60d54ae 16#include "dataplacement.h"
a7e8aae0
KB
17
18static int fdp_ruh_info(struct thread_data *td, struct fio_file *f,
19 struct fio_ruhs_info *ruhs)
20{
21 int ret = -EINVAL;
22
5a85d6d8
JA
23 if (!td->io_ops) {
24 log_err("fio: no ops set in fdp init?!\n");
25 return ret;
26 }
27
28 if (td->io_ops->fdp_fetch_ruhs) {
a7e8aae0
KB
29 ret = td->io_ops->fdp_fetch_ruhs(td, f, ruhs);
30 if (ret < 0) {
31 td_verror(td, errno, "fdp fetch ruhs failed");
32 log_err("%s: fdp fetch ruhs failed (%d)\n",
33 f->file_name, errno);
34 }
5a85d6d8 35 } else {
a7e8aae0
KB
36 log_err("%s: engine (%s) lacks fetch ruhs\n",
37 f->file_name, td->io_ops->name);
5a85d6d8 38 }
a7e8aae0
KB
39
40 return ret;
41}
42
43static int init_ruh_info(struct thread_data *td, struct fio_file *f)
44{
45 struct fio_ruhs_info *ruhs, *tmp;
56d12245 46 uint32_t nr_ruhs;
a7e8aae0
KB
47 int i, ret;
48
1a3a21b7
VF
49 /* set up the data structure used for FDP to work with the supplied stream IDs */
50 if (td->o.dp_type == FIO_DP_STREAMS) {
51 if (!td->o.dp_nr_ids) {
52 log_err("fio: stream IDs must be provided for dataplacement=streams\n");
53 return -EINVAL;
54 }
8ac0eec7 55 ruhs = scalloc(1, sizeof(*ruhs) + td->o.dp_nr_ids * sizeof(*ruhs->plis));
56d12245
AK
56 if (!ruhs)
57 return -ENOMEM;
58
1a3a21b7
VF
59 ruhs->nr_ruhs = td->o.dp_nr_ids;
60 for (int i = 0; i < ruhs->nr_ruhs; i++)
61 ruhs->plis[i] = td->o.dp_ids[i];
62
63 f->ruhs_info = ruhs;
64 return 0;
65 }
66
56d12245
AK
67 /*
68 * Since we don't know the actual number of ruhs. Only fetch the header.
69 * We will reallocate this buffer and then fetch all the ruhs again.
70 */
71 ruhs = calloc(1, sizeof(*ruhs));
a7e8aae0
KB
72 ret = fdp_ruh_info(td, f, ruhs);
73 if (ret) {
6715cca2
AK
74 log_err("fio: ruh info failed for %s (%d)\n",
75 f->file_name, -ret);
a7e8aae0
KB
76 goto out;
77 }
78
56d12245
AK
79 nr_ruhs = ruhs->nr_ruhs;
80 ruhs = realloc(ruhs, sizeof(*ruhs) + nr_ruhs * sizeof(*ruhs->plis));
81 if (!ruhs) {
6715cca2
AK
82 log_err("fio: ruhs buffer realloc failed for %s\n",
83 f->file_name);
56d12245
AK
84 ret = -ENOMEM;
85 goto out;
86 }
a7e8aae0 87
56d12245
AK
88 ruhs->nr_ruhs = nr_ruhs;
89 ret = fdp_ruh_info(td, f, ruhs);
90 if (ret) {
6715cca2
AK
91 log_err("fio: ruh info failed for %s (%d)\n",
92 f->file_name, -ret);
56d12245 93 goto out;
a7e8aae0
KB
94 }
95
56d12245 96 if (td->o.dp_nr_ids == 0) {
481b6e3d
AK
97 if (ruhs->nr_ruhs > FIO_MAX_DP_IDS)
98 ruhs->nr_ruhs = FIO_MAX_DP_IDS;
56d12245 99 } else {
56d12245
AK
100 for (i = 0; i < td->o.dp_nr_ids; i++) {
101 if (td->o.dp_ids[i] >= ruhs->nr_ruhs) {
481b6e3d
AK
102 log_err("fio: for %s PID index %d must be smaller than %d\n",
103 f->file_name, td->o.dp_ids[i],
104 ruhs->nr_ruhs);
56d12245
AK
105 ret = -EINVAL;
106 goto out;
107 }
108 }
109 ruhs->nr_ruhs = td->o.dp_nr_ids;
a7e8aae0
KB
110 }
111
112 tmp = scalloc(1, sizeof(*tmp) + ruhs->nr_ruhs * sizeof(*tmp->plis));
113 if (!tmp) {
114 ret = -ENOMEM;
115 goto out;
116 }
117
56d12245
AK
118 if (td->o.dp_nr_ids == 0) {
119 for (i = 0; i < ruhs->nr_ruhs; i++)
120 tmp->plis[i] = ruhs->plis[i];
121
122 tmp->nr_ruhs = ruhs->nr_ruhs;
123 f->ruhs_info = tmp;
124 free(ruhs);
125
126 return 0;
127 }
128
65ca6791
VF
129 tmp->nr_ruhs = td->o.dp_nr_ids;
130 for (i = 0; i < td->o.dp_nr_ids; i++)
131 tmp->plis[i] = ruhs->plis[td->o.dp_ids[i]];
a7e8aae0
KB
132 f->ruhs_info = tmp;
133out:
56d12245 134 free(ruhs);
a7e8aae0
KB
135 return ret;
136}
137
04d5add8
HP
138static int init_ruh_scheme(struct thread_data *td, struct fio_file *f)
139{
140 struct fio_ruhs_scheme *ruh_scheme;
141 FILE *scheme_fp;
142 unsigned long long start, end;
143 uint16_t pli;
144 int ret = 0;
145
146 if (td->o.dp_id_select != FIO_DP_SCHEME)
147 return 0;
148
149 /* Get the scheme from the file */
150 scheme_fp = fopen(td->o.dp_scheme_file, "r");
151
152 if (!scheme_fp) {
153 log_err("fio: ruh scheme failed to open scheme file %s\n",
6715cca2 154 td->o.dp_scheme_file);
04d5add8
HP
155 ret = -errno;
156 goto out;
157 }
158
159 ruh_scheme = scalloc(1, sizeof(*ruh_scheme));
160 if (!ruh_scheme) {
161 ret = -ENOMEM;
162 goto out_with_close_fp;
163 }
164
165 for (int i = 0;
166 i < DP_MAX_SCHEME_ENTRIES && fscanf(scheme_fp, "%llu,%llu,%hu\n", &start, &end, &pli) == 3;
167 i++) {
168
169 ruh_scheme->scheme_entries[i].start_offset = start;
170 ruh_scheme->scheme_entries[i].end_offset = end;
171 ruh_scheme->scheme_entries[i].pli = pli;
172 ruh_scheme->nr_schemes++;
173 }
174
175 if (fscanf(scheme_fp, "%llu,%llu,%hu\n", &start, &end, &pli) == 3)
176 log_info("fio: too many scheme entries in %s. Only the first %d scheme entries are applied\n",
177 td->o.dp_scheme_file,
178 DP_MAX_SCHEME_ENTRIES);
179
180 f->ruhs_scheme = ruh_scheme;
181
182out_with_close_fp:
183 fclose(scheme_fp);
184out:
185 return ret;
186}
187
c60d54ae 188int dp_init(struct thread_data *td)
a7e8aae0
KB
189{
190 struct fio_file *f;
191 int i, ret = 0;
192
193 for_each_file(td, f, i) {
194 ret = init_ruh_info(td, f);
195 if (ret)
196 break;
04d5add8
HP
197
198 ret = init_ruh_scheme(td, f);
199 if (ret)
200 break;
a7e8aae0
KB
201 }
202 return ret;
203}
204
205void fdp_free_ruhs_info(struct fio_file *f)
206{
207 if (!f->ruhs_info)
208 return;
209 sfree(f->ruhs_info);
210 f->ruhs_info = NULL;
04d5add8
HP
211
212 if (!f->ruhs_scheme)
213 return;
214 sfree(f->ruhs_scheme);
215 f->ruhs_scheme = NULL;
a7e8aae0
KB
216}
217
c60d54ae 218void dp_fill_dspec_data(struct thread_data *td, struct io_u *io_u)
a7e8aae0
KB
219{
220 struct fio_file *f = io_u->file;
221 struct fio_ruhs_info *ruhs = f->ruhs_info;
222 int dspec;
223
224 if (!ruhs || io_u->ddir != DDIR_WRITE) {
225 io_u->dtype = 0;
226 io_u->dspec = 0;
227 return;
228 }
229
65ca6791 230 if (td->o.dp_id_select == FIO_DP_RR) {
d3e310c5
AK
231 if (ruhs->pli_loc >= ruhs->nr_ruhs)
232 ruhs->pli_loc = 0;
233
234 dspec = ruhs->plis[ruhs->pli_loc++];
04d5add8
HP
235 } else if (td->o.dp_id_select == FIO_DP_SCHEME) {
236 struct fio_ruhs_scheme *ruhs_scheme = f->ruhs_scheme;
237 unsigned long long offset = io_u->offset;
238 int i;
239
240 for (i = 0; i < ruhs_scheme->nr_schemes; i++) {
241 if (offset >= ruhs_scheme->scheme_entries[i].start_offset &&
242 offset < ruhs_scheme->scheme_entries[i].end_offset) {
243 dspec = ruhs_scheme->scheme_entries[i].pli;
244 break;
245 }
246 }
247
248 /*
249 * If the write offset is not affected by any scheme entry,
250 * 0(default RUH) will be assigned to dspec
251 */
252 if (i == ruhs_scheme->nr_schemes)
253 dspec = 0;
d3e310c5
AK
254 } else {
255 ruhs->pli_loc = rand_between(&td->fdp_state, 0, ruhs->nr_ruhs - 1);
256 dspec = ruhs->plis[ruhs->pli_loc];
257 }
3b3c9877 258
1a3a21b7 259 io_u->dtype = td->o.dp_type == FIO_DP_FDP ? FDP_DIR_DTYPE : STREAMS_DIR_DTYPE;
a7e8aae0 260 io_u->dspec = dspec;
61d22139 261 dprint(FD_IO, "dtype set to 0x%x, dspec set to 0x%x\n", io_u->dtype, io_u->dspec);
a7e8aae0 262}