glusterfs: capable to test with one single glfs instance
[fio.git] / engines / glusterfs.c
index dec9fb5f6597c0754f8ee97da2193f253ebf8346..d0250b70eab0713941a0567c4b23da58ddd82c36 100644 (file)
@@ -27,21 +27,164 @@ struct fio_option gfapi_options[] = {
         .category = FIO_OPT_C_ENGINE,
         .group = FIO_OPT_G_GFAPI,
         },
+       {
+        .name = "single-instance",
+        .lname = "Single glusterfs instance",
+        .type = FIO_OPT_BOOL,
+        .help = "Only one glusterfs instance",
+        .off1 = offsetof(struct gf_options, gf_single_instance),
+        .category = FIO_OPT_C_ENGINE,
+        .group = FIO_OPT_G_GFAPI,
+        },
        {
         .name = NULL,
         },
 };
 
-int fio_gf_setup(struct thread_data *td)
+struct glfs_info {
+       struct flist_head       list;
+       char                    *volume;
+       char                    *brick;
+       glfs_t                  *fs;
+       int                     refcount;
+};
+
+static pthread_mutex_t glfs_lock = PTHREAD_MUTEX_INITIALIZER;
+static FLIST_HEAD(glfs_list_head);
+
+static glfs_t *fio_gf_new_fs(char *volume, char *brick)
 {
        int r = 0;
+       glfs_t *fs;
+       struct stat sb = { 0, };
+
+       fs = glfs_new(volume);
+       if (!fs) {
+               log_err("glfs_new failed.\n");
+               goto out;
+       }
+       glfs_set_logging(fs, "/tmp/fio_gfapi.log", 7);
+       /* default to tcp */
+       r = glfs_set_volfile_server(fs, "tcp", brick, 0);
+       if (r) {
+               log_err("glfs_set_volfile_server failed.\n");
+               goto out;
+       }
+       r = glfs_init(fs);
+       if (r) {
+               log_err("glfs_init failed. Is glusterd running on brick?\n");
+               goto out;
+       }
+       sleep(2);
+       r = glfs_lstat(fs, ".", &sb);
+       if (r) {
+               log_err("glfs_lstat failed.\n");
+               goto out;
+       }
+
+out:
+       if (r) {
+               glfs_fini(fs);
+               fs = NULL;
+       }
+       return fs;
+}
+
+static glfs_t *fio_gf_get_glfs(struct gf_options *opt,
+                              char *volume, char *brick)
+{
+       struct glfs_info *glfs = NULL;
+       struct glfs_info *tmp;
+       struct flist_head *entry;
+
+       if (!opt->gf_single_instance)
+               return fio_gf_new_fs(volume, brick);
+
+       pthread_mutex_lock (&glfs_lock);
+
+       flist_for_each(entry, &glfs_list_head) {
+               tmp = flist_entry(entry, struct glfs_info, list);
+               if (!strcmp(volume, tmp->volume) &&
+                   !strcmp(brick, tmp->brick)) {
+                       glfs = tmp;
+                       break;
+               }
+       }
+
+       if (glfs) {
+               glfs->refcount++;
+       } else {
+               glfs = malloc(sizeof(*glfs));
+               if (!glfs)
+                       goto out;
+               INIT_FLIST_HEAD(&glfs->list);
+               glfs->refcount = 0;
+               glfs->volume = strdup(volume);
+               glfs->brick = strdup(brick);
+               glfs->fs = fio_gf_new_fs(volume, brick);
+               if (!glfs->fs) {
+                       free(glfs);
+                       glfs = NULL;
+                       goto out;
+               }
+
+               flist_add_tail(&glfs->list, &glfs_list_head);
+               glfs->refcount = 1;
+       }
+
+out:
+       pthread_mutex_unlock (&glfs_lock);
+
+       if (glfs)
+               return glfs->fs;
+       return NULL;
+}
+
+static void fio_gf_put_glfs(struct gf_options *opt, glfs_t *fs)
+{
+       struct glfs_info *glfs = NULL;
+       struct glfs_info *tmp;
+       struct flist_head *entry;
+
+       if (!opt->gf_single_instance) {
+               glfs_fini(fs);
+               return;
+       }
+
+       pthread_mutex_lock (&glfs_lock);
+
+       flist_for_each(entry, &glfs_list_head) {
+               tmp = flist_entry(entry, struct glfs_info, list);
+               if (tmp->fs == fs) {
+                       glfs = tmp;
+                       break;
+               }
+       }
+
+       if (!glfs) {
+               log_err("glfs not found to fini.\n");
+       } else {
+               glfs->refcount--;
+
+               if (glfs->refcount == 0) {
+                       glfs_fini(glfs->fs);
+                       free(glfs->volume);
+                       free(glfs->brick);
+                       flist_del(&glfs->list);
+               }
+       }
+
+       pthread_mutex_unlock (&glfs_lock);
+}
+
+int fio_gf_setup(struct thread_data *td)
+{
        struct gf_data *g = NULL;
        struct gf_options *opt = td->eo;
-       struct stat sb = { 0, };
 
        dprint(FD_IO, "fio setup\n");
 
-       if (td->io_ops->data)
+       if (td->io_ops_data)
                return 0;
 
        g = malloc(sizeof(struct gf_data));
@@ -49,47 +192,25 @@ int fio_gf_setup(struct thread_data *td)
                log_err("malloc failed.\n");
                return -ENOMEM;
        }
