diff options
Diffstat (limited to 'extras')
| -rw-r--r-- | extras/Makefile.am | 13 | ||||
| -rw-r--r-- | extras/Portfile | 26 | ||||
| -rw-r--r-- | extras/benchmarking/Makefile.am | 7 | ||||
| -rw-r--r-- | extras/benchmarking/README | 18 | ||||
| -rw-r--r-- | extras/benchmarking/glfs-bm.c | 619 | ||||
| -rwxr-xr-x | extras/benchmarking/launch-script.sh | 18 | ||||
| -rwxr-xr-x | extras/benchmarking/local-script.sh | 26 | ||||
| -rw-r--r-- | extras/glusterfs-mode.el | 112 | ||||
| -rw-r--r-- | extras/glusterfs.vim | 211 | ||||
| -rw-r--r-- | extras/init.d/Makefile.am | 9 | ||||
| -rwxr-xr-x | extras/init.d/glusterfs-server | 100 | ||||
| -rw-r--r-- | extras/init.d/glusterfs-server.plist.in | 15 | ||||
| -rwxr-xr-x | extras/init.d/glusterfsd | 110 | ||||
| -rwxr-xr-x | extras/specgen.scm | 98 | ||||
| -rw-r--r-- | extras/stripe-merge.c | 48 | ||||
| -rw-r--r-- | extras/test/Makefile.am | 3 | ||||
| -rw-r--r-- | extras/test/rdd.c | 457 | 
17 files changed, 1890 insertions, 0 deletions
diff --git a/extras/Makefile.am b/extras/Makefile.am new file mode 100644 index 00000000000..f243a0da5b6 --- /dev/null +++ b/extras/Makefile.am @@ -0,0 +1,13 @@ + +docdir = $(datadir)/doc/glusterfs/ +EmacsModedir = $(docdir)/ +EmacsMode_DATA = glusterfs-mode.el + +SUBDIRS = init.d benchmarking + +EXTRA_DIST = specgen.scm glusterfs.vim glusterfs-mode.el Portfile \ +	     test/Makefile.am test/Makefile.in test/rdd.c \ +	     benchmarking/Makefile.am benchmarking/Makefile.in + +CLEANFILES =  + diff --git a/extras/Portfile b/extras/Portfile new file mode 100644 index 00000000000..4732c38ee34 --- /dev/null +++ b/extras/Portfile @@ -0,0 +1,26 @@ +# $Id$ + +PortSystem          1.0 + +name                glusterfs +version             2.0.0rc1 +categories          fuse +maintainers         amar@zresearch.com +description         GlusterFS +long_description    GlusterFS is a cluster file system, flexible to tune it for your needs. +homepage            http://www.gluster.org/ +platforms           darwin +master_sites        http://ftp.zresearch.com/pub/gluster/glusterfs/2.0/2.0.0 + +configure.args      --disable-bdb +checksums           md5 33c2d02344d4fab422e80cfb637e0b48 + +post-destroot { +    file mkdir ${destroot}/Library/LaunchDaemons/ +    file copy ${worksrcpath}/extras/glusterfs-server.plist \ +        ${destroot}/Library/LaunchDaemons/com.zresearch.glusterfs.plist + +    file mkdir ${destroot}/sbin/ +    file copy ${worksrcpath}/xlators/mount/fuse/utils/mount_glusterfs \ +	${destroot}/sbin/ +}
\ No newline at end of file diff --git a/extras/benchmarking/Makefile.am b/extras/benchmarking/Makefile.am new file mode 100644 index 00000000000..16f73cbaa6b --- /dev/null +++ b/extras/benchmarking/Makefile.am @@ -0,0 +1,7 @@ + +docdir = $(datadir)/doc/$(PACKAGE_NAME)/benchmarking + +EXTRA_DIST = glfs-bm.c README launch-script.sh local-script.sh + +CLEANFILES =  + diff --git a/extras/benchmarking/README b/extras/benchmarking/README new file mode 100644 index 00000000000..e83dd882235 --- /dev/null +++ b/extras/benchmarking/README @@ -0,0 +1,18 @@ + +-------------- +Parallel DD performance: + +* Copy the local-script.sh in ${mountpoint}/benchmark/ directory +* Edit it so the blocksize and count are as per the requirements + +* Edit the launch-script.sh script to make sure paths, mountpoints etc are alright. + +* run 'lauch-script.sh' + +* after the run, you can get the aggregated result by adding all the 3rd entry in output.$(hostname) entries in 'output/' directory. + +-------------- + +iozone: + +bash# iozone - +m iozone_cluster.config - t 62 - r ${block_size} - s ${file_size} - +n - i 0 - i 1
\ No newline at end of file diff --git a/extras/benchmarking/glfs-bm.c b/extras/benchmarking/glfs-bm.c new file mode 100644 index 00000000000..f5e63ae8014 --- /dev/null +++ b/extras/benchmarking/glfs-bm.c @@ -0,0 +1,619 @@ +/*                                                                   +  Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.com>  +  This file is part of GlusterFS.                              +  GlusterFS is free software; you can redistribute it and/or modify  +  it under the terms of the GNU General Public License as published  +  by the Free Software Foundation; either version 3 of the License,  +  or (at your option) any later version.                             + +  GlusterFS is distributed in the hope that it will be useful, but  +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  General Public License for more details.  +                                                                                    +  You should have received a copy of the GNU General Public License  +  along with this program.  If not, see  +  <http://www.gnu.org/licenses/>.   +*/ + +#define _GNU_SOURCE +#define __USE_FILE_OFFSET64 +#define _FILE_OFFSET_BITS 64 + +#include <stdio.h> +#include <argp.h> +#include <libglusterfsclient.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/xattr.h> +#include <string.h> +#include <libgen.h> +#include <errno.h> +#include <sys/time.h> + +struct state { +        char need_op_write:1; +        char need_op_read:1; + +        char need_iface_fileio:1; +        char need_iface_xattr:1; + +        char need_mode_posix:1; +        char need_mode_libglusterfsclient:1; + +        char prefix[512]; +        long int count; + +        size_t block_size; + +        char *specfile; +        void *libglusterfsclient_context; + +        long int io_size; +}; + + +#define MEASURE(func, arg) measure (func, #func, arg) + + +void +tv_difference (struct timeval *tv_stop, +               struct timeval *tv_start, +               struct timeval *tv_diff) +{ +        if (tv_stop->tv_usec < tv_start->tv_usec) { +                tv_diff->tv_usec = (tv_stop->tv_usec + 1000000) - tv_start->tv_usec; +                tv_diff->tv_sec = (tv_stop->tv_sec - 1 - tv_start->tv_sec); +        } else { +                tv_diff->tv_usec = tv_stop->tv_usec - tv_start->tv_usec; +                tv_diff->tv_sec = tv_stop->tv_sec - tv_start->tv_sec; +        } +} + + +void +measure (int (*func)(struct state *state), +         char *func_name, struct state *state) +{ +        struct timeval tv_start, tv_stop, tv_diff; +        state->io_size = 0; +        long int count; + +        gettimeofday (&tv_start, NULL); +        count = func (state); +        gettimeofday (&tv_stop, NULL); + +        tv_difference (&tv_stop, &tv_start, &tv_diff); + +        fprintf (stdout, "%s: count=%ld, size=%ld, time=%ld:%ld\n", +                 func_name, count, state->io_size, +                 tv_diff.tv_sec, tv_diff.tv_usec); +} + + +static error_t +parse_opts (int key, char *arg, +            struct argp_state *_state) +{ +        struct state *state = _state->input; + +        switch (key) +        { +        case 'o': +                if (strcasecmp (arg, "read") == 0) { +                        state->need_op_write = 0; +                        state->need_op_read = 1; +                } else if (strcasecmp (arg, "write") == 0) { +                        state->need_op_write = 1; +                        state->need_op_read = 0; +                } else if (strcasecmp (arg, "both") == 0) { +                        state->need_op_write = 1; +                        state->need_op_read = 1; +                } else { +                        fprintf (stderr, "unknown op: %s\n", arg); +                        return -1; +                } +                break; +        case 'i': +                if (strcasecmp (arg, "fileio") == 0) { +                        state->need_iface_fileio = 1; +                        state->need_iface_xattr = 0; +                } else if (strcasecmp (arg, "xattr") == 0) { +                        state->need_iface_fileio = 0; +                        state->need_iface_xattr = 1; +                } else if (strcasecmp (arg, "both") == 0) { +                        state->need_iface_fileio = 1; +                        state->need_iface_xattr = 1; +                } else { +                        fprintf (stderr, "unknown interface: %s\n", arg); +                        return -1; +                } +                break; +        case 'm': +                if (strcasecmp (arg, "posix") == 0) { +                        state->need_mode_posix = 1; +                        state->need_mode_libglusterfsclient = 0; +                } else if (strcasecmp (arg, "libglusterfsclient") == 0) { +                        state->need_mode_posix = 0; +                        state->need_mode_libglusterfsclient = 1; +                } else if (strcasecmp (arg, "both") == 0) { +                        state->need_mode_posix = 1; +                        state->need_mode_libglusterfsclient = 1; +                } else { +                        fprintf (stderr, "unknown mode: %s\n", arg); +                        return -1; +                } +                break; +        case 'b': +        { +                size_t block_size = atoi (arg); +                if (!block_size) { +                        fprintf (stderr, "incorrect size: %s\n", arg); +                        return -1; +                } +                state->block_size = block_size; +        } +        break; +        case 's': +                state->specfile = strdup (arg); +                break; +        case 'p': +                fprintf (stderr, "using prefix: %s\n", arg); +                strncpy (state->prefix, arg, 512); +                break; +        case 'c': +        { +                long count = atol (arg); +                if (!count) { +                        fprintf (stderr, "incorrect count: %s\n", arg); +                        return -1; +                } +                state->count = count; +        } +        break; +        case ARGP_KEY_NO_ARGS: +                break; +        case ARGP_KEY_ARG: +                break; +        } + +        return 0; +} + +int +do_mode_posix_iface_fileio_write (struct state *state) +{ +        long int i; +        int ret = -1; +        char block[state->block_size]; + +        for (i=0; i<state->count; i++) { +                int fd = -1; +                char filename[512]; + +                sprintf (filename, "%s.%06ld", state->prefix, i); + +                fd = open (filename, O_CREAT|O_WRONLY, 00600); +                if (fd == -1) { +                        fprintf (stderr, "open(%s) => %s\n", filename, strerror (errno)); +                        break; +                } +                ret = write (fd, block, state->block_size); +                if (ret != state->block_size) { +                        fprintf (stderr, "write (%s) => %d/%s\n", filename, ret, +                                 strerror (errno)); +                        close (fd); +                        break; +                } +                close (fd); +                state->io_size += ret; +        } + +        return i; +} + + +int +do_mode_posix_iface_fileio_read (struct state *state) +{ +        long int i; +        int ret = -1; +        char block[state->block_size]; + +        for (i=0; i<state->count; i++) { +                int fd = -1; +                char filename[512]; + +                sprintf (filename, "%s.%06ld", state->prefix, i); + +                fd = open (filename, O_RDONLY); +                if (fd == -1) { +                        fprintf (stderr, "open(%s) => %s\n", filename, strerror (errno)); +                        break; +                } +                ret = read (fd, block, state->block_size); +                if (ret == -1) { +                        fprintf (stderr, "read(%s) => %d/%s\n", filename, ret, strerror (errno)); +                        close (fd); +                        break; +                } +                close (fd); +                state->io_size += ret; +        } + +        return i; +} + + +int +do_mode_posix_iface_fileio (struct state *state) +{ +        if (state->need_op_write) +                MEASURE (do_mode_posix_iface_fileio_write, state); + +        if (state->need_op_read) +                MEASURE (do_mode_posix_iface_fileio_read, state); + +        return 0; +} + + +int +do_mode_posix_iface_xattr_write (struct state *state) +{ +        long int i; +        int ret = -1; +        char block[state->block_size]; +        char *dname = NULL, *dirc = NULL; +        char *bname = NULL, *basec = NULL; + +        dirc = strdup (state->prefix); +        basec = strdup (state->prefix); +        dname = dirname (dirc); +        bname = basename (basec); + +        for (i=0; i<state->count; i++) { +                char key[512]; + +                sprintf (key, "glusterfs.file.%s.%06ld", bname, i); + +                ret = lsetxattr (dname, key, block, state->block_size, 0); + +                if (ret != 0) { +                        fprintf (stderr, "lsetxattr (%s, %s, %p) => %s\n", +                                 dname, key, block, strerror (errno)); +                        break; +                } +                state->io_size += state->block_size; +        } + +        free (dirc); +        free (basec); + +        return i; +} + + +int +do_mode_posix_iface_xattr_read (struct state *state) +{ +        long int i; +        int ret = -1; +        char block[state->block_size]; +        char *dname = NULL, *dirc = NULL; +        char *bname = NULL, *basec = NULL; + +        dirc = strdup (state->prefix); +        basec = strdup (state->prefix); +        dname = dirname (dirc); +        bname = basename (basec); + +        for (i=0; i<state->count; i++) { +                char key[512]; + +                sprintf (key, "glusterfs.file.%s.%06ld", bname, i); + +                ret = lgetxattr (dname, key, block, state->block_size); + +                if (ret < 0) { +                        fprintf (stderr, "lgetxattr (%s, %s, %p) => %s\n", +                                 dname, key, block, strerror (errno)); +                        break; +                } +                state->io_size += ret; +        } + +        return i; +} + + +int +do_mode_posix_iface_xattr (struct state *state) +{ +        if (state->need_op_write) +                MEASURE (do_mode_posix_iface_xattr_write, state); + +        if (state->need_op_read) +                MEASURE (do_mode_posix_iface_xattr_read, state); + +        return 0; +} + + +int +do_mode_libglusterfsclient_iface_fileio_write (struct state *state) +{ +        long int i; +        int ret = -1; +        char block[state->block_size]; + +        for (i=0; i<state->count; i++) { +                long fd = 0; +                char filename[512]; + +                sprintf (filename, "/%s.%06ld", state->prefix, i); + +                fd = glusterfs_open (state->libglusterfsclient_context, +                                     filename, O_CREAT|O_WRONLY, 0); + +                if (fd == 0) { +                        fprintf (stderr, "open(%s) => %s\n", filename, strerror (errno)); +                        break; +                } +                ret = glusterfs_write (fd, block, state->block_size); +                if (ret == -1) { +                        fprintf (stderr, "glusterfs_write(%s) => %s\n", filename, strerror (errno)); +                        glusterfs_close (fd); +                        break; +                } +                glusterfs_close (fd); +                state->io_size += ret; +        } + +        return i; +} + + +int +do_mode_libglusterfsclient_iface_fileio_read (struct state *state) +{ +        long int i; +        int ret = -1; +        char block[state->block_size]; + +        for (i=0; i<state->count; i++) { +                long fd = 0; +                char filename[512]; + +                sprintf (filename, "/%s.%06ld", state->prefix, i); + +                fd = glusterfs_open (state->libglusterfsclient_context, +                                     filename, O_RDONLY, 0); + +                if (fd == 0) { +                        fprintf (stderr, "glusterfs_open(%s) => %s\n", filename, strerror (errno)); +                        break; +                } +                ret = glusterfs_read (fd, block, state->block_size); +                if (ret == -1) { +                        fprintf (stderr, "glusterfs_read(%s) => %s\n", filename, strerror (errno)); +                        glusterfs_close (fd); +                        break; +                } +                glusterfs_close (fd); +                state->io_size += ret; +        } + +        return i; +} + + +int +do_mode_libglusterfsclient_iface_fileio (struct state *state) +{ +        if (state->need_op_write) +                MEASURE (do_mode_libglusterfsclient_iface_fileio_write, state); + +        if (state->need_op_read) +                MEASURE (do_mode_libglusterfsclient_iface_fileio_read, state); + +        return 0; +} + + +int +do_mode_libglusterfsclient_iface_xattr_write (struct state *state) +{ +        long int i; +        int ret = -1; +        char block[state->block_size]; +        char *dname = NULL, *dirc = NULL; +        char *bname = NULL, *basec = NULL; + +        asprintf (&dirc, "/%s", state->prefix); +        asprintf (&basec, "/%s", state->prefix); +        dname = dirname (dirc); +        bname = basename (basec); + +        for (i=0; i<state->count; i++) { +                char key[512]; + +                sprintf (key, "glusterfs.file.%s.%06ld", bname, i); + +                ret = glusterfs_setxattr (state->libglusterfsclient_context, +                                          dname, key, block, state->block_size, 0); + +                if (ret < 0) { +                        fprintf (stderr, "glusterfs_setxattr (%s, %s, %p) => %s\n", +                                 dname, key, block, strerror (errno)); +                        break; +                } +                state->io_size += state->block_size; +        } + +        return i; + +} + + +int +do_mode_libglusterfsclient_iface_xattr_read (struct state *state) +{ +        long int i; +        int ret = -1; +        char block[state->block_size]; +        char *dname = NULL, *dirc = NULL; +        char *bname = NULL, *basec = NULL; + +        dirc = strdup (state->prefix); +        basec = strdup (state->prefix); +        dname = dirname (dirc); +        bname = basename (basec); + +        for (i=0; i<state->count; i++) { +                char key[512]; + +                sprintf (key, "glusterfs.file.%s.%06ld", bname, i); + +                ret = glusterfs_getxattr (state->libglusterfsclient_context, +                                          dname, key, block, state->block_size); + +                if (ret < 0) { +                        fprintf (stderr, "glusterfs_getxattr (%s, %s, %p) => %s\n", +                                 dname, key, block, strerror (errno)); +                        break; +                } +                state->io_size += ret; +        } + +        return i;   +} + + +int +do_mode_libglusterfsclient_iface_xattr (struct state *state) +{ +        if (state->need_op_write) +                MEASURE (do_mode_libglusterfsclient_iface_xattr_write, state); + +        if (state->need_op_read) +                MEASURE (do_mode_libglusterfsclient_iface_xattr_read, state); + +        return 0; +} + + +int +do_mode_posix (struct state *state) +{ +        if (state->need_iface_fileio) +                do_mode_posix_iface_fileio (state); + +        if (state->need_iface_xattr) +                do_mode_posix_iface_xattr (state); + +        return 0; +} + + +int +do_mode_libglusterfsclient (struct state *state) +{ +        glusterfs_init_ctx_t ctx = { +                .logfile = "/dev/stderr", +                .loglevel = "error", +                .lookup_timeout = 60, +                .stat_timeout = 60, +        }; + +	ctx.specfile = state->specfile; +        if (state->specfile) { +                state->libglusterfsclient_context = glusterfs_init (&ctx); + +                if (!state->libglusterfsclient_context) { +                        fprintf (stdout, "Unable to initialize glusterfs context, skipping libglusterfsclient mode\n"); +                        return -1; +                } +        } else { +                fprintf (stdout, "glusterfs volume specification file not provided, skipping libglusterfsclient mode\n"); +                return -1; +        } + +        if (state->need_iface_fileio) +                do_mode_libglusterfsclient_iface_fileio (state); + +        if (state->need_iface_xattr) +                do_mode_libglusterfsclient_iface_xattr (state); + +        return 0; +} + + +int +do_actions (struct state *state) +{ +        if (state->need_mode_libglusterfsclient) +                do_mode_libglusterfsclient (state); + +        if (state->need_mode_posix) +                do_mode_posix (state); + +        return 0; +} + +static struct argp_option options[] = { +        {"op", 'o', "OPERATIONS", 0, +         "WRITE|READ|BOTH - defaults to BOTH"}, +        {"iface", 'i', "INTERFACE", 0, +         "FILEIO|XATTR|BOTH - defaults to FILEIO"}, +        {"mode", 'm', "MODE", 0, +         "POSIX|LIBGLUSTERFSCLIENT|BOTH - defaults to POSIX"}, +        {"block", 'b', "BLOCKSIZE", 0, +         "<NUM> - defaults to 4096"}, +        {"specfile", 's', "SPECFILE", 0, +         "absolute path to specfile"}, +        {"prefix", 'p', "PREFIX", 0, +         "filename prefix"}, +        {"count", 'c', "COUNT", 0, +         "number of files"}, +        {0, 0, 0, 0, 0} +}; + +static struct argp argp = { +        options, +        parse_opts, +        "tool", +        "tool to benchmark small file performance" +}; + +int +main (int argc, char *argv[]) +{ +        struct state state = {0, }; + +        state.need_op_write = 1; +        state.need_op_read = 1; + +        state.need_iface_fileio = 1; +        state.need_iface_xattr = 0; + +        state.need_mode_posix = 1; +        state.need_mode_libglusterfsclient = 0; + +        state.block_size = 4096; + +        strcpy (state.prefix, "tmpfile"); +        state.count = 1048576; + +        if (argp_parse (&argp, argc, argv, 0, 0, &state) != 0) { +                fprintf (stderr, "argp_parse() failed\n"); +                return 1; +        } + +        do_actions (&state); + +        return 0; +} diff --git a/extras/benchmarking/launch-script.sh b/extras/benchmarking/launch-script.sh new file mode 100755 index 00000000000..5d5050d4146 --- /dev/null +++ b/extras/benchmarking/launch-script.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +# This script is to launch the script in parallel across all the nodes. + +mount_point="/mnt/glusterfs" +path_to_script="$mount_point}/benchmark/local-script.sh" + +num_hosts=8 + +for i in $(seq 1 $num_hosts); do  +    ssh node$i path_to_script & +done + +sleep 3; + +touch ${mount_point}/benchmark/start-test + + diff --git a/extras/benchmarking/local-script.sh b/extras/benchmarking/local-script.sh new file mode 100755 index 00000000000..80a7fafe816 --- /dev/null +++ b/extras/benchmarking/local-script.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# This script needs to be present on glusterfs mount, (ie, on every node which wants to run benchmark) + +ifilename="/dev/zero" +ofilename="testdir/testfile.$(hostname)" +result="output/output.$(hostname)" +blocksize=128k +count=8 + +mkdir -p testdir; +mkdir -p output; +echo > ${result} +while [ ! -e start-test ]; do +    sleep 1; +done; + + +for i in $(seq 1 5); do  +    # write +    dd if=${ifilename} of=${ofilename} bs=${blocksize} count=${count} 2>&1 | tail -n 1 | cut -f 8,9 -d ' ' >> ${result} ; +    # read +    #dd if=${ofilename} of=/dev/null bs=${blocksize} count=${count} 2>&1 | tail -n 1 | cut -f 8,9 -d ' ' >> ${result} ; +done + +rm -f start-test diff --git a/extras/glusterfs-mode.el b/extras/glusterfs-mode.el new file mode 100644 index 00000000000..e65fbf4604a --- /dev/null +++ b/extras/glusterfs-mode.el @@ -0,0 +1,112 @@ +;;; Copyright (C) 2007, 2008 Z RESEARCH Inc. <http://www.zresearch.com>
 +;;;  
 +;;; This program is free software; you can redistribute it and/or modify
 +;;; it under the terms of the GNU General Public License as published by
 +;;; the Free Software Foundation; either version 2 of the License, or
 +;;; (at your option) any later version.
 +;;;  
 +;;; This program is distributed in the hope that it will be useful,
 +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +;;; GNU General Public License for more details.
 +;;;  
 +;;; You should have received a copy of the GNU General Public License
 +;;; along with this program; if not, write to the Free Software
 +;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 +;;;  
 +
 +(defvar glusterfs-mode-hook nil)
 +
 +;; (defvar glusterfs-mode-map
 +;;   (let ((glusterfs-mode-map (make-keymap)))
 +;;     (define-key glusterfs-mode-map "\C-j" 'newline-and-indent)
 +;;     glusterfs-mode-map)
 +;;   "Keymap for WPDL major mode")
 +
 +(add-to-list 'auto-mode-alist '("\\.vol\\'" . glusterfs-mode))
 +
 +(defconst glusterfs-font-lock-keywords-1
 +  (list
 +					; "cluster/{unify,afr,stripe}" 
 +					; "performance/{io-cache,io-threads,write-behind,read-ahead,stat-prefetch}"
 +					; "protocol/{client/server}"
 +					; "features/{trash,posix-locks,fixed-id,filter}"
 +					; "stroage/posix"
 +					; "encryption/rot-13"
 +					; "debug/trace"
 +    '("\\<\\(cluster/\\(unify\\|afr\\|replicate\\|stripe\\|ha\\|dht\\|distribute\\)\\|\\performance/\\(io-\\(cache\\|threads\\)\\|write-behind\\|read-ahead\\|symlink-cache\\)\\|protocol/\\(server\\|client\\)\\|features/\\(trash\\|posix-locks\\|locks\\|path-converter\\|filter\\)\\|storage/\\(posix\\|bdb\\)\\|encryption/rot-13\\|debug/trace\\)\\>" . font-lock-keyword-face))
 +"Additional Keywords to highlight in GlusterFS mode.")
 +
 +(defconst glusterfs-font-lock-keywords-2
 +  (append glusterfs-font-lock-keywords-1
 +	  (list
 +      ; "replicate" "namespace" "scheduler" "remote-subvolume" "remote-host" 
 +      ; "auth.addr" "block-size" "remote-port" "listen-port" "transport-type"
 +      ; "limits.min-free-disk" "directory"
 +	; TODO: add all the keys here.
 +	   '("\\<\\(inode-lru-limit\\|replicate\\|namespace\\|scheduler\\|username\\|password\\|allow\\|reject\\|block-size\\|listen-port\\|transport-type\\|transport-timeout\\|directory\\|page-size\\|page-count\\|aggregate-size\\|non-blocking-io\\|client-volume-filename\\|bind-address\\|self-heal\\|read-only-subvolumes\\|read-subvolume\\|thread-count\\|cache-size\\|window-size\\|force-revalidate-timeout\\|priority\\|include\\|exclude\\|remote-\\(host\\|subvolume\\|port\\)\\|auth.\\(addr\\|login\\)\\|limits.\\(min-disk-free\\|transaction-size\\|ib-verbs-\\(work-request-\\(send-\\|recv-\\(count\\|size\\)\\)\\|port\\|mtu\\|device-name\\)\\)\\)\ \\>" . font-lock-constant-face)))
 +  "option keys in GlusterFS mode.")
 +
 +(defconst glusterfs-font-lock-keywords-3
 +  (append glusterfs-font-lock-keywords-2
 +	  (list
 +					; "option" "volume" "end-volume" "subvolumes" "type"
 +	   '("\\<\\(option\ \\|volume\ \\|subvolumes\ \\|type\ \\|end-volume\\)\\>" . font-lock-builtin-face)))
 +					;'((regexp-opt (" option " "^volume " "^end-volume" "subvolumes " " type ") t) . font-lock-builtin-face))
 +  "Minimal highlighting expressions for GlusterFS mode.")
 +
 +
 +(defvar glusterfs-font-lock-keywords glusterfs-font-lock-keywords-3
 +  "Default highlighting expressions for GlusterFS mode.")
 +
 +(defvar glusterfs-mode-syntax-table
 +  (let ((glusterfs-mode-syntax-table (make-syntax-table)))
 +    (modify-syntax-entry ?\# "<"  glusterfs-mode-syntax-table)
 +    (modify-syntax-entry ?* ". 23"  glusterfs-mode-syntax-table)
 +    (modify-syntax-entry ?\n ">#"  glusterfs-mode-syntax-table)
 +    glusterfs-mode-syntax-table)
 +  "Syntax table for glusterfs-mode")
 +
 +;; TODO: add an indentation table
 +
 +(defun glusterfs-indent-line ()
 +  "Indent current line as GlusterFS code"
 +  (interactive)
 +  (beginning-of-line)
 +  (if (bobp)
 +      (indent-line-to 0)   ; First line is always non-indented
 +    (let ((not-indented t) cur-indent)
 +      (if (looking-at "^[ \t]*volume\ ")
 +	  (progn
 +	    (save-excursion
 +	      (forward-line -1)
 +	      (setq not-indented nil)
 +	      (setq cur-indent 0))))
 +      (if (looking-at "^[ \t]*end-volume")
 +	  (progn
 +	    (save-excursion
 +	      (forward-line -1)
 +	      (setq cur-indent 0))
 +	    (if (< cur-indent 0) ; We can't indent past the left margin
 +		(setq cur-indent 0)))
 +	(save-excursion
 +	  (while not-indented ; Iterate backwards until we find an indentation hint
 +	    (progn
 +	      (setq cur-indent 2) ; Do the actual indenting
 +	      (setq not-indented nil)))))
 +      (if cur-indent
 +	  (indent-line-to cur-indent)
 +	(indent-line-to 0)))))
 +
 +(defun glusterfs-mode ()
 +  (interactive)
 +  (kill-all-local-variables)
 +  ;; (use-local-map glusterfs-mode-map)
 +  (set-syntax-table glusterfs-mode-syntax-table)
 +  (set (make-local-variable 'indent-line-function) 'glusterfs-indent-line)  
 +  (set (make-local-variable 'font-lock-defaults) '(glusterfs-font-lock-keywords))
 +  (setq major-mode 'glusterfs-mode)
 +  (setq mode-name "GlusterFS")
 +  (run-hooks 'glusterfs-mode-hook))
 +
 +(provide 'glusterfs-mode)
 diff --git a/extras/glusterfs.vim b/extras/glusterfs.vim new file mode 100644 index 00000000000..0de6b5b2f1f --- /dev/null +++ b/extras/glusterfs.vim @@ -0,0 +1,211 @@ +" glusterfs.vim: GNU Vim Syntax file for GlusterFS .vol specification +" Copyright (C) 2007 Z RESEARCH, Inc. <http://www.zresearch.com> +" This file is part of GlusterFS. +" +" GlusterFS is free software; you can redistribute it and/or modify +" it under the terms of the GNU General Public License as published +" by the Free Software Foundation; either version 3 of the License, +" or (at your option) any later version. +" +" GlusterFS is distributed in the hope that it will be useful, but +" WITHOUT ANY WARRANTY; without even the implied warranty of +" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +" General Public License for more details. +" +" You should have received a copy of the GNU General Public License +" along with this program.  If not, see +" <http://www.gnu.org/licenses/>. +" +" Last Modified: Wed Aug  1 00:47:10 IST 2007 +" Version: 0.8  + +syntax clear +syntax case match + +setlocal iskeyword+=- +setlocal iskeyword+=% +setlocal iskeyword+=. +setlocal iskeyword+=* +setlocal iskeyword+=: +setlocal iskeyword+=, + + +"************************************************************************ +" Initially, consider everything an error. Then start eliminating one +"   field after the other. Whatever is not eliminated (due to defined +"   properties) is an error - Multiples Values for a key +"************************************************************************ +syn match glusterfsError /[^ 	]\+/ skipwhite +syn match glusterfsComment "#.*" contains=glusterfsTodo + +syn keyword	glusterfsTodo	contained TODO FIXME NOTE + +"------------------------------------------------------------------------ +" 'Type' Begin +"------------------------------------------------------------------------ +" Handle all the 'Type' keys and values. Here, a '/' is used to separate +" the key-value pair, they are clubbed together for convenience +syn match glusterfsType "^\s*type\s\+" skipwhite nextgroup=glusterfsTypeKeyVal + +syn match glusterfsTypeKeyVal contained "\<protocol/\(client\|server\)\>" +syn match glusterfsTypeKeyVal contained "\<cluster/\(unify\|afr\|stripe\)\>" +syn match glusterfsTypeKeyVal contained "\<debug/\(trace\)\>" +syn match glusterfsTypeKeyVal contained "\<encryption/\(rot-13\)\>" +syn match glusterfsTypeKeyVal contained "\<storage/\(posix\)\>" +"syn match glusterfsTypeKeyVal contained "\<features/\(trash\)\>" +syn match glusterfsTypeKeyVal contained "\<features/\(trash\|posix-locks\|fixed-id\|filter\)\>" +syn match glusterfsTypeKeyVal contained "\<performance/\(io-threads\|write-behind\|io-cache\|read-ahead\)\>" +"------------------------------------------------------------------------ +" 'Type' End +"------------------------------------------------------------------------ + + +"************************************************************************ + +"------------------------------------------------------------------------ +" 'Volume' Begin +"------------------------------------------------------------------------ +" NOTE 1: Only one volume name allowed after 'volume' keyword +" NOTE 2: Multiple volumes allowed after 'subvolumes' +" NOTE 3: Some other options (like remote-subvolume, namespace etc) use +"   volume name (single) +syn match glusterfsVol "^\s*volume\s\+" nextgroup=glusterfsVolName +syn match glusterfsVolName "\<\k\+" contained + +syn match glusterfsVol "^\s*subvolumes\s\+" skipwhite nextgroup=glusterfsSubVolName +syn match glusterfsSubVolName "\<\k\+\>" skipwhite contained nextgroup=glusterfsSubVolName + +syn match glusterfsVol "^\s*end-volume\>" +"------------------------------------------------------------------------ +" 'Volume' End +"------------------------------------------------------------------------ + + + + + +"------------------------------------------------------------------------ +" 'Options' Begin +"------------------------------------------------------------------------ +syn match glusterfsOpt "^\s*option\s\+" nextgroup=glusterfsOptKey + + +syn keyword glusterfsOptKey contained transport-type skipwhite nextgroup=glusterfsOptValTransportType +syn match glusterfsOptValTransportType contained "\<\(tcp\|ib\-verbs\|ib-sdp\)/\(client\|server\)\>" + +syn keyword glusterfsOptKey contained remote-subvolume skipwhite nextgroup=glusterfsVolName + +syn keyword glusterfsOptKey contained auth.addr.ra8.allow auth.addr.ra7.allow auth.addr.ra6.allow auth.addr.ra5.allow auth.addr.ra4.allow auth.addr.ra3.allow auth.addr.ra2.allow auth.addr.ra1.allow auth.addr.brick-ns.allow skipwhite nextgroup=glusterfsOptVal + +syn keyword glusterfsOptKey contained client-volume-filename directory trash-dir skipwhite nextgroup=glusterfsOpt_Path +syn match glusterfsOpt_Path contained "\s\+\f\+\>" + +syn keyword glusterfsOptKey contained debug self-heal encrypt-write decrypt-read mandatory nextgroup=glusterfsOpt_OnOff +syn match glusterfsOpt_OnOff contained "\s\+\(on\|off\)\>" + +syn keyword glusterfsOptKey contained flush-behind non-blocking-connect nextgroup=glusterfsOpt_OnOffNoYes +syn keyword glusterfsOpt_OnOffNoYes contained on off no yes + +syn keyword glusterfsOptKey contained page-size cache-size nextgroup=glusterfsOpt_Size + +syn keyword glusterfsOptKey contained fixed-gid fixed-uid cache-seconds page-count thread-count aggregate-size listen-port remote-port transport-timeout inode-lru-limit nextgroup=glusterfsOpt_Number + +syn keyword glusterfsOptKey contained alu.disk-usage.entry-threshold alu.disk-usage.exit-threshold nextgroup=glusterfsOpt_Size + +syn keyword glusterfsOptKey contained alu.order skipwhite nextgroup=glusterfsOptValAluOrder +syn match glusterfsOptValAluOrder contained "\s\+\(\(disk-usage\|write-usage\|read-usage\|open-files-usage\|disk-speed\):\)*\(disk-usage\|write-usage\|read-usage\|open-files-usage\|disk-speed\)\>" + +syn keyword glusterfsOptKey contained alu.open-files-usage.entry-threshold alu.open-files-usage.exit-threshold alu.limits.max-open-files rr.refresh-interval random.refresh-interval nufa.refresh-interval nextgroup=glusterfsOpt_Number + +syn keyword glusterfsOptKey contained nufa.local-volume-name skipwhite nextgroup=glusterfsVolName + +syn keyword glusterfsOptKey contained ib-verbs-work-request-send-size ib-verbs-work-request-recv-size nextgroup=glusterfsOpt_Size +syn match glusterfsOpt_Size contained "\s\+\d\+\([gGmMkK][bB]\)\=\>" + +syn keyword glusterfsOptKey contained ib-verbs-work-request-send-count ib-verbs-work-request-recv-count ib-verbs-port nextgroup=glusterfsOpt_Number + +syn keyword glusterfsOptKey contained ib-verbs-mtu nextgroup=glusterfsOptValIBVerbsMtu +syn match glusterfsOptValIBVerbsMtu "\s\+\(256\|512\|1024\|2048\|4096\)\>" contained + +syn keyword glusterfsOptKey contained ib-verbs-device-name nextgroup=glusterfsOptVal + +syn match glusterfsOpt_Number contained "\s\+\d\+\>" + +syn keyword glusterfsOptKey contained scheduler skipwhite nextgroup=glusterfsOptValScheduler +syn keyword glusterfsOptValScheduler contained rr alu random nufa + +syn keyword glusterfsOptKey contained namespace skipwhite nextgroup=glusterfsVolName + +syn keyword glusterfsOptKey contained lock-node skipwhite nextgroup=glusterfsVolName + + + +syn keyword glusterfsOptKey contained alu.write-usage.entry-threshold alu.write-usage.exit-threshold alu.read-usage.entry-threshold alu.read-usage.exit-threshold alu.limits.min-free-disk nextgroup=glusterfsOpt_Percentage + +syn keyword glusterfsOptKey contained random.limits.min-free-disk nextgroup=glusterfsOpt_Percentage +syn keyword glusterfsOptKey contained rr.limits.min-disk-free nextgroup=glusterfsOpt_Size + +syn keyword glusterfsOptKey contained nufa.limits.min-free-disk nextgroup=glusterfsOpt_Percentage + +syn match glusterfsOpt_Percentage contained "\s\+\d\+%\=\>" + + + + + + + + + +syn keyword glusterfsOptKey contained remote-host bind-address nextgroup=glusterfsOpt_IP,glusterfsOpt_Domain +syn match glusterfsOpt_IP contained "\s\+\d\d\=\d\=\.\d\d\=\d\=\.\d\d\=\d\=\.\d\d\=\d\=\>" +syn match glusterfsOpt_Domain contained "\s\+\a[a-zA-Z0-9_-]*\(\.\a\+\)*\>" + +syn match glusterfsVolNames "\s*\<\S\+\>" contained skipwhite nextgroup=glusterfsVolNames + +syn keyword glusterfsOptKey contained block-size replicate skipwhite nextgroup=glusterfsOpt_Pattern + +syn match glusterfsOpt_Pattern contained "\s\+\k\+\>" +syn match glusterfsOptVal contained "\s\+\S\+\>" + + + + + +hi link glusterfsError Error +hi link glusterfsComment Comment + +hi link glusterfsVol keyword + +hi link glusterfsVolName function +hi link glusterfsSubVolName function + +hi link glusterfsType Keyword +hi link glusterfsTypeKeyVal String + +hi link glusterfsOpt Keyword + +hi link glusterfsOptKey Special +hi link glusterfsOptVal Normal + +hi link glusterfsOptValTransportType String +hi link glusterfsOptValScheduler String +hi link glusterfsOptValAluOrder String +hi link glusterfsOptValIBVerbsMtu String + +hi link glusterfsOpt_OnOff String +hi link glusterfsOpt_OnOffNoYes String + + +" Options that require +hi link glusterfsOpt_Size PreProc +hi link glusterfsOpt_Domain PreProc +hi link glusterfsOpt_Percentage PreProc +hi link glusterfsOpt_IP PreProc +hi link glusterfsOpt_Pattern PreProc +hi link glusterfsOpt_Number Preproc +hi link glusterfsOpt_Path Preproc + + + +let b:current_syntax = "glusterfs" diff --git a/extras/init.d/Makefile.am b/extras/init.d/Makefile.am new file mode 100644 index 00000000000..608b5bb2d4d --- /dev/null +++ b/extras/init.d/Makefile.am @@ -0,0 +1,9 @@ + +EXTRA_DIST = glusterfsd glusterfs-server glusterfs-server.plist + +CLEANFILES =  + +install-data-am: +if GF_DARWIN_HOST_OS +	cp glusterfs-server.plist /Library/LaunchDaemons/com.zresearch.glusterfs.plist +endif diff --git a/extras/init.d/glusterfs-server b/extras/init.d/glusterfs-server new file mode 100755 index 00000000000..975283982b2 --- /dev/null +++ b/extras/init.d/glusterfs-server @@ -0,0 +1,100 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides:          glusterfsd +# Required-Start:    $local_fs $network +# Required-Stop:     $local_fs $network +# Default-Start:     2 3 4 5 +# Default-Stop:      0 1 6 +# Short-Description: gluster server +# Description:       This file starts / stops the gluster server +### END INIT INFO + +# Author: Chris AtLee <chris@atlee.ca> +# Patched by: Matthias Albert < matthias@linux4experts.de> + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +NAME=glusterfsd +SCRIPTNAME=/etc/init.d/$NAME +DAEMON=/usr/sbin/$NAME +PIDFILE=/var/run/$NAME.pid +CONFIGFILE=/etc/glusterfs/server.vol +GLUSTERFS_OPTS="-f $CONFIGFILE" +PID=`test -f $PIDFILE && cat $PIDFILE` + + +# Gracefully exit if the package has been removed. +test -x $DAEMON || exit 0 + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +. /lib/lsb/init-functions + +check_config() +{ +  if [ ! -f "$CONFIGFILE" ]; then +    echo "Config file $CONFIGFILE is missing...exiting!" +    exit 0 +  fi +} + +do_start() +{ +    check_config; +    pidofproc -p $PIDFILE $DAEMON >/dev/null +    status=$? +    if [ $status -eq 0 ]; then +      log_success_msg "glusterfs server is already running with pid $PID" +    else +      log_daemon_msg "Starting glusterfs server" "glusterfsd" +      start-stop-daemon --start --quiet --oknodo --pidfile $PIDFILE --startas $DAEMON -- -p $PIDFILE $GLUSTERFS_OPTS +      log_end_msg $? +      start_daemon -p $PIDFILE $DAEMON -f $CONFIGFILE +      return $? +    fi +} + +do_stop() +{ +    log_daemon_msg "Stopping glusterfs server" "glusterfsd" +    start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE +    log_end_msg $? +    rm -f $PIDFILE +    killproc -p $PIDFILE $DAEMON +    return $? +} + +do_status() +{ +     pidofproc -p $PIDFILE $DAEMON >/dev/null +     status=$? +     if [ $status -eq 0 ]; then +       log_success_msg "glusterfs server is running with pid $PID" +     else +       log_failure_msg "glusterfs server is not running." +     fi +     exit $status +} + +case "$1" in +  start) +        do_start +        ;; +  stop) +        do_stop +        ;; +  status) +        do_status; +        ;; +  restart|force-reload) +        do_stop +        sleep 2 +        do_start +        ;; +  *) +        echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 +        exit 3 +        ;; +esac + diff --git a/extras/init.d/glusterfs-server.plist.in b/extras/init.d/glusterfs-server.plist.in new file mode 100644 index 00000000000..4d2287c5759 --- /dev/null +++ b/extras/init.d/glusterfs-server.plist.in @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> +        <key>Label</key> +        <string>com.zresearch.glusterfs</string> +        <key>ProgramArguments</key> +        <array> +                <string>@prefix@/sbin/glusterfsd</string> +                <string>-N</string> +                <string>-f</string> +                <string>@prefix@/etc/glusterfs/server.vol</string> +        </array> +</dict> +</plist> diff --git a/extras/init.d/glusterfsd b/extras/init.d/glusterfsd new file mode 100755 index 00000000000..866a0010e9a --- /dev/null +++ b/extras/init.d/glusterfsd @@ -0,0 +1,110 @@ +#!/bin/bash +# +# chkconfig: 35 90 12 +# description: Glusterfsd server +# + +# Get function from functions library +# . /etc/rc.d/init.d/functions + +BASE=glusterfsd +GSERVER="/sbin/$BASE -f /etc/glusterfs/glusterfs-server.vol" + +# A function to stop gluster +killgluster() +{ +       killlevel="-9" +       # Find pid. +       pid= +       if [ -f /var/run/$BASE.pid ]; then +               local line p +               read line < /var/run/$BASE.pid +               for p in $line ; do +                       [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid="$pid +$p" +               done +       fi +       if [ -z "$pid" ]; then +               pid=`pidof -o $$ -o $PPID -o %PPID -x $1 || \ +                       pidof -o $$ -o $PPID -o %PPID -x $BASE` +       fi +       # Kill it. +       kill $killlevel $pid +       if [ "$?" = 0 ] +         then +            echo "Gluster process $pid has been killed" +            initlog -n "Kill gluster" -e 1 +         else +            echo "Failed: Gluster process $pid has not been killed" +            initlog -n "Kill gluster" -e 2 +       fi + +       # Remove pid and lock file if any. +        if [ -f /var/run/$BASE.pid ] +           then +             rm -f /var/run/$BASE.pid && initlog -n "Remove $BASE.pid:" -e +1 +           else echo "$BASE.pid not found" && initlog -n "Remove +$BASE.pid:" -e 2 +        fi + +        if [ -f /var/lock/subsys/$BASE ] +           then +             rm -f /var/lock/subsys/$BASE && initlog -n "Remove $BASE lock +file:" -e 1 +           else echo "$BASE lock file not found" && initlog -n "Remove +$BASE lock file:" -e 2 +        fi +} + +# Start the service $BASE +start() +{ +       initlog -c "echo -n Starting $BASE:" +       $GSERVER +       if [ $? = 0 ] +        then +          touch /var/lock/subsys/$BASE +          initlog -n "Starting $BASE" -e 1 +          echo "  [OK]" +        else +          echo "$BASE start failed." +          initlog -n "$BASE start" -e 2 +       fi +} + +# Stop the service $BASE +stop() +{ +       echo "Stopping $BASE:" +       killgluster +} +status() +{ +       if test "`lsof |grep -c /sbin/$BASE`" = "0" +         then echo "$BASE is stopped." +         else echo "$BASE is running..." +       fi +} + +### service arguments ### +case $1 in + start) +       start +       ;; + stop) +       stop +       ;; + status) +       status +       ;; + restart|reload|condrestart) +       stop +       start +       ;; + *) +       echo $.Usage: $0 {start|stop|restart|reload|status}. +       exit 1 +esac + +exit 0 diff --git a/extras/specgen.scm b/extras/specgen.scm new file mode 100755 index 00000000000..279afe896ca --- /dev/null +++ b/extras/specgen.scm @@ -0,0 +1,98 @@ +#!/usr/bin/guile -s +!# + +;;; Copyright (C) 2007 Z RESEARCH Inc. <http://www.zresearch.com> +;;;   +;;; This program is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 2 of the License, or +;;; (at your option) any later version. +;;;   +;;; This program is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +;;; GNU General Public License for more details. +;;;   +;;; You should have received a copy of the GNU General Public License +;;; along with this program; if not, write to the Free Software +;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +;;;   + +;;; This script lets you specify the xlator graph as a Scheme list +;;; and provides a function to generate the spec file for the graph. + + +(define (volume args) +  (apply +   (lambda (name type options) +     (lambda args +       (display "volume ") (display name) (newline) +       (display "  type ") (display type) (newline) +       (map (lambda (key-value-cons) +	      (let ((key (car key-value-cons)) +		    (value (cdr key-value-cons))) +		(display "  option ") (display key) (display " ") +		(display value) (newline))) +	    options) +       (if (> (length args) 0) +	   (begin +	     (display "  subvolumes ") +	     (map (lambda (subvol) +		    (display subvol) (display " ")) +		  args) +	     (newline))) +       (display "end-volume") (newline) (newline) +       name)) +   args)) + +;; define volumes with names/type/options and bind to a symbol +;; relate them seperately (see below) +;; more convinient to seperate volume definition and relation + +(define wb (volume '(wb0 +		     performance/write-behind +		     ((aggregate-size . 0) +		      (flush-behind . off) +		      )))) + +(define ra (volume '(ra0 +		     performance/read-ahead +		     ((page-size . 128KB) +		      (page-count . 1) +		      )))) + +(define ioc (volume '(ioc0 +		      performance/io-cache +		      ((page-size . 128KB) +		       (cache-size . 64MB) +		      )))) + +(define iot (volume '(iot0 +		      performance/io-threads +		      () +		      ))) + +(define client1 (volume '(client1 +			  protocol/client +			  ((transport-type . tcp/client) +			   (remote-host . localhost) +			   (remote-subvolume . brick1) +			   )))) + +(define client2 (volume '(client2 +			  protocol/client +			  ((transport-type . tcp/client) +			   (remote-host . localhost) +			   (remote-subvolume . brick2) +			   )))) + +(define unify (volume '(unify0 +			cluster/unify +			((scheduler . rr) +			 )))) + +;; relate the symbols to output a spec file +;; note: relating with symbols lets you change volume name in one place + +(wb (ra (ioc (iot (unify (client1) +			 (client2)))))) diff --git a/extras/stripe-merge.c b/extras/stripe-merge.c new file mode 100644 index 00000000000..3f8e4b1244d --- /dev/null +++ b/extras/stripe-merge.c @@ -0,0 +1,48 @@ +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + +int +main (int argc, char *argv[]) +{ +	int fds[argc-1]; +	char buf[argc-1][4096]; +	int i; +	int max_ret, ret; + +	if (argc < 2) { +		printf ("Usage: %s file1 file2 ... >file\n", argv[0]); +		return 1; +	} + +	for (i=0; i<argc-1; i++) { +		fds[i] = open (argv[i+1], O_RDONLY); +		if (fds[i] == -1) { +			perror (argv[i+1]); +			return 1; +		} +	} + +	max_ret = 0; +	do { +		char newbuf[4096] = {0, }; +		int j; + +		max_ret = 0; +		for (i=0; i<argc-1; i++) { +			memset (buf[i], 0, 4096); +			ret = read (fds[i], buf[i], 4096);  +			if (ret > max_ret) +				max_ret = ret; +		} +		for (i=0; i<max_ret;i++) +			for (j=0; j<argc-1; j++) +				newbuf[i] |= buf[j][i]; +		write (1, newbuf, max_ret); +	} while (max_ret); + +	return 0; +} + diff --git a/extras/test/Makefile.am b/extras/test/Makefile.am new file mode 100644 index 00000000000..e6877054991 --- /dev/null +++ b/extras/test/Makefile.am @@ -0,0 +1,3 @@ +bin_PROGRAMS = rdd +rdd_SOURCES = rdd.c +AM_CFLAGS = -pthread diff --git a/extras/test/rdd.c b/extras/test/rdd.c new file mode 100644 index 00000000000..3636c636d16 --- /dev/null +++ b/extras/test/rdd.c @@ -0,0 +1,457 @@ +/* +  Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.com> +  This file is part of GlusterFS. + +  GlusterFS is free software; you can redistribute it and/or modify +  it under the terms of the GNU General Public License as published +  by the Free Software Foundation; either version 3 of the License, +  or (at your option) any later version. + +  GlusterFS is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with this program.  If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> +#include <pthread.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <argp.h> + +#define TWO_POWER(power) (2UL << (power)) + +#define RDD_INTEGER_VALUE ((TWO_POWER ((sizeof (int) * 8))) - 1) + +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 +#endif + +struct rdd_file { +	char path[UNIX_PATH_MAX]; +	struct stat st; +	int fd; +}; +  +struct rdd_config { +	long iters; +	long max_ops_per_seq; +	size_t max_bs; +	size_t min_bs; +	int thread_count; +	pthread_t *threads; +	pthread_barrier_t barrier; +	pthread_mutex_t lock; +	struct rdd_file in_file; +	struct rdd_file out_file; +}; +static struct rdd_config rdd_config; + +enum rdd_keys { +	RDD_MIN_BS_KEY = 1, +	RDD_MAX_BS_KEY, +}; +  +static error_t +rdd_parse_opts (int key, char *arg, +		struct argp_state *_state) +{ +	switch (key) { +	case 'o': +	{ +		int len = 0; +		len = strlen (arg); +		if (len > UNIX_PATH_MAX) { +			fprintf (stderr, "output file name too long (%s)\n", arg); +			return -1; +		} + +		strncpy (rdd_config.out_file.path, arg, len); +	} +	break; + +	case 'i': +	{ +		int len = 0; +		len = strlen (arg); +		if (len > UNIX_PATH_MAX) { +			fprintf (stderr, "input file name too long (%s)\n", arg); +			return -1; +		} + +		strncpy (rdd_config.in_file.path, arg, len); +	} +	break; + +	case RDD_MIN_BS_KEY: +	{ +		char *tmp = NULL; +		long bs = 0; +		bs = strtol (arg, &tmp, 10); +		if ((bs == LONG_MAX) || (bs == LONG_MIN) || (tmp && *tmp)) { +			fprintf (stderr, "invalid argument for minimum block size (%s)\n", arg); +			return -1; +		} + +		rdd_config.min_bs = bs; +	} +	break; + +	case RDD_MAX_BS_KEY: +	{ +		char *tmp = NULL; +		long bs = 0; +		bs = strtol (arg, &tmp, 10); +		if ((bs == LONG_MAX) || (bs == LONG_MIN) || (tmp && *tmp)) { +			fprintf (stderr, "invalid argument for maximum block size (%s)\n", arg); +			return -1; +		} + +		rdd_config.max_bs = bs; +	} +	break; + +	case 'r': +	{ +		char *tmp = NULL; +		long iters = 0; +		iters = strtol (arg, &tmp, 10); +		if ((iters == LONG_MAX) || (iters == LONG_MIN) || (tmp && *tmp)) { +			fprintf (stderr, "invalid argument for iterations (%s)\n", arg); +			return -1; +		} + +		rdd_config.iters = iters; +	} +	break; + +	case 'm': +	{ +		char *tmp = NULL; +		long max_ops = 0; +		max_ops = strtol (arg, &tmp, 10); +		if ((max_ops == LONG_MAX) || (max_ops == LONG_MIN) || (tmp && *tmp)) { +			fprintf (stderr, "invalid argument for max-ops (%s)\n", arg); +			return -1; +		} + +		rdd_config.max_ops_per_seq = max_ops; +	} +	break; + +	case 't': +	{ +		char *tmp = NULL; +		long threads = 0; +		threads = strtol (arg, &tmp, 10); +		if ((threads == LONG_MAX) || (threads == LONG_MIN) || (tmp && *tmp)) { +			fprintf (stderr, "invalid argument for thread count (%s)\n", arg); +			return -1; +		} + +		rdd_config.thread_count = threads; +	} +	break; + +	case ARGP_KEY_NO_ARGS: +		break; +	case ARGP_KEY_ARG: +		break; +	case ARGP_KEY_END: +		if (_state->argc == 1) { +			argp_usage (_state);  +		} + +	} + +	return 0; +} + +static struct argp_option rdd_options[] = { +	{"if", 'i', "INPUT_FILE", 0, "input-file"}, +	{"of", 'o', "OUTPUT_FILE", 0, "output-file"}, +	{"threads", 't', "COUNT", 0, "number of threads to spawn (defaults to 2)"}, +	{"min-bs", RDD_MIN_BS_KEY, "MIN_BLOCK_SIZE", 0,  +	 "Minimum block size in bytes (defaults to 1024)"}, +	{"max-bs", RDD_MAX_BS_KEY, "MAX_BLOCK_SIZE", 0, +	 "Maximum block size in bytes (defaults to 4096)"}, +	{"iters", 'r', "ITERS", 0, +	 "Number of read-write sequences (defaults to 1000000)"}, +	{"max-ops", 'm', "MAXOPS", 0, +	 "maximum number of read-writes to be performed in a sequence (defaults to 1)"}, +	{0, 0, 0, 0, 0} +}; + +static struct argp argp = { +  rdd_options, +  rdd_parse_opts, +  "", +  "random dd - tool to do a sequence of random block-sized continuous read writes starting at a random offset" +}; + + +static void +rdd_default_config (void) +{ +	rdd_config.thread_count = 2; +	rdd_config.iters = 1000000; +	rdd_config.max_bs = 4096; +	rdd_config.min_bs = 1024; +	rdd_config.in_file.fd = rdd_config.out_file.fd = -1; +	rdd_config.max_ops_per_seq = 1; + +	return; +} + + +static char +rdd_valid_config (void) +{ +	char ret = 1; +	int fd = -1; + +	fd = open (rdd_config.in_file.path, O_RDONLY); +	if (fd == -1) { +		ret = 0; +		goto out; +	} +	close (fd); + +	if (rdd_config.min_bs > rdd_config.max_bs) { +		ret = 0; +		goto out; +	} + +	if (strlen (rdd_config.out_file.path) == 0) { +		sprintf (rdd_config.out_file.path, "%s.rddout", rdd_config.in_file.path); +	} + +out: +	return ret; +} + + +static void * +rdd_read_write (void *arg) +{ +	int i = 0, ret = 0; +	size_t bs = 0; +	off_t offset = 0; +	long rand = 0; +	long max_ops = 0; +	char *buf = NULL; + +	buf = CALLOC (1, rdd_config.max_bs); +	if (!buf) { +		fprintf (stderr, "calloc failed (%s)\n", strerror (errno)); +		ret = -1; +		goto out; +	} + +	for (i = 0; i < rdd_config.iters; i++)  +	{ +		pthread_mutex_lock (&rdd_config.lock); +		{ +			int bytes = 0; +			rand = random (); +			 +			if (rdd_config.min_bs == rdd_config.max_bs) { +				bs = rdd_config.max_bs; +			} else { +				bs = rdd_config.min_bs + (rand % (rdd_config.max_bs - rdd_config.min_bs)); +			} +			 +			offset = rand % rdd_config.in_file.st.st_size; +			max_ops = rand % rdd_config.max_ops_per_seq; +			if (!max_ops) { +				max_ops ++; +			} + +			ret = lseek (rdd_config.in_file.fd, offset, SEEK_SET); +			if (ret != offset) { +				fprintf (stderr, "lseek failed (%s)\n", strerror (errno)); +				ret = -1; +				goto unlock; +			} + +			ret = lseek (rdd_config.out_file.fd, offset, SEEK_SET); +			if (ret != offset) { +				fprintf (stderr, "lseek failed (%s)\n", strerror (errno)); +				ret = -1; +				goto unlock; +			} + +			while (max_ops--)  +			{  +				bytes = read (rdd_config.in_file.fd, buf, bs); +				if (!bytes) { +					break; +				} + +				if (bytes == -1) { +					fprintf (stderr, "read failed (%s)\n", strerror (errno)); +					ret = -1; +					goto unlock; +				} + +				if (write (rdd_config.out_file.fd, buf, bytes) != bytes) { +					fprintf (stderr, "write failed (%s)\n", strerror (errno)); +					ret = -1; +					goto unlock; +				} +			} +		} +	unlock: +		pthread_mutex_unlock (&rdd_config.lock); +		if (ret == -1) { +			goto out; +		} +		ret = 0; +	} +out: +	free (buf); +	pthread_barrier_wait (&rdd_config.barrier); + +	return NULL; +} + + +static int +rdd_spawn_threads (void) +{ +	int i = 0, ret = -1, fd = -1; +	char buf[4096];  + +	fd = open (rdd_config.in_file.path, O_RDONLY); +	if (fd < 0) { +		fprintf (stderr, "cannot open %s (%s)\n", rdd_config.in_file.path, strerror (errno)); +		ret = -1; +		goto out; +	} +	ret = fstat (fd, &rdd_config.in_file.st); +	if (ret != 0) { +		close (fd); +		fprintf (stderr, "cannot stat %s (%s)\n", rdd_config.in_file.path, strerror (errno)); +		ret = -1; +		goto out; +	} +	rdd_config.in_file.fd = fd; + +	fd = open (rdd_config.out_file.path, O_WRONLY | O_CREAT, S_IRWXU | S_IROTH); +	if (fd < 0) { +		close (rdd_config.in_file.fd); +		rdd_config.in_file.fd = -1; +		fprintf (stderr, "cannot open %s (%s)\n", rdd_config.out_file.path, strerror (errno)); +		ret = -1; +		goto out; +	} +	rdd_config.out_file.fd = fd; + +	while ((ret = read (rdd_config.in_file.fd, buf, 4096)) > 0) { +		if (write (rdd_config.out_file.fd, buf, ret) != ret) { +			fprintf (stderr, "write failed (%s)\n", strerror (errno)); +			close (rdd_config.in_file.fd); +			close (rdd_config.out_file.fd); +			rdd_config.in_file.fd = rdd_config.out_file.fd = -1; +			ret = -1; +			goto out; +		} +	} + +	rdd_config.threads = CALLOC (rdd_config.thread_count, sizeof (pthread_t)); +	if (rdd_config.threads == NULL) { +		fprintf (stderr, "calloc() failed (%s)\n", strerror (errno)); + +		ret = -1; +		close (rdd_config.in_file.fd); +		close (rdd_config.out_file.fd); +		rdd_config.in_file.fd = rdd_config.out_file.fd = -1; +		goto out; +	} + +	ret = pthread_barrier_init (&rdd_config.barrier, NULL, rdd_config.thread_count + 1); +	if (ret != 0) { +		fprintf (stderr, "pthread_barrier_init() failed (%s)\n", strerror (ret)); + +		free (rdd_config.threads); +		close (rdd_config.in_file.fd); +		close (rdd_config.out_file.fd); +		rdd_config.in_file.fd = rdd_config.out_file.fd = -1; +		ret = -1; +		goto out; +	} + +	ret = pthread_mutex_init (&rdd_config.lock, NULL); +	if (ret != 0) { +		fprintf (stderr, "pthread_mutex_init() failed (%s)\n", strerror (ret)); + +		free (rdd_config.threads); +		pthread_barrier_destroy (&rdd_config.barrier); +		close (rdd_config.in_file.fd); +		close (rdd_config.out_file.fd); +		rdd_config.in_file.fd = rdd_config.out_file.fd = -1; +		ret = -1; +		goto out; +	} + +	for (i = 0; i < rdd_config.thread_count; i++) +	{ +		ret = pthread_create (&rdd_config.threads[i], NULL, rdd_read_write, NULL); +		if (ret != 0) { +			fprintf (stderr, "pthread_create failed (%s)\n", strerror (errno)); +			exit (1); +		} +	} + +out: +	return ret; +} + + +static void +rdd_wait_for_completion (void) +{ +	pthread_barrier_wait (&rdd_config.barrier); +} + + +int  +main (int argc, char *argv[]) +{ +	int ret = -1; + +	rdd_default_config (); + +	ret = argp_parse (&argp, argc, argv, 0, 0, NULL); +	if (ret != 0) { +		ret = -1; +		fprintf (stderr, "%s: argp_parse() failed\n", argv[0]); +		goto err; +	} + +	if (!rdd_valid_config ()) { +		ret = -1; +		fprintf (stderr, "%s: configuration validation failed\n", argv[0]); +		goto err; +	} + +	ret = rdd_spawn_threads (); +	if (ret != 0) { +		fprintf (stderr, "%s: spawning threads failed\n", argv[0]); +		goto err; +	} + +	rdd_wait_for_completion (); + +err: +	return ret; +}   | 
