summaryrefslogtreecommitdiffstats
path: root/extras
diff options
context:
space:
mode:
authorVikas Gorur <vikas@zresearch.com>2009-02-18 17:36:07 +0530
committerVikas Gorur <vikas@zresearch.com>2009-02-18 17:36:07 +0530
commit77adf4cd648dce41f89469dd185deec6b6b53a0b (patch)
tree02e155a5753b398ee572b45793f889b538efab6b /extras
parentf3b2e6580e5663292ee113c741343c8a43ee133f (diff)
Added all files
Diffstat (limited to 'extras')
-rw-r--r--extras/Makefile.am13
-rw-r--r--extras/Portfile26
-rw-r--r--extras/benchmarking/Makefile.am7
-rw-r--r--extras/benchmarking/README18
-rw-r--r--extras/benchmarking/glfs-bm.c619
-rwxr-xr-xextras/benchmarking/launch-script.sh18
-rwxr-xr-xextras/benchmarking/local-script.sh26
-rw-r--r--extras/glusterfs-mode.el112
-rw-r--r--extras/glusterfs.vim211
-rw-r--r--extras/init.d/Makefile.am9
-rwxr-xr-xextras/init.d/glusterfs-server100
-rw-r--r--extras/init.d/glusterfs-server.plist.in15
-rwxr-xr-xextras/init.d/glusterfsd110
-rwxr-xr-xextras/specgen.scm98
-rw-r--r--extras/stripe-merge.c48
-rw-r--r--extras/test/Makefile.am3
-rw-r--r--extras/test/rdd.c457
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;
+}