-       g->fs = NULL;
        g->fd = NULL;
        g->aio_events = NULL;
 
-       g->fs = glfs_new(opt->gf_vol);
-       if (!g->fs) {
-               log_err("glfs_new failed.\n");
-               goto cleanup;
-       }
-       glfs_set_logging(g->fs, "/tmp/fio_gfapi.log", 7);
-       /* default to tcp */
-       r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 0);
-       if (r) {
-               log_err("glfs_set_volfile_server failed.\n");
+       g->fs = fio_gf_get_glfs(opt, opt->gf_vol, opt->gf_brick);
+       if (!g->fs)
                goto cleanup;
-       }
-       r = glfs_init(g->fs);
-       if (r) {
-               log_err("glfs_init failed. Is glusterd running on brick?\n");
-               goto cleanup;
-       }
-       sleep(2);
-       r = glfs_lstat(g->fs, ".", &sb);
-       if (r) {
-               log_err("glfs_lstat failed.\n");
-               goto cleanup;
-       }
+
        dprint(FD_FILE, "fio setup %p\n", g->fs);
-       td->io_ops->data = g;
+       td->io_ops_data = g;
        return 0;
 cleanup:
-       if (g->fs)
-               glfs_fini(g->fs);
        free(g);
-       td->io_ops->data = NULL;
-       return r;
+       td->io_ops_data = NULL;
+       return -EIO;
 }
 
 void fio_gf_cleanup(struct thread_data *td)
 {
-       struct gf_data *g = td->io_ops->data;
+       struct gf_data *g = td->io_ops_data;
 
        if (g) {
                if (g->aio_events)
@@ -97,9 +218,9 @@ void fio_gf_cleanup(struct thread_data *td)
                if (g->fd)
                        glfs_close(g->fd);
                if (g->fs)
-                       glfs_fini(g->fs);
+                       fio_gf_put_glfs(td->eo, g->fs);
                free(g);
-               td->io_ops->data = NULL;
+               td->io_ops_data = NULL;
        }
 }
 
@@ -107,7 +228,7 @@ int fio_gf_get_file_size(struct thread_data *td, struct fio_file *f)
 {
        struct stat buf;
        int ret;
-       struct gf_data *g = td->io_ops->data;
+       struct gf_data *g = td->io_ops_data;
 
        dprint(FD_FILE, "get file size %s\n", f->file_name);
 
@@ -135,7 +256,7 @@ int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
 
        int flags = 0;
        int ret = 0;
-       struct gf_data *g = td->io_ops->data;
+       struct gf_data *g = td->io_ops_data;
        struct stat sb = { 0, };
 
        if (td_write(td)) {
@@ -165,11 +286,11 @@ int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
        if (td_read(td)) {
                if (glfs_lstat(g->fs, f->file_name, &sb)
                    || sb.st_size < f->real_file_size) {
-                       dprint(FD_FILE, "fio extend file %s from %ld to %ld\n",
-                              f->file_name, sb.st_size, f->real_file_size);
+                       dprint(FD_FILE, "fio extend file %s from %jd to %" PRIu64 "\n",
+                              f->file_name, (intmax_t) sb.st_size, f->real_file_size);
                        ret = glfs_ftruncate(g->fd, f->real_file_size);
                        if (ret) {
-                               log_err("failed fio extend file %s to %ld\n",
+                               log_err("failed fio extend file %s to %" PRIu64 "\n",
                                        f->file_name, f->real_file_size);
                        } else {
                                unsigned long long left;
@@ -190,7 +311,7 @@ int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
 
                                        r = glfs_write(g->fd, b, bs, 0);
                                        dprint(FD_IO,
-                                              "fio write %d of %ld file %s\n",
+                                              "fio write %d of %" PRIu64 " file %s\n",
                                               r, f->real_file_size,
                                               f->file_name);
 
@@ -268,7 +389,7 @@ int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
 int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
 {
        int ret = 0;
-       struct gf_data *g = td->io_ops->data;
+       struct gf_data *g = td->io_ops_data;
 
        dprint(FD_FILE, "fd close %s\n", f->file_name);
 
@@ -284,7 +405,7 @@ int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
 int fio_gf_unlink_file(struct thread_data *td, struct fio_file *f)
 {
        int ret = 0;
-       struct gf_data *g = td->io_ops->data;
+       struct gf_data *g = td->io_ops_data;
 
        dprint(FD_FILE, "fd unlink %s\n", f->file_name);
 
@@ -300,7 +421,7 @@ int fio_gf_unlink_file(struct thread_data *td, struct fio_file *f)
                g->fd = NULL;
                free(g);
        }
-       td->io_ops->data = NULL;
+       td->io_ops_data = NULL;
 
        return ret;
 }