1 /*
2 * glusterfs engine
3 *
4 * common Glusterfs's gfapi interface
5 *
6 */
7
8 #include "gfapi.h"
9
10 struct fio_option gfapi_options[] = {
11 {
12 .name = "volume",
13 .lname = "Glusterfs volume",
14 .type = FIO_OPT_STR_STORE,
15 .help = "Name of the Glusterfs volume",
16 .off1 = offsetof(struct gf_options, gf_vol),
17 .category = FIO_OPT_C_ENGINE,
18 .group = FIO_OPT_G_GFAPI,
19 },
20 {
21 .name = "brick",
22 .lname = "Glusterfs brick name",
23 .type = FIO_OPT_STR_STORE,
24 .help = "Name of the Glusterfs brick to connect",
25 .off1 = offsetof(struct gf_options, gf_brick),
26 .category = FIO_OPT_C_ENGINE,
27 .group = FIO_OPT_G_GFAPI,
28 },
29 {
30 .name = NULL,
31 },
32 };
33
fio_gf_setup(struct thread_data * td)34 int fio_gf_setup(struct thread_data *td)
35 {
36 int r = 0;
37 struct gf_data *g = NULL;
38 struct gf_options *opt = td->eo;
39 struct stat sb = { 0, };
40
41 dprint(FD_IO, "fio setup\n");
42
43 if (td->io_ops->data)
44 return 0;
45
46 g = malloc(sizeof(struct gf_data));
47 if (!g) {
48 log_err("malloc failed.\n");
49 return -ENOMEM;
50 }
51 g->fs = NULL;
52 g->fd = NULL;
53 g->aio_events = NULL;
54
55 g->fs = glfs_new(opt->gf_vol);
56 if (!g->fs) {
57 log_err("glfs_new failed.\n");
58 goto cleanup;
59 }
60 glfs_set_logging(g->fs, "/tmp/fio_gfapi.log", 7);
61 /* default to tcp */
62 r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 0);
63 if (r) {
64 log_err("glfs_set_volfile_server failed.\n");
65 goto cleanup;
66 }
67 r = glfs_init(g->fs);
68 if (r) {
69 log_err("glfs_init failed. Is glusterd running on brick?\n");
70 goto cleanup;
71 }
72 sleep(2);
73 r = glfs_lstat(g->fs, ".", &sb);
74 if (r) {
75 log_err("glfs_lstat failed.\n");
76 goto cleanup;
77 }
78 dprint(FD_FILE, "fio setup %p\n", g->fs);
79 td->io_ops->data = g;
80 return 0;
81 cleanup:
82 if (g->fs)
83 glfs_fini(g->fs);
84 free(g);
85 td->io_ops->data = NULL;
86 return r;
87 }
88
fio_gf_cleanup(struct thread_data * td)89 void fio_gf_cleanup(struct thread_data *td)
90 {
91 struct gf_data *g = td->io_ops->data;
92
93 if (g) {
94 if (g->aio_events)
95 free(g->aio_events);
96 if (g->fd)
97 glfs_close(g->fd);
98 if (g->fs)
99 glfs_fini(g->fs);
100 free(g);
101 td->io_ops->data = NULL;
102 }
103 }
104
fio_gf_get_file_size(struct thread_data * td,struct fio_file * f)105 int fio_gf_get_file_size(struct thread_data *td, struct fio_file *f)
106 {
107 struct stat buf;
108 int ret;
109 struct gf_data *g = td->io_ops->data;
110
111 dprint(FD_FILE, "get file size %s\n", f->file_name);
112
113 if (!g || !g->fs) {
114 return 0;
115 }
116 if (fio_file_size_known(f))
117 return 0;
118
119 ret = glfs_lstat(g->fs, f->file_name, &buf);
120 if (ret < 0) {
121 log_err("glfs_lstat failed.\n");
122 return ret;
123 }
124
125 f->real_file_size = buf.st_size;
126 fio_file_set_size_known(f);
127
128 return 0;
129
130 }
131
fio_gf_open_file(struct thread_data * td,struct fio_file * f)132 int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
133 {
134
135 int flags = 0;
136 int ret = 0;
137 struct gf_data *g = td->io_ops->data;
138 struct stat sb = { 0, };
139
140 if (td_write(td)) {
141 if (!read_only)
142 flags = O_RDWR;
143 } else if (td_read(td)) {
144 if (!read_only)
145 flags = O_RDWR;
146 else
147 flags = O_RDONLY;
148 }
149
150 if (td->o.odirect)
151 flags |= OS_O_DIRECT;
152 if (td->o.sync_io)
153 flags |= O_SYNC;
154
155 dprint(FD_FILE, "fio file %s open mode %s td rw %s\n", f->file_name,
156 flags & O_RDONLY ? "ro" : "rw", td_read(td) ? "read" : "write");
157 g->fd = glfs_creat(g->fs, f->file_name, flags, 0644);
158 if (!g->fd) {
159 ret = errno;
160 log_err("glfs_creat failed.\n");
161 return ret;
162 }
163 /* file for read doesn't exist or shorter than required, create/extend it */
164 if (td_read(td)) {
165 if (glfs_lstat(g->fs, f->file_name, &sb)
166 || sb.st_size < f->real_file_size) {
167 dprint(FD_FILE, "fio extend file %s from %ld to %ld\n",
168 f->file_name, sb.st_size, f->real_file_size);
169 ret = glfs_ftruncate(g->fd, f->real_file_size);
170 if (ret) {
171 log_err("failed fio extend file %s to %ld\n",
172 f->file_name, f->real_file_size);
173 } else {
174 unsigned long long left;
175 unsigned int bs;
176 char *b;
177 int r;
178
179 /* fill the file, copied from extend_file */
180 b = malloc(td->o.max_bs[DDIR_WRITE]);
181
182 left = f->real_file_size;
183 while (left && !td->terminate) {
184 bs = td->o.max_bs[DDIR_WRITE];
185 if (bs > left)
186 bs = left;
187
188 fill_io_buffer(td, b, bs, bs);
189
190 r = glfs_write(g->fd, b, bs, 0);
191 dprint(FD_IO,
192 "fio write %d of %ld file %s\n",
193 r, f->real_file_size,
194 f->file_name);
195
196 if (r > 0) {
197 left -= r;
198 continue;
199 } else {
200 if (r < 0) {
201 int __e = errno;
202
203 if (__e == ENOSPC) {
204 if (td->o.
205 fill_device)
206 break;
207 log_info
208 ("fio: ENOSPC on laying out "
209 "file, stopping\n");
210 break;
211 }
212 td_verror(td, errno,
213 "write");
214 } else
215 td_verror(td, EIO,
216 "write");
217
218 break;
219 }
220 }
221
222 if (b)
223 free(b);
224 glfs_lseek(g->fd, 0, SEEK_SET);
225
226 if (td->terminate && td->o.unlink) {
227 dprint(FD_FILE, "terminate unlink %s\n",
228 f->file_name);
229 glfs_unlink(g->fs, f->file_name);
230 } else if (td->o.create_fsync) {
231 if (glfs_fsync(g->fd) < 0) {
232 dprint(FD_FILE,
233 "failed to sync, close %s\n",
234 f->file_name);
235 td_verror(td, errno, "fsync");
236 glfs_close(g->fd);
237 g->fd = NULL;
238 return 1;
239 }
240 }
241 }
242 }
243 }
244 #if defined(GFAPI_USE_FADVISE)
245 {
246 int r = 0;
247 if (td_random(td)) {
248 r = glfs_fadvise(g->fd, 0, f->real_file_size,
249 POSIX_FADV_RANDOM);
250 } else {
251 r = glfs_fadvise(g->fd, 0, f->real_file_size,
252 POSIX_FADV_SEQUENTIAL);
253 }
254 if (r) {
255 dprint(FD_FILE, "fio %p fadvise %s status %d\n", g->fs,
256 f->file_name, r);
257 }
258 }
259 #endif
260 dprint(FD_FILE, "fio %p created %s\n", g->fs, f->file_name);
261 f->fd = -1;
262 f->shadow_fd = -1;
263 td->o.open_files ++;
264 return ret;
265 }
266
fio_gf_close_file(struct thread_data * td,struct fio_file * f)267 int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
268 {
269 int ret = 0;
270 struct gf_data *g = td->io_ops->data;
271
272 dprint(FD_FILE, "fd close %s\n", f->file_name);
273
274 if (g) {
275 if (g->fd && glfs_close(g->fd) < 0)
276 ret = errno;
277 g->fd = NULL;
278 }
279
280 return ret;
281 }
282
fio_gf_unlink_file(struct thread_data * td,struct fio_file * f)283 int fio_gf_unlink_file(struct thread_data *td, struct fio_file *f)
284 {
285 int ret = 0;
286 struct gf_data *g = td->io_ops->data;
287
288 dprint(FD_FILE, "fd unlink %s\n", f->file_name);
289
290 if (g) {
291 if (g->fd && glfs_close(g->fd) < 0)
292 ret = errno;
293
294 glfs_unlink(g->fs, f->file_name);
295
296 if (g->fs)
297 glfs_fini(g->fs);
298
299 g->fd = NULL;
300 free(g);
301 }
302 td->io_ops->data = NULL;
303
304 return ret;
305 }
306