glusterfs: update for new API
[fio.git] / engines / glusterfs.c
CommitLineData
6e7d7dfb 1/*
2 * glusterfs engine
3 *
cc47f094 4 * common Glusterfs's gfapi interface
6e7d7dfb 5 *
6 */
7
cc47f094 8#include "gfapi.h"
d220c761 9#include "../optgroup.h"
6e7d7dfb 10
cc47f094 11struct fio_option gfapi_options[] = {
b29c813f
JA
12 {
13 .name = "volume",
14 .lname = "Glusterfs volume",
15 .type = FIO_OPT_STR_STORE,
16 .help = "Name of the Glusterfs volume",
17 .off1 = offsetof(struct gf_options, gf_vol),
18 .category = FIO_OPT_C_ENGINE,
19 .group = FIO_OPT_G_GFAPI,
20 },
21 {
22 .name = "brick",
23 .lname = "Glusterfs brick name",
24 .type = FIO_OPT_STR_STORE,
25 .help = "Name of the Glusterfs brick to connect",
26 .off1 = offsetof(struct gf_options, gf_brick),
27 .category = FIO_OPT_C_ENGINE,
28 .group = FIO_OPT_G_GFAPI,
29 },
53c508dd
ZH
30 {
31 .name = "single-instance",
32 .lname = "Single glusterfs instance",
33 .type = FIO_OPT_BOOL,
34 .help = "Only one glusterfs instance",
35 .off1 = offsetof(struct gf_options, gf_single_instance),
36 .category = FIO_OPT_C_ENGINE,
37 .group = FIO_OPT_G_GFAPI,
38 },
b29c813f
JA
39 {
40 .name = NULL,
41 },
6e7d7dfb 42};
43
53c508dd
ZH
44struct glfs_info {
45 struct flist_head list;
46 char *volume;
47 char *brick;
48 glfs_t *fs;
49 int refcount;
50};
51
52static pthread_mutex_t glfs_lock = PTHREAD_MUTEX_INITIALIZER;
53static FLIST_HEAD(glfs_list_head);
54
55static glfs_t *fio_gf_new_fs(char *volume, char *brick)
6e7d7dfb 56{
57 int r = 0;
53c508dd
ZH
58 glfs_t *fs;
59 struct stat sb = { 0, };
60
61 fs = glfs_new(volume);
62 if (!fs) {
63 log_err("glfs_new failed.\n");
64 goto out;
65 }
66 glfs_set_logging(fs, "/tmp/fio_gfapi.log", 7);
67 /* default to tcp */
68 r = glfs_set_volfile_server(fs, "tcp", brick, 0);
69 if (r) {
70 log_err("glfs_set_volfile_server failed.\n");
71 goto out;
72 }
73 r = glfs_init(fs);
74 if (r) {
75 log_err("glfs_init failed. Is glusterd running on brick?\n");
76 goto out;
77 }
78 sleep(2);
79 r = glfs_lstat(fs, ".", &sb);
80 if (r) {
81 log_err("glfs_lstat failed.\n");
82 goto out;
83 }
84
85out:
86 if (r) {
87 glfs_fini(fs);
88 fs = NULL;
89 }
90 return fs;
91}
92
93static glfs_t *fio_gf_get_glfs(struct gf_options *opt,
94 char *volume, char *brick)
95{
96 struct glfs_info *glfs = NULL;
97 struct glfs_info *tmp;
98 struct flist_head *entry;
99
100 if (!opt->gf_single_instance)
101 return fio_gf_new_fs(volume, brick);
102
103 pthread_mutex_lock (&glfs_lock);
104
105 flist_for_each(entry, &glfs_list_head) {
106 tmp = flist_entry(entry, struct glfs_info, list);
107 if (!strcmp(volume, tmp->volume) &&
108 !strcmp(brick, tmp->brick)) {
109 glfs = tmp;
110 break;
111 }
112 }
113
114 if (glfs) {
115 glfs->refcount++;
116 } else {
117 glfs = malloc(sizeof(*glfs));
118 if (!glfs)
119 goto out;
120 INIT_FLIST_HEAD(&glfs->list);
121 glfs->refcount = 0;
122 glfs->volume = strdup(volume);
123 glfs->brick = strdup(brick);
124 glfs->fs = fio_gf_new_fs(volume, brick);
125 if (!glfs->fs) {
126 free(glfs);
127 glfs = NULL;
128 goto out;
129 }
130
131 flist_add_tail(&glfs->list, &glfs_list_head);
132 glfs->refcount = 1;
133 }
134
135out:
136 pthread_mutex_unlock (&glfs_lock);
137
138 if (glfs)
139 return glfs->fs;
140 return NULL;
141}
142
143static void fio_gf_put_glfs(struct gf_options *opt, glfs_t *fs)
144{
145 struct glfs_info *glfs = NULL;
146 struct glfs_info *tmp;
147 struct flist_head *entry;
148
149 if (!opt->gf_single_instance) {
150 glfs_fini(fs);
151 return;
152 }
153
154 pthread_mutex_lock (&glfs_lock);
155
156 flist_for_each(entry, &glfs_list_head) {
157 tmp = flist_entry(entry, struct glfs_info, list);
158 if (tmp->fs == fs) {
159 glfs = tmp;
160 break;
161 }
162 }
163
164 if (!glfs) {
165 log_err("glfs not found to fini.\n");
166 } else {
167 glfs->refcount--;
168
169 if (glfs->refcount == 0) {
170 glfs_fini(glfs->fs);
171 free(glfs->volume);
172 free(glfs->brick);
173 flist_del(&glfs->list);
174 }
175 }
176
177 pthread_mutex_unlock (&glfs_lock);
178}
179
180int fio_gf_setup(struct thread_data *td)
181{
6e7d7dfb 182 struct gf_data *g = NULL;
183 struct gf_options *opt = td->eo;
7cb57176 184
185 dprint(FD_IO, "fio setup\n");
6e7d7dfb 186
565e784d 187 if (td->io_ops_data)
b29c813f 188 return 0;
6e7d7dfb 189
190 g = malloc(sizeof(struct gf_data));
b29c813f
JA
191 if (!g) {
192 log_err("malloc failed.\n");
193 return -ENOMEM;
6e7d7dfb 194 }
b29c813f
JA
195 g->fd = NULL;
196 g->aio_events = NULL;
197
53c508dd
ZH
198 g->fs = fio_gf_get_glfs(opt, opt->gf_vol, opt->gf_brick);
199 if (!g->fs)
b29c813f 200 goto cleanup;
53c508dd 201
7cb57176 202 dprint(FD_FILE, "fio setup %p\n", g->fs);
565e784d 203 td->io_ops_data = g;
93782cbb 204 return 0;
6e7d7dfb 205cleanup:
93782cbb 206 free(g);
565e784d 207 td->io_ops_data = NULL;
53c508dd 208 return -EIO;
6e7d7dfb 209}
210
cc47f094 211void fio_gf_cleanup(struct thread_data *td)
6e7d7dfb 212{
565e784d 213 struct gf_data *g = td->io_ops_data;
cc47f094 214
215 if (g) {
b29c813f
JA
216 if (g->aio_events)
217 free(g->aio_events);
218 if (g->fd)
219 glfs_close(g->fd);
220 if (g->fs)
53c508dd 221 fio_gf_put_glfs(td->eo, g->fs);
b29c813f 222 free(g);
565e784d 223 td->io_ops_data = NULL;
cc47f094 224 }
6e7d7dfb 225}
226
cc47f094 227int fio_gf_get_file_size(struct thread_data *td, struct fio_file *f)
6e7d7dfb 228{
b29c813f
JA
229 struct stat buf;
230 int ret;
565e784d 231 struct gf_data *g = td->io_ops_data;
6e7d7dfb 232
b29c813f 233 dprint(FD_FILE, "get file size %s\n", f->file_name);
6aa56500 234
b29c813f
JA
235 if (!g || !g->fs) {
236 return 0;
237 }
238 if (fio_file_size_known(f))
239 return 0;
6e7d7dfb 240
b29c813f
JA
241 ret = glfs_lstat(g->fs, f->file_name, &buf);
242 if (ret < 0) {
243 log_err("glfs_lstat failed.\n");
244 return ret;
245 }
6e7d7dfb 246
b29c813f
JA
247 f->real_file_size = buf.st_size;
248 fio_file_set_size_known(f);
6e7d7dfb 249
b29c813f 250 return 0;
6e7d7dfb 251
252}
253
cc47f094 254int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
6e7d7dfb 255{
a8a93dee 256
b29c813f
JA
257 int flags = 0;
258 int ret = 0;
565e784d 259 struct gf_data *g = td->io_ops_data;
b29c813f
JA
260 struct stat sb = { 0, };
261
262 if (td_write(td)) {
263 if (!read_only)
264 flags = O_RDWR;
265 } else if (td_read(td)) {
266 if (!read_only)
267 flags = O_RDWR;
268 else
269 flags = O_RDONLY;
270 }
65bea10f
TM
271
272 if (td->o.odirect)
273 flags |= OS_O_DIRECT;
274 if (td->o.sync_io)
275 flags |= O_SYNC;
276
b29c813f 277 dprint(FD_FILE, "fio file %s open mode %s td rw %s\n", f->file_name,
65bea10f 278 flags & O_RDONLY ? "ro" : "rw", td_read(td) ? "read" : "write");
b29c813f
JA
279 g->fd = glfs_creat(g->fs, f->file_name, flags, 0644);
280 if (!g->fd) {
b29c813f 281 ret = errno;
1a889967
TM
282 log_err("glfs_creat failed.\n");
283 return ret;
b29c813f
JA
284 }
285 /* file for read doesn't exist or shorter than required, create/extend it */
286 if (td_read(td)) {
287 if (glfs_lstat(g->fs, f->file_name, &sb)
288 || sb.st_size < f->real_file_size) {
f6149216
SW
289 dprint(FD_FILE, "fio extend file %s from %jd to %" PRIu64 "\n",
290 f->file_name, (intmax_t) sb.st_size, f->real_file_size);
ce4d13ca
JA
291#if defined(CONFIG_GF_NEW_API)
292 ret = glfs_ftruncate(g->fd, f->real_file_size, NULL, NULL);
293#else
b29c813f 294 ret = glfs_ftruncate(g->fd, f->real_file_size);
ce4d13ca 295#endif
b29c813f 296 if (ret) {
f6149216 297 log_err("failed fio extend file %s to %" PRIu64 "\n",
b29c813f
JA
298 f->file_name, f->real_file_size);
299 } else {
300 unsigned long long left;
301 unsigned int bs;
302 char *b;
303 int r;
304
305 /* fill the file, copied from extend_file */
306 b = malloc(td->o.max_bs[DDIR_WRITE]);
307
308 left = f->real_file_size;
309 while (left && !td->terminate) {
310 bs = td->o.max_bs[DDIR_WRITE];
311 if (bs > left)
312 bs = left;
313
314 fill_io_buffer(td, b, bs, bs);
315
316 r = glfs_write(g->fd, b, bs, 0);
317 dprint(FD_IO,
f6149216 318 "fio write %d of %" PRIu64 " file %s\n",
b29c813f
JA
319 r, f->real_file_size,
320 f->file_name);
321
322 if (r > 0) {
323 left -= r;
324 continue;
325 } else {
326 if (r < 0) {
327 int __e = errno;
328
329 if (__e == ENOSPC) {
330 if (td->o.
331 fill_device)
332 break;
333 log_info
334 ("fio: ENOSPC on laying out "
335 "file, stopping\n");
336 break;
337 }
338 td_verror(td, errno,
339 "write");
340 } else
341 td_verror(td, EIO,
342 "write");
343
344 break;
345 }
346 }
347
348 if (b)
349 free(b);
350 glfs_lseek(g->fd, 0, SEEK_SET);
351
38ef9c90 352 if (td->terminate && td->o.unlink) {
b29c813f
JA
353 dprint(FD_FILE, "terminate unlink %s\n",
354 f->file_name);
38ef9c90 355 glfs_unlink(g->fs, f->file_name);
b29c813f 356 } else if (td->o.create_fsync) {
ce4d13ca
JA
357#if defined(CONFIG_GF_NEW_API)
358 if (glfs_fsync(g->fd, NULL, NULL) < 0) {
359#else
b29c813f 360 if (glfs_fsync(g->fd) < 0) {
ce4d13ca 361#endif
b29c813f
JA
362 dprint(FD_FILE,
363 "failed to sync, close %s\n",
364 f->file_name);
365 td_verror(td, errno, "fsync");
366 glfs_close(g->fd);
367 g->fd = NULL;
368 return 1;
369 }
370 }
371 }
372 }
373 }
6fa14b99 374#if defined(GFAPI_USE_FADVISE)
b29c813f
JA
375 {
376 int r = 0;
377 if (td_random(td)) {
378 r = glfs_fadvise(g->fd, 0, f->real_file_size,
379 POSIX_FADV_RANDOM);
380 } else {
381 r = glfs_fadvise(g->fd, 0, f->real_file_size,
382 POSIX_FADV_SEQUENTIAL);
383 }
384 if (r) {
385 dprint(FD_FILE, "fio %p fadvise %s status %d\n", g->fs,
386 f->file_name, r);
387 }
388 }
6fa14b99 389#endif
b29c813f
JA
390 dprint(FD_FILE, "fio %p created %s\n", g->fs, f->file_name);
391 f->fd = -1;
392 f->shadow_fd = -1;
e6590c12 393 td->o.open_files ++;
b29c813f 394 return ret;
6e7d7dfb 395}
396
cc47f094 397int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
6e7d7dfb 398{
399 int ret = 0;
565e784d 400 struct gf_data *g = td->io_ops_data;
6e7d7dfb 401
402 dprint(FD_FILE, "fd close %s\n", f->file_name);
403
b29c813f
JA
404 if (g) {
405 if (g->fd && glfs_close(g->fd) < 0)
406 ret = errno;
38ef9c90
CF
407 g->fd = NULL;
408 }
409
410 return ret;
411}
412
413int fio_gf_unlink_file(struct thread_data *td, struct fio_file *f)
414{
415 int ret = 0;
565e784d 416 struct gf_data *g = td->io_ops_data;
38ef9c90
CF
417
418 dprint(FD_FILE, "fd unlink %s\n", f->file_name);
419
420 if (g) {
421 if (g->fd && glfs_close(g->fd) < 0)
422 ret = errno;
423
424 glfs_unlink(g->fs, f->file_name);
7cb57176 425
b29c813f
JA
426 if (g->fs)
427 glfs_fini(g->fs);
6e7d7dfb 428
b29c813f
JA
429 g->fd = NULL;
430 free(g);
431 }
565e784d 432 td->io_ops_data = NULL;
6e7d7dfb 433
434 return ret;
435}