docs: move rate_cycle description
[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 "fio.h"
13 #include "file.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) {
24                 log_err("fio: no ops set in fdp init?!\n");
25                 return ret;
26         }
27
28         if (td->io_ops->fdp_fetch_ruhs) {
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                 }
35         } else {
36                 log_err("%s: engine (%s) lacks fetch ruhs\n",
37                         f->file_name, td->io_ops->name);
38         }
39
40         return ret;
41 }
42
43 static 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
48         ruhs = scalloc(1, sizeof(*ruhs) + 128 * sizeof(*ruhs->plis));
49         if (!ruhs)
50                 return -ENOMEM;
51
52         ret = fdp_ruh_info(td, f, ruhs);
53         if (ret) {
54                 log_info("fio: ruh info failed for %s (%d)\n",
55                          f->file_name, -ret);
56                 goto out;
57         }
58
59         if (ruhs->nr_ruhs > 128)
60                 ruhs->nr_ruhs = 128;
61
62         if (td->o.fdp_nrpli == 0) {
63                 f->ruhs_info = ruhs;
64                 return 0;
65         }
66
67         for (i = 0; i < td->o.fdp_nrpli; i++) {
68                 if (td->o.fdp_plis[i] > ruhs->nr_ruhs) {
69                         ret = -EINVAL;
70                         goto out;
71                 }
72         }
73
74         tmp = scalloc(1, sizeof(*tmp) + ruhs->nr_ruhs * sizeof(*tmp->plis));
75         if (!tmp) {
76                 ret = -ENOMEM;
77                 goto out;
78         }
79
80         tmp->nr_ruhs = td->o.fdp_nrpli;
81         for (i = 0; i < td->o.fdp_nrpli; i++)
82                 tmp->plis[i] = ruhs->plis[td->o.fdp_plis[i]];
83         f->ruhs_info = tmp;
84 out:
85         sfree(ruhs);
86         return ret;
87 }
88
89 int fdp_init(struct thread_data *td)
90 {
91         struct fio_file *f;
92         int i, ret = 0;
93
94         for_each_file(td, f, i) {
95                 ret = init_ruh_info(td, f);
96                 if (ret)
97                         break;
98         }
99         return ret;
100 }
101
102 void fdp_free_ruhs_info(struct fio_file *f)
103 {
104         if (!f->ruhs_info)
105                 return;
106         sfree(f->ruhs_info);
107         f->ruhs_info = NULL;
108 }
109
110 void fdp_fill_dspec_data(struct thread_data *td, struct io_u *io_u)
111 {
112         struct fio_file *f = io_u->file;
113         struct fio_ruhs_info *ruhs = f->ruhs_info;
114         int dspec;
115
116         if (!ruhs || io_u->ddir != DDIR_WRITE) {
117                 io_u->dtype = 0;
118                 io_u->dspec = 0;
119                 return;
120         }
121
122         if (ruhs->pli_loc >= ruhs->nr_ruhs)
123                 ruhs->pli_loc = 0;
124
125         dspec = ruhs->plis[ruhs->pli_loc++];
126         io_u->dtype = 2;
127         io_u->dspec = dspec;
128 }