Glusterfs libgfapi engine - initial deposit
authorchenh <hchen@redhat.com>
Thu, 27 Mar 2014 19:19:43 +0000 (15:19 -0400)
committerchenh <hchen@redhat.com>
Thu, 27 Mar 2014 19:19:43 +0000 (15:19 -0400)
Makefile
configure
engines/glusterfs.c [new file with mode: 0644]
options.h

index 1113c2f..a072d3a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -91,6 +91,9 @@ endif
 ifndef CONFIG_INET_ATON
   SOURCE += lib/inet_aton.c
 endif
+ifdef CONFIG_GFAPI
+  SOURCE += engines/glusterfs.c
+endif
 
 ifeq ($(CONFIG_TARGET_OS), Linux)
   SOURCE += diskutil.c fifo.c blktrace.c cgroup.c trim.c engines/sg.c \
index 63aa02d..3a4a37a 100755 (executable)
--- a/configure
+++ b/configure
@@ -1163,6 +1163,26 @@ if compile_prog "" "-lrbd -lrados" "rbd"; then
 fi
 echo "Rados Block Device engine     $rbd"
 
+##########################################
+# check for gfapi
+gfapi="no"
+cat > $TMPC << EOF
+#include <glusterfs/api/glfs.h>
+
+int main(int argc, char **argv)
+{
+
+  glfs_t *g = glfs_new("foo");
+
+  return 0;
+}
+EOF
+if compile_prog "" "-lgfapi -lglusterfs" "gfapi"; then
+  LIBS="-lgfapi -lglusterfs $LIBS"
+  gfapi="yes"
+fi
+echo "Gluster API engine            $gfapi"
+
 
 #############################################################################
 
@@ -1291,6 +1311,9 @@ fi
 if test "$cpu_count" = "yes" ; then
   output_sym "CONFIG_CPU_COUNT"
 fi
+if test "$gfapi" = "yes" ; then
+  output_sym "CONFIG_GFAPI"
+fi
 
 echo "LIBS+=$LIBS" >> $config_host_mak
 echo "CFLAGS+=$CFLAGS" >> $config_host_mak
