Merge branch 'nvme/support-sync-fua-for-iouring-v2' of https://github.com/minwooim/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;
46 int i, ret;
47
98cd3c0e 48 ruhs = scalloc(1, sizeof(*ruhs) + FDP_MAX_RUHS * sizeof(*ruhs->plis));
a7e8aae0
KB
49 if (!ruhs)
50 return -ENOMEM;
51
1a3a21b7
VF
52 /* set up the data structure used for FDP to work with the supplied stream IDs */
53 if (td->o.dp_type == FIO_DP_STREAMS) {
54 if (!td->o.dp_nr_ids) {
55 log_err("fio: stream IDs must be provided for dataplacement=streams\n");
56 return -EINVAL;
57 }
58 ruhs->nr_ruhs = td->o.dp_nr_ids;
59 for (int i = 0; i < ruhs->nr_ruhs; i++)
60 ruhs->plis[i] = td->o.dp_ids[i];
61
62 f->ruhs_info = ruhs;
63 return 0;
64 }
65
a7e8aae0
KB
66 ret = fdp_ruh_info(td, f, ruhs);
67 if (ret) {
68 log_info("fio: ruh info failed for %s (%d)\n",
69 f->file_name, -ret);
70 goto out;
71 }
72
98cd3c0e
AK
73 if (ruhs->nr_ruhs > FDP_MAX_RUHS)
74 ruhs->nr_ruhs = FDP_MAX_RUHS;
a7e8aae0 75
65ca6791 76 if (td->o.dp_nr_ids == 0) {
a7e8aae0
KB
77 f->ruhs_info = ruhs;
78 return 0;
79 }
80
65ca6791
VF
81 for (i = 0; i < td->o.dp_nr_ids; i++) {
82 if (td->o.dp_ids[i] >= ruhs->nr_ruhs) {
a7e8aae0
KB
83 ret = -EINVAL;
84 goto out;
85 }
86 }
87
88 tmp = scalloc(1, sizeof(*tmp) + ruhs->nr_ruhs * sizeof(*tmp->plis));
89 if (!tmp) {
90 ret = -ENOMEM;
91 goto out;
92 }
93
65ca6791
VF
94 tmp->nr_ruhs = td->o.dp_nr_ids;
95 for (i = 0; i < td->o.dp_nr_ids; i++)
96 tmp->plis[i] = ruhs->plis[td->o.dp_ids[i]];
a7e8aae0
KB
97 f->ruhs_info = tmp;
98out:
99 sfree(ruhs);
100 return ret;
101}
102
04d5add8
HP
103static int init_ruh_scheme(struct thread_data *td, struct fio_file *f)
104{
105 struct fio_ruhs_scheme *ruh_scheme;
106 FILE *scheme_fp;
107 unsigned long long start, end;
108 uint16_t pli;
109 int ret = 0;
110
111 if (td->o.dp_id_select != FIO_DP_SCHEME)
112 return 0;
113
114 /* Get the scheme from the file */
115 scheme_fp = fopen(td->o.dp_scheme_file, "r");
116
117 if (!scheme_fp) {
118 log_err("fio: ruh scheme failed to open scheme file %s\n",
119 td->o.dp_scheme_file);
120 ret = -errno;
121 goto out;
122 }
123
124 ruh_scheme = scalloc(1, sizeof(*ruh_scheme));
125 if (!ruh_scheme) {
126 ret = -ENOMEM;
127 goto out_with_close_fp;
128 }
129
130 for (int i = 0;
131 i < DP_MAX_SCHEME_ENTRIES && fscanf(scheme_fp, "%llu,%llu,%hu\n", &start, &end, &pli) == 3;
132 i++) {
133
134 ruh_scheme->scheme_entries[i].start_offset = start;
135 ruh_scheme->scheme_entries[i].end_offset = end;
136 ruh_scheme->scheme_entries[i].pli = pli;
137 ruh_scheme->nr_schemes++;
138 }
139
140 if (fscanf(scheme_fp, "%llu,%llu,%hu\n", &start, &end, &pli) == 3)
141 log_info("fio: too many scheme entries in %s. Only the first %d scheme entries are applied\n",
142 td->o.dp_scheme_file,
143 DP_MAX_SCHEME_ENTRIES);
144
145 f->ruhs_scheme = ruh_scheme;
146
147out_with_close_fp:
148 fclose(scheme_fp);
149out:
150 return ret;
151}
152
c60d54ae 153int dp_init(struct thread_data *td)
a7e8aae0
KB
154{
155 struct fio_file *f;
156 int i, ret = 0;
157
158 for_each_file(td, f, i) {
159 ret = init_ruh_info(td, f);
160 if (ret)
161 break;
04d5add8
HP
162
163 ret = init_ruh_scheme(td, f);
164 if (ret)
165 break;
a7e8aae0
KB
166 }
167 return ret;
168}
169
170void fdp_free_ruhs_info(struct fio_file *f)
171{
172 if (!f->ruhs_info)
173 return;
174 sfree(f->ruhs_info);
175 f->ruhs_info = NULL;
04d5add8
HP
176
177 if (!f->ruhs_scheme)
178 return;
179 sfree(f->ruhs_scheme);
180 f->ruhs_scheme = NULL;
a7e8aae0
KB
181}
182
c60d54ae 183void dp_fill_dspec_data(struct thread_data *td, struct io_u *io_u)
a7e8aae0
KB
184{
185 struct fio_file *f = io_u->file;
186 struct fio_ruhs_info *ruhs = f->ruhs_info;
187 int dspec;
188
189 if (!ruhs || io_u->ddir != DDIR_WRITE) {
190 io_u->dtype = 0;
191 io_u->dspec = 0;
192 return;
193 }
194
65ca6791 195 if (td->o.dp_id_select == FIO_DP_RR) {
d3e310c5
AK
196 if (ruhs->pli_loc >= ruhs->nr_ruhs)
197 ruhs->pli_loc = 0;
198
199 dspec = ruhs->plis[ruhs->pli_loc++];
04d5add8
HP
200 } else if (td->o.dp_id_select == FIO_DP_SCHEME) {
201 struct fio_ruhs_scheme *ruhs_scheme = f->ruhs_scheme;
202 unsigned long long offset = io_u->offset;
203 int i;
204
205 for (i = 0; i < ruhs_scheme->nr_schemes; i++) {
206 if (offset >= ruhs_scheme->scheme_entries[i].start_offset &&
207 offset < ruhs_scheme->scheme_entries[i].end_offset) {
208 dspec = ruhs_scheme->scheme_entries[i].pli;
209 break;
210 }
211 }
212
213 /*
214 * If the write offset is not affected by any scheme entry,
215 * 0(default RUH) will be assigned to dspec
216 */
217 if (i == ruhs_scheme->nr_schemes)
218 dspec = 0;
d3e310c5
AK
219 } else {
220 ruhs->pli_loc = rand_between(&td->fdp_state, 0, ruhs->nr_ruhs - 1);
221 dspec = ruhs->plis[ruhs->pli_loc];
222 }
3b3c9877 223
1a3a21b7 224 io_u->dtype = td->o.dp_type == FIO_DP_FDP ? FDP_DIR_DTYPE : STREAMS_DIR_DTYPE;
a7e8aae0 225 io_u->dspec = dspec;
61d22139 226 dprint(FD_IO, "dtype set to 0x%x, dspec set to 0x%x\n", io_u->dtype, io_u->dspec);
a7e8aae0 227}