fio: add fdp support for io_uring_cmd nvme engine
[fio.git] / fdp.c
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>
12 #include "file.h"
13 #include "fio.h"
14
15 #include "pshared.h"
16 #include "fdp.h"
17
18 static int fdp_ruh_info(struct thread_data *td, struct fio_file *f,
19                         struct fio_ruhs_info *ruhs)
20 {
21         int ret = -EINVAL;
22
23         if (td->io_ops && td->io_ops->fdp_fetch_ruhs) {
24                 ret = td->io_ops->fdp_fetch_ruhs(td, f, ruhs);
25                 if (ret < 0) {
26                         td_verror(td, errno, "fdp fetch ruhs failed");
27                         log_err("%s: fdp fetch ruhs failed (%d)\n",
28                                 f->file_name, errno);
29                 }
30         } else
31                 log_err("%s: engine (%s) lacks fetch ruhs\n",
32                         f->file_name, td->io_ops->name);
33
34         return ret;
35 }
36
37 static int init_ruh_info(struct thread_data *td, struct fio_file *f)
38 {
39         struct fio_ruhs_info *ruhs, *tmp;
40         int i, ret;
41
42         ruhs = scalloc(1, sizeof(*ruhs) + 128 * sizeof(*ruhs->plis));
43         if (!ruhs)
44                 return -ENOMEM;
45
46         ret = fdp_ruh_info(td, f, ruhs);
47         if (ret) {
48                 log_info("fio: ruh info failed for %s (%d)\n",
49                          f->file_name, -ret);
50                 goto out;
51         }
52
53         if (ruhs->nr_ruhs > 128)
54                 ruhs->nr_ruhs = 128;
55
56         if (td->o.fdp_nrpli == 0) {
57                 f->ruhs_info = ruhs;
58                 return 0;
59         }
60
61         for (i = 0; i < td->o.fdp_nrpli; i++) {
62                 if (td->o.fdp_plis[i] > ruhs->nr_ruhs) {
63                         ret = -EINVAL;
64                         goto out;
65                 }
66         }
67
68         tmp = scalloc(1, sizeof(*tmp) + ruhs->nr_ruhs * sizeof(*tmp->plis));
69         if (!tmp) {
70                 ret = -ENOMEM;
71                 goto out;
72         }
73
74         tmp->nr_ruhs = td->o.fdp_nrpli;
75         for (i = 0; i < td->o.fdp_nrpli; i++)
76                 tmp->plis[i] = ruhs->plis[td->o.fdp_plis[i]];
77         f->ruhs_info = tmp;
78 out:
79         sfree(ruhs);
80         return ret;
81 }
82
83 int fdp_init(struct thread_data *td)
84 {
85         struct fio_file *f;
86         int i, ret = 0;
87
88         for_each_file(td, f, i) {
89                 ret = init_ruh_info(td, f);
90                 if (ret)
91                         break;
92         }
93         return ret;
94 }
95
96 void fdp_free_ruhs_info(struct fio_file *f)
97 {
98         if (!f->ruhs_info)
99                 return;
100         sfree(f->ruhs_info);
101         f->ruhs_info = NULL;
102 }
103
104 void fdp_fill_dspec_data(struct thread_data *td, struct io_u *io_u)
105 {
106         struct fio_file *f = io_u->file;
107         struct fio_ruhs_info *ruhs = f->ruhs_info;
108         int dspec;
109
110         if (!ruhs || io_u->ddir != DDIR_WRITE) {
111                 io_u->dtype = 0;
112                 io_u->dspec = 0;
113                 return;
114         }
115
116         dspec = ruhs->plis[ruhs->pli_loc++ % ruhs->nr_ruhs];
117         io_u->dtype = 2;
118         io_u->dspec = dspec;
119 }