diff --git a/engines/glusterfs.c b/engines/glusterfs.c
new file mode 100644 (file)
index 0000000..a89aeb8
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * glusterfs engine
+ *
+ * IO engine using Glusterfs's gfapi interface
+ *
+ */
+
+#include <glusterfs/api/glfs.h>
+
+#include "../fio.h"
+
+struct gf_options {
+    struct thread_data *td;
+    char *gf_vol;
+    char *gf_brick;
+};
+
+struct gf_data {
+    glfs_t *fs;
+    glfs_fd_t *fd;
+};
+static struct fio_option options[] = {
+    {
+       .name     = "volume",
+       .lname    = "Glusterfs volume",
+       .type     = FIO_OPT_STR_STORE,
+       .help     = "Name of the Glusterfs volume",
+       .off1     = offsetof(struct gf_options, gf_vol),
+       .category = FIO_OPT_C_ENGINE,
+       .group    = FIO_OPT_G_GFAPI,
+    },
+    {
+       .name     = "brick",
+       .lname    = "Glusterfs brick name",
+       .type     = FIO_OPT_STR_STORE,
+       .help     = "Name of the Glusterfs brick to connect",
+       .off1     = offsetof(struct gf_options, gf_brick),
+       .category = FIO_OPT_C_ENGINE,
+       .group    = FIO_OPT_G_GFAPI,
+    },
+    {
+       .name = NULL,
+    },
+};
+
+static int fio_gf_setup(struct thread_data *td)
+{
+       int r = 0;
+       struct gf_data *g = NULL;
+       struct gf_options *opt = td->eo;
+
+       if (td->io_ops->data)
+           return 0;
+
+       g = malloc(sizeof(struct gf_data));
+       if (!g){
+           log_err("malloc failed.\n");
+           return -ENOMEM;
+       }
+       g->fs = NULL; g->fd = NULL;
+
+       g->fs = glfs_new (opt->gf_vol);
+       if (!g->fs){
+           log_err("glfs_new failed.\n");
+           goto cleanup;
+       }
+
+       /* default to tcp */
+       r = glfs_set_volfile_server(g->fs, "tcp", opt->gf_brick, 24007);
+       if (r){
+           log_err("glfs_set_volfile_server failed.\n");
+           goto cleanup;
+       }
+       r = glfs_init(g->fs);
+       if (r){
+           log_err("glfs_init failed.\n");
+           goto cleanup;
+       }
+       glfs_set_logging (g->fs, "/dev/stderr", 7);
+       
+       td->io_ops->data = g;
+cleanup:
+       if (g){
+           if (g->fs){
+               glfs_fini(g->fs);
+           }
+           free(g);
+       }
+       return r;
+}
+
+static void fio_gf_cleanup(struct thread_data *td)
+{
+       struct gf_data *g = td->io_ops->data;
+
+       if (g){
+           if (g->fs){
+               glfs_fini(g->fs);
+           }
+           free(g);
+       }
+}
+
+static 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;
+
+    if (fio_file_size_known(f))
+       return 0;
+
+    ret = glfs_lstat (g->fs, f->file_name, &buf);
+    if (ret < 0)
+       return ret;
+
+    f->real_file_size = buf.st_size;
+    fio_file_set_size_known(f);
+
+    return 0;
+
+}
+
+static int fio_gf_open_file(struct thread_data *td, struct fio_file *f)
+{
+    struct gf_data *g = td->io_ops->data;
+    int flags = 0;
+
+    dprint(FD_FILE, "fd open %s\n", f->file_name);
+
+    if (td_write(td)) {
+       if (!read_only)
+           flags = O_RDWR;
+    } else if (td_read(td)) {
+       if (!read_only)
+           flags = O_RDWR;
+       else
+           flags = O_RDONLY;
+    }
+    if (td->o.create_on_open)
+       flags |= O_CREAT;
+
+    g->fd = glfs_open(g->fs, f->file_name, flags);
+    f->fd = -1;
+    return 0;
+}
+
+static int fio_gf_close_file(struct thread_data *td, struct fio_file *f)
+{
+       int ret = 0;
+       struct gf_data *g = td->io_ops->data;
+
+       dprint(FD_FILE, "fd close %s\n", f->file_name);
+
+       if (!g->fd && glfs_close(g->fd) < 0)
+               ret = errno;
+
+       g->fd = NULL;
+       f->engine_data = 0;
+
+       return ret;
+}
+
+#define LAST_POS(f)    ((f)->engine_data)
+static int fio_gf_prep(struct thread_data *td, struct io_u *io_u)
+{
+       struct fio_file *f = io_u->file;
+       struct gf_data *g = td->io_ops->data;
+
+       if (!ddir_rw(io_u->ddir))
+               return 0;
+
+       if (LAST_POS(f) != -1ULL && LAST_POS(f) == io_u->offset)
+               return 0;
+
+       if (glfs_lseek(g->fd, io_u->offset, SEEK_SET) < 0) {
+               td_verror(td, errno, "lseek");
+               return 1;
+       }
+
+       return 0;
+}
+
+static int fio_gf_queue(struct thread_data *td, struct io_u *io_u)
+{
+    struct gf_data *g = td->io_ops->data;
+    int ret = 0;
+
+    fio_ro_check(td, io_u);
+
+    if (io_u->ddir == DDIR_READ)
+       ret = glfs_read(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
+    else if (io_u->ddir == DDIR_WRITE)
+       ret = glfs_write(g->fd, io_u->xfer_buf, io_u->xfer_buflen, 0);
+    else {         
+       log_err("unsupported operation.\n");
+       return -EINVAL;
+    }
+    if (io_u->file && ret >= 0 && ddir_rw(io_u->ddir))
+       LAST_POS(io_u->file) = io_u->offset + ret;
+
+    if (ret != (int) io_u->xfer_buflen) {
+       if (ret >= 0) {
+           io_u->resid = io_u->xfer_buflen - ret;
+           io_u->error = 0;
+           return FIO_Q_COMPLETED;
+       } else
+           io_u->error = errno;
+    }
+
+    if (io_u->error)
+       td_verror(td, io_u->error, "xfer");
+
+    return FIO_Q_COMPLETED;
+
+}
+
+static struct ioengine_ops ioengine = {
+       .name               = "gfapi",
+       .version            = FIO_IOOPS_VERSION,
+       .setup              = fio_gf_setup,
+       .cleanup            = fio_gf_cleanup,
+       .prep               = fio_gf_prep,
+       .queue              = fio_gf_queue,
+       .open_file          = fio_gf_open_file,
+       .close_file         = fio_gf_close_file,
+       .get_file_size      = fio_gf_get_file_size,
+       .options            = options,
+       .option_struct_size = sizeof(struct gf_options),
+       .flags              = FIO_SYNCIO,
+};
+
+static void fio_init fio_gf_register(void)
+{
+    register_ioengine(&ioengine);
+}
+
+static void fio_exit fio_gf_unregister(void)
+{
+    unregister_ioengine(&ioengine);
+}
index de9f610..b2e2c0c 100644 (file)
--- a/options.h
+++ b/options.h
@@ -98,6 +98,7 @@ enum opt_category_group {
        __FIO_OPT_G_ACT,
        __FIO_OPT_G_LATPROF,
         __FIO_OPT_G_RBD,
+        __FIO_OPT_G_GFAPI,
        __FIO_OPT_G_NR,
 
        FIO_OPT_G_RATE          = (1U << __FIO_OPT_G_RATE),
@@ -128,6 +129,7 @@ enum opt_category_group {
        FIO_OPT_G_ACT           = (1U << __FIO_OPT_G_ACT),
        FIO_OPT_G_LATPROF       = (1U << __FIO_OPT_G_LATPROF),
        FIO_OPT_G_RBD           = (1U << __FIO_OPT_G_RBD),
+       FIO_OPT_G_GFAPI         = (1U << __FIO_OPT_G_GFAPI),
        FIO_OPT_G_INVALID       = (1U << __FIO_OPT_G_NR),
 };