stat: make add lat percentile functions inline
[fio.git] / engines / glusterfs.c
1 /*
2  * glusterfs engine
3  *
4  * common Glusterfs's gfapi interface
5  *
6  */
7
8 #include "gfapi.h"
9 #include "../optgroup.h"
10
11 struct fio_option gfapi_options[] = {
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          },
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          },
39         {
40          .name = NULL,
41          },
42 };
43
44 struct glfs_info {
45         struct flist_head       list;
46         char                    *volume;
47         char                    *brick;
48         glfs_t                  *fs;
49         int                     refcount;
50 };
51
52 static pthread_mutex_t glfs_lock = PTHREAD_MUTEX_INITIALIZER;
53 static FLIST_HEAD(glfs_list_head);
54
55 static glfs_t *fio_gf_new_fs(char *volume, char *brick)
56 {
57         int r = 0;
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
85 out:
86         if (r) {
87                 glfs_fini(fs);
88                 fs = NULL;
89         }
90         return fs;
91 }
92
93 static 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
135 out:
136         pthread_mutex_unlock (&glfs_lock);
137
138         if (glfs)
139                 return glfs->fs;
140         return NULL;
141 }
142
143 static 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
180 int fio_gf_setup(struct thread_data *td)
181 {
182         struct gf_data *g = NULL;
183         struct gf_options *opt = td->eo;
184
185         dprint(FD_IO, "fio setup\n");
186
187         if (td->io_ops_data)
188                 return 0;
189
190         g = malloc(sizeof(struct gf_data));
191         if (!g) {
192                 log_err("malloc failed.\n");
193                 return -ENOMEM;
194         }
195         g->fd = NULL;
196         g->aio_events = NULL;
197
198         g->fs = fio_gf_get_glfs(opt, opt->gf_vol, opt->gf_brick);
199         if (!g->fs)
200                 goto cleanup;
201
202         dprint(FD_FILE, "fio setup %p\n", g->fs);
203         td->io_ops_data = g;
204         return 0;
205 cleanup:
206         free(g);
207         td->io_ops_data = NULL;
208         return -EIO;
209 }
210
211 void fio_gf_cleanup(struct thread_data *td)
212 {
213         struct gf_data *g = td->io_ops_data;
214
215         if (g) {
216                 if (g->aio_events)
217                         free(g->aio_events);
218                 if (g->fd)
219                         glfs_close(g->fd);
220                 if (g->fs)
221                         fio_gf_put_glfs(td->eo, g->fs);
222                 free(g);
223                 td->io_ops_data = NULL;
224         }
225 }
226
227 int fio_gf_get_file_size(struct thread_data *td, struct fio_file *f)
228 {
229         struct stat buf;
230         int ret;
231         struct gf_data *g = td->io_ops_data;
232
233         dprint(FD_FILE, "get file size %s\n", f->file_name);
234
235         if (!g || !g->fs) {
236                 return 0;
237         }
238         if (fio_file_size_known(f))
239                 return 0;
240
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         }
246
247         f->real_file_size = buf.st_size;
248         fio_file_set_size_known(f);
249
250         return 0;
251
252 }
253
254 int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
255 {
256
257         int flags = 0;
258         int ret = 0;
259         struct gf_data *g = td->io_ops_data;
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         }
271
272         if (td->o.odirect)
273                 flags |= OS_O_DIRECT;
274         flags |= td->o.sync_io;
275
276         dprint(FD_FILE, "fio file %s open mode %s td rw %s\n", f->file_name,
277                flags & O_RDONLY ? "ro" : "rw", td_read(td) ? "read" : "write");
278         g->fd = glfs_creat(g->fs, f->file_name, flags, 0644);
279         if (!g->fd) {
280                 ret = errno;
281                 log_err("glfs_creat failed.\n");
282                 return ret;
283         }
284         /* file for read doesn't exist or shorter than required, create/extend it */
285         if (td_read(td)) {
286                 if (glfs_lstat(g->fs, f->file_name, &sb)
287                     || sb.st_size < f->real_file_size) {
288                         dprint(FD_FILE, "fio extend file %s from %jd to %" PRIu64 "\n",
289                                f->file_name, (intmax_t) sb.st_size, f->real_file_size);
290 #if defined(CONFIG_GF_NEW_API)
291                         ret = glfs_ftruncate(g->fd, f->real_file_size, NULL, NULL);
292 #else
293                         ret = glfs_ftruncate(g->fd, f->real_file_size);
294 #endif
295                         if (ret) {
296                                 log_err("failed fio extend file %s to %" PRIu64 "\n",
297                                         f->file_name, f->real_file_size);
298                         } else {
299                                 unsigned long long left;
300                                 unsigned int bs;
301                                 char *b;
302                                 int r;
303
304                                 /* fill the file, copied from extend_file */
305                                 b = malloc(td->o.max_bs[DDIR_WRITE]);
306
307                                 left = f->real_file_size;
308                                 while (left && !td->terminate) {
309                                         bs = td->o.max_bs[DDIR_WRITE];
310                                         if (bs > left)
311                                                 bs = left;
312
313                                         fill_io_buffer(td, b, bs, bs);
314
315                                         r = glfs_write(g->fd, b, bs, 0);
316                                         dprint(FD_IO,
317                                                "fio write %d of %" PRIu64 " file %s\n",
318                                                r, f->real_file_size,
319                                                f->file_name);
320
321                                         if (r > 0) {
322                                                 left -= r;
323                                                 continue;
324                                         } else {
325                                                 if (r < 0) {
326                                                         int __e = errno;
327
328                                                         if (__e == ENOSPC) {
329                                                                 if (td->o.
330                                                                     fill_device)
331                                                                         break;
332                                                                 log_info
333                                                                     ("fio: ENOSPC on laying out "
334                                                                      "file, stopping\n");
335                                                                 break;
336                                                         }
337                                                         td_verror(td, errno,
338                                                                   "write");
339                                                 } else
340                                                         td_verror(td, EIO,
341                                                                   "write");
342
343                                                 break;
344                                         }
345                                 }
346
347                                 if (b)
348                                         free(b);
349                                 glfs_lseek(g->fd, 0, SEEK_SET);
350
351                                 if (td->terminate && td->o.unlink) {
352                                         dprint(FD_FILE, "terminate unlink %s\n",
353                                                f->file_name);
354                                         glfs_unlink(g->fs, f->file_name);
355                                 } else if (td->o.create_fsync) {
356 #if defined(CONFIG_GF_NEW_API)
357                                         if (glfs_fsync(g->fd, NULL, NULL) < 0) {
358 #else
359                                         if (glfs_fsync(g->fd) < 0) {
360 #endif
361                                                 dprint(FD_FILE,
362                                                        "failed to sync, close %s\n",
363                                                        f->file_name);
364                                                 td_verror(td, errno, "fsync");
365                                                 glfs_close(g->fd);
366                                                 g->fd = NULL;
367                                                 return 1;
368                                         }
369                                 }
370                         }
371                 }
372         }
373 #if defined(GFAPI_USE_FADVISE)
374         {
375                 int r = 0;
376                 if (td_random(td)) {
377                         r = glfs_fadvise(g->fd, 0, f->real_file_size,
378                                          POSIX_FADV_RANDOM);
379                 } else {
380                         r = glfs_fadvise(g->fd, 0, f->real_file_size,
381                                          POSIX_FADV_SEQUENTIAL);
382                 }
383                 if (r) {
384                         dprint(FD_FILE, "fio %p fadvise %s status %d\n", g->fs,
385                                f->file_name, r);
386                 }
387         }
388 #endif
389         dprint(FD_FILE, "fio %p created %s\n", g->fs, f->file_name);
390         f->fd = -1;
391         f->shadow_fd = -1;
392         td->o.open_files ++;
393         return ret;
394 }
395
396 int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
397 {
398         int ret = 0;
399         struct gf_data *g = td->io_ops_data;
400
401         dprint(FD_FILE, "fd close %s\n", f->file_name);
402
403         if (g) {
404                 if (g->fd && glfs_close(g->fd) < 0)
405                         ret = errno;
406                 g->fd = NULL;
407         }
408
409         return ret;
410 }
411
412 int fio_gf_unlink_file(struct thread_data *td, struct fio_file *f)
413 {
414         int ret = 0;
415         struct gf_data *g = td->io_ops_data;
416
417         dprint(FD_FILE, "fd unlink %s\n", f->file_name);
418
419         if (g) {
420                 if (g->fd && glfs_close(g->fd) < 0)
421                         ret = errno;
422
423                 glfs_unlink(g->fs, f->file_name);
424
425                 if (g->fs)
426                         glfs_fini(g->fs);
427
428                 g->fd = NULL;
429                 free(g);
430         }
431         td->io_ops_data = NULL;
432
433         return ret;
434 }