Commit | Line | Data |
---|---|---|
cc47f094 | 1 | /* |
2 | * glusterfs engine | |
3 | * | |
4 | * IO engine using Glusterfs's gfapi async interface | |
5 | * | |
6 | */ | |
7 | #include "gfapi.h" | |
88db2717 | 8 | #define NOT_YET 1 |
cc47f094 | 9 | struct fio_gf_iou { |
10 | struct io_u *io_u; | |
11 | int io_complete; | |
12 | }; | |
6fa14b99 | 13 | static ulong cb_count = 0, issued = 0; |
cc47f094 | 14 | |
15 | static struct io_u *fio_gf_event(struct thread_data *td, int event) | |
16 | { | |
17 | struct gf_data *gf_data = td->io_ops->data; | |
18 | dprint(FD_IO, "%s\n", __FUNCTION__); | |
19 | return gf_data->aio_events[event]; | |
20 | } | |
21 | ||
22 | static int fio_gf_getevents(struct thread_data *td, unsigned int min, | |
1f440ece | 23 | unsigned int max, const struct timespec *t) |
cc47f094 | 24 | { |
25 | struct gf_data *g = td->io_ops->data; | |
26 | unsigned int events = 0; | |
27 | struct io_u *io_u; | |
28 | int i = 0; | |
29 | struct fio_gf_iou *io = NULL; | |
30 | ||
31 | dprint(FD_IO, "%s\n", __FUNCTION__); | |
32 | do { | |
33 | io_u_qiter(&td->io_u_all, io_u, i) { | |
34 | if (!(io_u->flags & IO_U_F_FLIGHT)) | |
35 | continue; | |
36 | ||
37 | io = (struct fio_gf_iou *)io_u->engine_data; | |
38 | ||
39 | if (io && io->io_complete) { | |
40 | io->io_complete = 0; | |
41 | g->aio_events[events] = io_u; | |
42 | events++; | |
88db2717 | 43 | |
b29c813f JA |
44 | if (events >= max) |
45 | break; | |
cc47f094 | 46 | } |
47 | ||
48 | } | |
49 | if (events < min) | |
6fa14b99 | 50 | usleep(100); |
cc47f094 | 51 | else |
52 | break; | |
53 | ||
54 | } while (1); | |
55 | ||
56 | return events; | |
57 | } | |
58 | ||
88db2717 | 59 | static void fio_gf_io_u_free(struct thread_data *td, struct io_u *io_u) |
cc47f094 | 60 | { |
88db2717 | 61 | struct fio_gf_iou *io = io_u->engine_data; |
62 | ||
63 | if (io) { | |
b29c813f JA |
64 | if (io->io_complete) { |
65 | log_err("incomplete IO found.\n"); | |
66 | } | |
88db2717 | 67 | io_u->engine_data = NULL; |
68 | free(io); | |
69 | } | |
7d4a8e7e | 70 | log_err("issued %lu finished %lu\n", issued, cb_count); |
88db2717 | 71 | } |
cc47f094 | 72 | |
88db2717 | 73 | static int fio_gf_io_u_init(struct thread_data *td, struct io_u *io_u) |
74 | { | |
75 | struct fio_gf_iou *io = NULL; | |
cc47f094 | 76 | |
88db2717 | 77 | dprint(FD_FILE, "%s\n", __FUNCTION__); |
78 | ||
b29c813f JA |
79 | if (!io_u->engine_data) { |
80 | io = malloc(sizeof(struct fio_gf_iou)); | |
81 | if (!io) { | |
82 | td_verror(td, errno, "malloc"); | |
83 | return 1; | |
84 | } | |
85 | io->io_complete = 0; | |
86 | io->io_u = io_u; | |
87 | io_u->engine_data = io; | |
88 | } | |
cc47f094 | 89 | return 0; |
90 | } | |
91 | ||
b29c813f | 92 | static void gf_async_cb(glfs_fd_t * fd, ssize_t ret, void *data) |
cc47f094 | 93 | { |
94 | struct io_u *io_u = (struct io_u *)data; | |
b29c813f | 95 | struct fio_gf_iou *iou = (struct fio_gf_iou *)io_u->engine_data; |
cc47f094 | 96 | |
b29c813f JA |
97 | dprint(FD_IO, "%s ret %lu\n", __FUNCTION__, ret); |
98 | iou->io_complete = 1; | |
99 | cb_count++; | |
cc47f094 | 100 | } |
101 | ||
b29c813f JA |
102 | static int fio_gf_async_queue(struct thread_data fio_unused * td, |
103 | struct io_u *io_u) | |
cc47f094 | 104 | { |
105 | struct gf_data *g = td->io_ops->data; | |
b29c813f | 106 | int r = 0; |
cc47f094 | 107 | |
b29c813f JA |
108 | dprint(FD_IO, "%s op %s\n", __FUNCTION__, |
109 | io_u->ddir == DDIR_READ ? "read" : io_u->ddir == | |
110 | DDIR_WRITE ? "write" : io_u->ddir == | |
111 | DDIR_SYNC ? "sync" : "unknown"); | |
88db2717 | 112 | |
cc47f094 | 113 | fio_ro_check(td, io_u); |
114 | ||
115 | if (io_u->ddir == DDIR_READ) | |
b29c813f JA |
116 | r = glfs_pread_async(g->fd, io_u->xfer_buf, io_u->xfer_buflen, |
117 | io_u->offset, 0, gf_async_cb, | |
118 | (void *)io_u); | |
cc47f094 | 119 | else if (io_u->ddir == DDIR_WRITE) |
b29c813f JA |
120 | r = glfs_pwrite_async(g->fd, io_u->xfer_buf, io_u->xfer_buflen, |
121 | io_u->offset, 0, gf_async_cb, | |
122 | (void *)io_u); | |
123 | else if (io_u->ddir == DDIR_SYNC) { | |
124 | r = glfs_fsync_async(g->fd, gf_async_cb, (void *)io_u); | |
125 | } else { | |
126 | log_err("unsupported operation.\n"); | |
127 | io_u->error = -EINVAL; | |
128 | goto failed; | |
129 | } | |
130 | if (r) { | |
131 | log_err("glfs failed.\n"); | |
132 | io_u->error = r; | |
133 | goto failed; | |
134 | } | |
135 | issued++; | |
cc47f094 | 136 | return FIO_Q_QUEUED; |
137 | ||
138 | failed: | |
139 | io_u->error = r; | |
140 | td_verror(td, io_u->error, "xfer"); | |
141 | return FIO_Q_COMPLETED; | |
142 | } | |
143 | ||
88db2717 | 144 | int fio_gf_async_setup(struct thread_data *td) |
145 | { | |
146 | int r = 0; | |
147 | struct gf_data *g = NULL; | |
7d4a8e7e | 148 | |
88db2717 | 149 | #if defined(NOT_YET) |
7d4a8e7e | 150 | log_err("the async interface is still very experimental...\n"); |
88db2717 | 151 | #endif |
b29c813f JA |
152 | r = fio_gf_setup(td); |
153 | if (r) { | |
154 | return r; | |
155 | } | |
6fa14b99 | 156 | td->o.use_thread = 1; |
b29c813f JA |
157 | g = td->io_ops->data; |
158 | g->aio_events = malloc(td->o.iodepth * sizeof(struct io_u *)); | |
159 | if (!g->aio_events) { | |
160 | r = -ENOMEM; | |
161 | fio_gf_cleanup(td); | |
162 | return r; | |
163 | } | |
88db2717 | 164 | |
165 | memset(g->aio_events, 0, td->o.iodepth * sizeof(struct io_u *)); | |
166 | ||
b29c813f | 167 | return r; |
88db2717 | 168 | |
169 | } | |
170 | ||
171 | static int fio_gf_async_prep(struct thread_data *td, struct io_u *io_u) | |
172 | { | |
173 | dprint(FD_FILE, "%s\n", __FUNCTION__); | |
174 | ||
175 | if (!ddir_rw(io_u->ddir)) | |
176 | return 0; | |
177 | ||
178 | return 0; | |
179 | } | |
cc47f094 | 180 | |
181 | static struct ioengine_ops ioengine = { | |
b29c813f JA |
182 | .name = "gfapi_async", |
183 | .version = FIO_IOOPS_VERSION, | |
184 | .init = fio_gf_async_setup, | |
185 | .cleanup = fio_gf_cleanup, | |
186 | .prep = fio_gf_async_prep, | |
187 | .queue = fio_gf_async_queue, | |
188 | .open_file = fio_gf_open_file, | |
189 | .close_file = fio_gf_close_file, | |
38ef9c90 | 190 | .unlink_file = fio_gf_unlink_file, |
b29c813f JA |
191 | .get_file_size = fio_gf_get_file_size, |
192 | .getevents = fio_gf_getevents, | |
193 | .event = fio_gf_event, | |
194 | .io_u_init = fio_gf_io_u_init, | |
195 | .io_u_free = fio_gf_io_u_free, | |
196 | .options = gfapi_options, | |
cc47f094 | 197 | .option_struct_size = sizeof(struct gf_options), |
b29c813f | 198 | .flags = FIO_DISKLESSIO, |
cc47f094 | 199 | }; |
200 | ||
201 | static void fio_init fio_gf_register(void) | |
202 | { | |
b29c813f | 203 | register_ioengine(&ioengine); |
cc47f094 | 204 | } |
205 | ||
206 | static void fio_exit fio_gf_unregister(void) | |
207 | { | |
b29c813f | 208 | unregister_ioengine(&ioengine); |
cc47f094 | 209 | } |