summaryrefslogtreecommitdiffstats
path: root/libglusterfs
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 /libglusterfs
parentf3b2e6580e5663292ee113c741343c8a43ee133f (diff)
Added all files
Diffstat (limited to 'libglusterfs')
-rw-r--r--libglusterfs/Makefile.am3
-rw-r--r--libglusterfs/src/Makefile.am21
-rw-r--r--libglusterfs/src/authenticate.c240
-rw-r--r--libglusterfs/src/authenticate.h61
-rw-r--r--libglusterfs/src/byte-order.h150
-rw-r--r--libglusterfs/src/call-stub.c3822
-rw-r--r--libglusterfs/src/call-stub.h1104
-rw-r--r--libglusterfs/src/common-utils.c1349
-rw-r--r--libglusterfs/src/common-utils.h313
-rw-r--r--libglusterfs/src/compat-errno.c938
-rw-r--r--libglusterfs/src/compat-errno.h240
-rw-r--r--libglusterfs/src/compat.c383
-rw-r--r--libglusterfs/src/compat.h356
-rw-r--r--libglusterfs/src/defaults.c1388
-rw-r--r--libglusterfs/src/defaults.h273
-rw-r--r--libglusterfs/src/dict.c2243
-rw-r--r--libglusterfs/src/dict.h179
-rw-r--r--libglusterfs/src/event.c978
-rw-r--r--libglusterfs/src/event.h90
-rw-r--r--libglusterfs/src/fd.c611
-rw-r--r--libglusterfs/src/fd.h107
-rw-r--r--libglusterfs/src/gf-dirent.c157
-rw-r--r--libglusterfs/src/gf-dirent.h60
-rw-r--r--libglusterfs/src/glusterfs.h277
-rw-r--r--libglusterfs/src/hashfn.c89
-rw-r--r--libglusterfs/src/hashfn.h33
-rw-r--r--libglusterfs/src/inode.c1174
-rw-r--r--libglusterfs/src/inode.h160
-rw-r--r--libglusterfs/src/list.h154
-rw-r--r--libglusterfs/src/locking.h49
-rw-r--r--libglusterfs/src/logging.c207
-rw-r--r--libglusterfs/src/logging.h132
-rw-r--r--libglusterfs/src/mem-pool.c174
-rw-r--r--libglusterfs/src/mem-pool.h54
-rw-r--r--libglusterfs/src/protocol.h777
-rw-r--r--libglusterfs/src/revision.h1
-rw-r--r--libglusterfs/src/scheduler.c80
-rw-r--r--libglusterfs/src/scheduler.h40
-rw-r--r--libglusterfs/src/spec.l94
-rw-r--r--libglusterfs/src/spec.y613
-rw-r--r--libglusterfs/src/stack.h266
-rw-r--r--libglusterfs/src/timer.c220
-rw-r--r--libglusterfs/src/timer.h68
-rw-r--r--libglusterfs/src/transport.c339
-rw-r--r--libglusterfs/src/transport.h85
-rw-r--r--libglusterfs/src/xlator.c728
-rw-r--r--libglusterfs/src/xlator.h842
47 files changed, 21722 insertions, 0 deletions
diff --git a/libglusterfs/Makefile.am b/libglusterfs/Makefile.am
new file mode 100644
index 000000000..d471a3f92
--- /dev/null
+++ b/libglusterfs/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = src
+
+CLEANFILES =
diff --git a/libglusterfs/src/Makefile.am b/libglusterfs/src/Makefile.am
new file mode 100644
index 000000000..16e6717de
--- /dev/null
+++ b/libglusterfs/src/Makefile.am
@@ -0,0 +1,21 @@
+libglusterfs_la_CFLAGS = -fPIC -Wall -g -shared -nostartfiles $(GF_CFLAGS) $(GF_DARWIN_LIBGLUSTERFS_CFLAGS)
+
+libglusterfs_la_CPPFLAGS = -D_FILE_OFFSET_BITS=64 -D__USE_FILE_OFFSET64 -D_GNU_SOURCE -DXLATORDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator\" -DSCHEDULERDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/scheduler\" -DTRANSPORTDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/transport\" -D$(GF_HOST_OS) -DLIBDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/auth\"
+
+libglusterfs_la_LIBADD = @LEXLIB@
+
+lib_LTLIBRARIES = libglusterfs.la
+
+libglusterfs_la_SOURCES = dict.c spec.lex.c y.tab.c xlator.c logging.c hashfn.c defaults.c scheduler.c common-utils.c transport.c timer.c inode.c call-stub.c compat.c authenticate.c fd.c compat-errno.c event.c mem-pool.c gf-dirent.c
+
+noinst_HEADERS = common-utils.h defaults.h dict.h glusterfs.h hashfn.h logging.h protocol.h scheduler.h xlator.h transport.h stack.h timer.h list.h inode.h call-stub.h compat.h authenticate.h fd.h revision.h compat-errno.h event.h mem-pool.h byte-order.h gf-dirent.h locking.h
+
+EXTRA_DIST = spec.l spec.y
+
+spec.lex.c: spec.l y.tab.h
+ $(LEX) -t $(srcdir)/spec.l > $@
+
+y.tab.c y.tab.h: spec.y
+ $(YACC) -d $(srcdir)/spec.y
+
+CLEANFILES = spec.lex.c y.tab.c y.tab.h
diff --git a/libglusterfs/src/authenticate.c b/libglusterfs/src/authenticate.c
new file mode 100644
index 000000000..69cc8d99c
--- /dev/null
+++ b/libglusterfs/src/authenticate.c
@@ -0,0 +1,240 @@
+/*
+ Copyright (c) 2007, 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/>.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include "authenticate.h"
+
+static void
+init (dict_t *this,
+ char *key,
+ data_t *value,
+ void *data)
+{
+ void *handle = NULL;
+ char *auth_file = NULL;
+ auth_handle_t *auth_handle = NULL;
+ auth_fn_t authenticate = NULL;
+ int *error = NULL;
+
+ /* It gets over written */
+ error = data;
+
+ if (!strncasecmp (key, "ip", strlen ("ip"))) {
+ gf_log ("authenticate", GF_LOG_ERROR,
+ "AUTHENTICATION MODULE \"IP\" HAS BEEN REPLACED "
+ "BY \"ADDR\"");
+ dict_set (this, key, data_from_dynptr (NULL, 0));
+ /* TODO: 1.3.x backword compatibility */
+ // *error = -1;
+ // return;
+ key = "addr";
+ }
+
+ asprintf (&auth_file, "%s/%s.so", LIBDIR, key);
+ handle = dlopen (auth_file, RTLD_LAZY);
+ if (!handle) {
+ gf_log ("authenticate", GF_LOG_ERROR, "dlopen(%s): %s\n",
+ auth_file, dlerror ());
+ dict_set (this, key, data_from_dynptr (NULL, 0));
+ FREE (auth_file);
+ *error = -1;
+ return;
+ }
+ FREE (auth_file);
+
+ authenticate = dlsym (handle, "gf_auth");
+ if (!authenticate) {
+ gf_log ("authenticate", GF_LOG_ERROR,
+ "dlsym(gf_auth) on %s\n", dlerror ());
+ dict_set (this, key, data_from_dynptr (NULL, 0));
+ *error = -1;
+ return;
+ }
+
+ auth_handle = CALLOC (1, sizeof (*auth_handle));
+ if (!auth_handle) {
+ gf_log ("authenticate", GF_LOG_ERROR, "Out of memory");
+ dict_set (this, key, data_from_dynptr (NULL, 0));
+ *error = -1;
+ return;
+ }
+ auth_handle->vol_opt = CALLOC (1, sizeof (volume_opt_list_t));
+ auth_handle->vol_opt->given_opt = dlsym (handle, "options");
+ if (auth_handle->vol_opt->given_opt == NULL) {
+ gf_log ("authenticate", GF_LOG_DEBUG,
+ "volume option validation not specified");
+ }
+
+ auth_handle->authenticate = authenticate;
+ auth_handle->handle = handle;
+
+ dict_set (this, key,
+ data_from_dynptr (auth_handle, sizeof (*auth_handle)));
+}
+
+static void
+fini (dict_t *this,
+ char *key,
+ data_t *value,
+ void *data)
+{
+ auth_handle_t *handle = data_to_ptr (value);
+ if (handle) {
+ dlclose (handle->handle);
+ }
+}
+
+int32_t
+gf_auth_init (xlator_t *xl, dict_t *auth_modules)
+{
+ int ret = 0;
+ auth_handle_t *handle = NULL;
+ data_pair_t *pair = NULL;
+ dict_foreach (auth_modules, init, &ret);
+ if (!ret) {
+ pair = auth_modules->members_list;
+ while (pair) {
+ handle = data_to_ptr (pair->value);
+ if (handle) {
+ list_add_tail (&(handle->vol_opt->list),
+ &(xl->volume_options));
+ if (-1 ==
+ validate_xlator_volume_options (xl,
+ handle->vol_opt->given_opt)) {
+ gf_log ("authenticate", GF_LOG_ERROR,
+ "volume option validation "
+ "failed");
+ ret = -1;
+ }
+ }
+ pair = pair->next;
+ }
+ }
+ if (ret) {
+ gf_log (xl->name, GF_LOG_ERROR, "authentication init failed");
+ dict_foreach (auth_modules, fini, &ret);
+ ret = -1;
+ }
+ return ret;
+}
+
+static dict_t *__input_params;
+static dict_t *__config_params;
+
+void
+map (dict_t *this,
+ char *key,
+ data_t *value,
+ void *data)
+{
+ dict_t *res = data;
+ auth_fn_t authenticate;
+ auth_handle_t *handle = NULL;
+
+ if (value && (handle = data_to_ptr (value)) &&
+ (authenticate = handle->authenticate)) {
+ dict_set (res, key,
+ int_to_data (authenticate (__input_params,
+ __config_params)));
+ } else {
+ dict_set (res, key, int_to_data (AUTH_DONT_CARE));
+ }
+}
+
+void
+reduce (dict_t *this,
+ char *key,
+ data_t *value,
+ void *data)
+{
+ int64_t val = 0;
+ int64_t *res = data;
+ if (!data)
+ return;
+
+ val = data_to_int64 (value);
+ switch (val)
+ {
+ case AUTH_ACCEPT:
+ if (AUTH_DONT_CARE == *res)
+ *res = AUTH_ACCEPT;
+ break;
+
+ case AUTH_REJECT:
+ *res = AUTH_REJECT;
+ break;
+
+ case AUTH_DONT_CARE:
+ break;
+ }
+}
+
+
+auth_result_t
+gf_authenticate (dict_t *input_params,
+ dict_t *config_params,
+ dict_t *auth_modules)
+{
+ dict_t *results = NULL;
+ int64_t result = AUTH_DONT_CARE;
+
+ results = get_new_dict ();
+ __input_params = input_params;
+ __config_params = config_params;
+
+ dict_foreach (auth_modules, map, results);
+
+ dict_foreach (results, reduce, &result);
+ if (AUTH_DONT_CARE == result) {
+ data_t *peerinfo_data = dict_get (input_params, "peer-info");
+ char *name = NULL;
+
+ if (peerinfo_data) {
+ peer_info_t *peerinfo = data_to_ptr (peerinfo_data);
+ name = peerinfo->identifier;
+ }
+
+ gf_log ("auth", GF_LOG_ERROR,
+ "no authentication module is interested in "
+ "accepting remote-client %s", name);
+ result = AUTH_REJECT;
+ }
+
+ dict_destroy (results);
+ return result;
+}
+
+void
+gf_auth_fini (dict_t *auth_modules)
+{
+ int32_t dummy;
+
+ dict_foreach (auth_modules, fini, &dummy);
+}
diff --git a/libglusterfs/src/authenticate.h b/libglusterfs/src/authenticate.h
new file mode 100644
index 000000000..3d9b78527
--- /dev/null
+++ b/libglusterfs/src/authenticate.h
@@ -0,0 +1,61 @@
+/*
+ Copyright (c) 2007, 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/>.
+*/
+
+#ifndef _AUTHENTICATE_H
+#define _AUTHENTICATE_H
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <fnmatch.h>
+#include "dict.h"
+#include "compat.h"
+#include "list.h"
+#include "transport.h"
+#include "xlator.h"
+
+typedef enum {
+ AUTH_ACCEPT,
+ AUTH_REJECT,
+ AUTH_DONT_CARE
+} auth_result_t;
+
+typedef auth_result_t (*auth_fn_t) (dict_t *input_params,
+ dict_t *config_params);
+
+typedef struct {
+ void *handle;
+ auth_fn_t authenticate;
+ volume_opt_list_t *vol_opt;
+} auth_handle_t;
+
+auth_result_t gf_authenticate (dict_t *input_params,
+ dict_t *config_params,
+ dict_t *auth_modules);
+int32_t gf_auth_init (xlator_t *xl, dict_t *auth_modules);
+void gf_auth_fini (dict_t *auth_modules);
+
+#endif /* _AUTHENTICATE_H */
diff --git a/libglusterfs/src/byte-order.h b/libglusterfs/src/byte-order.h
new file mode 100644
index 000000000..b0cf90b09
--- /dev/null
+++ b/libglusterfs/src/byte-order.h
@@ -0,0 +1,150 @@
+/*
+ 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/>.
+*/
+
+#ifndef _BYTE_ORDER_H
+#define _BYTE_ORDER_H
+
+#include <inttypes.h>
+
+#define LS1 0x00ffU
+#define MS1 0xff00U
+#define LS2 0x0000ffffU
+#define MS2 0xffff0000U
+#define LS4 0x00000000ffffffffULL
+#define MS4 0xffffffff00000000ULL
+
+
+static uint16_t (*hton16) (uint16_t);
+static uint32_t (*hton32) (uint32_t);
+static uint64_t (*hton64) (uint64_t);
+
+#define ntoh16 hton16
+#define ntoh32 hton32
+#define ntoh64 hton64
+
+#define do_swap2(x) (((x&LS1) << 8)|(((x&MS1) >> 8)))
+#define do_swap4(x) ((do_swap2(x&LS2) << 16)|(do_swap2((x&MS2) >> 16)))
+#define do_swap8(x) ((do_swap4(x&LS4) << 32)|(do_swap4((x&MS4) >> 32)))
+
+
+static inline uint16_t
+__swap16 (uint16_t x)
+{
+ return do_swap2(x);
+}
+
+
+static inline uint32_t
+__swap32 (uint32_t x)
+{
+ return do_swap4(x);
+}
+
+
+static inline uint64_t
+__swap64 (uint64_t x)
+{
+ return do_swap8(x);
+}
+
+
+static inline uint16_t
+__noswap16 (uint16_t x)
+{
+ return do_swap2(x);
+}
+
+
+static inline uint32_t
+__noswap32 (uint32_t x)
+{
+ return do_swap4(x);
+}
+
+
+static inline uint64_t
+__noswap64 (uint64_t x)
+{
+ return do_swap8(x);
+}
+
+
+static inline uint16_t
+__byte_order_init16 (uint16_t i)
+{
+ uint32_t num = 1;
+
+ if (((char *)(&num))[0] == 1) {
+ hton16 = __swap16;
+ hton32 = __swap32;
+ hton64 = __swap64;
+ } else {
+ hton16 = __noswap16;
+ hton32 = __noswap32;
+ hton64 = __noswap64;
+ }
+
+ return hton16 (i);
+}
+
+
+static inline uint32_t
+__byte_order_init32 (uint32_t i)
+{
+ uint32_t num = 1;
+
+ if (((char *)(&num))[0] == 1) {
+ hton16 = __swap16;
+ hton32 = __swap32;
+ hton64 = __swap64;
+ } else {
+ hton16 = __noswap16;
+ hton32 = __noswap32;
+ hton64 = __noswap64;
+ }
+
+ return hton32 (i);
+}
+
+
+static inline uint64_t
+__byte_order_init64 (uint64_t i)
+{
+ uint32_t num = 1;
+
+ if (((char *)(&num))[0] == 1) {
+ hton16 = __swap16;
+ hton32 = __swap32;
+ hton64 = __swap64;
+ } else {
+ hton16 = __noswap16;
+ hton32 = __noswap32;
+ hton64 = __noswap64;
+ }
+
+ return hton64 (i);
+}
+
+
+static uint16_t (*hton16) (uint16_t) = __byte_order_init16;
+static uint32_t (*hton32) (uint32_t) = __byte_order_init32;
+static uint64_t (*hton64) (uint64_t) = __byte_order_init64;
+
+
+#endif /* _BYTE_ORDER_H */
diff --git a/libglusterfs/src/call-stub.c b/libglusterfs/src/call-stub.c
new file mode 100644
index 000000000..cd7357259
--- /dev/null
+++ b/libglusterfs/src/call-stub.c
@@ -0,0 +1,3822 @@
+/*
+ Copyright (c) 2007, 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/>.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "call-stub.h"
+
+
+static call_stub_t *
+stub_new (call_frame_t *frame,
+ char wind,
+ glusterfs_fop_t fop)
+{
+ call_stub_t *new = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ new = CALLOC (1, sizeof (*new));
+ GF_VALIDATE_OR_GOTO ("call-stub", new, out);
+
+ new->frame = frame;
+ new->wind = wind;
+ new->fop = fop;
+
+ INIT_LIST_HEAD (&new->list);
+out:
+ return new;
+}
+
+
+call_stub_t *
+fop_lookup_stub (call_frame_t *frame,
+ fop_lookup_t fn,
+ loc_t *loc,
+ dict_t *xattr_req)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_LOOKUP);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.lookup.fn = fn;
+
+ if (xattr_req)
+ stub->args.lookup.xattr_req = dict_ref (xattr_req);
+
+ loc_copy (&stub->args.lookup.loc, loc);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_lookup_cbk_stub (call_frame_t *frame,
+ fop_lookup_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf,
+ dict_t *dict)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_LOOKUP);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.lookup_cbk.fn = fn;
+ stub->args.lookup_cbk.op_ret = op_ret;
+ stub->args.lookup_cbk.op_errno = op_errno;
+ if (inode)
+ stub->args.lookup_cbk.inode = inode_ref (inode);
+ if (buf)
+ stub->args.lookup_cbk.buf = *buf;
+ if (dict)
+ stub->args.lookup_cbk.dict = dict_ref (dict);
+out:
+ return stub;
+}
+
+
+
+call_stub_t *
+fop_stat_stub (call_frame_t *frame,
+ fop_stat_t fn,
+ loc_t *loc)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_STAT);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.stat.fn = fn;
+ loc_copy (&stub->args.stat.loc, loc);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_stat_cbk_stub (call_frame_t *frame,
+ fop_stat_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_STAT);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.stat_cbk.fn = fn;
+ stub->args.stat_cbk.op_ret = op_ret;
+ stub->args.stat_cbk.op_errno = op_errno;
+ if (op_ret == 0)
+ stub->args.stat_cbk.buf = *buf;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_fstat_stub (call_frame_t *frame,
+ fop_fstat_t fn,
+ fd_t *fd)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 1, GF_FOP_FSTAT);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.fstat.fn = fn;
+
+ if (fd)
+ stub->args.fstat.fd = fd_ref (fd);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_fstat_cbk_stub (call_frame_t *frame,
+ fop_fstat_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_FSTAT);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.fstat_cbk.fn = fn;
+ stub->args.fstat_cbk.op_ret = op_ret;
+ stub->args.fstat_cbk.op_errno = op_errno;
+ if (buf)
+ stub->args.fstat_cbk.buf = *buf;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_chmod_stub (call_frame_t *frame,
+ fop_chmod_t fn,
+ loc_t *loc,
+ mode_t mode)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_CHMOD);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.chmod.fn = fn;
+ loc_copy (&stub->args.chmod.loc, loc);
+ stub->args.chmod.mode = mode;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_chmod_cbk_stub (call_frame_t *frame,
+ fop_chmod_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_CHMOD);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.chmod_cbk.fn = fn;
+ stub->args.chmod_cbk.op_ret = op_ret;
+ stub->args.chmod_cbk.op_errno = op_errno;
+ if (buf)
+ stub->args.chmod_cbk.buf = *buf;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_fchmod_stub (call_frame_t *frame,
+ fop_fchmod_t fn,
+ fd_t *fd,
+ mode_t mode)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 1, GF_FOP_FCHMOD);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.fchmod.fn = fn;
+ if (fd)
+ stub->args.fchmod.fd = fd_ref (fd);
+ stub->args.fchmod.mode = mode;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_fchmod_cbk_stub (call_frame_t *frame,
+ fop_fchmod_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_FCHMOD);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.fchmod_cbk.fn = fn;
+ stub->args.fchmod_cbk.op_ret = op_ret;
+ stub->args.fchmod_cbk.op_errno = op_errno;
+ if (buf)
+ stub->args.fchmod_cbk.buf = *buf;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_chown_stub (call_frame_t *frame,
+ fop_chown_t fn,
+ loc_t *loc,
+ uid_t uid,
+ gid_t gid)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_CHOWN);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.chown.fn = fn;
+ loc_copy (&stub->args.chown.loc, loc);
+ stub->args.chown.uid = uid;
+ stub->args.chown.gid = gid;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_chown_cbk_stub (call_frame_t *frame,
+ fop_chown_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_CHOWN);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.chown_cbk.fn = fn;
+ stub->args.chown_cbk.op_ret = op_ret;
+ stub->args.chown_cbk.op_errno = op_errno;
+ if (buf)
+ stub->args.chown_cbk.buf = *buf;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_fchown_stub (call_frame_t *frame,
+ fop_fchown_t fn,
+ fd_t *fd,
+ uid_t uid,
+ gid_t gid)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 1, GF_FOP_FCHOWN);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.fchown.fn = fn;
+ if (fd)
+ stub->args.fchown.fd = fd_ref (fd);
+ stub->args.fchown.uid = uid;
+ stub->args.fchown.gid = gid;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_fchown_cbk_stub (call_frame_t *frame,
+ fop_fchown_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_FCHOWN);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.fchown_cbk.fn = fn;
+ stub->args.fchown_cbk.op_ret = op_ret;
+ stub->args.fchown_cbk.op_errno = op_errno;
+ if (buf)
+ stub->args.fchown_cbk.buf = *buf;
+out:
+ return stub;
+}
+
+
+/* truncate */
+
+call_stub_t *
+fop_truncate_stub (call_frame_t *frame,
+ fop_truncate_t fn,
+ loc_t *loc,
+ off_t off)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_TRUNCATE);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.truncate.fn = fn;
+ loc_copy (&stub->args.truncate.loc, loc);
+ stub->args.truncate.off = off;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_truncate_cbk_stub (call_frame_t *frame,
+ fop_truncate_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_TRUNCATE);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.truncate_cbk.fn = fn;
+ stub->args.truncate_cbk.op_ret = op_ret;
+ stub->args.truncate_cbk.op_errno = op_errno;
+ if (buf)
+ stub->args.truncate_cbk.buf = *buf;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_ftruncate_stub (call_frame_t *frame,
+ fop_ftruncate_t fn,
+ fd_t *fd,
+ off_t off)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 1, GF_FOP_FTRUNCATE);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.ftruncate.fn = fn;
+ if (fd)
+ stub->args.ftruncate.fd = fd_ref (fd);
+
+ stub->args.ftruncate.off = off;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_ftruncate_cbk_stub (call_frame_t *frame,
+ fop_ftruncate_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_FTRUNCATE);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.ftruncate_cbk.fn = fn;
+ stub->args.ftruncate_cbk.op_ret = op_ret;
+ stub->args.ftruncate_cbk.op_errno = op_errno;
+ if (buf)
+ stub->args.ftruncate_cbk.buf = *buf;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_utimens_stub (call_frame_t *frame,
+ fop_utimens_t fn,
+ loc_t *loc,
+ struct timespec tv[2])
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_UTIMENS);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.utimens.fn = fn;
+ loc_copy (&stub->args.utimens.loc, loc);
+ stub->args.utimens.tv[0] = tv[0];
+ stub->args.utimens.tv[1] = tv[1];
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_utimens_cbk_stub (call_frame_t *frame,
+ fop_utimens_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_UTIMENS);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.utimens_cbk.fn = fn;
+ stub->args.utimens_cbk.op_ret = op_ret;
+ stub->args.utimens_cbk.op_errno = op_errno;
+ if (buf)
+ stub->args.utimens_cbk.buf = *buf;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_access_stub (call_frame_t *frame,
+ fop_access_t fn,
+ loc_t *loc,
+ int32_t mask)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_ACCESS);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.access.fn = fn;
+ loc_copy (&stub->args.access.loc, loc);
+ stub->args.access.mask = mask;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_access_cbk_stub (call_frame_t *frame,
+ fop_access_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_ACCESS);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.access_cbk.fn = fn;
+ stub->args.access_cbk.op_ret = op_ret;
+ stub->args.access_cbk.op_errno = op_errno;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_readlink_stub (call_frame_t *frame,
+ fop_readlink_t fn,
+ loc_t *loc,
+ size_t size)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_READLINK);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.readlink.fn = fn;
+ loc_copy (&stub->args.readlink.loc, loc);
+ stub->args.readlink.size = size;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_readlink_cbk_stub (call_frame_t *frame,
+ fop_readlink_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ const char *path)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_READLINK);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.readlink_cbk.fn = fn;
+ stub->args.readlink_cbk.op_ret = op_ret;
+ stub->args.readlink_cbk.op_errno = op_errno;
+ if (path)
+ stub->args.readlink_cbk.buf = strdup (path);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_mknod_stub (call_frame_t *frame,
+ fop_mknod_t fn,
+ loc_t *loc,
+ mode_t mode,
+ dev_t rdev)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_MKNOD);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.mknod.fn = fn;
+ loc_copy (&stub->args.mknod.loc, loc);
+ stub->args.mknod.mode = mode;
+ stub->args.mknod.rdev = rdev;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_mknod_cbk_stub (call_frame_t *frame,
+ fop_mknod_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_MKNOD);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.mknod_cbk.fn = fn;
+ stub->args.mknod_cbk.op_ret = op_ret;
+ stub->args.mknod_cbk.op_errno = op_errno;
+ if (inode)
+ stub->args.mknod_cbk.inode = inode_ref (inode);
+ if (buf)
+ stub->args.mknod_cbk.buf = *buf;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_mkdir_stub (call_frame_t *frame,
+ fop_mkdir_t fn,
+ loc_t *loc,
+ mode_t mode)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_MKDIR);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.mkdir.fn = fn;
+ loc_copy (&stub->args.mkdir.loc, loc);
+ stub->args.mkdir.mode = mode;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_mkdir_cbk_stub (call_frame_t *frame,
+ fop_mkdir_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_MKDIR);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.mkdir_cbk.fn = fn;
+ stub->args.mkdir_cbk.op_ret = op_ret;
+ stub->args.mkdir_cbk.op_errno = op_errno;
+ if (inode)
+ stub->args.mkdir_cbk.inode = inode_ref (inode);
+ if (buf)
+ stub->args.mkdir_cbk.buf = *buf;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_unlink_stub (call_frame_t *frame,
+ fop_unlink_t fn,
+ loc_t *loc)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_UNLINK);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.unlink.fn = fn;
+ loc_copy (&stub->args.unlink.loc, loc);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_unlink_cbk_stub (call_frame_t *frame,
+ fop_unlink_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_UNLINK);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.unlink_cbk.fn = fn;
+ stub->args.unlink_cbk.op_ret = op_ret;
+ stub->args.unlink_cbk.op_errno = op_errno;
+out:
+ return stub;
+}
+
+
+
+call_stub_t *
+fop_rmdir_stub (call_frame_t *frame,
+ fop_rmdir_t fn,
+ loc_t *loc)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_RMDIR);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.rmdir.fn = fn;
+ loc_copy (&stub->args.rmdir.loc, loc);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_rmdir_cbk_stub (call_frame_t *frame,
+ fop_rmdir_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_RMDIR);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.rmdir_cbk.fn = fn;
+ stub->args.rmdir_cbk.op_ret = op_ret;
+ stub->args.rmdir_cbk.op_errno = op_errno;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_symlink_stub (call_frame_t *frame,
+ fop_symlink_t fn,
+ const char *linkname,
+ loc_t *loc)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", linkname, out);
+
+ stub = stub_new (frame, 1, GF_FOP_SYMLINK);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.symlink.fn = fn;
+ stub->args.symlink.linkname = strdup (linkname);
+ loc_copy (&stub->args.symlink.loc, loc);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_symlink_cbk_stub (call_frame_t *frame,
+ fop_symlink_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_SYMLINK);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.symlink_cbk.fn = fn;
+ stub->args.symlink_cbk.op_ret = op_ret;
+ stub->args.symlink_cbk.op_errno = op_errno;
+ if (inode)
+ stub->args.symlink_cbk.inode = inode_ref (inode);
+ if (buf)
+ stub->args.symlink_cbk.buf = *buf;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_rename_stub (call_frame_t *frame,
+ fop_rename_t fn,
+ loc_t *oldloc,
+ loc_t *newloc)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", oldloc, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", newloc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_RENAME);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.rename.fn = fn;
+ loc_copy (&stub->args.rename.old, oldloc);
+ loc_copy (&stub->args.rename.new, newloc);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_rename_cbk_stub (call_frame_t *frame,
+ fop_rename_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_RENAME);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.rename_cbk.fn = fn;
+ stub->args.rename_cbk.op_ret = op_ret;
+ stub->args.rename_cbk.op_errno = op_errno;
+ if (buf)
+ stub->args.rename_cbk.buf = *buf;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_link_stub (call_frame_t *frame,
+ fop_link_t fn,
+ loc_t *oldloc,
+ loc_t *newloc)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", oldloc, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", newloc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_LINK);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.link.fn = fn;
+ loc_copy (&stub->args.link.oldloc, oldloc);
+ loc_copy (&stub->args.link.newloc, newloc);
+
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_link_cbk_stub (call_frame_t *frame,
+ fop_link_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_LINK);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.link_cbk.fn = fn;
+ stub->args.link_cbk.op_ret = op_ret;
+ stub->args.link_cbk.op_errno = op_errno;
+ if (inode)
+ stub->args.link_cbk.inode = inode_ref (inode);
+ if (buf)
+ stub->args.link_cbk.buf = *buf;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_create_stub (call_frame_t *frame,
+ fop_create_t fn,
+ loc_t *loc,
+ int32_t flags,
+ mode_t mode, fd_t *fd)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_CREATE);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.create.fn = fn;
+ loc_copy (&stub->args.create.loc, loc);
+ stub->args.create.flags = flags;
+ stub->args.create.mode = mode;
+ if (fd)
+ stub->args.create.fd = fd_ref (fd);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_create_cbk_stub (call_frame_t *frame,
+ fop_create_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ fd_t *fd,
+ inode_t *inode,
+ struct stat *buf)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_CREATE);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.create_cbk.fn = fn;
+ stub->args.create_cbk.op_ret = op_ret;
+ stub->args.create_cbk.op_errno = op_errno;
+ if (fd)
+ stub->args.create_cbk.fd = fd_ref (fd);
+ if (inode)
+ stub->args.create_cbk.inode = inode_ref (inode);
+ if (buf)
+ stub->args.create_cbk.buf = *buf;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_open_stub (call_frame_t *frame,
+ fop_open_t fn,
+ loc_t *loc,
+ int32_t flags, fd_t *fd)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_OPEN);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.open.fn = fn;
+ loc_copy (&stub->args.open.loc, loc);
+ stub->args.open.flags = flags;
+ if (fd)
+ stub->args.open.fd = fd_ref (fd);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_open_cbk_stub (call_frame_t *frame,
+ fop_open_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ fd_t *fd)
+
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_OPEN);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.open_cbk.fn = fn;
+ stub->args.open_cbk.op_ret = op_ret;
+ stub->args.open_cbk.op_errno = op_errno;
+ if (fd)
+ stub->args.open_cbk.fd = fd_ref (fd);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_readv_stub (call_frame_t *frame,
+ fop_readv_t fn,
+ fd_t *fd,
+ size_t size,
+ off_t off)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 1, GF_FOP_READ);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.readv.fn = fn;
+ if (fd)
+ stub->args.readv.fd = fd_ref (fd);
+ stub->args.readv.size = size;
+ stub->args.readv.off = off;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_readv_cbk_stub (call_frame_t *frame,
+ fop_readv_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct iovec *vector,
+ int32_t count,
+ struct stat *stbuf)
+
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_READ);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.readv_cbk.fn = fn;
+ stub->args.readv_cbk.op_ret = op_ret;
+ stub->args.readv_cbk.op_errno = op_errno;
+ if (op_ret >= 0) {
+ stub->args.readv_cbk.vector = iov_dup (vector, count);
+ stub->args.readv_cbk.count = count;
+ stub->args.readv_cbk.stbuf = *stbuf;
+ stub->args.readv_cbk.rsp_refs =
+ dict_ref (frame->root->rsp_refs);
+ }
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_writev_stub (call_frame_t *frame,
+ fop_writev_t fn,
+ fd_t *fd,
+ struct iovec *vector,
+ int32_t count,
+ off_t off)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", vector, out);
+
+ stub = stub_new (frame, 1, GF_FOP_WRITE);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.writev.fn = fn;
+ if (fd)
+ stub->args.writev.fd = fd_ref (fd);
+ stub->args.writev.vector = iov_dup (vector, count);
+ stub->args.writev.count = count;
+ stub->args.writev.off = off;
+
+ if (frame->root->req_refs)
+ stub->args.writev.req_refs = dict_ref (frame->root->req_refs);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_writev_cbk_stub (call_frame_t *frame,
+ fop_writev_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *stbuf)
+
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_WRITE);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.writev_cbk.fn = fn;
+ stub->args.writev_cbk.op_ret = op_ret;
+ stub->args.writev_cbk.op_errno = op_errno;
+ if (op_ret >= 0)
+ stub->args.writev_cbk.stbuf = *stbuf;
+out:
+ return stub;
+}
+
+
+
+call_stub_t *
+fop_flush_stub (call_frame_t *frame,
+ fop_flush_t fn,
+ fd_t *fd)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 1, GF_FOP_FLUSH);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.flush.fn = fn;
+ if (fd)
+ stub->args.flush.fd = fd_ref (fd);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_flush_cbk_stub (call_frame_t *frame,
+ fop_flush_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno)
+
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_FLUSH);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.flush_cbk.fn = fn;
+ stub->args.flush_cbk.op_ret = op_ret;
+ stub->args.flush_cbk.op_errno = op_errno;
+out:
+ return stub;
+}
+
+
+
+
+call_stub_t *
+fop_fsync_stub (call_frame_t *frame,
+ fop_fsync_t fn,
+ fd_t *fd,
+ int32_t datasync)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 1, GF_FOP_FSYNC);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.fsync.fn = fn;
+ if (fd)
+ stub->args.fsync.fd = fd_ref (fd);
+ stub->args.fsync.datasync = datasync;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_fsync_cbk_stub (call_frame_t *frame,
+ fop_fsync_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno)
+
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_FSYNC);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.fsync_cbk.fn = fn;
+ stub->args.fsync_cbk.op_ret = op_ret;
+ stub->args.fsync_cbk.op_errno = op_errno;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_opendir_stub (call_frame_t *frame,
+ fop_opendir_t fn,
+ loc_t *loc, fd_t *fd)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_OPENDIR);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.opendir.fn = fn;
+ loc_copy (&stub->args.opendir.loc, loc);
+ if (stub->args.opendir.fd)
+ stub->args.opendir.fd = fd_ref (fd);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_opendir_cbk_stub (call_frame_t *frame,
+ fop_opendir_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ fd_t *fd)
+
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_OPENDIR);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.opendir_cbk.fn = fn;
+ stub->args.opendir_cbk.op_ret = op_ret;
+ stub->args.opendir_cbk.op_errno = op_errno;
+
+ if (fd)
+ stub->args.opendir_cbk.fd = fd_ref (fd);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_getdents_stub (call_frame_t *frame,
+ fop_getdents_t fn,
+ fd_t *fd,
+ size_t size,
+ off_t off,
+ int32_t flag)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 1, GF_FOP_GETDENTS);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.getdents.fn = fn;
+ stub->args.getdents.size = size;
+ stub->args.getdents.off = off;
+ if (fd)
+ stub->args.getdents.fd = fd_ref (fd);
+ stub->args.getdents.flag = flag;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_getdents_cbk_stub (call_frame_t *frame,
+ fop_getdents_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ dir_entry_t *entries,
+ int32_t count)
+
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_GETDENTS);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.getdents_cbk.fn = fn;
+ stub->args.getdents_cbk.op_ret = op_ret;
+ stub->args.getdents_cbk.op_errno = op_errno;
+ if (op_ret >= 0) {
+ stub->args.getdents_cbk.entries.next = entries->next;
+ /* FIXME: are entries not needed in the caller after
+ * creating stub? */
+ entries->next = NULL;
+ }
+
+ stub->args.getdents_cbk.count = count;
+out:
+ return stub;
+}
+
+
+
+call_stub_t *
+fop_fsyncdir_stub (call_frame_t *frame,
+ fop_fsyncdir_t fn,
+ fd_t *fd,
+ int32_t datasync)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 1, GF_FOP_FSYNCDIR);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.fsyncdir.fn = fn;
+ if (fd)
+ stub->args.fsyncdir.fd = fd_ref (fd);
+ stub->args.fsyncdir.datasync = datasync;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_fsyncdir_cbk_stub (call_frame_t *frame,
+ fop_fsyncdir_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno)
+
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_FSYNCDIR);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.fsyncdir_cbk.fn = fn;
+ stub->args.fsyncdir_cbk.op_ret = op_ret;
+ stub->args.fsyncdir_cbk.op_errno = op_errno;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_statfs_stub (call_frame_t *frame,
+ fop_statfs_t fn,
+ loc_t *loc)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_STATFS);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.statfs.fn = fn;
+ loc_copy (&stub->args.statfs.loc, loc);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_statfs_cbk_stub (call_frame_t *frame,
+ fop_statfs_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct statvfs *buf)
+
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_STATFS);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.statfs_cbk.fn = fn;
+ stub->args.statfs_cbk.op_ret = op_ret;
+ stub->args.statfs_cbk.op_errno = op_errno;
+ if (op_ret == 0)
+ stub->args.statfs_cbk.buf = *buf;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_setxattr_stub (call_frame_t *frame,
+ fop_setxattr_t fn,
+ loc_t *loc,
+ dict_t *dict,
+ int32_t flags)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_SETXATTR);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.setxattr.fn = fn;
+ loc_copy (&stub->args.setxattr.loc, loc);
+ /* TODO */
+ if (dict)
+ stub->args.setxattr.dict = dict_ref (dict);
+ stub->args.setxattr.flags = flags;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_setxattr_cbk_stub (call_frame_t *frame,
+ fop_setxattr_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_SETXATTR);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.setxattr_cbk.fn = fn;
+ stub->args.setxattr_cbk.op_ret = op_ret;
+ stub->args.setxattr_cbk.op_errno = op_errno;
+out:
+ return stub;
+}
+
+call_stub_t *
+fop_getxattr_stub (call_frame_t *frame,
+ fop_getxattr_t fn,
+ loc_t *loc,
+ const char *name)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_GETXATTR);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.getxattr.fn = fn;
+ loc_copy (&stub->args.getxattr.loc, loc);
+
+ if (name)
+ stub->args.getxattr.name = strdup (name);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_getxattr_cbk_stub (call_frame_t *frame,
+ fop_getxattr_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ dict_t *dict)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_GETXATTR);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.getxattr_cbk.fn = fn;
+ stub->args.getxattr_cbk.op_ret = op_ret;
+ stub->args.getxattr_cbk.op_errno = op_errno;
+ /* TODO */
+ if (dict)
+ stub->args.getxattr_cbk.dict = dict_ref (dict);
+out:
+ return stub;
+}
+
+call_stub_t *
+fop_removexattr_stub (call_frame_t *frame,
+ fop_removexattr_t fn,
+ loc_t *loc,
+ const char *name)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", name, out);
+
+ stub = stub_new (frame, 1, GF_FOP_REMOVEXATTR);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.removexattr.fn = fn;
+ loc_copy (&stub->args.removexattr.loc, loc);
+ stub->args.removexattr.name = strdup (name);
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_removexattr_cbk_stub (call_frame_t *frame,
+ fop_removexattr_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_REMOVEXATTR);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.removexattr_cbk.fn = fn;
+ stub->args.removexattr_cbk.op_ret = op_ret;
+ stub->args.removexattr_cbk.op_errno = op_errno;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_lk_stub (call_frame_t *frame,
+ fop_lk_t fn,
+ fd_t *fd,
+ int32_t cmd,
+ struct flock *lock)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", lock, out);
+
+ stub = stub_new (frame, 1, GF_FOP_LK);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.lk.fn = fn;
+ if (fd)
+ stub->args.lk.fd = fd_ref (fd);
+ stub->args.lk.cmd = cmd;
+ stub->args.lk.lock = *lock;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_lk_cbk_stub (call_frame_t *frame,
+ fop_lk_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct flock *lock)
+
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_LK);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.lk_cbk.fn = fn;
+ stub->args.lk_cbk.op_ret = op_ret;
+ stub->args.lk_cbk.op_errno = op_errno;
+ if (op_ret == 0)
+ stub->args.lk_cbk.lock = *lock;
+out:
+ return stub;
+}
+
+call_stub_t *
+fop_inodelk_stub (call_frame_t *frame, fop_inodelk_t fn,
+ loc_t *loc, int32_t cmd, struct flock *lock)
+{
+ call_stub_t *stub = NULL;
+
+ if (!frame || !lock)
+ return NULL;
+
+ stub = stub_new (frame, 1, GF_FOP_INODELK);
+ if (!stub)
+ return NULL;
+
+ stub->args.inodelk.fn = fn;
+
+ loc_copy (&stub->args.inodelk.loc, loc);
+ stub->args.inodelk.cmd = cmd;
+ stub->args.inodelk.lock = *lock;
+
+ return stub;
+}
+
+call_stub_t *
+fop_inodelk_cbk_stub (call_frame_t *frame, fop_inodelk_cbk_t fn,
+ int32_t op_ret, int32_t op_errno)
+{
+ call_stub_t *stub = NULL;
+
+ if (!frame)
+ return NULL;
+
+ stub = stub_new (frame, 0, GF_FOP_INODELK);
+ if (!stub)
+ return NULL;
+
+ stub->args.inodelk_cbk.fn = fn;
+ stub->args.inodelk_cbk.op_ret = op_ret;
+ stub->args.inodelk_cbk.op_errno = op_errno;
+
+ return stub;
+}
+
+
+call_stub_t *
+fop_finodelk_stub (call_frame_t *frame, fop_finodelk_t fn,
+ fd_t *fd, int32_t cmd, struct flock *lock)
+{
+ call_stub_t *stub = NULL;
+
+ if (!frame || !lock)
+ return NULL;
+
+ stub = stub_new (frame, 1, GF_FOP_FINODELK);
+ if (!stub)
+ return NULL;
+
+ stub->args.finodelk.fn = fn;
+
+ if (fd)
+ stub->args.finodelk.fd = fd_ref (fd);
+ stub->args.finodelk.cmd = cmd;
+ stub->args.finodelk.lock = *lock;
+
+ return stub;
+}
+
+
+call_stub_t *
+fop_finodelk_cbk_stub (call_frame_t *frame, fop_inodelk_cbk_t fn,
+ int32_t op_ret, int32_t op_errno)
+{
+ call_stub_t *stub = NULL;
+
+ if (!frame)
+ return NULL;
+
+ stub = stub_new (frame, 0, GF_FOP_FINODELK);
+ if (!stub)
+ return NULL;
+
+ stub->args.finodelk_cbk.fn = fn;
+ stub->args.finodelk_cbk.op_ret = op_ret;
+ stub->args.finodelk_cbk.op_errno = op_errno;
+
+ return stub;
+}
+
+
+call_stub_t *
+fop_entrylk_stub (call_frame_t *frame, fop_entrylk_t fn,
+ loc_t *loc, const char *name,
+ entrylk_cmd cmd, entrylk_type type)
+{
+ call_stub_t *stub = NULL;
+
+ if (!frame)
+ return NULL;
+
+ stub = stub_new (frame, 1, GF_FOP_ENTRYLK);
+ if (!stub)
+ return NULL;
+
+ stub->args.entrylk.fn = fn;
+ loc_copy (&stub->args.entrylk.loc, loc);
+
+ stub->args.entrylk.cmd = cmd;
+ stub->args.entrylk.type = type;
+ if (name)
+ stub->args.entrylk.name = strdup (name);
+
+ return stub;
+}
+
+call_stub_t *
+fop_entrylk_cbk_stub (call_frame_t *frame, fop_entrylk_cbk_t fn,
+ int32_t op_ret, int32_t op_errno)
+{
+ call_stub_t *stub = NULL;
+
+ if (!frame)
+ return NULL;
+
+ stub = stub_new (frame, 0, GF_FOP_ENTRYLK);
+ if (!stub)
+ return NULL;
+
+ stub->args.entrylk_cbk.fn = fn;
+ stub->args.entrylk_cbk.op_ret = op_ret;
+ stub->args.entrylk_cbk.op_errno = op_errno;
+
+ return stub;
+}
+
+
+call_stub_t *
+fop_fentrylk_stub (call_frame_t *frame, fop_fentrylk_t fn,
+ fd_t *fd, const char *name,
+ entrylk_cmd cmd, entrylk_type type)
+{
+ call_stub_t *stub = NULL;
+
+ if (!frame)
+ return NULL;
+
+ stub = stub_new (frame, 1, GF_FOP_FENTRYLK);
+ if (!stub)
+ return NULL;
+
+ stub->args.fentrylk.fn = fn;
+
+ if (fd)
+ stub->args.fentrylk.fd = fd_ref (fd);
+ stub->args.fentrylk.cmd = cmd;
+ stub->args.fentrylk.type = type;
+ if (name)
+ stub->args.fentrylk.name = strdup (name);
+
+ return stub;
+}
+
+call_stub_t *
+fop_fentrylk_cbk_stub (call_frame_t *frame, fop_fentrylk_cbk_t fn,
+ int32_t op_ret, int32_t op_errno)
+{
+ call_stub_t *stub = NULL;
+
+ if (!frame)
+ return NULL;
+
+ stub = stub_new (frame, 0, GF_FOP_FENTRYLK);
+ if (!stub)
+ return NULL;
+
+ stub->args.fentrylk_cbk.fn = fn;
+ stub->args.fentrylk_cbk.op_ret = op_ret;
+ stub->args.fentrylk_cbk.op_errno = op_errno;
+
+ return stub;
+}
+
+
+call_stub_t *
+fop_setdents_stub (call_frame_t *frame,
+ fop_setdents_t fn,
+ fd_t *fd,
+ int32_t flags,
+ dir_entry_t *entries,
+ int32_t count)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 1, GF_FOP_SETDENTS);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ if (fd)
+ stub->args.setdents.fd = fd_ref (fd);
+ stub->args.setdents.fn = fn;
+ stub->args.setdents.flags = flags;
+ stub->args.setdents.count = count;
+ if (entries) {
+ stub->args.setdents.entries.next = entries->next;
+ entries->next = NULL;
+ }
+out:
+ return stub;
+}
+
+call_stub_t *
+fop_setdents_cbk_stub (call_frame_t *frame,
+ fop_setdents_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_SETDENTS);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.setdents_cbk.fn = fn;
+ stub->args.setdents_cbk.op_ret = op_ret;
+ stub->args.setdents_cbk.op_errno = op_errno;
+out:
+ return stub;
+
+}
+
+call_stub_t *
+fop_readdir_cbk_stub (call_frame_t *frame,
+ fop_readdir_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ gf_dirent_t *entries)
+{
+ call_stub_t *stub = NULL;
+ gf_dirent_t *stub_entry = NULL, *entry = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_READDIR);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.readdir_cbk.fn = fn;
+ stub->args.readdir_cbk.op_ret = op_ret;
+ stub->args.readdir_cbk.op_errno = op_errno;
+ INIT_LIST_HEAD (&stub->args.readdir_cbk.entries.list);
+
+ if (op_ret > 0) {
+ list_for_each_entry (entry, &entries->list, list) {
+ stub_entry = gf_dirent_for_name (entry->d_name);
+ ERR_ABORT (stub_entry);
+ stub_entry->d_off = entry->d_off;
+ stub_entry->d_ino = entry->d_ino;
+
+ list_add_tail (&stub_entry->list,
+ &stub->args.readdir_cbk.entries.list);
+ }
+ }
+out:
+ return stub;
+}
+
+call_stub_t *
+fop_readdir_stub (call_frame_t *frame,
+ fop_readdir_t fn,
+ fd_t *fd,
+ size_t size,
+ off_t off)
+{
+ call_stub_t *stub = NULL;
+
+ stub = stub_new (frame, 1, GF_FOP_READDIR);
+ stub->args.readdir.fn = fn;
+ stub->args.readdir.fd = fd_ref (fd);
+ stub->args.readdir.size = size;
+ stub->args.readdir.off = off;
+
+ return stub;
+}
+call_stub_t *
+fop_checksum_stub (call_frame_t *frame,
+ fop_checksum_t fn,
+ loc_t *loc,
+ int32_t flags)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+ GF_VALIDATE_OR_GOTO ("call-stub", loc, out);
+
+ stub = stub_new (frame, 1, GF_FOP_CHECKSUM);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.checksum.fn = fn;
+ loc_copy (&stub->args.checksum.loc, loc);
+ stub->args.checksum.flags = flags;
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_checksum_cbk_stub (call_frame_t *frame,
+ fop_checksum_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ uint8_t *file_checksum,
+ uint8_t *dir_checksum)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_CHECKSUM);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.checksum_cbk.fn = fn;
+ stub->args.checksum_cbk.op_ret = op_ret;
+ stub->args.checksum_cbk.op_errno = op_errno;
+ if (op_ret >= 0)
+ {
+ stub->args.checksum_cbk.file_checksum =
+ memdup (file_checksum, ZR_FILENAME_MAX);
+
+ stub->args.checksum_cbk.dir_checksum =
+ memdup (dir_checksum, ZR_FILENAME_MAX);
+ }
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_xattrop_cbk_stub (call_frame_t *frame,
+ fop_xattrop_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ call_stub_t *stub = NULL;
+
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 0, GF_FOP_XATTROP);
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ stub->args.xattrop_cbk.fn = fn;
+ stub->args.xattrop_cbk.op_ret = op_ret;
+ stub->args.xattrop_cbk.op_errno = op_errno;
+
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_fxattrop_cbk_stub (call_frame_t *frame,
+ fop_fxattrop_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ dict_t *xattr)
+{
+ call_stub_t *stub = NULL;
+ GF_VALIDATE_OR_GOTO ("call-stub", frame, out);
+
+ stub = stub_new (frame, 1, GF_FOP_FXATTROP);
+ stub->args.fxattrop_cbk.fn = fn;
+ stub->args.fxattrop_cbk.op_ret = op_ret;
+ stub->args.fxattrop_cbk.op_errno = op_errno;
+ if (xattr)
+ stub->args.fxattrop_cbk.xattr = dict_ref (xattr);
+
+out:
+ return stub;
+}
+
+
+call_stub_t *
+fop_xattrop_stub (call_frame_t *frame,
+ fop_xattrop_t fn,
+ loc_t *loc,
+ gf_xattrop_flags_t optype,
+ dict_t *xattr)
+{
+ call_stub_t *stub = NULL;
+
+ if (!frame || !xattr)
+ return NULL;
+
+ stub = stub_new (frame, 1, GF_FOP_XATTROP);
+ if (!stub)
+ return NULL;
+
+ stub->args.xattrop.fn = fn;
+
+ loc_copy (&stub->args.xattrop.loc, loc);
+
+ stub->args.xattrop.optype = optype;
+ stub->args.xattrop.xattr = dict_ref (xattr);
+
+ return stub;
+}
+
+call_stub_t *
+fop_fxattrop_stub (call_frame_t *frame,
+ fop_fxattrop_t fn,
+ fd_t *fd,
+ gf_xattrop_flags_t optype,
+ dict_t *xattr)
+{
+ call_stub_t *stub = NULL;
+
+ if (!frame || !xattr)
+ return NULL;
+
+ stub = stub_new (frame, 1, GF_FOP_FXATTROP);
+ if (!stub)
+ return NULL;
+
+ stub->args.fxattrop.fn = fn;
+
+ stub->args.fxattrop.fd = fd_ref (fd);
+
+ stub->args.fxattrop.optype = optype;
+ stub->args.fxattrop.xattr = dict_ref (xattr);
+
+ return stub;
+}
+
+
+static void
+call_resume_wind (call_stub_t *stub)
+{
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ switch (stub->fop) {
+ case GF_FOP_OPEN:
+ {
+ stub->args.open.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.open.loc,
+ stub->args.open.flags, stub->args.open.fd);
+ break;
+ }
+ case GF_FOP_CREATE:
+ {
+ stub->args.create.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.create.loc,
+ stub->args.create.flags,
+ stub->args.create.mode,
+ stub->args.create.fd);
+ break;
+ }
+ case GF_FOP_STAT:
+ {
+ stub->args.stat.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.stat.loc);
+ break;
+ }
+ case GF_FOP_READLINK:
+ {
+ stub->args.readlink.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.readlink.loc,
+ stub->args.readlink.size);
+ break;
+ }
+
+ case GF_FOP_MKNOD:
+ {
+ stub->args.mknod.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.mknod.loc,
+ stub->args.mknod.mode,
+ stub->args.mknod.rdev);
+ }
+ break;
+
+ case GF_FOP_MKDIR:
+ {
+ stub->args.mkdir.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.mkdir.loc,
+ stub->args.mkdir.mode);
+ }
+ break;
+
+ case GF_FOP_UNLINK:
+ {
+ stub->args.unlink.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.unlink.loc);
+ }
+ break;
+
+ case GF_FOP_RMDIR:
+ {
+ stub->args.rmdir.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.rmdir.loc);
+ }
+ break;
+
+ case GF_FOP_SYMLINK:
+ {
+ stub->args.symlink.fn (stub->frame,
+ stub->frame->this,
+ stub->args.symlink.linkname,
+ &stub->args.symlink.loc);
+ }
+ break;
+
+ case GF_FOP_RENAME:
+ {
+ stub->args.rename.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.rename.old,
+ &stub->args.rename.new);
+ }
+ break;
+
+ case GF_FOP_LINK:
+ {
+ stub->args.link.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.link.oldloc,
+ &stub->args.link.newloc);
+ }
+ break;
+
+ case GF_FOP_CHMOD:
+ {
+ stub->args.chmod.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.chmod.loc,
+ stub->args.chmod.mode);
+ }
+ break;
+
+ case GF_FOP_CHOWN:
+ {
+ stub->args.chown.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.chown.loc,
+ stub->args.chown.uid,
+ stub->args.chown.gid);
+ break;
+ }
+ case GF_FOP_TRUNCATE:
+ {
+ stub->args.truncate.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.truncate.loc,
+ stub->args.truncate.off);
+ break;
+ }
+
+ case GF_FOP_READ:
+ {
+ stub->args.readv.fn (stub->frame,
+ stub->frame->this,
+ stub->args.readv.fd,
+ stub->args.readv.size,
+ stub->args.readv.off);
+ break;
+ }
+
+ case GF_FOP_WRITE:
+ {
+ stub->args.writev.fn (stub->frame,
+ stub->frame->this,
+ stub->args.writev.fd,
+ stub->args.writev.vector,
+ stub->args.writev.count,
+ stub->args.writev.off);
+ break;
+ }
+
+ case GF_FOP_STATFS:
+ {
+ stub->args.statfs.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.statfs.loc);
+ break;
+ }
+ case GF_FOP_FLUSH:
+ {
+ stub->args.flush.fn (stub->frame,
+ stub->frame->this,
+ stub->args.flush.fd);
+ break;
+ }
+
+ case GF_FOP_FSYNC:
+ {
+ stub->args.fsync.fn (stub->frame,
+ stub->frame->this,
+ stub->args.fsync.fd,
+ stub->args.fsync.datasync);
+ break;
+ }
+
+ case GF_FOP_SETXATTR:
+ {
+ stub->args.setxattr.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.setxattr.loc,
+ stub->args.setxattr.dict,
+ stub->args.setxattr.flags);
+ break;
+ }
+
+ case GF_FOP_GETXATTR:
+ {
+ stub->args.getxattr.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.getxattr.loc,
+ stub->args.getxattr.name);
+ break;
+ }
+
+ case GF_FOP_REMOVEXATTR:
+ {
+ stub->args.removexattr.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.removexattr.loc,
+ stub->args.removexattr.name);
+ break;
+ }
+
+ case GF_FOP_OPENDIR:
+ {
+ stub->args.opendir.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.opendir.loc,
+ stub->args.opendir.fd);
+ break;
+ }
+
+ case GF_FOP_GETDENTS:
+ {
+ stub->args.getdents.fn (stub->frame,
+ stub->frame->this,
+ stub->args.getdents.fd,
+ stub->args.getdents.size,
+ stub->args.getdents.off,
+ stub->args.getdents.flag);
+ break;
+ }
+
+ case GF_FOP_FSYNCDIR:
+ {
+ stub->args.fsyncdir.fn (stub->frame,
+ stub->frame->this,
+ stub->args.fsyncdir.fd,
+ stub->args.fsyncdir.datasync);
+ break;
+ }
+
+ case GF_FOP_ACCESS:
+ {
+ stub->args.access.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.access.loc,
+ stub->args.access.mask);
+ break;
+ }
+
+ case GF_FOP_FTRUNCATE:
+ {
+ stub->args.ftruncate.fn (stub->frame,
+ stub->frame->this,
+ stub->args.ftruncate.fd,
+ stub->args.ftruncate.off);
+ break;
+ }
+
+ case GF_FOP_FSTAT:
+ {
+ stub->args.fstat.fn (stub->frame,
+ stub->frame->this,
+ stub->args.fstat.fd);
+ break;
+ }
+
+ case GF_FOP_LK:
+ {
+ stub->args.lk.fn (stub->frame,
+ stub->frame->this,
+ stub->args.lk.fd,
+ stub->args.lk.cmd,
+ &stub->args.lk.lock);
+ break;
+ }
+
+ case GF_FOP_INODELK:
+ {
+ stub->args.inodelk.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.inodelk.loc,
+ stub->args.inodelk.cmd,
+ &stub->args.inodelk.lock);
+ break;
+ }
+
+ case GF_FOP_FINODELK:
+ {
+ stub->args.finodelk.fn (stub->frame,
+ stub->frame->this,
+ stub->args.finodelk.fd,
+ stub->args.finodelk.cmd,
+ &stub->args.finodelk.lock);
+ break;
+ }
+
+ case GF_FOP_ENTRYLK:
+ {
+ stub->args.entrylk.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.entrylk.loc,
+ stub->args.entrylk.name,
+ stub->args.entrylk.cmd,
+ stub->args.entrylk.type);
+ break;
+ }
+
+ case GF_FOP_FENTRYLK:
+ {
+ stub->args.fentrylk.fn (stub->frame,
+ stub->frame->this,
+ stub->args.fentrylk.fd,
+ stub->args.fentrylk.name,
+ stub->args.fentrylk.cmd,
+ stub->args.fentrylk.type);
+ break;
+ }
+
+ case GF_FOP_UTIMENS:
+ {
+ stub->args.utimens.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.utimens.loc,
+ stub->args.utimens.tv);
+ break;
+ }
+
+
+ break;
+ case GF_FOP_FCHMOD:
+ {
+ stub->args.fchmod.fn (stub->frame,
+ stub->frame->this,
+ stub->args.fchmod.fd,
+ stub->args.fchmod.mode);
+ break;
+ }
+
+ case GF_FOP_FCHOWN:
+ {
+ stub->args.fchown.fn (stub->frame,
+ stub->frame->this,
+ stub->args.fchown.fd,
+ stub->args.fchown.uid,
+ stub->args.fchown.gid);
+ break;
+ }
+
+ case GF_FOP_LOOKUP:
+ {
+ stub->args.lookup.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.lookup.loc,
+ stub->args.lookup.xattr_req);
+ break;
+ }
+
+ case GF_FOP_SETDENTS:
+ {
+ stub->args.setdents.fn (stub->frame,
+ stub->frame->this,
+ stub->args.setdents.fd,
+ stub->args.setdents.flags,
+ &stub->args.setdents.entries,
+ stub->args.setdents.count);
+ break;
+ }
+
+ case GF_FOP_CHECKSUM:
+ {
+ stub->args.checksum.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.checksum.loc,
+ stub->args.checksum.flags);
+ break;
+ }
+ case GF_FOP_READDIR:
+ {
+ stub->args.readdir.fn (stub->frame,
+ stub->frame->this,
+ stub->args.readdir.fd,
+ stub->args.readdir.size,
+ stub->args.readdir.off);
+ break;
+ }
+ case GF_FOP_XATTROP:
+ {
+ stub->args.xattrop.fn (stub->frame,
+ stub->frame->this,
+ &stub->args.xattrop.loc,
+ stub->args.xattrop.optype,
+ stub->args.xattrop.xattr);
+
+ break;
+ }
+ case GF_FOP_FXATTROP:
+ {
+ stub->args.fxattrop.fn (stub->frame,
+ stub->frame->this,
+ stub->args.fxattrop.fd,
+ stub->args.fxattrop.optype,
+ stub->args.fxattrop.xattr);
+
+ break;
+ }
+ default:
+ {
+ gf_log ("call-stub",
+ GF_LOG_DEBUG,
+ "Invalid value of FOP");
+ }
+ break;
+ }
+out:
+ return;
+}
+
+
+
+static void
+call_resume_unwind (call_stub_t *stub)
+{
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ switch (stub->fop) {
+ case GF_FOP_OPEN:
+ {
+ if (!stub->args.open_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.open_cbk.op_ret,
+ stub->args.open_cbk.op_errno,
+ stub->args.open_cbk.fd);
+ else
+ stub->args.open_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.open_cbk.op_ret,
+ stub->args.open_cbk.op_errno,
+ stub->args.open_cbk.fd);
+ break;
+ }
+
+ case GF_FOP_CREATE:
+ {
+ if (!stub->args.create_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.create_cbk.op_ret,
+ stub->args.create_cbk.op_errno,
+ stub->args.create_cbk.fd,
+ stub->args.create_cbk.inode,
+ &stub->args.create_cbk.buf);
+ else
+ stub->args.create_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.create_cbk.op_ret,
+ stub->args.create_cbk.op_errno,
+ stub->args.create_cbk.fd,
+ stub->args.create_cbk.inode,
+ &stub->args.create_cbk.buf);
+
+ break;
+ }
+
+ case GF_FOP_STAT:
+ {
+ if (!stub->args.stat_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.stat_cbk.op_ret,
+ stub->args.stat_cbk.op_errno,
+ &stub->args.stat_cbk.buf);
+ else
+ stub->args.stat_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.stat_cbk.op_ret,
+ stub->args.stat_cbk.op_errno,
+ &stub->args.stat_cbk.buf);
+
+ break;
+ }
+
+ case GF_FOP_READLINK:
+ {
+ if (!stub->args.readlink_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.readlink_cbk.op_ret,
+ stub->args.readlink_cbk.op_errno,
+ stub->args.readlink_cbk.buf);
+ else
+ stub->args.readlink_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.readlink_cbk.op_ret,
+ stub->args.readlink_cbk.op_errno,
+ stub->args.readlink_cbk.buf);
+
+ break;
+ }
+
+ case GF_FOP_MKNOD:
+ {
+ if (!stub->args.mknod_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.mknod_cbk.op_ret,
+ stub->args.mknod_cbk.op_errno,
+ stub->args.mknod_cbk.inode,
+ &stub->args.mknod_cbk.buf);
+ else
+ stub->args.mknod_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.mknod_cbk.op_ret,
+ stub->args.mknod_cbk.op_errno,
+ stub->args.mknod_cbk.inode,
+ &stub->args.mknod_cbk.buf);
+ break;
+ }
+
+ case GF_FOP_MKDIR:
+ {
+ if (!stub->args.mkdir_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.mkdir_cbk.op_ret,
+ stub->args.mkdir_cbk.op_errno,
+ stub->args.mkdir_cbk.inode,
+ &stub->args.mkdir_cbk.buf);
+ else
+ stub->args.mkdir_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.mkdir_cbk.op_ret,
+ stub->args.mkdir_cbk.op_errno,
+ stub->args.mkdir_cbk.inode,
+ &stub->args.mkdir_cbk.buf);
+
+ if (stub->args.mkdir_cbk.inode)
+ inode_unref (stub->args.mkdir_cbk.inode);
+
+ break;
+ }
+
+ case GF_FOP_UNLINK:
+ {
+ if (!stub->args.unlink_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.unlink_cbk.op_ret,
+ stub->args.unlink_cbk.op_errno);
+ else
+ stub->args.unlink_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.unlink_cbk.op_ret,
+ stub->args.unlink_cbk.op_errno);
+ break;
+ }
+
+ case GF_FOP_RMDIR:
+ {
+ if (!stub->args.rmdir_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.rmdir_cbk.op_ret,
+ stub->args.rmdir_cbk.op_errno);
+ else
+ stub->args.unlink_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.rmdir_cbk.op_ret,
+ stub->args.rmdir_cbk.op_errno);
+ break;
+ }
+
+ case GF_FOP_SYMLINK:
+ {
+ if (!stub->args.symlink_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.symlink_cbk.op_ret,
+ stub->args.symlink_cbk.op_errno,
+ stub->args.symlink_cbk.inode,
+ &stub->args.symlink_cbk.buf);
+ else
+ stub->args.symlink_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.symlink_cbk.op_ret,
+ stub->args.symlink_cbk.op_errno,
+ stub->args.symlink_cbk.inode,
+ &stub->args.symlink_cbk.buf);
+ }
+ break;
+
+ case GF_FOP_RENAME:
+ {
+#if 0
+ if (!stub->args.rename_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.rename_cbk.op_ret,
+ stub->args.rename_cbk.op_errno,
+ &stub->args.rename_cbk.buf);
+ else
+ stub->args.rename_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.rename_cbk.op_ret,
+ stub->args.rename_cbk.op_errno,
+ &stub->args.rename_cbk.buf);
+#endif
+ break;
+ }
+
+ case GF_FOP_LINK:
+ {
+ if (!stub->args.link_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.link_cbk.op_ret,
+ stub->args.link_cbk.op_errno,
+ stub->args.link_cbk.inode,
+ &stub->args.link_cbk.buf);
+ else
+ stub->args.link_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.link_cbk.op_ret,
+ stub->args.link_cbk.op_errno,
+ stub->args.link_cbk.inode,
+ &stub->args.link_cbk.buf);
+ break;
+ }
+
+ case GF_FOP_CHMOD:
+ {
+ if (!stub->args.chmod_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.chmod_cbk.op_ret,
+ stub->args.chmod_cbk.op_errno,
+ &stub->args.chmod_cbk.buf);
+ else
+ stub->args.chmod_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.chmod_cbk.op_ret,
+ stub->args.chmod_cbk.op_errno,
+ &stub->args.chmod_cbk.buf);
+ break;
+ }
+
+ case GF_FOP_CHOWN:
+ {
+ if (!stub->args.chown_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.chown_cbk.op_ret,
+ stub->args.chown_cbk.op_errno,
+ &stub->args.chown_cbk.buf);
+ else
+ stub->args.chown_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.chown_cbk.op_ret,
+ stub->args.chown_cbk.op_errno,
+ &stub->args.chown_cbk.buf);
+ break;
+ }
+
+ case GF_FOP_TRUNCATE:
+ {
+ if (!stub->args.truncate_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.truncate_cbk.op_ret,
+ stub->args.truncate_cbk.op_errno,
+ &stub->args.truncate_cbk.buf);
+ else
+ stub->args.truncate_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.truncate_cbk.op_ret,
+ stub->args.truncate_cbk.op_errno,
+ &stub->args.truncate_cbk.buf);
+ break;
+ }
+
+ case GF_FOP_READ:
+ {
+ if (!stub->args.readv_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.readv_cbk.op_ret,
+ stub->args.readv_cbk.op_errno,
+ stub->args.readv_cbk.vector,
+ stub->args.readv_cbk.count,
+ &stub->args.readv_cbk.stbuf);
+ else
+ stub->args.readv_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.readv_cbk.op_ret,
+ stub->args.readv_cbk.op_errno,
+ stub->args.readv_cbk.vector,
+ stub->args.readv_cbk.count,
+ &stub->args.readv_cbk.stbuf);
+ }
+ break;
+
+ case GF_FOP_WRITE:
+ {
+ if (!stub->args.writev_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.writev_cbk.op_ret,
+ stub->args.writev_cbk.op_errno,
+ &stub->args.writev_cbk.stbuf);
+ else
+ stub->args.writev_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.writev_cbk.op_ret,
+ stub->args.writev_cbk.op_errno,
+ &stub->args.writev_cbk.stbuf);
+ break;
+ }
+
+ case GF_FOP_STATFS:
+ {
+ if (!stub->args.statfs_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.statfs_cbk.op_ret,
+ stub->args.statfs_cbk.op_errno,
+ &(stub->args.statfs_cbk.buf));
+ else
+ stub->args.statfs_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.statfs_cbk.op_ret,
+ stub->args.statfs_cbk.op_errno,
+ &(stub->args.statfs_cbk.buf));
+ }
+ break;
+
+ case GF_FOP_FLUSH:
+ {
+ if (!stub->args.flush_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.flush_cbk.op_ret,
+ stub->args.flush_cbk.op_errno);
+ else
+ stub->args.flush_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.flush_cbk.op_ret,
+ stub->args.flush_cbk.op_errno);
+
+ break;
+ }
+
+ case GF_FOP_FSYNC:
+ {
+ if (!stub->args.fsync_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.fsync_cbk.op_ret,
+ stub->args.fsync_cbk.op_errno);
+ else
+ stub->args.fsync_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.fsync_cbk.op_ret,
+ stub->args.fsync_cbk.op_errno);
+ break;
+ }
+
+ case GF_FOP_SETXATTR:
+ {
+ if (!stub->args.setxattr_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.setxattr_cbk.op_ret,
+ stub->args.setxattr_cbk.op_errno);
+
+ else
+ stub->args.setxattr_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.setxattr_cbk.op_ret,
+ stub->args.setxattr_cbk.op_errno);
+
+ break;
+ }
+
+ case GF_FOP_GETXATTR:
+ {
+ if (!stub->args.getxattr_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.getxattr_cbk.op_ret,
+ stub->args.getxattr_cbk.op_errno,
+ stub->args.getxattr_cbk.dict);
+ else
+ stub->args.getxattr_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.getxattr_cbk.op_ret,
+ stub->args.getxattr_cbk.op_errno,
+ stub->args.getxattr_cbk.dict);
+ break;
+ }
+
+ case GF_FOP_REMOVEXATTR:
+ {
+ if (!stub->args.removexattr_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.removexattr_cbk.op_ret,
+ stub->args.removexattr_cbk.op_errno);
+ else
+ stub->args.removexattr_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.removexattr_cbk.op_ret,
+ stub->args.removexattr_cbk.op_errno);
+
+ break;
+ }
+
+ case GF_FOP_OPENDIR:
+ {
+ if (!stub->args.opendir_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.opendir_cbk.op_ret,
+ stub->args.opendir_cbk.op_errno,
+ stub->args.opendir_cbk.fd);
+ else
+ stub->args.opendir_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.opendir_cbk.op_ret,
+ stub->args.opendir_cbk.op_errno,
+ stub->args.opendir_cbk.fd);
+ break;
+ }
+
+ case GF_FOP_GETDENTS:
+ {
+ if (!stub->args.getdents_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.getdents_cbk.op_ret,
+ stub->args.getdents_cbk.op_errno,
+ &stub->args.getdents_cbk.entries,
+ stub->args.getdents_cbk.count);
+ else
+ stub->args.getdents_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.getdents_cbk.op_ret,
+ stub->args.getdents_cbk.op_errno,
+ &stub->args.getdents_cbk.entries,
+ stub->args.getdents_cbk.count);
+ break;
+ }
+
+ case GF_FOP_FSYNCDIR:
+ {
+ if (!stub->args.fsyncdir_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.fsyncdir_cbk.op_ret,
+ stub->args.fsyncdir_cbk.op_errno);
+ else
+ stub->args.fsyncdir_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.fsyncdir_cbk.op_ret,
+ stub->args.fsyncdir_cbk.op_errno);
+ break;
+ }
+
+ case GF_FOP_ACCESS:
+ {
+ if (!stub->args.access_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.access_cbk.op_ret,
+ stub->args.access_cbk.op_errno);
+ else
+ stub->args.access_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.access_cbk.op_ret,
+ stub->args.access_cbk.op_errno);
+
+ break;
+ }
+
+ case GF_FOP_FTRUNCATE:
+ {
+ if (!stub->args.ftruncate_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.ftruncate_cbk.op_ret,
+ stub->args.ftruncate_cbk.op_errno,
+ &stub->args.ftruncate_cbk.buf);
+ else
+ stub->args.ftruncate_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.ftruncate_cbk.op_ret,
+ stub->args.ftruncate_cbk.op_errno,
+ &stub->args.ftruncate_cbk.buf);
+ break;
+ }
+
+ case GF_FOP_FSTAT:
+ {
+ if (!stub->args.fstat_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.fstat_cbk.op_ret,
+ stub->args.fstat_cbk.op_errno,
+ &stub->args.fstat_cbk.buf);
+ else
+ stub->args.fstat_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.fstat_cbk.op_ret,
+ stub->args.fstat_cbk.op_errno,
+ &stub->args.fstat_cbk.buf);
+
+ break;
+ }
+
+ case GF_FOP_LK:
+ {
+ if (!stub->args.lk_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.lk_cbk.op_ret,
+ stub->args.lk_cbk.op_errno,
+ &stub->args.lk_cbk.lock);
+ else
+ stub->args.lk_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.lk_cbk.op_ret,
+ stub->args.lk_cbk.op_errno,
+ &stub->args.lk_cbk.lock);
+ break;
+ }
+
+ case GF_FOP_INODELK:
+ {
+ if (!stub->args.inodelk_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.inodelk_cbk.op_ret,
+ stub->args.inodelk_cbk.op_errno);
+
+ else
+ stub->args.inodelk_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.inodelk_cbk.op_ret,
+ stub->args.inodelk_cbk.op_errno);
+ break;
+ }
+
+ case GF_FOP_FINODELK:
+ {
+ if (!stub->args.finodelk_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.finodelk_cbk.op_ret,
+ stub->args.finodelk_cbk.op_errno);
+
+ else
+ stub->args.finodelk_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.finodelk_cbk.op_ret,
+ stub->args.finodelk_cbk.op_errno);
+ break;
+ }
+
+ case GF_FOP_ENTRYLK:
+ {
+ if (!stub->args.entrylk_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.entrylk_cbk.op_ret,
+ stub->args.entrylk_cbk.op_errno);
+
+ else
+ stub->args.entrylk_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.entrylk_cbk.op_ret,
+ stub->args.entrylk_cbk.op_errno);
+ break;
+ }
+
+ case GF_FOP_FENTRYLK:
+ {
+ if (!stub->args.fentrylk_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.fentrylk_cbk.op_ret,
+ stub->args.fentrylk_cbk.op_errno);
+
+ else
+ stub->args.fentrylk_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.fentrylk_cbk.op_ret,
+ stub->args.fentrylk_cbk.op_errno);
+ break;
+ }
+
+ case GF_FOP_UTIMENS:
+ {
+ if (!stub->args.utimens_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.utimens_cbk.op_ret,
+ stub->args.utimens_cbk.op_errno,
+ &stub->args.utimens_cbk.buf);
+ else
+ stub->args.utimens_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.utimens_cbk.op_ret,
+ stub->args.utimens_cbk.op_errno,
+ &stub->args.utimens_cbk.buf);
+
+ break;
+ }
+
+
+ break;
+ case GF_FOP_FCHMOD:
+ {
+ if (!stub->args.fchmod_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.fchmod_cbk.op_ret,
+ stub->args.fchmod_cbk.op_errno,
+ &stub->args.fchmod_cbk.buf);
+ else
+ stub->args.fchmod_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.fchmod_cbk.op_ret,
+ stub->args.fchmod_cbk.op_errno,
+ &stub->args.fchmod_cbk.buf);
+ break;
+ }
+
+ case GF_FOP_FCHOWN:
+ {
+ if (!stub->args.fchown_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.fchown_cbk.op_ret,
+ stub->args.fchown_cbk.op_errno,
+ &stub->args.fchown_cbk.buf);
+ else
+ stub->args.fchown_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.fchown_cbk.op_ret,
+ stub->args.fchown_cbk.op_errno,
+ &stub->args.fchown_cbk.buf);
+ break;
+ }
+
+ case GF_FOP_LOOKUP:
+ {
+ if (!stub->args.lookup_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.lookup_cbk.op_ret,
+ stub->args.lookup_cbk.op_errno,
+ stub->args.lookup_cbk.inode,
+ &stub->args.lookup_cbk.buf,
+ stub->args.lookup_cbk.dict);
+ else
+ stub->args.lookup_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.lookup_cbk.op_ret,
+ stub->args.lookup_cbk.op_errno,
+ stub->args.lookup_cbk.inode,
+ &stub->args.lookup_cbk.buf,
+ stub->args.lookup_cbk.dict);
+ /* FIXME NULL should not be passed */
+
+ if (stub->args.lookup_cbk.dict)
+ dict_unref (stub->args.lookup_cbk.dict);
+ if (stub->args.lookup_cbk.inode)
+ inode_unref (stub->args.lookup_cbk.inode);
+
+ break;
+ }
+ case GF_FOP_SETDENTS:
+ {
+ if (!stub->args.setdents_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.setdents_cbk.op_ret,
+ stub->args.setdents_cbk.op_errno);
+ else
+ stub->args.setdents_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.setdents_cbk.op_ret,
+ stub->args.setdents_cbk.op_errno);
+ break;
+ }
+
+ case GF_FOP_CHECKSUM:
+ {
+ if (!stub->args.checksum_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.checksum_cbk.op_ret,
+ stub->args.checksum_cbk.op_errno,
+ stub->args.checksum_cbk.file_checksum,
+ stub->args.checksum_cbk.dir_checksum);
+ else
+ stub->args.checksum_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.checksum_cbk.op_ret,
+ stub->args.checksum_cbk.op_errno,
+ stub->args.checksum_cbk.file_checksum,
+ stub->args.checksum_cbk.dir_checksum);
+ if (stub->args.checksum_cbk.op_ret >= 0)
+ {
+ FREE (stub->args.checksum_cbk.file_checksum);
+ FREE (stub->args.checksum_cbk.dir_checksum);
+ }
+
+ break;
+ }
+
+ case GF_FOP_READDIR:
+ {
+ if (!stub->args.readdir_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.readdir_cbk.op_ret,
+ stub->args.readdir_cbk.op_errno,
+ &stub->args.readdir_cbk.entries);
+ else
+ stub->args.readdir_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.readdir_cbk.op_ret,
+ stub->args.readdir_cbk.op_errno,
+ &stub->args.readdir_cbk.entries);
+
+ if (stub->args.readdir_cbk.op_ret > 0)
+ gf_dirent_free (&stub->args.readdir_cbk.entries);
+
+ break;
+ }
+
+ case GF_FOP_XATTROP:
+ {
+ if (!stub->args.xattrop_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.xattrop_cbk.op_ret,
+ stub->args.xattrop_cbk.op_errno);
+ else
+ stub->args.xattrop_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.xattrop_cbk.op_ret,
+ stub->args.xattrop_cbk.op_errno,
+ stub->args.xattrop_cbk.xattr);
+
+ if (stub->args.xattrop_cbk.xattr)
+ dict_unref (stub->args.xattrop_cbk.xattr);
+
+ break;
+ }
+ case GF_FOP_FXATTROP:
+ {
+ if (!stub->args.fxattrop_cbk.fn)
+ STACK_UNWIND (stub->frame,
+ stub->args.fxattrop_cbk.op_ret,
+ stub->args.fxattrop_cbk.op_errno);
+ else
+ stub->args.fxattrop_cbk.fn (stub->frame,
+ stub->frame->cookie,
+ stub->frame->this,
+ stub->args.fxattrop_cbk.op_ret,
+ stub->args.fxattrop_cbk.op_errno,
+ stub->args.fxattrop_cbk.xattr);
+
+ if (stub->args.fxattrop_cbk.xattr)
+ dict_unref (stub->args.fxattrop_cbk.xattr);
+
+ break;
+ }
+ case GF_FOP_MAXVALUE:
+ {
+ gf_log ("call-stub",
+ GF_LOG_DEBUG,
+ "Invalid value of FOP");
+ }
+ break;
+ }
+out:
+ return;
+}
+
+
+static void
+call_stub_destroy_wind (call_stub_t *stub)
+{
+ switch (stub->fop) {
+ case GF_FOP_OPEN:
+ {
+ loc_wipe (&stub->args.open.loc);
+ if (stub->args.open.fd)
+ fd_unref (stub->args.open.fd);
+ break;
+ }
+ case GF_FOP_CREATE:
+ {
+ loc_wipe (&stub->args.create.loc);
+ if (stub->args.create.fd)
+ fd_unref (stub->args.create.fd);
+ break;
+ }
+ case GF_FOP_STAT:
+ {
+ loc_wipe (&stub->args.stat.loc);
+ break;
+ }
+ case GF_FOP_READLINK:
+ {
+ loc_wipe (&stub->args.readlink.loc);
+ break;
+ }
+
+ case GF_FOP_MKNOD:
+ {
+ loc_wipe (&stub->args.mknod.loc);
+ }
+ break;
+
+ case GF_FOP_MKDIR:
+ {
+ loc_wipe (&stub->args.mkdir.loc);
+ }
+ break;
+
+ case GF_FOP_UNLINK:
+ {
+ loc_wipe (&stub->args.unlink.loc);
+ }
+ break;
+
+ case GF_FOP_RMDIR:
+ {
+ loc_wipe (&stub->args.rmdir.loc);
+ }
+ break;
+
+ case GF_FOP_SYMLINK:
+ {
+ FREE (stub->args.symlink.linkname);
+ loc_wipe (&stub->args.symlink.loc);
+ }
+ break;
+
+ case GF_FOP_RENAME:
+ {
+ loc_wipe (&stub->args.rename.old);
+ loc_wipe (&stub->args.rename.new);
+ }
+ break;
+
+ case GF_FOP_LINK:
+ {
+ loc_wipe (&stub->args.link.oldloc);
+ loc_wipe (&stub->args.link.newloc);
+ }
+ break;
+
+ case GF_FOP_CHMOD:
+ {
+ loc_wipe (&stub->args.chmod.loc);
+ }
+ break;
+
+ case GF_FOP_CHOWN:
+ {
+ loc_wipe (&stub->args.chown.loc);
+ break;
+ }
+ case GF_FOP_TRUNCATE:
+ {
+ loc_wipe (&stub->args.truncate.loc);
+ break;
+ }
+
+ case GF_FOP_READ:
+ {
+ if (stub->args.readv.fd)
+ fd_unref (stub->args.readv.fd);
+ break;
+ }
+
+ case GF_FOP_WRITE:
+ {
+ dict_t *refs = stub->args.writev.req_refs;
+ if (stub->args.writev.fd)
+ fd_unref (stub->args.writev.fd);
+ FREE (stub->args.writev.vector);
+ if (refs)
+ dict_unref (refs);
+ break;
+ }
+
+ case GF_FOP_STATFS:
+ {
+ loc_wipe (&stub->args.statfs.loc);
+ break;
+ }
+ case GF_FOP_FLUSH:
+ {
+ if (stub->args.flush.fd)
+ fd_unref (stub->args.flush.fd);
+ break;
+ }
+
+ case GF_FOP_FSYNC:
+ {
+ if (stub->args.fsync.fd)
+ fd_unref (stub->args.fsync.fd);
+ break;
+ }
+
+ case GF_FOP_SETXATTR:
+ {
+ loc_wipe (&stub->args.setxattr.loc);
+ if (stub->args.setxattr.dict)
+ dict_unref (stub->args.setxattr.dict);
+ break;
+ }
+
+ case GF_FOP_GETXATTR:
+ {
+ if (stub->args.getxattr.name)
+ FREE (stub->args.getxattr.name);
+ loc_wipe (&stub->args.getxattr.loc);
+ break;
+ }
+
+ case GF_FOP_REMOVEXATTR:
+ {
+ loc_wipe (&stub->args.removexattr.loc);
+ FREE (stub->args.removexattr.name);
+ break;
+ }
+
+ case GF_FOP_OPENDIR:
+ {
+ loc_wipe (&stub->args.opendir.loc);
+ if (stub->args.opendir.fd)
+ fd_unref (stub->args.opendir.fd);
+ break;
+ }
+
+ case GF_FOP_GETDENTS:
+ {
+ if (stub->args.getdents.fd)
+ fd_unref (stub->args.getdents.fd);
+ break;
+ }
+
+ case GF_FOP_FSYNCDIR:
+ {
+ if (stub->args.fsyncdir.fd)
+ fd_unref (stub->args.fsyncdir.fd);
+ break;
+ }
+
+ case GF_FOP_ACCESS:
+ {
+ loc_wipe (&stub->args.access.loc);
+ break;
+ }
+
+ case GF_FOP_FTRUNCATE:
+ {
+ if (stub->args.ftruncate.fd)
+ fd_unref (stub->args.ftruncate.fd);
+ break;
+ }
+
+ case GF_FOP_FSTAT:
+ {
+ if (stub->args.fstat.fd)
+ fd_unref (stub->args.fstat.fd);
+ break;
+ }
+
+ case GF_FOP_LK:
+ {
+ if (stub->args.lk.fd)
+ fd_unref (stub->args.lk.fd);
+ break;
+ }
+
+ case GF_FOP_INODELK:
+ {
+ loc_wipe (&stub->args.inodelk.loc);
+ break;
+ }
+ case GF_FOP_FINODELK:
+ {
+ if (stub->args.finodelk.fd)
+ fd_unref (stub->args.finodelk.fd);
+ break;
+ }
+ case GF_FOP_ENTRYLK:
+ {
+ if (stub->args.entrylk.name)
+ FREE (stub->args.entrylk.name);
+ loc_wipe (&stub->args.entrylk.loc);
+ break;
+ }
+ case GF_FOP_FENTRYLK:
+ {
+ if (stub->args.fentrylk.name)
+ FREE (stub->args.fentrylk.name);
+
+ if (stub->args.fentrylk.fd)
+ fd_unref (stub->args.fentrylk.fd);
+ break;
+ }
+ case GF_FOP_UTIMENS:
+ {
+ loc_wipe (&stub->args.utimens.loc);
+ break;
+ }
+ break;
+ case GF_FOP_FCHMOD:
+ {
+ if (stub->args.fchmod.fd)
+ fd_unref (stub->args.fchmod.fd);
+ break;
+ }
+
+ case GF_FOP_FCHOWN:
+ {
+ if (stub->args.fchown.fd)
+ fd_unref (stub->args.fchown.fd);
+ break;
+ }
+
+ case GF_FOP_LOOKUP:
+ {
+ loc_wipe (&stub->args.lookup.loc);
+ if (stub->args.lookup.xattr_req)
+ dict_unref (stub->args.lookup.xattr_req);
+ break;
+ }
+
+ case GF_FOP_SETDENTS:
+ {
+ dir_entry_t *entry, *next;
+ if (stub->args.setdents.fd)
+ fd_unref (stub->args.setdents.fd);
+ entry = stub->args.setdents.entries.next;
+ while (entry) {
+ next = entry->next;
+ FREE (entry->name);
+ FREE (entry);
+ entry = next;
+ }
+ break;
+ }
+
+ case GF_FOP_CHECKSUM:
+ {
+ loc_wipe (&stub->args.checksum.loc);
+ break;
+ }
+ break;
+ case GF_FOP_READDIR:
+ {
+ if (stub->args.readdir.fd)
+ fd_unref (stub->args.readdir.fd);
+ break;
+ }
+ case GF_FOP_XATTROP:
+ {
+ loc_wipe (&stub->args.xattrop.loc);
+ dict_unref (stub->args.xattrop.xattr);
+ break;
+ }
+ case GF_FOP_FXATTROP:
+ {
+ if (stub->args.fxattrop.fd)
+ fd_unref (stub->args.fxattrop.fd);
+ dict_unref (stub->args.xattrop.xattr);
+ break;
+ }
+ case GF_FOP_MAXVALUE:
+ {
+ gf_log ("call-stub",
+ GF_LOG_DEBUG,
+ "Invalid value of FOP");
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
+static void
+call_stub_destroy_unwind (call_stub_t *stub)
+{
+ switch (stub->fop) {
+ case GF_FOP_OPEN:
+ {
+ if (stub->args.open_cbk.fd)
+ fd_unref (stub->args.open_cbk.fd);
+ }
+ break;
+
+ case GF_FOP_CREATE:
+ {
+ if (stub->args.create_cbk.fd)
+ fd_unref (stub->args.create_cbk.fd);
+
+ if (stub->args.create_cbk.inode)
+ inode_unref (stub->args.create_cbk.inode);
+ }
+ break;
+
+ case GF_FOP_STAT:
+ break;
+
+ case GF_FOP_READLINK:
+ {
+ if (stub->args.readlink_cbk.buf)
+ FREE (stub->args.readlink_cbk.buf);
+ }
+ break;
+
+ case GF_FOP_MKNOD:
+ {
+ if (stub->args.mknod_cbk.inode)
+ inode_unref (stub->args.mknod_cbk.inode);
+ }
+ break;
+
+ case GF_FOP_MKDIR:
+ {
+ if (stub->args.mkdir_cbk.inode)
+ inode_unref (stub->args.mkdir_cbk.inode);
+ }
+ break;
+
+ case GF_FOP_UNLINK:
+ break;
+
+ case GF_FOP_RMDIR:
+ break;
+
+ case GF_FOP_SYMLINK:
+ {
+ if (stub->args.symlink_cbk.inode)
+ inode_unref (stub->args.symlink_cbk.inode);
+ }
+ break;
+
+ case GF_FOP_RENAME:
+ break;
+
+ case GF_FOP_LINK:
+ {
+ if (stub->args.link_cbk.inode)
+ inode_unref (stub->args.link_cbk.inode);
+ }
+ break;
+
+ case GF_FOP_CHMOD:
+ break;
+
+ case GF_FOP_CHOWN:
+ break;
+
+ case GF_FOP_TRUNCATE:
+ break;
+
+ case GF_FOP_READ:
+ {
+ if (stub->args.readv_cbk.op_ret >= 0) {
+ dict_t *refs = stub->args.readv_cbk.rsp_refs;
+ FREE (stub->args.readv_cbk.vector);
+
+ if (refs) {
+ dict_unref (refs);
+ }
+ }
+ }
+ break;
+
+ case GF_FOP_WRITE:
+ break;
+
+ case GF_FOP_STATFS:
+ break;
+
+ case GF_FOP_FLUSH:
+ break;
+
+ case GF_FOP_FSYNC:
+ break;
+
+ case GF_FOP_SETXATTR:
+ break;
+
+ case GF_FOP_GETXATTR:
+ {
+ if (stub->args.getxattr_cbk.dict)
+ dict_unref (stub->args.getxattr_cbk.dict);
+ }
+ break;
+
+ case GF_FOP_REMOVEXATTR:
+ break;
+
+ case GF_FOP_OPENDIR:
+ {
+ if (stub->args.opendir_cbk.fd)
+ fd_unref (stub->args.opendir_cbk.fd);
+ }
+ break;
+
+ case GF_FOP_GETDENTS:
+ {
+ dir_entry_t *tmp = NULL, *entries = NULL;
+
+ entries = &stub->args.getdents_cbk.entries;
+ if (stub->args.getdents_cbk.op_ret >= 0) {
+ while (entries->next) {
+ tmp = entries->next;
+ entries->next = entries->next->next;
+ FREE (tmp->name);
+ FREE (tmp);
+ }
+ }
+ }
+ break;
+
+ case GF_FOP_FSYNCDIR:
+ break;
+
+ case GF_FOP_ACCESS:
+ break;
+
+ case GF_FOP_FTRUNCATE:
+ break;
+
+ case GF_FOP_FSTAT:
+ break;
+
+ case GF_FOP_LK:
+ break;
+
+ case GF_FOP_INODELK:
+ break;
+
+ case GF_FOP_FINODELK:
+ break;
+
+ case GF_FOP_ENTRYLK:
+ break;
+
+ case GF_FOP_FENTRYLK:
+ break;
+
+ case GF_FOP_UTIMENS:
+ break;
+
+ case GF_FOP_FCHMOD:
+ break;
+
+ case GF_FOP_FCHOWN:
+ break;
+
+ case GF_FOP_LOOKUP:
+ {
+ if (stub->args.lookup_cbk.inode)
+ inode_unref (stub->args.lookup_cbk.inode);
+
+ if (stub->args.lookup_cbk.dict)
+ dict_unref (stub->args.lookup_cbk.dict);
+ }
+ break;
+
+ case GF_FOP_SETDENTS:
+ break;
+
+ case GF_FOP_CHECKSUM:
+ {
+ if (stub->args.checksum_cbk.op_ret >= 0) {
+ FREE (stub->args.checksum_cbk.file_checksum);
+ FREE (stub->args.checksum_cbk.dir_checksum);
+ }
+ }
+ break;
+
+ case GF_FOP_READDIR:
+ {
+ if (stub->args.readdir_cbk.op_ret > 0) {
+ gf_dirent_free (&stub->args.readdir_cbk.entries);
+ }
+ }
+ break;
+
+ case GF_FOP_XATTROP:
+ {
+ if (stub->args.xattrop_cbk.xattr)
+ dict_unref (stub->args.xattrop_cbk.xattr);
+ }
+ break;
+
+ case GF_FOP_FXATTROP:
+ {
+ if (stub->args.fxattrop_cbk.xattr)
+ dict_unref (stub->args.fxattrop_cbk.xattr);
+ }
+ break;
+
+ case GF_FOP_MAXVALUE:
+ {
+ gf_log ("call-stub",
+ GF_LOG_DEBUG,
+ "Invalid value of FOP");
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+void
+call_stub_destroy (call_stub_t *stub)
+{
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ if (stub->wind) {
+ call_stub_destroy_wind (stub);
+ } else {
+ call_stub_destroy_unwind (stub);
+ }
+
+ FREE (stub);
+out:
+ return;
+}
+
+void
+call_resume (call_stub_t *stub)
+{
+ errno = EINVAL;
+ GF_VALIDATE_OR_GOTO ("call-stub", stub, out);
+
+ list_del_init (&stub->list);
+
+ if (stub->wind)
+ call_resume_wind (stub);
+ else
+ call_resume_unwind (stub);
+
+ call_stub_destroy (stub);
+out:
+ return;
+}
+
+
diff --git a/libglusterfs/src/call-stub.h b/libglusterfs/src/call-stub.h
new file mode 100644
index 000000000..12e94a158
--- /dev/null
+++ b/libglusterfs/src/call-stub.h
@@ -0,0 +1,1104 @@
+/*
+ Copyright (c) 2007, 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/>.
+*/
+
+#ifndef _CALL_STUB_H_
+#define _CALL_STUB_H_
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "xlator.h"
+#include "stack.h"
+#include "list.h"
+
+typedef struct {
+ struct list_head list;
+ char wind;
+ call_frame_t *frame;
+ glusterfs_fop_t fop;
+
+ union {
+ /* lookup */
+ struct {
+ fop_lookup_t fn;
+ loc_t loc;
+ dict_t *xattr_req;
+ } lookup;
+ struct {
+ fop_lookup_cbk_t fn;
+ int32_t op_ret, op_errno;
+ inode_t *inode;
+ struct stat buf;
+ dict_t *dict;
+ } lookup_cbk;
+
+ /* stat */
+ struct {
+ fop_stat_t fn;
+ loc_t loc;
+ } stat;
+ struct {
+ fop_stat_cbk_t fn;
+ int32_t op_ret, op_errno;
+ struct stat buf;
+ } stat_cbk;
+
+ /* fstat */
+ struct {
+ fop_fstat_t fn;
+ fd_t *fd;
+ } fstat;
+ struct {
+ fop_fstat_cbk_t fn;
+ int32_t op_ret, op_errno;
+ struct stat buf;
+ } fstat_cbk;
+
+ /* chmod */
+ struct {
+ fop_chmod_t fn;
+ loc_t loc;
+ mode_t mode;
+ } chmod;
+ struct {
+ fop_chmod_cbk_t fn;
+ int32_t op_ret, op_errno;
+ struct stat buf;
+ } chmod_cbk;
+
+ /* fchmod */
+ struct {
+ fop_fchmod_t fn;
+ fd_t *fd;
+ mode_t mode;
+ } fchmod;
+ struct {
+ fop_fchmod_cbk_t fn;
+ int32_t op_ret, op_errno;
+ struct stat buf;
+ } fchmod_cbk;
+
+ /* chown */
+ struct {
+ fop_chown_t fn;
+ loc_t loc;
+ uid_t uid;
+ gid_t gid;
+ } chown;
+ struct {
+ fop_chown_cbk_t fn;
+ int32_t op_ret, op_errno;
+ struct stat buf;
+ } chown_cbk;
+
+ /* fchown */
+ struct {
+ fop_fchown_t fn;
+ fd_t *fd;
+ uid_t uid;
+ gid_t gid;
+ } fchown;
+ struct {
+ fop_fchown_cbk_t fn;
+ int32_t op_ret, op_errno;
+ struct stat buf;
+ } fchown_cbk;
+
+ /* truncate */
+ struct {
+ fop_truncate_t fn;
+ loc_t loc;
+ off_t off;
+ } truncate;
+ struct {
+ fop_truncate_cbk_t fn;
+ int32_t op_ret, op_errno;
+ struct stat buf;
+ } truncate_cbk;
+
+ /* ftruncate */
+ struct {
+ fop_ftruncate_t fn;
+ fd_t *fd;
+ off_t off;
+ } ftruncate;
+ struct {
+ fop_ftruncate_cbk_t fn;
+ int32_t op_ret, op_errno;
+ struct stat buf;
+ } ftruncate_cbk;
+
+ /* utimens */
+ struct {
+ fop_utimens_t fn;
+ loc_t loc;
+ struct timespec tv[2];
+ } utimens;
+ struct {
+ fop_utimens_cbk_t fn;
+ int32_t op_ret, op_errno;
+ struct stat buf;
+ } utimens_cbk;
+
+ /* access */
+ struct {
+ fop_access_t fn;
+ loc_t loc;
+ int32_t mask;
+ } access;
+ struct {
+ fop_access_cbk_t fn;
+ int32_t op_ret, op_errno;
+ } access_cbk;
+
+ /* readlink */
+ struct {
+ fop_readlink_t fn;
+ loc_t loc;
+ size_t size;
+ } readlink;
+ struct {
+ fop_readlink_cbk_t fn;
+ int32_t op_ret, op_errno;
+ const char *buf;
+ } readlink_cbk;
+
+ /* mknod */
+ struct {
+ fop_mknod_t fn;
+ loc_t loc;
+ mode_t mode;
+ dev_t rdev;
+ } mknod;
+ struct {
+ fop_mknod_cbk_t fn;
+ int32_t op_ret, op_errno;
+ inode_t *inode;
+ struct stat buf;
+ } mknod_cbk;
+
+ /* mkdir */
+ struct {
+ fop_mkdir_t fn;
+ loc_t loc;
+ mode_t mode;
+ } mkdir;
+ struct {
+ fop_mkdir_cbk_t fn;
+ int32_t op_ret, op_errno;
+ inode_t *inode;
+ struct stat buf;
+ } mkdir_cbk;
+
+ /* unlink */
+ struct {
+ fop_unlink_t fn;
+ loc_t loc;
+ } unlink;
+ struct {
+ fop_unlink_cbk_t fn;
+ int32_t op_ret, op_errno;
+ } unlink_cbk;
+
+ /* rmdir */
+ struct {
+ fop_rmdir_t fn;
+ loc_t loc;
+ } rmdir;
+ struct {
+ fop_rmdir_cbk_t fn;
+ int32_t op_ret, op_errno;
+ } rmdir_cbk;
+
+ /* symlink */
+ struct {
+ fop_symlink_t fn;
+ const char *linkname;
+ loc_t loc;
+ } symlink;
+ struct {
+ fop_symlink_cbk_t fn;
+ int32_t op_ret, op_errno;
+ inode_t *inode;
+ struct stat buf;
+ } symlink_cbk;
+
+ /* rename */
+ struct {
+ fop_rename_t fn;
+ loc_t old;
+ loc_t new;
+ } rename;
+ struct {
+ fop_rename_cbk_t fn;
+ int32_t op_ret, op_errno;
+ struct stat buf;
+ } rename_cbk;
+
+ /* link */
+ struct {
+ fop_link_t fn;
+ loc_t oldloc;
+ loc_t newloc;
+ } link;
+ struct {
+ fop_link_cbk_t fn;
+ int32_t op_ret, op_errno;
+ inode_t *inode;
+ struct stat buf;
+ } link_cbk;
+
+ /* create */
+ struct {
+ fop_create_t fn;
+ loc_t loc;
+ int32_t flags;
+ mode_t mode;
+ fd_t *fd;
+ } create;
+ struct {
+ fop_create_cbk_t fn;
+ int32_t op_ret, op_errno;
+ fd_t *fd;
+ inode_t *inode;
+ struct stat buf;
+ } create_cbk;
+
+ /* open */
+ struct {
+ fop_open_t fn;
+ loc_t loc;
+ int32_t flags;
+ fd_t *fd;
+ } open;
+ struct {
+ fop_open_cbk_t fn;
+ int32_t op_ret, op_errno;
+ fd_t *fd;
+ } open_cbk;
+
+ /* readv */
+ struct {
+ fop_readv_t fn;
+ fd_t *fd;
+ size_t size;
+ off_t off;
+ } readv;
+ struct {
+ fop_readv_cbk_t fn;
+ int32_t op_ret;
+ int32_t op_errno;
+ struct iovec *vector;
+ int32_t count;
+ struct stat stbuf;
+ dict_t *rsp_refs;
+ } readv_cbk;
+
+ /* writev */
+ struct {
+ fop_writev_t fn;
+ fd_t *fd;
+ struct iovec *vector;
+ int32_t count;
+ off_t off;
+ dict_t *req_refs;
+ } writev;
+ struct {
+ fop_writev_cbk_t fn;
+ int32_t op_ret, op_errno;
+ struct stat stbuf;
+ } writev_cbk;
+
+ /* flush */
+ struct {
+ fop_flush_t fn;
+ fd_t *fd;
+ } flush;
+ struct {
+ fop_flush_cbk_t fn;
+ int32_t op_ret, op_errno;
+ } flush_cbk;
+
+ /* fsync */
+ struct {
+ fop_fsync_t fn;
+ fd_t *fd;
+ int32_t datasync;
+ } fsync;
+ struct {
+ fop_fsync_cbk_t fn;
+ int32_t op_ret, op_errno;
+ } fsync_cbk;
+
+ /* opendir */
+ struct {
+ fop_opendir_t fn;
+ loc_t loc;
+ fd_t *fd;
+ } opendir;
+ struct {
+ fop_opendir_cbk_t fn;
+ int32_t op_ret, op_errno;
+ fd_t *fd;
+ } opendir_cbk;
+
+ /* getdents */
+ struct {
+ fop_getdents_t fn;
+ fd_t *fd;
+ size_t size;
+ off_t off;
+ int32_t flag;
+ } getdents;
+ struct {
+ fop_getdents_cbk_t fn;
+ int32_t op_ret;
+ int32_t op_errno;
+ dir_entry_t entries;
+ int32_t count;
+ } getdents_cbk;
+
+ /* setdents */
+ struct {
+ fop_setdents_t fn;
+ fd_t *fd;
+ int32_t flags;
+ dir_entry_t entries;
+ int32_t count;
+ } setdents;
+ struct {
+ fop_setdents_cbk_t fn;
+ int32_t op_ret;
+ int32_t op_errno;
+ } setdents_cbk;
+
+ /* fsyncdir */
+ struct {
+ fop_fsyncdir_t fn;
+ fd_t *fd;
+ int32_t datasync;
+ } fsyncdir;
+ struct {
+ fop_fsyncdir_cbk_t fn;
+ int32_t op_ret, op_errno;
+ } fsyncdir_cbk;
+
+ /* statfs */
+ struct {
+ fop_statfs_t fn;
+ loc_t loc;
+ } statfs;
+ struct {
+ fop_statfs_cbk_t fn;
+ int32_t op_ret, op_errno;
+ struct statvfs buf;
+ } statfs_cbk;
+
+ /* setxattr */
+ struct {
+ fop_setxattr_t fn;
+ loc_t loc;
+ dict_t *dict;
+ int32_t flags;
+ } setxattr;
+ struct {
+ fop_setxattr_cbk_t fn;
+ int32_t op_ret, op_errno;
+ } setxattr_cbk;
+
+ /* getxattr */
+ struct {
+ fop_getxattr_t fn;
+ loc_t loc;
+ const char *name;
+ } getxattr;
+ struct {
+ fop_getxattr_cbk_t fn;
+ int32_t op_ret, op_errno;
+ dict_t *dict;
+ } getxattr_cbk;
+
+ /* removexattr */
+ struct {
+ fop_removexattr_t fn;
+ loc_t loc;
+ const char *name;
+ } removexattr;
+ struct {
+ fop_removexattr_cbk_t fn;
+ int32_t op_ret, op_errno;
+ } removexattr_cbk;
+
+ /* lk */
+ struct {
+ fop_lk_t fn;
+ fd_t *fd;
+ int32_t cmd;
+ struct flock lock;
+ } lk;
+ struct {
+ fop_lk_cbk_t fn;
+ int32_t op_ret, op_errno;
+ struct flock lock;
+ } lk_cbk;
+
+ /* inodelk */
+ struct {
+ fop_inodelk_t fn;
+ loc_t loc;
+ int32_t cmd;
+ struct flock lock;
+ } inodelk;
+
+ struct {
+ fop_inodelk_cbk_t fn;
+ int32_t op_ret, op_errno;
+ } inodelk_cbk;
+
+ /* finodelk */
+ struct {
+ fop_finodelk_t fn;
+ fd_t *fd;
+ int32_t cmd;
+ struct flock lock;
+ } finodelk;
+
+ struct {
+ fop_finodelk_cbk_t fn;
+ int32_t op_ret, op_errno;
+ } finodelk_cbk;
+
+ /* entrylk */
+ struct {
+ fop_entrylk_t fn;
+ loc_t loc;
+ const char *name;
+ entrylk_cmd cmd;
+ entrylk_type type;
+ } entrylk;
+
+ struct {
+ fop_entrylk_cbk_t fn;
+ int32_t op_ret, op_errno;
+ } entrylk_cbk;
+
+ /* fentrylk */
+ struct {
+ fop_fentrylk_t fn;
+ fd_t *fd;
+ const char *name;
+ entrylk_cmd cmd;
+ entrylk_type type;
+ } fentrylk;
+
+ struct {
+ fop_fentrylk_cbk_t fn;
+ int32_t op_ret, op_errno;
+ } fentrylk_cbk;
+
+ /* readdir */
+ struct {
+ fop_readdir_t fn;
+ fd_t *fd;
+ size_t size;
+ off_t off;
+ } readdir;
+ struct {
+ fop_readdir_cbk_t fn;
+ int32_t op_ret, op_errno;
+ gf_dirent_t entries;
+ } readdir_cbk;
+
+ /* checksum */
+ struct {
+ fop_checksum_t fn;
+ loc_t loc;
+ int32_t flags;
+ } checksum;
+ struct {
+ fop_checksum_cbk_t fn;
+ int32_t op_ret, op_errno;
+ uint8_t *file_checksum;
+ uint8_t *dir_checksum;
+ } checksum_cbk;
+
+ /* xattrop */
+ struct {
+ fop_xattrop_t fn;
+ loc_t loc;
+ gf_xattrop_flags_t optype;
+ dict_t *xattr;
+ } xattrop;
+ struct {
+ fop_xattrop_cbk_t fn;
+ int32_t op_ret;
+ int32_t op_errno;
+ dict_t *xattr;
+ } xattrop_cbk;
+
+ /* fxattrop */
+ struct {
+ fop_fxattrop_t fn;
+ fd_t *fd;
+ gf_xattrop_flags_t optype;
+ dict_t *xattr;
+ } fxattrop;
+ struct {
+ fop_fxattrop_cbk_t fn;
+ int32_t op_ret;
+ int32_t op_errno;
+ dict_t *xattr;
+ } fxattrop_cbk;
+ } args;
+} call_stub_t;
+
+call_stub_t *
+fop_lookup_stub (call_frame_t *frame,
+ fop_lookup_t fn,
+ loc_t *loc,
+ dict_t *xattr_req);
+
+call_stub_t *
+fop_lookup_cbk_stub (call_frame_t *frame,
+ fop_lookup_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf,
+ dict_t *dict);
+call_stub_t *
+fop_stat_stub (call_frame_t *frame,
+ fop_stat_t fn,
+ loc_t *loc);
+call_stub_t *
+fop_stat_cbk_stub (call_frame_t *frame,
+ fop_stat_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+call_stub_t *
+fop_fstat_stub (call_frame_t *frame,
+ fop_fstat_t fn,
+ fd_t *fd);
+call_stub_t *
+fop_fstat_cbk_stub (call_frame_t *frame,
+ fop_fstat_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+call_stub_t *
+fop_chmod_stub (call_frame_t *frame,
+ fop_chmod_t fn,
+ loc_t *loc,
+ mode_t mode);
+call_stub_t *
+fop_chmod_cbk_stub (call_frame_t *frame,
+ fop_chmod_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+call_stub_t *
+fop_fchmod_stub (call_frame_t *frame,
+ fop_fchmod_t fn,
+ fd_t *fd,
+ mode_t mode);
+call_stub_t *
+fop_fchmod_cbk_stub (call_frame_t *frame,
+ fop_fchmod_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+call_stub_t *
+fop_chown_stub (call_frame_t *frame,
+ fop_chown_t fn,
+ loc_t *loc,
+ uid_t uid,
+ gid_t gid);
+
+call_stub_t *
+fop_chown_cbk_stub (call_frame_t *frame,
+ fop_chown_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+
+call_stub_t *
+fop_fchown_stub (call_frame_t *frame,
+ fop_fchown_t fn,
+ fd_t *fd,
+ uid_t uid,
+ gid_t gid);
+
+call_stub_t *
+fop_fchown_cbk_stub (call_frame_t *frame,
+ fop_fchown_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+
+call_stub_t *
+fop_truncate_stub (call_frame_t *frame,
+ fop_truncate_t fn,
+ loc_t *loc,
+ off_t off);
+
+call_stub_t *
+fop_truncate_cbk_stub (call_frame_t *frame,
+ fop_truncate_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+
+call_stub_t *
+fop_ftruncate_stub (call_frame_t *frame,
+ fop_ftruncate_t fn,
+ fd_t *fd,
+ off_t off);
+
+call_stub_t *
+fop_ftruncate_cbk_stub (call_frame_t *frame,
+ fop_ftruncate_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+
+call_stub_t *
+fop_utimens_stub (call_frame_t *frame,
+ fop_utimens_t fn,
+ loc_t *loc,
+ struct timespec tv[2]);
+
+call_stub_t *
+fop_utimens_cbk_stub (call_frame_t *frame,
+ fop_utimens_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+
+call_stub_t *
+fop_access_stub (call_frame_t *frame,
+ fop_access_t fn,
+ loc_t *loc,
+ int32_t mask);
+
+call_stub_t *
+fop_access_cbk_stub (call_frame_t *frame,
+ fop_access_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno);
+
+call_stub_t *
+fop_readlink_stub (call_frame_t *frame,
+ fop_readlink_t fn,
+ loc_t *loc,
+ size_t size);
+
+call_stub_t *
+fop_readlink_cbk_stub (call_frame_t *frame,
+ fop_readlink_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ const char *path);
+
+call_stub_t *
+fop_mknod_stub (call_frame_t *frame,
+ fop_mknod_t fn,
+ loc_t *loc,
+ mode_t mode,
+ dev_t rdev);
+
+call_stub_t *
+fop_mknod_cbk_stub (call_frame_t *frame,
+ fop_mknod_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf);
+
+call_stub_t *
+fop_mkdir_stub (call_frame_t *frame,
+ fop_mkdir_t fn,
+ loc_t *loc,
+ mode_t mode);
+
+call_stub_t *
+fop_mkdir_cbk_stub (call_frame_t *frame,
+ fop_mkdir_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf);
+
+call_stub_t *
+fop_unlink_stub (call_frame_t *frame,
+ fop_unlink_t fn,
+ loc_t *loc);
+
+call_stub_t *
+fop_unlink_cbk_stub (call_frame_t *frame,
+ fop_unlink_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno);
+
+call_stub_t *
+fop_rmdir_stub (call_frame_t *frame,
+ fop_rmdir_t fn,
+ loc_t *loc);
+
+call_stub_t *
+fop_rmdir_cbk_stub (call_frame_t *frame,
+ fop_rmdir_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno);
+
+call_stub_t *
+fop_symlink_stub (call_frame_t *frame,
+ fop_symlink_t fn,
+ const char *linkname,
+ loc_t *loc);
+
+call_stub_t *
+fop_symlink_cbk_stub (call_frame_t *frame,
+ fop_symlink_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf);
+
+call_stub_t *
+fop_rename_stub (call_frame_t *frame,
+ fop_rename_t fn,
+ loc_t *oldloc,
+ loc_t *newloc);
+
+call_stub_t *
+fop_rename_cbk_stub (call_frame_t *frame,
+ fop_rename_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+
+call_stub_t *
+fop_link_stub (call_frame_t *frame,
+ fop_link_t fn,
+ loc_t *oldloc,
+ loc_t *newloc);
+
+call_stub_t *
+fop_link_cbk_stub (call_frame_t *frame,
+ fop_link_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf);
+
+call_stub_t *
+fop_create_stub (call_frame_t *frame,
+ fop_create_t fn,
+ loc_t *loc,
+ int32_t flags,
+ mode_t mode, fd_t *fd);
+
+call_stub_t *
+fop_create_cbk_stub (call_frame_t *frame,
+ fop_create_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ fd_t *fd,
+ inode_t *inode,
+ struct stat *buf);
+
+call_stub_t *
+fop_open_stub (call_frame_t *frame,
+ fop_open_t fn,
+ loc_t *loc,
+ int32_t flags,
+ fd_t *fd);
+
+call_stub_t *
+fop_open_cbk_stub (call_frame_t *frame,
+ fop_open_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ fd_t *fd);
+
+call_stub_t *
+fop_readv_stub (call_frame_t *frame,
+ fop_readv_t fn,
+ fd_t *fd,
+ size_t size,
+ off_t off);
+
+call_stub_t *
+fop_readv_cbk_stub (call_frame_t *frame,
+ fop_readv_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct iovec *vector,
+ int32_t count,
+ struct stat *stbuf);
+
+call_stub_t *
+fop_writev_stub (call_frame_t *frame,
+ fop_writev_t fn,
+ fd_t *fd,
+ struct iovec *vector,
+ int32_t count,
+ off_t off);
+
+call_stub_t *
+fop_writev_cbk_stub (call_frame_t *frame,
+ fop_writev_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *stbuf);
+
+call_stub_t *
+fop_flush_stub (call_frame_t *frame,
+ fop_flush_t fn,
+ fd_t *fd);
+
+call_stub_t *
+fop_flush_cbk_stub (call_frame_t *frame,
+ fop_flush_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno);
+
+call_stub_t *
+fop_fsync_stub (call_frame_t *frame,
+ fop_fsync_t fn,
+ fd_t *fd,
+ int32_t datasync);
+
+call_stub_t *
+fop_fsync_cbk_stub (call_frame_t *frame,
+ fop_fsync_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno);
+
+call_stub_t *
+fop_opendir_stub (call_frame_t *frame,
+ fop_opendir_t fn,
+ loc_t *loc, fd_t *fd);
+
+call_stub_t *
+fop_opendir_cbk_stub (call_frame_t *frame,
+ fop_opendir_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ fd_t *fd);
+
+call_stub_t *
+fop_getdents_stub (call_frame_t *frame,
+ fop_getdents_t fn,
+ fd_t *fd,
+ size_t size,
+ off_t off,
+ int32_t flag);
+
+call_stub_t *
+fop_getdents_cbk_stub (call_frame_t *frame,
+ fop_getdents_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ dir_entry_t *entries,
+ int32_t count);
+
+call_stub_t *
+fop_setdents_stub (call_frame_t *frame,
+ fop_setdents_t fn,
+ fd_t *fd,
+ int32_t flags,
+ dir_entry_t *entries,
+ int32_t count);
+
+call_stub_t *
+fop_setdents_cbk_stub (call_frame_t *frame,
+ fop_setdents_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno);
+
+call_stub_t *
+fop_fsyncdir_stub (call_frame_t *frame,
+ fop_fsyncdir_t fn,
+ fd_t *fd,
+ int32_t datasync);
+
+call_stub_t *
+fop_fsyncdir_cbk_stub (call_frame_t *frame,
+ fop_fsyncdir_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno);
+
+call_stub_t *
+fop_statfs_stub (call_frame_t *frame,
+ fop_statfs_t fn,
+ loc_t *loc);
+
+call_stub_t *
+fop_statfs_cbk_stub (call_frame_t *frame,
+ fop_statfs_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct statvfs *buf);
+
+call_stub_t *
+fop_setxattr_stub (call_frame_t *frame,
+ fop_setxattr_t fn,
+ loc_t *loc,
+ dict_t *dict,
+ int32_t flags);
+
+call_stub_t *
+fop_setxattr_cbk_stub (call_frame_t *frame,
+ fop_setxattr_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno);
+
+call_stub_t *
+fop_getxattr_stub (call_frame_t *frame,
+ fop_getxattr_t fn,
+ loc_t *loc,
+ const char *name);
+
+call_stub_t *
+fop_getxattr_cbk_stub (call_frame_t *frame,
+ fop_getxattr_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ dict_t *value);
+
+call_stub_t *
+fop_removexattr_stub (call_frame_t *frame,
+ fop_removexattr_t fn,
+ loc_t *loc,
+ const char *name);
+
+call_stub_t *
+fop_removexattr_cbk_stub (call_frame_t *frame,
+ fop_removexattr_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno);
+call_stub_t *
+fop_lk_stub (call_frame_t *frame,
+ fop_lk_t fn,
+ fd_t *fd,
+ int32_t cmd,
+ struct flock *lock);
+
+call_stub_t *
+fop_lk_cbk_stub (call_frame_t *frame,
+ fop_lk_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct flock *lock);
+
+call_stub_t *
+fop_inodelk_stub (call_frame_t *frame, fop_inodelk_t fn,
+ loc_t *loc, int32_t cmd, struct flock *lock);
+
+call_stub_t *
+fop_finodelk_stub (call_frame_t *frame, fop_finodelk_t fn,
+ fd_t *fd, int32_t cmd, struct flock *lock);
+
+call_stub_t *
+fop_entrylk_stub (call_frame_t *frame, fop_entrylk_t fn,
+ loc_t *loc, const char *basename,
+ entrylk_cmd cmd, entrylk_type type);
+
+call_stub_t *
+fop_fentrylk_stub (call_frame_t *frame, fop_fentrylk_t fn,
+ fd_t *fd, const char *basename,
+ entrylk_cmd cmd, entrylk_type type);
+
+call_stub_t *
+fop_inodelk_cbk_stub (call_frame_t *frame, fop_inodelk_cbk_t fn,
+ int32_t op_ret, int32_t op_errno);
+
+call_stub_t *
+fop_finodelk_cbk_stub (call_frame_t *frame, fop_inodelk_cbk_t fn,
+ int32_t op_ret, int32_t op_errno);
+
+call_stub_t *
+fop_entrylk_cbk_stub (call_frame_t *frame, fop_entrylk_cbk_t fn,
+ int32_t op_ret, int32_t op_errno);
+
+call_stub_t *
+fop_fentrylk_cbk_stub (call_frame_t *frame, fop_entrylk_cbk_t fn,
+ int32_t op_ret, int32_t op_errno);
+
+call_stub_t *
+fop_readdir_stub (call_frame_t *frame,
+ fop_readdir_t fn,
+ fd_t *fd,
+ size_t size,
+ off_t off);
+
+call_stub_t *
+fop_readdir_cbk_stub (call_frame_t *frame,
+ fop_readdir_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ gf_dirent_t *entries);
+
+call_stub_t *
+fop_checksum_stub (call_frame_t *frame,
+ fop_checksum_t fn,
+ loc_t *loc,
+ int32_t flags);
+
+call_stub_t *
+fop_checksum_cbk_stub (call_frame_t *frame,
+ fop_checksum_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno,
+ uint8_t *file_checksum,
+ uint8_t *dir_checksum);
+
+call_stub_t *
+fop_xattrop_stub (call_frame_t *frame,
+ fop_xattrop_t fn,
+ loc_t *loc,
+ gf_xattrop_flags_t optype,
+ dict_t *xattr);
+
+call_stub_t *
+fop_xattrop_stub_cbk_stub (call_frame_t *frame,
+ fop_xattrop_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno);
+
+call_stub_t *
+fop_fxattrop_stub (call_frame_t *frame,
+ fop_fxattrop_t fn,
+ fd_t *fd,
+ gf_xattrop_flags_t optype,
+ dict_t *xattr);
+
+call_stub_t *
+fop_fxattrop_stub_cbk_stub (call_frame_t *frame,
+ fop_xattrop_cbk_t fn,
+ int32_t op_ret,
+ int32_t op_errno);
+
+void call_resume (call_stub_t *stub);
+void call_stub_destroy (call_stub_t *stub);
+#endif
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c
new file mode 100644
index 000000000..616c7a8ce
--- /dev/null
+++ b/libglusterfs/src/common-utils.c
@@ -0,0 +1,1349 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_BACKTRACE
+#include <execinfo.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+#include <time.h>
+#include <locale.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <signal.h>
+
+#include "logging.h"
+#include "common-utils.h"
+#include "revision.h"
+#include "glusterfs.h"
+#include "stack.h"
+
+typedef int32_t (*rw_op_t)(int32_t fd, char *buf, int32_t size);
+typedef int32_t (*rwv_op_t)(int32_t fd, const struct iovec *buf, int32_t size);
+static glusterfs_ctx_t *gf_global_ctx;
+
+
+struct dnscache6 {
+ struct addrinfo *first;
+ struct addrinfo *next;
+};
+
+int32_t
+gf_resolve_ip6 (const char *hostname,
+ uint16_t port,
+ int family,
+ void **dnscache,
+ struct addrinfo **addr_info)
+{
+ int32_t ret = 0;
+ struct addrinfo hints;
+ struct dnscache6 *cache = NULL;
+ char service[NI_MAXSERV], host[NI_MAXHOST];
+
+ if (!hostname) {
+ gf_log ("resolver", GF_LOG_WARNING, "hostname is NULL");
+ return -1;
+ }
+
+ if (!*dnscache) {
+ *dnscache = CALLOC (1, sizeof (struct dnscache6));
+ }
+
+ cache = *dnscache;
+ if (cache->first && !cache->next) {
+ freeaddrinfo(cache->first);
+ cache->first = cache->next = NULL;
+ gf_log ("resolver", GF_LOG_DEBUG,
+ "flushing DNS cache");
+ }
+
+ if (!cache->first) {
+ char *port_str = NULL;
+ gf_log ("resolver", GF_LOG_DEBUG,
+ "DNS cache not present, freshly probing hostname: %s",
+ hostname);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_ADDRCONFIG;
+
+ asprintf (&port_str, "%d", port);
+ if ((ret = getaddrinfo(hostname, port_str, &hints, &cache->first)) != 0) {
+ gf_log ("resolver", GF_LOG_ERROR,
+ "getaddrinfo failed (%s)", gai_strerror (ret));
+
+ free (*dnscache);
+ *dnscache = NULL;
+ free (port_str);
+ return -1;
+ }
+ free (port_str);
+
+ cache->next = cache->first;
+ }
+
+ if (cache->next) {
+ ret = getnameinfo((struct sockaddr *)cache->next->ai_addr,
+ cache->next->ai_addrlen,
+ host, sizeof (host),
+ service, sizeof (service),
+ NI_NUMERICHOST);
+ if (ret != 0) {
+ gf_log ("resolver",
+ GF_LOG_ERROR,
+ "getnameinfo failed (%s)", gai_strerror (ret));
+ goto err;
+ }
+
+ gf_log ("resolver", GF_LOG_DEBUG,
+ "returning ip-%s (port-%s) for hostname: %s and port: %d",
+ host, service, hostname, port);
+
+ *addr_info = cache->next;
+ }
+
+ cache->next = cache->next->ai_next;
+ if (cache->next) {
+ ret = getnameinfo((struct sockaddr *)cache->next->ai_addr,
+ cache->next->ai_addrlen,
+ host, sizeof (host),
+ service, sizeof (service),
+ NI_NUMERICHOST);
+ if (ret != 0) {
+ gf_log ("resolver",
+ GF_LOG_ERROR,
+ "getnameinfo failed (%s)", gai_strerror (ret));
+ goto err;
+ }
+
+ gf_log ("resolver", GF_LOG_DEBUG,
+ "next DNS query will return: ip-%s port-%s", host, service);
+ }
+
+ return 0;
+
+err:
+ freeaddrinfo (cache->first);
+ cache->first = cache->next = NULL;
+ free (cache);
+ *dnscache = NULL;
+ return -1;
+}
+
+char *gf_fop_list[GF_FOP_MAXVALUE];
+char *gf_mop_list[GF_MOP_MAXVALUE];
+char *gf_cbk_list[GF_CBK_MAXVALUE];
+
+void
+gf_global_variable_init()
+{
+ gf_fop_list[GF_FOP_STAT] = "STAT"; /* 0 */
+ gf_fop_list[GF_FOP_READLINK] = "READLINK"; /* 1 */
+ gf_fop_list[GF_FOP_MKNOD] = "MKNOD"; /* 2 */
+ gf_fop_list[GF_FOP_MKDIR] = "MKDIR";
+ gf_fop_list[GF_FOP_UNLINK] = "UNLINK";
+ gf_fop_list[GF_FOP_RMDIR] = "RMDIR"; /* 5 */
+ gf_fop_list[GF_FOP_SYMLINK] = "SYMLINK";
+ gf_fop_list[GF_FOP_RENAME] = "RENAME";
+ gf_fop_list[GF_FOP_LINK] = "LINK";
+ gf_fop_list[GF_FOP_CHMOD] = "CHMOD";
+ gf_fop_list[GF_FOP_CHOWN] = "CHOWN"; /* 10 */
+ gf_fop_list[GF_FOP_TRUNCATE] = "TRUNCATE";
+ gf_fop_list[GF_FOP_OPEN] = "OPEN";
+ gf_fop_list[GF_FOP_READ] = "READ";
+ gf_fop_list[GF_FOP_WRITE] = "WRITE";
+ gf_fop_list[GF_FOP_STATFS] = "STATFS"; /* 15 */
+ gf_fop_list[GF_FOP_FLUSH] = "FLUSH";
+ gf_fop_list[GF_FOP_FSYNC] = "FSYNC";
+ gf_fop_list[GF_FOP_SETXATTR] = "SETXATTR";
+ gf_fop_list[GF_FOP_GETXATTR] = "GETXATTR"; /* 20 */
+ gf_fop_list[GF_FOP_REMOVEXATTR] = "REMOVEXATTR";
+ gf_fop_list[GF_FOP_OPENDIR] = "OPENDIR";
+ gf_fop_list[GF_FOP_GETDENTS] = "GETDENTS";
+ gf_fop_list[GF_FOP_FSYNCDIR] = "FSYNCDIR"; /* 25 */
+ gf_fop_list[GF_FOP_ACCESS] = "ACCESS";
+ gf_fop_list[GF_FOP_CREATE] = "CREATE";
+ gf_fop_list[GF_FOP_FTRUNCATE] = "FTRUNCATE";
+ gf_fop_list[GF_FOP_FSTAT] = "FSTAT";
+ gf_fop_list[GF_FOP_LK] = "LK"; /* 30 */
+ gf_fop_list[GF_FOP_UTIMENS] = "UTIMENS";
+ gf_fop_list[GF_FOP_FCHMOD] = "FCHMOD";
+ gf_fop_list[GF_FOP_FCHOWN] = "FCHOWN";
+ gf_fop_list[GF_FOP_LOOKUP] = "LOOKUP";
+ gf_fop_list[GF_FOP_SETDENTS] = "SETDENTS"; /* 35 */
+ gf_fop_list[GF_FOP_READDIR] = "READDIR";
+ gf_fop_list[GF_FOP_INODELK] = "INODELK";
+ gf_fop_list[GF_FOP_FINODELK] = "FINODELK";
+ gf_fop_list[GF_FOP_ENTRYLK] = "ENTRYLK";
+ gf_fop_list[GF_FOP_FENTRYLK] = "FENTRYLK"; /* 40 */
+ gf_fop_list[GF_FOP_CHECKSUM] = "CHECKSUM"; /* 41 */
+ gf_fop_list[GF_FOP_XATTROP] = "XATTROP";
+
+ gf_mop_list[GF_MOP_SETVOLUME] = "SETVOLUME"; /* 0 */
+ gf_mop_list[GF_MOP_GETVOLUME] = "GETVOLUME"; /* 1 */
+ gf_mop_list[GF_MOP_STATS] = "STATS";
+ gf_mop_list[GF_MOP_SETSPEC] = "SETSPEC";
+ gf_mop_list[GF_MOP_GETSPEC] = "GETSPEC";
+
+ gf_cbk_list[GF_CBK_FORGET] = "FORGET";
+ gf_cbk_list[GF_CBK_RELEASE] = "RELEASE";
+ gf_cbk_list[GF_CBK_RELEASEDIR] = "RELEASEDIR";
+ /* Are there any more variables to be included? All global
+ variables initialization should go here */
+
+ return;
+}
+
+void
+set_global_ctx_ptr (glusterfs_ctx_t *ctx)
+{
+ gf_global_ctx = ctx;
+}
+
+glusterfs_ctx_t *
+get_global_ctx_ptr (void)
+{
+ return gf_global_ctx;
+}
+
+void
+gf_log_volume_file (FILE *specfp)
+{
+ extern FILE *gf_log_logfile;
+ int lcount = 0;
+ char data[GF_UNIT_KB];
+
+ fseek (specfp, 0L, SEEK_SET);
+
+ fprintf (gf_log_logfile, "Given volfile:\n");
+ fprintf (gf_log_logfile,
+ "+---------------------------------------"
+ "---------------------------------------+\n");
+ while (!feof (specfp)) {
+ if (fgets (data, GF_UNIT_KB, specfp) == NULL)
+ break;
+ lcount++;
+ fprintf (gf_log_logfile, "%3d: %s", lcount, data);
+ }
+ fprintf (gf_log_logfile,
+ "\n+---------------------------------------"
+ "---------------------------------------+\n");
+ fflush (gf_log_logfile);
+ fseek (specfp, 0L, SEEK_SET);
+}
+
+static void
+gf_dump_config_flags (int fd)
+{
+
+ write (fd, "configuration details:\n", 22);
+
+/* have argp */
+#ifdef HAVE_ARGP
+ write (fd, "argp 1\n", 7);
+#endif
+
+/* ifdef if found backtrace */
+#ifdef HAVE_BACKTRACE
+ write (fd, "backtrace 1\n", 12);
+#endif
+
+/* Berkeley-DB version has cursor->get() */
+#ifdef HAVE_BDB_CURSOR_GET
+ write (fd, "bdb->cursor->get 1\n", 19);
+#endif
+
+/* Define to 1 if you have the <db.h> header file. */
+#ifdef HAVE_DB_H
+ write (fd, "db.h 1\n", 7);
+#endif
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#ifdef HAVE_DLFCN_H
+ write (fd, "dlfcn 1\n", 8);
+#endif
+
+/* define if fdatasync exists */
+#ifdef HAVE_FDATASYNC
+ write (fd, "fdatasync 1\n", 12);
+#endif
+
+/* Define to 1 if you have the `pthread' library (-lpthread). */
+#ifdef HAVE_LIBPTHREAD
+ write (fd, "libpthread 1\n", 13);
+#endif
+
+/* define if llistxattr exists */
+#ifdef HAVE_LLISTXATTR
+ write (fd, "llistxattr 1\n", 13);
+#endif
+
+/* define if found setfsuid setfsgid */
+#ifdef HAVE_SET_FSID
+ write (fd, "setfsid 1\n", 10);
+#endif
+
+/* define if found spinlock */
+#ifdef HAVE_SPINLOCK
+ write (fd, "spinlock 1\n", 11);
+#endif
+
+/* Define to 1 if you have the <sys/epoll.h> header file. */
+#ifdef HAVE_SYS_EPOLL_H
+ write (fd, "epoll.h 1\n", 10);
+#endif
+
+/* Define to 1 if you have the <sys/extattr.h> header file. */
+#ifdef HAVE_SYS_EXTATTR_H
+ write (fd, "extattr.h 1\n", 12);
+#endif
+
+/* Define to 1 if you have the <sys/xattr.h> header file. */
+#ifdef HAVE_SYS_XATTR_H
+ write (fd, "xattr.h 1\n", 10);
+#endif
+
+/* define if found st_atim.tv_nsec */
+#ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
+ write (fd, "st_atim.tv_nsec 1\n", 18);
+#endif
+
+/* define if found st_atimespec.tv_nsec */
+#ifdef HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC
+ write (fd, "st_atimespec.tv_nsec 1\n",23);
+#endif
+
+/* Define to the full name and version of this package. */
+#ifdef PACKAGE_STRING
+ {
+ char msg[128];
+ sprintf (msg, "package-string: %s\n", PACKAGE_STRING);
+ write (fd, msg, strlen (msg));
+ }
+#endif
+
+ return;
+}
+
+/* Obtain a backtrace and print it to stdout. */
+/* TODO: It looks like backtrace_symbols allocates memory,
+ it may be problem because mostly memory allocation/free causes 'sigsegv' */
+void
+gf_print_trace (int32_t signum)
+{
+ extern FILE *gf_log_logfile;
+ int fd = fileno (gf_log_logfile);
+ char msg[1024];
+
+
+ /* Pending frames, (if any), list them in order */
+ write (fd, "pending frames:\n", 16);
+ {
+ extern glusterfs_ctx_t *gf_global_ctx;
+ glusterfs_ctx_t *ctx = gf_global_ctx;
+ struct list_head *trav = ((call_pool_t *)ctx->pool)->all_frames.next;
+ while (trav != (&((call_pool_t *)ctx->pool)->all_frames)) {
+ call_frame_t *tmp = (call_frame_t *)(&((call_stack_t *)trav)->frames);
+ if ((tmp->root->type == GF_OP_TYPE_FOP_REQUEST) ||
+ (tmp->root->type == GF_OP_TYPE_FOP_REPLY))
+ sprintf (msg,"frame : type(%d) op(%s)\n",
+ tmp->root->type,
+ gf_fop_list[tmp->root->op]);
+ if ((tmp->root->type == GF_OP_TYPE_MOP_REQUEST) ||
+ (tmp->root->type == GF_OP_TYPE_MOP_REPLY))
+ sprintf (msg,"frame : type(%d) op(%s)\n",
+ tmp->root->type,
+ gf_mop_list[tmp->root->op]);
+ if ((tmp->root->type == GF_OP_TYPE_CBK_REQUEST) ||
+ (tmp->root->type == GF_OP_TYPE_CBK_REPLY))
+ sprintf (msg,"frame : type(%d) op(%s)\n",
+ tmp->root->type,
+ gf_cbk_list[tmp->root->op]);
+
+ write (fd, msg, strlen (msg));
+ trav = trav->next;
+ }
+ write (fd, "\n", 1);
+ }
+
+ sprintf (msg, "patchset: %s\n", GLUSTERFS_REPOSITORY_REVISION);
+ write (fd, msg, strlen (msg));
+
+ sprintf (msg, "signal received: %d\n", signum);
+ write (fd, msg, strlen (msg));
+
+ gf_dump_config_flags (fd);
+#if HAVE_BACKTRACE
+ /* Print 'backtrace' */
+ {
+ void *array[200];
+ size_t size;
+
+ size = backtrace (array, 200);
+ backtrace_symbols_fd (&array[1], size-1, fd);
+ sprintf (msg, "---------\n");
+ write (fd, msg, strlen (msg));
+ }
+#endif /* HAVE_BACKTRACE */
+
+ /* Send a signal to terminate the process */
+ signal (signum, SIG_DFL);
+ raise (signum);
+}
+
+void
+trap (void)
+{
+
+}
+
+char *
+gf_trim (char *string)
+{
+ register char *s, *t;
+
+ if (string == NULL)
+ {
+ return NULL;
+ }
+
+ for (s = string; isspace (*s); s++)
+ ;
+
+ if (*s == 0)
+ return s;
+
+ t = s + strlen (s) - 1;
+ while (t > s && isspace (*t))
+ t--;
+ *++t = '\0';
+
+ return s;
+}
+
+int
+gf_strsplit (const char *str, const char *delim,
+ char ***tokens, int *token_count)
+{
+ char *_running = NULL;
+ char *running = NULL;
+ char *token = NULL;
+ char **token_list = NULL;
+ int count = 0;
+ int i = 0;
+ int j = 0;
+
+ if (str == NULL || delim == NULL || tokens == NULL || token_count == NULL)
+ {
+ return -1;
+ }
+
+ if ((_running = strdup (str)) == NULL)
+ {
+ return -1;
+ }
+ running = _running;
+
+ while ((token = strsep (&running, delim)) != NULL)
+ {
+ if (token[0] != '\0')
+ count++;
+ }
+ free (_running);
+
+ if ((_running = strdup (str)) == NULL)
+ {
+ return -1;
+ }
+ running = _running;
+
+ if ((token_list = CALLOC (count, sizeof (char *))) == NULL)
+ {
+ free (_running);
+ return -1;
+ }
+
+ while ((token = strsep (&running, delim)) != NULL)
+ {
+ if (token[0] == '\0')
+ continue;
+
+ if ((token_list[i++] = strdup (token)) == NULL)
+ goto free_exit;
+ }
+
+ free (_running);
+
+ *tokens = token_list;
+ *token_count = count;
+ return 0;
+
+free_exit:
+ free (_running);
+ for (j = 0; j < i; j++)
+ {
+ free (token_list[j]);
+ }
+ free (token_list);
+ return -1;
+}
+
+int
+gf_volume_name_validate (const char *volume_name)
+{
+ const char *vname = NULL;
+
+ if (volume_name == NULL)
+ {
+ return -1;
+ }
+
+ if (!isalpha (volume_name[0]))
+ {
+ return 1;
+ }
+
+ for (vname = &volume_name[1]; *vname != '\0'; vname++)
+ {
+ if (!(isalnum (*vname) || *vname == '_'))
+ return 1;
+ }
+
+ return 0;
+}
+
+
+int
+gf_string2time (const char *str, uint32_t *n)
+{
+ unsigned long value = 0;
+ char *tail = NULL;
+ int old_errno = 0;
+ const char *s = NULL;
+
+ if (str == NULL || n == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ for (s = str; *s != '\0'; s++)
+ {
+ if (isspace (*s))
+ {
+ continue;
+ }
+ if (*s == '-')
+ {
+ return -1;
+ }
+ break;
+ }
+
+ old_errno = errno;
+ errno = 0;
+ value = strtol (str, &tail, 0);
+
+ if (errno == ERANGE || errno == EINVAL)
+ {
+ return -1;
+ }
+
+ if (errno == 0)
+ {
+ errno = old_errno;
+ }
+
+ if (!((tail[0] == '\0') ||
+ ((tail[0] == 's') && (tail[1] == '\0')) ||
+ ((tail[0] == 's') && (tail[1] == 'e') && (tail[2] == 'c') && (tail[3] == '\0'))))
+ {
+ return -1;
+ }
+
+ *n = value;
+
+ return 0;
+}
+
+
+int
+gf_string2percent (const char *str, uint32_t *n)
+{
+ unsigned long value = 0;
+ char *tail = NULL;
+ int old_errno = 0;
+ const char *s = NULL;
+
+ if (str == NULL || n == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ for (s = str; *s != '\0'; s++)
+ {
+ if (isspace (*s))
+ {
+ continue;
+ }
+ if (*s == '-')
+ {
+ return -1;
+ }
+ break;
+ }
+
+ old_errno = errno;
+ errno = 0;
+ value = strtol (str, &tail, 0);
+
+ if (errno == ERANGE || errno == EINVAL)
+ {
+ return -1;
+ }
+
+ if (errno == 0)
+ {
+ errno = old_errno;
+ }
+
+ if (!((tail[0] == '\0') ||
+ ((tail[0] == '%') && (tail[1] == '\0'))))
+ {
+ return -1;
+ }
+
+ *n = value;
+
+ return 0;
+}
+
+
+static int
+_gf_string2long (const char *str, long *n, int base)
+{
+ long value = 0;
+ char *tail = NULL;
+ int old_errno = 0;
+
+ if (str == NULL || n == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ old_errno = errno;
+ errno = 0;
+ value = strtol (str, &tail, base);
+
+ if (errno == ERANGE || errno == EINVAL)
+ {
+ return -1;
+ }
+
+ if (errno == 0)
+ {
+ errno = old_errno;
+ }
+
+ if (tail[0] != '\0')
+ {
+ /* bala: invalid integer format */
+ return -1;
+ }
+
+ *n = value;
+
+ return 0;
+}
+
+static int
+_gf_string2ulong (const char *str, unsigned long *n, int base)
+{
+ unsigned long value = 0;
+ char *tail = NULL;
+ int old_errno = 0;
+ const char *s = NULL;
+
+ if (str == NULL || n == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ for (s = str; *s != '\0'; s++)
+ {
+ if (isspace (*s))
+ {
+ continue;
+ }
+ if (*s == '-')
+ {
+ /* bala: we do not support suffixed (-) sign and
+ invalid integer format */
+ return -1;
+ }
+ break;
+ }
+
+ old_errno = errno;
+ errno = 0;
+ value = strtoul (str, &tail, base);
+
+ if (errno == ERANGE || errno == EINVAL)
+ {
+ return -1;
+ }
+
+ if (errno == 0)
+ {
+ errno = old_errno;
+ }
+
+ if (tail[0] != '\0')
+ {
+ /* bala: invalid integer format */
+ return -1;
+ }
+
+ *n = value;
+
+ return 0;
+}
+
+static int
+_gf_string2uint (const char *str, unsigned int *n, int base)
+{
+ unsigned long value = 0;
+ char *tail = NULL;
+ int old_errno = 0;
+ const char *s = NULL;
+
+ if (str == NULL || n == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ for (s = str; *s != '\0'; s++)
+ {
+ if (isspace (*s))
+ {
+ continue;
+ }
+ if (*s == '-')
+ {
+ /* bala: we do not support suffixed (-) sign and
+ invalid integer format */
+ return -1;
+ }
+ break;
+ }
+
+ old_errno = errno;
+ errno = 0;
+ value = strtoul (str, &tail, base);
+
+ if (errno == ERANGE || errno == EINVAL)
+ {
+ return -1;
+ }
+
+ if (errno == 0)
+ {
+ errno = old_errno;
+ }
+
+ if (tail[0] != '\0')
+ {
+ /* bala: invalid integer format */
+ return -1;
+ }
+
+ *n = (unsigned int)value;
+
+ return 0;
+}
+
+static int
+_gf_string2longlong (const char *str, long long *n, int base)
+{
+ long long value = 0;
+ char *tail = NULL;
+ int old_errno = 0;
+
+ if (str == NULL || n == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ old_errno = errno;
+ errno = 0;
+ value = strtoll (str, &tail, base);
+
+ if (errno == ERANGE || errno == EINVAL)
+ {
+ return -1;
+ }
+
+ if (errno == 0)
+ {
+ errno = old_errno;
+ }
+
+ if (tail[0] != '\0')
+ {
+ /* bala: invalid integer format */
+ return -1;
+ }
+
+ *n = value;
+
+ return 0;
+}
+
+static int
+_gf_string2ulonglong (const char *str, unsigned long long *n, int base)
+{
+ unsigned long long value = 0;
+ char *tail = NULL;
+ int old_errno = 0;
+ const char *s = NULL;
+
+ if (str == NULL || n == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ for (s = str; *s != '\0'; s++)
+ {
+ if (isspace (*s))
+ {
+ continue;
+ }
+ if (*s == '-')
+ {
+ /* bala: we do not support suffixed (-) sign and
+ invalid integer format */
+ return -1;
+ }
+ break;
+ }
+
+ old_errno = errno;
+ errno = 0;
+ value = strtoull (str, &tail, base);
+
+ if (errno == ERANGE || errno == EINVAL)
+ {
+ return -1;
+ }
+
+ if (errno == 0)
+ {
+ errno = old_errno;
+ }
+
+ if (tail[0] != '\0')
+ {
+ /* bala: invalid integer format */
+ return -1;
+ }
+
+ *n = value;
+
+ return 0;
+}
+
+int
+gf_string2long (const char *str, long *n)
+{
+ return _gf_string2long (str, n, 0);
+}
+
+int
+gf_string2ulong (const char *str, unsigned long *n)
+{
+ return _gf_string2ulong (str, n, 0);
+}
+
+int
+gf_string2int (const char *str, int *n)
+{
+ return _gf_string2long (str, (long *) n, 0);
+}
+
+int
+gf_string2uint (const char *str, unsigned int *n)
+{
+ return _gf_string2uint (str, n, 0);
+}
+
+int
+gf_string2longlong (const char *str, long long *n)
+{
+ return _gf_string2longlong (str, n, 0);
+}
+
+int
+gf_string2ulonglong (const char *str, unsigned long long *n)
+{
+ return _gf_string2ulonglong (str, n, 0);
+}
+
+int
+gf_string2int8 (const char *str, int8_t *n)
+{
+ long l = 0L;
+ int rv = 0;
+
+ rv = _gf_string2long (str, &l, 0);
+ if (rv != 0)
+ return rv;
+
+ if (l >= INT8_MIN && l <= INT8_MAX)
+ {
+ *n = (int8_t) l;
+ return 0;
+ }
+
+ errno = ERANGE;
+ return -1;
+}
+
+int
+gf_string2int16 (const char *str, int16_t *n)
+{
+ long l = 0L;
+ int rv = 0;
+
+ rv = _gf_string2long (str, &l, 0);
+ if (rv != 0)
+ return rv;
+
+ if (l >= INT16_MIN && l <= INT16_MAX)
+ {
+ *n = (int16_t) l;
+ return 0;
+ }
+
+ errno = ERANGE;
+ return -1;
+}
+
+int
+gf_string2int32 (const char *str, int32_t *n)
+{
+ long l = 0L;
+ int rv = 0;
+
+ rv = _gf_string2long (str, &l, 0);
+ if (rv != 0)
+ return rv;
+
+ if (l >= INT32_MIN && l <= INT32_MAX)
+ {
+ *n = (int32_t) l;
+ return 0;
+ }
+
+ errno = ERANGE;
+ return -1;
+}
+
+int
+gf_string2int64 (const char *str, int64_t *n)
+{
+ long long l = 0LL;
+ int rv = 0;
+
+ rv = _gf_string2longlong (str, &l, 0);
+ if (rv != 0)
+ return rv;
+
+ if (l >= INT64_MIN && l <= INT64_MAX)
+ {
+ *n = (int64_t) l;
+ return 0;
+ }
+
+ errno = ERANGE;
+ return -1;
+}
+
+int
+gf_string2uint8 (const char *str, uint8_t *n)
+{
+ unsigned long l = 0L;
+ int rv = 0;
+
+ rv = _gf_string2ulong (str, &l, 0);
+ if (rv != 0)
+ return rv;
+
+ if (l >= 0 && l <= UINT8_MAX)
+ {
+ *n = (uint8_t) l;
+ return 0;
+ }
+
+ errno = ERANGE;
+ return -1;
+}
+
+int
+gf_string2uint16 (const char *str, uint16_t *n)
+{
+ unsigned long l = 0L;
+ int rv = 0;
+
+ rv = _gf_string2ulong (str, &l, 0);
+ if (rv != 0)
+ return rv;
+
+ if (l >= 0 && l <= UINT16_MAX)
+ {
+ *n = (uint16_t) l;
+ return 0;
+ }
+
+ errno = ERANGE;
+ return -1;
+}
+
+int
+gf_string2uint32 (const char *str, uint32_t *n)
+{
+ unsigned long l = 0L;
+ int rv = 0;
+
+ rv = _gf_string2ulong (str, &l, 0);
+ if (rv != 0)
+ return rv;
+
+ if (l >= 0 && l <= UINT32_MAX)
+ {
+ *n = (uint32_t) l;
+ return 0;
+ }
+
+ errno = ERANGE;
+ return -1;
+}
+
+int
+gf_string2uint64 (const char *str, uint64_t *n)
+{
+ unsigned long long l = 0ULL;
+ int rv = 0;
+
+ rv = _gf_string2ulonglong (str, &l, 0);
+ if (rv != 0)
+ return rv;
+
+ if (l >= 0 && l <= UINT64_MAX)
+ {
+ *n = (uint64_t) l;
+ return 0;
+ }
+
+ errno = ERANGE;
+ return -1;
+}
+
+int
+gf_string2ulong_base10 (const char *str, unsigned long *n)
+{
+ return _gf_string2ulong (str, n, 10);
+}
+
+int
+gf_string2uint_base10 (const char *str, unsigned int *n)
+{
+ return _gf_string2uint (str, n, 10);
+}
+
+int
+gf_string2uint8_base10 (const char *str, uint8_t *n)
+{
+ unsigned long l = 0L;
+ int rv = 0;
+
+ rv = _gf_string2ulong (str, &l, 10);
+ if (rv != 0)
+ return rv;
+
+ if (l >= 0 && l <= UINT8_MAX)
+ {
+ *n = (uint8_t) l;
+ return 0;
+ }
+
+ errno = ERANGE;
+ return -1;
+}
+
+int
+gf_string2uint16_base10 (const char *str, uint16_t *n)
+{
+ unsigned long l = 0L;
+ int rv = 0;
+
+ rv = _gf_string2ulong (str, &l, 10);
+ if (rv != 0)
+ return rv;
+
+ if (l >= 0 && l <= UINT16_MAX)
+ {
+ *n = (uint16_t) l;
+ return 0;
+ }
+
+ errno = ERANGE;
+ return -1;
+}
+
+int
+gf_string2uint32_base10 (const char *str, uint32_t *n)
+{
+ unsigned long l = 0L;
+ int rv = 0;
+
+ rv = _gf_string2ulong (str, &l, 10);
+ if (rv != 0)
+ return rv;
+
+ if (l >= 0 && l <= UINT32_MAX)
+ {
+ *n = (uint32_t) l;
+ return 0;
+ }
+
+ errno = ERANGE;
+ return -1;
+}
+
+int
+gf_string2uint64_base10 (const char *str, uint64_t *n)
+{
+ unsigned long long l = 0ULL;
+ int rv = 0;
+
+ rv = _gf_string2ulonglong (str, &l, 10);
+ if (rv != 0)
+ return rv;
+
+ if (l >= 0 && l <= UINT64_MAX)
+ {
+ *n = (uint64_t) l;
+ return 0;
+ }
+
+ errno = ERANGE;
+ return -1;
+}
+
+int
+gf_string2bytesize (const char *str, uint64_t *n)
+{
+ uint64_t value = 0ULL;
+ char *tail = NULL;
+ int old_errno = 0;
+ const char *s = NULL;
+
+ if (str == NULL || n == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ for (s = str; *s != '\0'; s++)
+ {
+ if (isspace (*s))
+ {
+ continue;
+ }
+ if (*s == '-')
+ {
+ /* bala: we do not support suffixed (-) sign and
+ invalid integer format */
+ return -1;
+ }
+ break;
+ }
+
+ old_errno = errno;
+ errno = 0;
+ value = strtoull (str, &tail, 10);
+
+ if (errno == ERANGE || errno == EINVAL)
+ {
+ return -1;
+ }
+
+ if (errno == 0)
+ {
+ errno = old_errno;
+ }
+
+ if (tail[0] != '\0')
+ {
+ if (strcasecmp (tail, GF_UNIT_KB_STRING) == 0)
+ {
+ value *= GF_UNIT_KB;
+ }
+ else if (strcasecmp (tail, GF_UNIT_MB_STRING) == 0)
+ {
+ value *= GF_UNIT_MB;
+ }
+ else if (strcasecmp (tail, GF_UNIT_GB_STRING) == 0)
+ {
+ value *= GF_UNIT_GB;
+ }
+ else if (strcasecmp (tail, GF_UNIT_TB_STRING) == 0)
+ {
+ value *= GF_UNIT_TB;
+ }
+ else if (strcasecmp (tail, GF_UNIT_PB_STRING) == 0)
+ {
+ value *= GF_UNIT_PB;
+ }
+ else
+ {
+ /* bala: invalid integer format */
+ return -1;
+ }
+ }
+
+ *n = value;
+
+ return 0;
+}
+
+int64_t
+gf_str_to_long_long (const char *number)
+{
+ int64_t unit = 1;
+ int64_t ret = 0;
+ char *endptr = NULL ;
+ if (!number)
+ return 0;
+
+ ret = strtoll (number, &endptr, 0);
+
+ if (endptr) {
+ switch (*endptr) {
+ case 'G':
+ case 'g':
+ if ((* (endptr + 1) == 'B') ||(* (endptr + 1) == 'b'))
+ unit = 1024 * 1024 * 1024;
+ break;
+ case 'M':
+ case 'm':
+ if ((* (endptr + 1) == 'B') ||(* (endptr + 1) == 'b'))
+ unit = 1024 * 1024;
+ break;
+ case 'K':
+ case 'k':
+ if ((* (endptr + 1) == 'B') ||(* (endptr + 1) == 'b'))
+ unit = 1024;
+ break;
+ case '%':
+ unit = 1;
+ break;
+ default:
+ unit = 1;
+ break;
+ }
+ }
+ return ret * unit;
+}
+
+int
+gf_string2boolean (const char *str, gf_boolean_t *b)
+{
+ if (str == NULL) {
+ return -1;
+ }
+
+ if ((strcasecmp (str, "1") == 0) ||
+ (strcasecmp (str, "on") == 0) ||
+ (strcasecmp (str, "yes") == 0) ||
+ (strcasecmp (str, "true") == 0) ||
+ (strcasecmp (str, "enable") == 0)) {
+ *b = _gf_true;
+ return 0;
+ }
+
+ if ((strcasecmp (str, "0") == 0) ||
+ (strcasecmp (str, "off") == 0) ||
+ (strcasecmp (str, "no") == 0) ||
+ (strcasecmp (str, "false") == 0) ||
+ (strcasecmp (str, "disable") == 0)) {
+ *b = _gf_false;
+ return 0;
+ }
+
+ return -1;
+}
+
+
+int
+gf_lockfd (int fd)
+{
+ struct flock fl;
+
+ fl.l_type = F_WRLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+
+ return fcntl (fd, F_SETLK, &fl);
+}
+
+
+int
+gf_unlockfd (int fd)
+{
+ struct flock fl;
+
+ fl.l_type = F_UNLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+
+ return fcntl (fd, F_SETLK, &fl);
+}
+
diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h
new file mode 100644
index 000000000..2016b51eb
--- /dev/null
+++ b/libglusterfs/src/common-utils.h
@@ -0,0 +1,313 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+#ifndef _COMMON_UTILS_H
+#define _COMMON_UTILS_H
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include <sys/uio.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <pthread.h>
+#ifndef GF_BSD_HOST_OS
+#include <alloca.h>
+#endif
+
+void trap (void);
+
+#define GF_UNIVERSAL_ANSWER 42 /* :O */
+
+/* To solve type punned error */
+#define VOID(ptr) ((void **) ((void *) ptr))
+
+#include "logging.h"
+#include "glusterfs.h"
+#include "locking.h"
+#include "mem-pool.h"
+
+
+#define min(a,b) ((a)<(b)?(a):(b))
+#define max(a,b) ((a)>(b)?(a):(b))
+#define roof(a,b) ((((a)+(b)-1)/((b)?(b):1))*(b))
+#define floor(a,b) (((a)/((b)?(b):1))*(b))
+
+
+#define GF_UNIT_KB 1024ULL
+#define GF_UNIT_MB 1048576ULL
+#define GF_UNIT_GB 1073741824ULL
+#define GF_UNIT_TB 1099511627776ULL
+#define GF_UNIT_PB 1125899906842624ULL
+
+#define GF_UNIT_KB_STRING "KB"
+#define GF_UNIT_MB_STRING "MB"
+#define GF_UNIT_GB_STRING "GB"
+#define GF_UNIT_TB_STRING "TB"
+#define GF_UNIT_PB_STRING "PB"
+
+
+#define ERR_ABORT(ptr) \
+ if (ptr == NULL) { \
+ abort (); \
+ }
+
+enum _gf_boolean
+{
+ _gf_false = 0,
+ _gf_true = 1
+};
+
+typedef enum _gf_boolean gf_boolean_t;
+
+void gf_global_variable_init(void);
+void set_global_ctx_ptr (glusterfs_ctx_t *ctx);
+glusterfs_ctx_t *get_global_ctx_ptr (void);
+
+in_addr_t gf_resolve_ip (const char *hostname, void **dnscache);
+
+void gf_log_volume_file (FILE *specfp);
+void gf_print_trace (int32_t signal);
+
+extern char *gf_fop_list[GF_FOP_MAXVALUE];
+extern char *gf_mop_list[GF_MOP_MAXVALUE];
+extern char *gf_cbk_list[GF_CBK_MAXVALUE];
+
+#define VECTORSIZE(count) (count * (sizeof (struct iovec)))
+
+#define STRLEN_0(str) (strlen(str) + 1)
+#define VALIDATE_OR_GOTO(arg,label) do { \
+ if (!arg) { \
+ errno = EINVAL; \
+ gf_log ((this ? this->name : "(Govinda! Govinda!)"), \
+ GF_LOG_ERROR, \
+ "invalid argument: " #arg); \
+ goto label; \
+ } \
+ } while (0);
+
+#define GF_VALIDATE_OR_GOTO(name,arg,label) do { \
+ if (!arg) { \
+ errno = EINVAL; \
+ gf_log (name, GF_LOG_ERROR, \
+ "invalid argument: " #arg); \
+ goto label; \
+ } \
+ } while (0);
+
+
+#define GF_FILE_CONTENT_REQUESTED(_xattr_req,_content_limit) \
+ (dict_get_uint64 (_xattr_req, "glusterfs.content", _content_limit) == 0)
+
+static inline void
+iov_free (struct iovec *vector, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ FREE (vector[i].iov_base);
+
+ FREE (vector);
+}
+
+
+static inline int
+iov_length (const struct iovec *vector, int count)
+{
+ int i = 0;
+ size_t size = 0;
+
+ for (i = 0; i < count; i++)
+ size += vector[i].iov_len;
+
+ return size;
+}
+
+
+static inline struct iovec *
+iov_dup (struct iovec *vector, int count)
+{
+ int bytecount = 0;
+ int i;
+ struct iovec *newvec = NULL;
+
+ bytecount = (count * sizeof (struct iovec));
+ newvec = MALLOC (bytecount);
+ if (!newvec)
+ return NULL;
+
+ for (i = 0; i < count; i++) {
+ newvec[i].iov_len = vector[i].iov_len;
+ newvec[i].iov_base = vector[i].iov_base;
+ }
+
+ return newvec;
+}
+
+
+static inline int
+iov_subset (struct iovec *orig, int orig_count,
+ off_t src_offset, off_t dst_offset,
+ struct iovec *new)
+{
+ int new_count = 0;
+ int i;
+ off_t offset = 0;
+ size_t start_offset = 0;
+ size_t end_offset = 0;
+
+
+ for (i = 0; i < orig_count; i++) {
+ if ((offset + orig[i].iov_len < src_offset)
+ || (offset > dst_offset)) {
+ goto not_subset;
+ }
+
+ if (!new) {
+ goto count_only;
+ }
+
+ start_offset = 0;
+ end_offset = orig[i].iov_len;
+
+ if (src_offset >= offset) {
+ start_offset = (src_offset - offset);
+ }
+
+ if (dst_offset <= (offset + orig[i].iov_len)) {
+ end_offset = (dst_offset - offset);
+ }
+
+ new[new_count].iov_base = orig[i].iov_base + start_offset;
+ new[new_count].iov_len = end_offset - start_offset;
+
+ count_only:
+ new_count++;
+
+ not_subset:
+ offset += orig[i].iov_len;
+ }
+
+ return new_count;
+}
+
+
+static inline void
+iov_unload (char *buf, const struct iovec *vector, int count)
+{
+ int i;
+ int copied = 0;
+
+ for (i = 0; i < count; i++) {
+ memcpy (buf + copied, vector[i].iov_base, vector[i].iov_len);
+ copied += vector[i].iov_len;
+ }
+}
+
+
+static inline int
+mem_0filled (const char *buf, size_t size)
+{
+ int i = 0;
+ int ret = 0;
+
+ for (i = 0; i < size; i++) {
+ ret = buf[i];
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+
+static inline int
+iov_0filled (struct iovec *vector, int count)
+{
+ int i = 0;
+ int ret = 0;
+
+ for (i = 0; i < count; i++) {
+ ret = mem_0filled (vector[i].iov_base, vector[i].iov_len);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+
+
+static inline void *
+memdup (const void *ptr, size_t size)
+{
+ void *newptr = NULL;
+
+ newptr = MALLOC (size);
+ if (!newptr)
+ return NULL;
+
+ memcpy (newptr, ptr, size);
+ return newptr;
+}
+
+
+char *gf_trim (char *string);
+int gf_strsplit (const char *str, const char *delim,
+ char ***tokens, int *token_count);
+int gf_volume_name_validate (const char *volume_name);
+
+int gf_string2long (const char *str, long *n);
+int gf_string2ulong (const char *str, unsigned long *n);
+int gf_string2int (const char *str, int *n);
+int gf_string2uint (const char *str, unsigned int *n);
+int gf_string2longlong (const char *str, long long *n);
+int gf_string2ulonglong (const char *str, unsigned long long *n);
+
+int gf_string2int8 (const char *str, int8_t *n);
+int gf_string2int16 (const char *str, int16_t *n);
+int gf_string2int32 (const char *str, int32_t *n);
+int gf_string2int64 (const char *str, int64_t *n);
+int gf_string2uint8 (const char *str, uint8_t *n);
+int gf_string2uint16 (const char *str, uint16_t *n);
+int gf_string2uint32 (const char *str, uint32_t *n);
+int gf_string2uint64 (const char *str, uint64_t *n);
+
+int gf_string2ulong_base10 (const char *str, unsigned long *n);
+int gf_string2uint_base10 (const char *str, unsigned int *n);
+int gf_string2uint8_base10 (const char *str, uint8_t *n);
+int gf_string2uint16_base10 (const char *str, uint16_t *n);
+int gf_string2uint32_base10 (const char *str, uint32_t *n);
+int gf_string2uint64_base10 (const char *str, uint64_t *n);
+
+int gf_string2bytesize (const char *str, uint64_t *n);
+
+int gf_string2boolean (const char *str, gf_boolean_t *b);
+int gf_string2percent (const char *str, uint32_t *n);
+int gf_string2time (const char *str, uint32_t *n);
+
+int gf_lockfd (int fd);
+int gf_unlockfd (int fd);
+
+#endif /* _COMMON_UTILS_H */
+
diff --git a/libglusterfs/src/compat-errno.c b/libglusterfs/src/compat-errno.c
new file mode 100644
index 000000000..a4a6c7106
--- /dev/null
+++ b/libglusterfs/src/compat-errno.c
@@ -0,0 +1,938 @@
+/*
+ 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/>.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+
+#include "compat-errno.h"
+
+
+static int32_t gf_error_to_errno_array[1024];
+static int32_t gf_errno_to_error_array[1024];
+
+static int32_t gf_compat_errno_init_done;
+
+#ifdef GF_SOLARIS_HOST_OS
+static void
+init_compat_errno_arrays ()
+{
+/* ENOMSG 35 / * No message of desired type */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOMSG] = ENOMSG;
+ gf_errno_to_error_array[ENOMSG] = GF_ERROR_CODE_NOMSG;
+
+/* EIDRM 36 / * Identifier removed */
+ gf_error_to_errno_array[GF_ERROR_CODE_IDRM] = EIDRM;
+ gf_errno_to_error_array[EIDRM] = GF_ERROR_CODE_IDRM;
+
+/* ECHRNG 37 / * Channel number out of range */
+ gf_error_to_errno_array[GF_ERROR_CODE_CHRNG] = ECHRNG;
+ gf_errno_to_error_array[ECHRNG] = GF_ERROR_CODE_CHRNG;
+
+/* EL2NSYNC 38 / * Level 2 not synchronized */
+ gf_error_to_errno_array[GF_ERROR_CODE_L2NSYNC] = EL2NSYNC;
+ gf_errno_to_error_array[EL2NSYNC] = GF_ERROR_CODE_L2NSYNC;
+
+/* EL3HLT 39 / * Level 3 halted */
+ gf_error_to_errno_array[GF_ERROR_CODE_L3HLT] = EL3HLT;
+ gf_errno_to_error_array[EL3HLT] = GF_ERROR_CODE_L3HLT;
+
+/* EL3RST 40 / * Level 3 reset */
+ gf_error_to_errno_array[GF_ERROR_CODE_L3RST] = EL3RST;
+ gf_errno_to_error_array[EL3RST] = GF_ERROR_CODE_L3RST;
+
+/* ELNRNG 41 / * Link number out of range */
+ gf_error_to_errno_array[GF_ERROR_CODE_LNRNG] = ELNRNG;
+ gf_errno_to_error_array[ELNRNG] = GF_ERROR_CODE_LNRNG;
+
+/* EUNATCH 42 / * Protocol driver not attached */
+ gf_error_to_errno_array[GF_ERROR_CODE_UNATCH] = EUNATCH;
+ gf_errno_to_error_array[EUNATCH] = GF_ERROR_CODE_UNATCH;
+
+/* ENOCSI 43 / * No CSI structure available */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOCSI] = ENOCSI;
+ gf_errno_to_error_array[ENOCSI] = GF_ERROR_CODE_NOCSI;
+
+/* EL2HLT 44 / * Level 2 halted */
+ gf_error_to_errno_array[GF_ERROR_CODE_L2HLT] = EL2HLT;
+ gf_errno_to_error_array[EL2HLT] = GF_ERROR_CODE_L2HLT;
+
+/* EDEADLK 45 / * Deadlock condition. */
+ gf_error_to_errno_array[GF_ERROR_CODE_DEADLK] = EDEADLK;
+ gf_errno_to_error_array[EDEADLK] = GF_ERROR_CODE_DEADLK;
+
+/* ENOLCK 46 / * No record locks available. */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOLCK] = ENOLCK;
+ gf_errno_to_error_array[ENOLCK] = GF_ERROR_CODE_NOLCK;
+
+/* ECANCELED 47 / * Operation canceled */
+ gf_error_to_errno_array[GF_ERROR_CODE_CANCELED] = ECANCELED;
+ gf_errno_to_error_array[ECANCELED] = GF_ERROR_CODE_CANCELED;
+
+/* ENOTSUP 48 / * Operation not supported */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOTSUPP] = ENOTSUP;
+ gf_errno_to_error_array[ENOTSUP] = GF_ERROR_CODE_NOTSUPP;
+
+/* Filesystem Quotas */
+/* EDQUOT 49 / * Disc quota exceeded */
+ gf_error_to_errno_array[GF_ERROR_CODE_DQUOT] = EDQUOT;
+ gf_errno_to_error_array[EDQUOT] = GF_ERROR_CODE_DQUOT;
+
+/* Convergent Error Returns */
+/* EBADE 50 / * invalid exchange */
+ gf_error_to_errno_array[GF_ERROR_CODE_BADE] = EBADE;
+ gf_errno_to_error_array[EBADE] = GF_ERROR_CODE_BADE;
+/* EBADR 51 / * invalid request descriptor */
+ gf_error_to_errno_array[GF_ERROR_CODE_BADR] = EBADR;
+ gf_errno_to_error_array[EBADR] = GF_ERROR_CODE_BADR;
+/* EXFULL 52 / * exchange full */
+ gf_error_to_errno_array[GF_ERROR_CODE_XFULL] = EXFULL;
+ gf_errno_to_error_array[EXFULL] = GF_ERROR_CODE_XFULL;
+/* ENOANO 53 / * no anode */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOANO] = ENOANO;
+ gf_errno_to_error_array[ENOANO] = GF_ERROR_CODE_NOANO;
+/* EBADRQC 54 / * invalid request code */
+ gf_error_to_errno_array[GF_ERROR_CODE_BADRQC] = EBADRQC;
+ gf_errno_to_error_array[EBADRQC] = GF_ERROR_CODE_BADRQC;
+/* EBADSLT 55 / * invalid slot */
+ gf_error_to_errno_array[GF_ERROR_CODE_BADSLT] = EBADSLT;
+ gf_errno_to_error_array[EBADSLT] = GF_ERROR_CODE_BADSLT;
+/* EDEADLOCK 56 / * file locking deadlock error */
+/* This is same as EDEADLK on linux */
+ gf_error_to_errno_array[GF_ERROR_CODE_DEADLK] = EDEADLOCK;
+ gf_errno_to_error_array[EDEADLOCK] = GF_ERROR_CODE_DEADLK;
+
+/* EBFONT 57 / * bad font file fmt */
+ gf_error_to_errno_array[GF_ERROR_CODE_BFONT] = EBFONT;
+ gf_errno_to_error_array[EBFONT] = GF_ERROR_CODE_BFONT;
+
+/* Interprocess Robust Locks */
+/* EOWNERDEAD 58 / * process died with the lock */
+ gf_error_to_errno_array[GF_ERROR_CODE_OWNERDEAD] = EOWNERDEAD;
+ gf_errno_to_error_array[EOWNERDEAD] = GF_ERROR_CODE_OWNERDEAD;
+/* ENOTRECOVERABLE 59 / * lock is not recoverable */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOTRECOVERABLE] = ENOTRECOVERABLE;
+ gf_errno_to_error_array[ENOTRECOVERABLE] = GF_ERROR_CODE_NOTRECOVERABLE;
+
+/* stream problems */
+/* ENOSTR 60 / * Device not a stream */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOSTR] = ENOSTR;
+ gf_errno_to_error_array[ENOSTR] = GF_ERROR_CODE_NOSTR;
+/* ENODATA 61 / * no data (for no delay io) */
+ gf_error_to_errno_array[GF_ERROR_CODE_NODATA] = ENODATA;
+ gf_errno_to_error_array[ENODATA] = GF_ERROR_CODE_NODATA;
+/* ETIME 62 / * timer expired */
+ gf_error_to_errno_array[GF_ERROR_CODE_TIME] = ETIME;
+ gf_errno_to_error_array[ETIME] = GF_ERROR_CODE_TIME;
+/* ENOSR 63 / * out of streams resources */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOSR] = ENOSR;
+ gf_errno_to_error_array[ENOSR] = GF_ERROR_CODE_NOSR;
+
+/* ENONET 64 / * Machine is not on the network */
+ gf_error_to_errno_array[GF_ERROR_CODE_NONET] = ENONET;
+ gf_errno_to_error_array[ENONET] = GF_ERROR_CODE_NONET;
+/* ENOPKG 65 / * Package not installed */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOPKG] = ENOPKG;
+ gf_errno_to_error_array[ENOPKG] = GF_ERROR_CODE_NOPKG;
+/* EREMOTE 66 / * The object is remote */
+ gf_error_to_errno_array[GF_ERROR_CODE_REMOTE] = EREMOTE;
+ gf_errno_to_error_array[EREMOTE] = GF_ERROR_CODE_REMOTE;
+/* ENOLINK 67 / * the link has been severed */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOLINK] = ENOLINK;
+ gf_errno_to_error_array[ENOLINK] = GF_ERROR_CODE_NOLINK;
+/* EADV 68 / * advertise error */
+ gf_error_to_errno_array[GF_ERROR_CODE_ADV] = EADV;
+ gf_errno_to_error_array[EADV] = GF_ERROR_CODE_ADV;
+/* ESRMNT 69 / * srmount error */
+ gf_error_to_errno_array[GF_ERROR_CODE_SRMNT] = ESRMNT;
+ gf_errno_to_error_array[ESRMNT] = GF_ERROR_CODE_SRMNT;
+
+/* ECOMM 70 / * Communication error on send */
+ gf_error_to_errno_array[GF_ERROR_CODE_COMM] = ECOMM;
+ gf_errno_to_error_array[ECOMM] = GF_ERROR_CODE_COMM;
+/* EPROTO 71 / * Protocol error */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROTO] = EPROTO;
+ gf_errno_to_error_array[EPROTO] = GF_ERROR_CODE_PROTO;
+
+/* Interprocess Robust Locks */
+/* ELOCKUNMAPPED 72 / * locked lock was unmapped */
+ gf_error_to_errno_array[GF_ERROR_CODE_LOCKUNMAPPED] = ELOCKUNMAPPED;
+ gf_errno_to_error_array[ELOCKUNMAPPED] = GF_ERROR_CODE_LOCKUNMAPPED;
+
+/* ENOTACTIVE 73 / * Facility is not active */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOTACTIVE] = ENOTACTIVE;
+ gf_errno_to_error_array[ENOTACTIVE] = GF_ERROR_CODE_NOTACTIVE;
+/* EMULTIHOP 74 / * multihop attempted */
+ gf_error_to_errno_array[GF_ERROR_CODE_MULTIHOP] = EMULTIHOP;
+ gf_errno_to_error_array[EMULTIHOP] = GF_ERROR_CODE_MULTIHOP;
+/* EBADMSG 77 / * trying to read unreadable message */
+ gf_error_to_errno_array[GF_ERROR_CODE_BADMSG] = EBADMSG;
+ gf_errno_to_error_array[EBADMSG] = GF_ERROR_CODE_BADMSG;
+/* ENAMETOOLONG 78 / * path name is too long */
+ gf_error_to_errno_array[GF_ERROR_CODE_NAMETOOLONG] = ENAMETOOLONG;
+ gf_errno_to_error_array[ENAMETOOLONG] = GF_ERROR_CODE_NAMETOOLONG;
+/* EOVERFLOW 79 / * value too large to be stored in data type */
+ gf_error_to_errno_array[GF_ERROR_CODE_OVERFLOW] = EOVERFLOW;
+ gf_errno_to_error_array[EOVERFLOW] = GF_ERROR_CODE_OVERFLOW;
+/* ENOTUNIQ 80 / * given log. name not unique */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOTUNIQ] = ENOTUNIQ;
+ gf_errno_to_error_array[ENOTUNIQ] = GF_ERROR_CODE_NOTUNIQ;
+/* EBADFD 81 / * f.d. invalid for this operation */
+ gf_error_to_errno_array[GF_ERROR_CODE_BADFD] = EBADFD;
+ gf_errno_to_error_array[EBADFD] = GF_ERROR_CODE_BADFD;
+/* EREMCHG 82 / * Remote address changed */
+ gf_error_to_errno_array[GF_ERROR_CODE_REMCHG] = EREMCHG;
+ gf_errno_to_error_array[EREMCHG] = GF_ERROR_CODE_REMCHG;
+
+/* shared library problems */
+/* ELIBACC 83 / * Can't access a needed shared lib. */
+ gf_error_to_errno_array[GF_ERROR_CODE_LIBACC] = ELIBACC;
+ gf_errno_to_error_array[ELIBACC] = GF_ERROR_CODE_LIBACC;
+/* ELIBBAD 84 / * Accessing a corrupted shared lib. */
+ gf_error_to_errno_array[GF_ERROR_CODE_LIBBAD] = ELIBBAD;
+ gf_errno_to_error_array[ELIBBAD] = GF_ERROR_CODE_LIBBAD;
+/* ELIBSCN 85 / * .lib section in a.out corrupted. */
+ gf_error_to_errno_array[GF_ERROR_CODE_LIBSCN] = ELIBSCN;
+ gf_errno_to_error_array[ELIBSCN] = GF_ERROR_CODE_LIBSCN;
+/* ELIBMAX 86 / * Attempting to link in too many libs. */
+ gf_error_to_errno_array[GF_ERROR_CODE_LIBMAX] = ELIBMAX;
+ gf_errno_to_error_array[ELIBMAX] = GF_ERROR_CODE_LIBMAX;
+/* ELIBEXEC 87 / * Attempting to exec a shared library. */
+ gf_error_to_errno_array[GF_ERROR_CODE_LIBEXEC] = ELIBEXEC;
+ gf_errno_to_error_array[ELIBEXEC] = GF_ERROR_CODE_LIBEXEC;
+/* EILSEQ 88 / * Illegal byte sequence. */
+ gf_error_to_errno_array[GF_ERROR_CODE_ILSEQ] = EILSEQ;
+ gf_errno_to_error_array[EILSEQ] = GF_ERROR_CODE_ILSEQ;
+/* ENOSYS 89 / * Unsupported file system operation */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOSYS] = ENOSYS;
+ gf_errno_to_error_array[ENOSYS] = GF_ERROR_CODE_NOSYS;
+/* ELOOP 90 / * Symbolic link loop */
+ gf_error_to_errno_array[GF_ERROR_CODE_LOOP] = ELOOP;
+ gf_errno_to_error_array[ELOOP] = GF_ERROR_CODE_LOOP;
+/* ERESTART 91 / * Restartable system call */
+ gf_error_to_errno_array[GF_ERROR_CODE_RESTART] = ERESTART;
+ gf_errno_to_error_array[ERESTART] = GF_ERROR_CODE_RESTART;
+/* ESTRPIPE 92 / * if pipe/FIFO, don't sleep in stream head */
+ gf_error_to_errno_array[GF_ERROR_CODE_STRPIPE] = ESTRPIPE;
+ gf_errno_to_error_array[ESTRPIPE] = GF_ERROR_CODE_STRPIPE;
+/* ENOTEMPTY 93 / * directory not empty */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOTEMPTY] = ENOTEMPTY;
+ gf_errno_to_error_array[ENOTEMPTY] = GF_ERROR_CODE_NOTEMPTY;
+/* EUSERS 94 / * Too many users (for UFS) */
+ gf_error_to_errno_array[GF_ERROR_CODE_USERS] = EUSERS;
+ gf_errno_to_error_array[EUSERS] = GF_ERROR_CODE_USERS;
+
+/* BSD Networking Software */
+ /* argument errors */
+/* ENOTSOCK 95 / * Socket operation on non-socket */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOTSOCK] = ENOTSOCK;
+ gf_errno_to_error_array[ENOTSOCK] = GF_ERROR_CODE_NOTSOCK;
+/* EDESTADDRREQ 96 / * Destination address required */
+ gf_error_to_errno_array[GF_ERROR_CODE_DESTADDRREQ] = EDESTADDRREQ;
+ gf_errno_to_error_array[EDESTADDRREQ] = GF_ERROR_CODE_DESTADDRREQ;
+/* EMSGSIZE 97 / * Message too long */
+ gf_error_to_errno_array[GF_ERROR_CODE_MSGSIZE] = EMSGSIZE;
+ gf_errno_to_error_array[EMSGSIZE] = GF_ERROR_CODE_MSGSIZE;
+/* EPROTOTYPE 98 / * Protocol wrong type for socket */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROTOTYPE] = EPROTOTYPE;
+ gf_errno_to_error_array[EPROTOTYPE] = GF_ERROR_CODE_PROTOTYPE;
+/* ENOPROTOOPT 99 / * Protocol not available */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOPROTOOPT] = ENOPROTOOPT;
+ gf_errno_to_error_array[ENOPROTOOPT] = GF_ERROR_CODE_NOPROTOOPT;
+/* EPROTONOSUPPORT 120 / * Protocol not supported */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROTONOSUPPORT] = EPROTONOSUPPORT;
+ gf_errno_to_error_array[EPROTONOSUPPORT] = GF_ERROR_CODE_PROTONOSUPPORT;
+/* ESOCKTNOSUPPORT 121 / * Socket type not supported */
+ gf_error_to_errno_array[GF_ERROR_CODE_SOCKTNOSUPPORT] = ESOCKTNOSUPPORT;
+ gf_errno_to_error_array[ESOCKTNOSUPPORT] = GF_ERROR_CODE_SOCKTNOSUPPORT;
+
+/* EOPNOTSUPP 122 / * Operation not supported on socket */
+ gf_error_to_errno_array[GF_ERROR_CODE_OPNOTSUPP] = EOPNOTSUPP;
+ gf_errno_to_error_array[EOPNOTSUPP] = GF_ERROR_CODE_OPNOTSUPP;
+/* EPFNOSUPPORT 123 / * Protocol family not supported */
+ gf_error_to_errno_array[GF_ERROR_CODE_PFNOSUPPORT] = EPFNOSUPPORT;
+ gf_errno_to_error_array[EPFNOSUPPORT] = GF_ERROR_CODE_PFNOSUPPORT;
+/* EAFNOSUPPORT 124 / * Address family not supported by */
+ /* protocol family */
+ gf_error_to_errno_array[GF_ERROR_CODE_AFNOSUPPORT] = EAFNOSUPPORT;
+ gf_errno_to_error_array[EAFNOSUPPORT] = GF_ERROR_CODE_AFNOSUPPORT;
+/* EADDRINUSE 125 / * Address already in use */
+ gf_error_to_errno_array[GF_ERROR_CODE_ADDRINUSE] = EADDRINUSE;
+ gf_errno_to_error_array[EADDRINUSE] = GF_ERROR_CODE_ADDRINUSE;
+/* EADDRNOTAVAIL 126 / * Can't assign requested address */
+ /* operational errors */
+ gf_error_to_errno_array[GF_ERROR_CODE_ADDRNOTAVAIL] = EADDRNOTAVAIL;
+ gf_errno_to_error_array[EADDRNOTAVAIL] = GF_ERROR_CODE_ADDRNOTAVAIL;
+/* ENETDOWN 127 / * Network is down */
+ gf_error_to_errno_array[GF_ERROR_CODE_NETDOWN] = ENETDOWN;
+ gf_errno_to_error_array[ENETDOWN] = GF_ERROR_CODE_NETDOWN;
+/* ENETUNREACH 128 / * Network is unreachable */
+ gf_error_to_errno_array[GF_ERROR_CODE_NETUNREACH] = ENETUNREACH;
+ gf_errno_to_error_array[ENETUNREACH] = GF_ERROR_CODE_NETUNREACH;
+/* ENETRESET 129 / * Network dropped connection because */
+ /* of reset */
+ gf_error_to_errno_array[GF_ERROR_CODE_NETRESET] = ENETRESET;
+ gf_errno_to_error_array[ENETRESET] = GF_ERROR_CODE_NETRESET;
+/* ECONNABORTED 130 / * Software caused connection abort */
+ gf_error_to_errno_array[GF_ERROR_CODE_CONNABORTED] = ECONNABORTED;
+ gf_errno_to_error_array[ECONNABORTED] = GF_ERROR_CODE_CONNABORTED;
+/* ECONNRESET 131 / * Connection reset by peer */
+ gf_error_to_errno_array[GF_ERROR_CODE_CONNRESET] = ECONNRESET;
+ gf_errno_to_error_array[ECONNRESET] = GF_ERROR_CODE_CONNRESET;
+/* ENOBUFS 132 / * No buffer space available */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOBUFS] = ENOBUFS;
+ gf_errno_to_error_array[ENOBUFS] = GF_ERROR_CODE_NOBUFS;
+/* EISCONN 133 / * Socket is already connected */
+ gf_error_to_errno_array[GF_ERROR_CODE_ISCONN] = EISCONN;
+ gf_errno_to_error_array[EISCONN] = GF_ERROR_CODE_ISCONN;
+/* ENOTCONN 134 / * Socket is not connected */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOTCONN] = ENOTCONN;
+ gf_errno_to_error_array[ENOTCONN] = GF_ERROR_CODE_NOTCONN;
+/* XENIX has 135 - 142 */
+/* ESHUTDOWN 143 / * Can't send after socket shutdown */
+ gf_error_to_errno_array[GF_ERROR_CODE_SHUTDOWN] = ESHUTDOWN;
+ gf_errno_to_error_array[ESHUTDOWN] = GF_ERROR_CODE_SHUTDOWN;
+/* ETOOMANYREFS 144 / * Too many references: can't splice */
+ gf_error_to_errno_array[GF_ERROR_CODE_TOOMANYREFS] = ETOOMANYREFS;
+ gf_errno_to_error_array[ETOOMANYREFS] = GF_ERROR_CODE_TOOMANYREFS;
+/* ETIMEDOUT 145 / * Connection timed out */
+ gf_error_to_errno_array[GF_ERROR_CODE_TIMEDOUT] = ETIMEDOUT;
+ gf_errno_to_error_array[ETIMEDOUT] = GF_ERROR_CODE_TIMEDOUT;
+
+/* ECONNREFUSED 146 / * Connection refused */
+ gf_error_to_errno_array[GF_ERROR_CODE_CONNREFUSED] = ECONNREFUSED;
+ gf_errno_to_error_array[ECONNREFUSED] = GF_ERROR_CODE_CONNREFUSED;
+/* EHOSTDOWN 147 / * Host is down */
+ gf_error_to_errno_array[GF_ERROR_CODE_HOSTDOWN] = EHOSTDOWN;
+ gf_errno_to_error_array[EHOSTDOWN] = GF_ERROR_CODE_HOSTDOWN;
+/* EHOSTUNREACH 148 / * No route to host */
+ gf_error_to_errno_array[GF_ERROR_CODE_HOSTUNREACH] = EHOSTUNREACH;
+ gf_errno_to_error_array[EHOSTUNREACH] = GF_ERROR_CODE_HOSTUNREACH;
+/* EALREADY 149 / * operation already in progress */
+ gf_error_to_errno_array[GF_ERROR_CODE_ALREADY] = EALREADY;
+ gf_errno_to_error_array[EALREADY] = GF_ERROR_CODE_ALREADY;
+/* EINPROGRESS 150 / * operation now in progress */
+ gf_error_to_errno_array[GF_ERROR_CODE_INPROGRESS] = EINPROGRESS;
+ gf_errno_to_error_array[EINPROGRESS] = GF_ERROR_CODE_INPROGRESS;
+
+/* SUN Network File System */
+/* ESTALE 151 / * Stale NFS file handle */
+ gf_error_to_errno_array[GF_ERROR_CODE_STALE] = ESTALE;
+ gf_errno_to_error_array[ESTALE] = GF_ERROR_CODE_STALE;
+
+ return ;
+}
+#endif /* GF_SOLARIS_HOST_OS */
+
+#ifdef GF_DARWIN_HOST_OS
+static void
+init_compat_errno_arrays ()
+{
+ /* EDEADLK 11 / * Resource deadlock would occur */
+ gf_error_to_errno_array[GF_ERROR_CODE_DEADLK] = EDEADLK;
+ gf_errno_to_error_array[EDEADLK] = GF_ERROR_CODE_DEADLK;
+
+ /* EAGAIN 35 / * Try Again */
+ gf_error_to_errno_array[GF_ERROR_CODE_AGAIN] = EAGAIN;
+ gf_errno_to_error_array[EAGAIN] = GF_ERROR_CODE_AGAIN;
+
+ /* EINPROGRESS 36 / * Operation now in progress */
+ gf_error_to_errno_array[GF_ERROR_CODE_INPROGRESS] = EINPROGRESS;
+ gf_errno_to_error_array[EINPROGRESS] = GF_ERROR_CODE_INPROGRESS;
+
+ /* EALREADY 37 / * Operation already in progress */
+ gf_error_to_errno_array[GF_ERROR_CODE_ALREADY] = EALREADY;
+ gf_errno_to_error_array[EALREADY] = GF_ERROR_CODE_ALREADY;
+
+ /* ENOTSOCK 38 / * Socket operation on non-socket */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOTSOCK] = ENOTSOCK;
+ gf_errno_to_error_array[ENOTSOCK] = GF_ERROR_CODE_NOTSOCK;
+
+ /* EDESTADDRREQ 39 / * Destination address required */
+ gf_error_to_errno_array[GF_ERROR_CODE_DESTADDRREQ] = EDESTADDRREQ;
+ gf_errno_to_error_array[EDESTADDRREQ] = GF_ERROR_CODE_DESTADDRREQ;
+
+ /* EMSGSIZE 40 / * Message too long */
+ gf_error_to_errno_array[GF_ERROR_CODE_MSGSIZE] = EMSGSIZE;
+ gf_errno_to_error_array[EMSGSIZE] = GF_ERROR_CODE_MSGSIZE;
+
+ /* EPROTOTYPE 41 / * Protocol wrong type for socket */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROTOTYPE] = EPROTOTYPE;
+ gf_errno_to_error_array[EPROTOTYPE] = GF_ERROR_CODE_PROTOTYPE;
+
+ /* ENOPROTOOPT 42 / * Protocol not available */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOPROTOOPT] = ENOPROTOOPT;
+ gf_errno_to_error_array[ENOPROTOOPT] = GF_ERROR_CODE_NOPROTOOPT;
+
+ /* EPROTONOSUPPORT 43 / * Protocol not supported */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROTONOSUPPORT] = EPROTONOSUPPORT;
+ gf_errno_to_error_array[EPROTONOSUPPORT] = GF_ERROR_CODE_PROTONOSUPPORT;
+
+ /* ESOCKTNOSUPPORT 44 / * Socket type not supported */
+ gf_error_to_errno_array[GF_ERROR_CODE_SOCKTNOSUPPORT] = ESOCKTNOSUPPORT;
+ gf_errno_to_error_array[ESOCKTNOSUPPORT] = GF_ERROR_CODE_SOCKTNOSUPPORT;
+
+ /* EOPNOTSUPP 45 / * Operation not supported */
+ gf_error_to_errno_array[GF_ERROR_CODE_OPNOTSUPP] = EOPNOTSUPP;
+ gf_errno_to_error_array[EOPNOTSUPP] = GF_ERROR_CODE_OPNOTSUPP;
+
+ /* EPFNOSUPPORT 46 / * Protocol family not supported */
+ gf_error_to_errno_array[GF_ERROR_CODE_PFNOSUPPORT] = EPFNOSUPPORT;
+ gf_errno_to_error_array[EPFNOSUPPORT] = GF_ERROR_CODE_PFNOSUPPORT;
+
+ /* EAFNOSUPPORT 47 / * Address family not supported by protocol family */
+ gf_error_to_errno_array[GF_ERROR_CODE_AFNOSUPPORT] = EAFNOSUPPORT;
+ gf_errno_to_error_array[EAFNOSUPPORT] = GF_ERROR_CODE_AFNOSUPPORT;
+
+ /* EADDRINUSE 48 / * Address already in use */
+ gf_error_to_errno_array[GF_ERROR_CODE_ADDRINUSE] = EADDRINUSE;
+ gf_errno_to_error_array[EADDRINUSE] = GF_ERROR_CODE_ADDRINUSE;
+
+ /* EADDRNOTAVAIL 49 / * Can't assign requested address */
+ gf_error_to_errno_array[GF_ERROR_CODE_ADDRNOTAVAIL] = EADDRNOTAVAIL;
+ gf_errno_to_error_array[EADDRNOTAVAIL] = GF_ERROR_CODE_ADDRNOTAVAIL;
+
+ /* ENETDOWN 50 / * Network is down */
+ gf_error_to_errno_array[GF_ERROR_CODE_NETDOWN] = ENETDOWN;
+ gf_errno_to_error_array[ENETDOWN] = GF_ERROR_CODE_NETDOWN;
+
+ /* ENETUNREACH 51 / * Network is unreachable */
+ gf_error_to_errno_array[GF_ERROR_CODE_NETUNREACH] = ENETUNREACH;
+ gf_errno_to_error_array[ENETUNREACH] = GF_ERROR_CODE_NETUNREACH;
+
+ /* ENETRESET 52 / * Network dropped connection on reset */
+ gf_error_to_errno_array[GF_ERROR_CODE_NETRESET] = ENETRESET;
+ gf_errno_to_error_array[ENETRESET] = GF_ERROR_CODE_NETRESET;
+
+ /* ECONNABORTED 53 / * Software caused connection abort */
+ gf_error_to_errno_array[GF_ERROR_CODE_CONNABORTED] = ECONNABORTED;
+ gf_errno_to_error_array[ECONNABORTED] = GF_ERROR_CODE_CONNABORTED;
+
+ /* ECONNRESET 54 / * Connection reset by peer */
+ gf_error_to_errno_array[GF_ERROR_CODE_CONNRESET] = ECONNRESET;
+ gf_errno_to_error_array[ECONNRESET] = GF_ERROR_CODE_CONNRESET;
+
+ /* ENOBUFS 55 / * No buffer space available */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOBUFS] = ENOBUFS;
+ gf_errno_to_error_array[ENOBUFS] = GF_ERROR_CODE_NOBUFS;
+
+ /* EISCONN 56 / * Socket is already connected */
+ gf_error_to_errno_array[GF_ERROR_CODE_ISCONN] = EISCONN;
+ gf_errno_to_error_array[EISCONN] = GF_ERROR_CODE_ISCONN;
+
+ /* ENOTCONN 57 / * Socket is not connected */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOTCONN] = ENOTCONN;
+ gf_errno_to_error_array[ENOTCONN] = GF_ERROR_CODE_NOTCONN;
+
+ /* ESHUTDOWN 58 / * Can't send after socket shutdown */
+ gf_error_to_errno_array[GF_ERROR_CODE_SHUTDOWN] = ESHUTDOWN;
+ gf_errno_to_error_array[ESHUTDOWN] = GF_ERROR_CODE_SHUTDOWN;
+
+ /* ETOOMANYREFS 59 / * Too many references: can't splice */
+ gf_error_to_errno_array[GF_ERROR_CODE_TOOMANYREFS] = ETOOMANYREFS;
+ gf_errno_to_error_array[ETOOMANYREFS] = GF_ERROR_CODE_TOOMANYREFS;
+
+ /* ETIMEDOUT 60 / * Operation timed out */
+ gf_error_to_errno_array[GF_ERROR_CODE_TIMEDOUT] = ETIMEDOUT;
+ gf_errno_to_error_array[ETIMEDOUT] = GF_ERROR_CODE_TIMEDOUT;
+
+ /* ECONNREFUSED 61 / * Connection refused */
+ gf_error_to_errno_array[GF_ERROR_CODE_CONNREFUSED] = ECONNREFUSED;
+ gf_errno_to_error_array[ECONNREFUSED] = GF_ERROR_CODE_CONNREFUSED;
+
+ /* ELOOP 62 / * Too many levels of symbolic links */
+ gf_error_to_errno_array[GF_ERROR_CODE_LOOP] = ELOOP;
+ gf_errno_to_error_array[ELOOP] = GF_ERROR_CODE_LOOP;
+
+ /* ENAMETOOLONG 63 / * File name too long */
+ gf_error_to_errno_array[GF_ERROR_CODE_NAMETOOLONG] = ENAMETOOLONG;
+ gf_errno_to_error_array[ENAMETOOLONG] = GF_ERROR_CODE_NAMETOOLONG;
+
+ /* EHOSTDOWN 64 / * Host is down */
+ gf_error_to_errno_array[GF_ERROR_CODE_HOSTDOWN] = EHOSTDOWN;
+ gf_errno_to_error_array[EHOSTDOWN] = GF_ERROR_CODE_HOSTDOWN;
+
+ /* EHOSTUNREACH 65 / * No route to host */
+ gf_error_to_errno_array[GF_ERROR_CODE_HOSTUNREACH] = EHOSTUNREACH;
+ gf_errno_to_error_array[EHOSTUNREACH] = GF_ERROR_CODE_HOSTUNREACH;
+
+ /* ENOTEMPTY 66 / * Directory not empty */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOTEMPTY] = ENOTEMPTY;
+ gf_errno_to_error_array[ENOTEMPTY] = GF_ERROR_CODE_NOTEMPTY;
+
+ /* EPROCLIM 67 / * Too many processes */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROCLIM] = EPROCLIM;
+ gf_errno_to_error_array[EPROCLIM] = GF_ERROR_CODE_PROCLIM;
+
+ /* EUSERS 68 / * Too many users */
+ gf_error_to_errno_array[GF_ERROR_CODE_USERS] = EUSERS;
+ gf_errno_to_error_array[EUSERS] = GF_ERROR_CODE_USERS;
+
+ /* EDQUOT 69 / * Disc quota exceeded */
+ gf_error_to_errno_array[GF_ERROR_CODE_DQUOT] = EDQUOT;
+ gf_errno_to_error_array[EDQUOT] = GF_ERROR_CODE_DQUOT;
+
+ /* ESTALE 70 / * Stale NFS file handle */
+ gf_error_to_errno_array[GF_ERROR_CODE_STALE] = ESTALE;
+ gf_errno_to_error_array[ESTALE] = GF_ERROR_CODE_STALE;
+
+ /* EREMOTE 71 / * Too many levels of remote in path */
+ gf_error_to_errno_array[GF_ERROR_CODE_REMOTE] = EREMOTE;
+ gf_errno_to_error_array[EREMOTE] = GF_ERROR_CODE_REMOTE;
+
+ /* EBADRPC 72 / * RPC struct is bad */
+ gf_error_to_errno_array[GF_ERROR_CODE_BADRPC] = EBADRPC;
+ gf_errno_to_error_array[EBADRPC] = GF_ERROR_CODE_BADRPC;
+
+ /* ERPCMISMATCH 73 / * RPC version wrong */
+ gf_error_to_errno_array[GF_ERROR_CODE_RPCMISMATCH] = ERPCMISMATCH;
+ gf_errno_to_error_array[ERPCMISMATCH] = GF_ERROR_CODE_RPCMISMATCH;
+
+ /* EPROGUNAVAIL 74 / * RPC prog. not avail */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROGUNAVAIL] = EPROGUNAVAIL;
+ gf_errno_to_error_array[EPROGUNAVAIL] = GF_ERROR_CODE_PROGUNAVAIL;
+
+ /* EPROGMISMATCH 75 / * Program version wrong */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROGMISMATCH] = EPROGMISMATCH;
+ gf_errno_to_error_array[EPROGMISMATCH] = GF_ERROR_CODE_PROGMISMATCH;
+
+ /* EPROCUNAVAIL 76 / * Bad procedure for program */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROCUNAVAIL] = EPROCUNAVAIL;
+ gf_errno_to_error_array[EPROCUNAVAIL] = GF_ERROR_CODE_PROCUNAVAIL;
+
+ /* ENOLCK 77 / * No locks available */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOLCK] = ENOLCK;
+ gf_errno_to_error_array[ENOLCK] = GF_ERROR_CODE_NOLCK;
+
+ /* ENOSYS 78 / * Function not implemented */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOSYS] = ENOSYS;
+ gf_errno_to_error_array[ENOSYS] = GF_ERROR_CODE_NOSYS;
+
+ /* EFTYPE 79 / * Inappropriate file type or format */
+ gf_error_to_errno_array[GF_ERROR_CODE_FTYPE] = EFTYPE;
+ gf_errno_to_error_array[EFTYPE] = GF_ERROR_CODE_FTYPE;
+
+ /* EAUTH 80 / * Authentication error */
+ gf_error_to_errno_array[GF_ERROR_CODE_AUTH] = EAUTH;
+ gf_errno_to_error_array[EAUTH] = GF_ERROR_CODE_AUTH;
+
+ /* ENEEDAUTH 81 / * Need authenticator */
+ gf_error_to_errno_array[GF_ERROR_CODE_NEEDAUTH] = ENEEDAUTH;
+ gf_errno_to_error_array[ENEEDAUTH] = GF_ERROR_CODE_NEEDAUTH;
+/* Intelligent device errors */
+/* EPWROFF 82 / * Device power is off */
+ gf_error_to_errno_array[GF_ERROR_CODE_PWROFF] = EPWROFF;
+ gf_errno_to_error_array[EPWROFF] = GF_ERROR_CODE_PWROFF;
+/* EDEVERR 83 / * Device error, e.g. paper out */
+ gf_error_to_errno_array[GF_ERROR_CODE_DEVERR] = EDEVERR;
+ gf_errno_to_error_array[EDEVERR] = GF_ERROR_CODE_DEVERR;
+
+ /* EOVERFLOW 84 / * Value too large to be stored in data type */
+ gf_error_to_errno_array[GF_ERROR_CODE_OVERFLOW] = EOVERFLOW;
+ gf_errno_to_error_array[EOVERFLOW] = GF_ERROR_CODE_OVERFLOW;
+
+/* Program loading errors */
+/* EBADEXEC 85 / * Bad executable */
+ gf_error_to_errno_array[GF_ERROR_CODE_BADEXEC] = EBADEXEC;
+ gf_errno_to_error_array[EBADEXEC] = GF_ERROR_CODE_BADEXEC;
+
+/* EBADARCH 86 / * Bad CPU type in executable */
+ gf_error_to_errno_array[GF_ERROR_CODE_BADARCH] = EBADARCH;
+ gf_errno_to_error_array[EBADARCH] = GF_ERROR_CODE_BADARCH;
+
+/* ESHLIBVERS 87 / * Shared library version mismatch */
+ gf_error_to_errno_array[GF_ERROR_CODE_SHLIBVERS] = ESHLIBVERS;
+ gf_errno_to_error_array[ESHLIBVERS] = GF_ERROR_CODE_SHLIBVERS;
+
+/* EBADMACHO 88 / * Malformed Macho file */
+ gf_error_to_errno_array[GF_ERROR_CODE_BADMACHO] = EBADMACHO;
+ gf_errno_to_error_array[EBADMACHO] = GF_ERROR_CODE_BADMACHO;
+
+#if 0
+ /* EDOOFUS 88 / * Programming error */
+ gf_error_to_errno_array[GF_ERROR_CODE_DOOFUS] = EDOOFUS;
+ gf_errno_to_error_array[EDOOFUS] = GF_ERROR_CODE_DOOFUS;
+#endif
+
+ /* ECANCELED 89 / * Operation canceled */
+ gf_error_to_errno_array[GF_ERROR_CODE_CANCELED] = ECANCELED;
+ gf_errno_to_error_array[ECANCELED] = GF_ERROR_CODE_CANCELED;
+
+ /* EIDRM 90 / * Identifier removed */
+ gf_error_to_errno_array[GF_ERROR_CODE_IDRM] = EIDRM;
+ gf_errno_to_error_array[EIDRM] = GF_ERROR_CODE_IDRM;
+ /* ENOMSG 91 / * No message of desired type */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOMSG] = ENOMSG;
+ gf_errno_to_error_array[ENOMSG] = GF_ERROR_CODE_NOMSG;
+
+ /* EILSEQ 92 / * Illegal byte sequence */
+ gf_error_to_errno_array[GF_ERROR_CODE_ILSEQ] = EILSEQ;
+ gf_errno_to_error_array[EILSEQ] = GF_ERROR_CODE_ILSEQ;
+
+ /* ENOATTR 93 / * Attribute not found */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOATTR] = ENOATTR;
+ gf_errno_to_error_array[ENOATTR] = GF_ERROR_CODE_NOATTR;
+
+ /* EBADMSG 94 / * Bad message */
+ gf_error_to_errno_array[GF_ERROR_CODE_BADMSG] = EBADMSG;
+ gf_errno_to_error_array[EBADMSG] = GF_ERROR_CODE_BADMSG;
+
+ /* EMULTIHOP 95 / * Reserved */
+ gf_error_to_errno_array[GF_ERROR_CODE_MULTIHOP] = EMULTIHOP;
+ gf_errno_to_error_array[EMULTIHOP] = GF_ERROR_CODE_MULTIHOP;
+
+ /* ENODATA 96 / * No message available on STREAM */
+ gf_error_to_errno_array[GF_ERROR_CODE_NEEDAUTH] = ENEEDAUTH;
+ gf_errno_to_error_array[ENEEDAUTH] = GF_ERROR_CODE_NEEDAUTH;
+
+ /* ENOLINK 97 / * Reserved */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOLINK] = ENOLINK;
+ gf_errno_to_error_array[ENOLINK] = GF_ERROR_CODE_NOLINK;
+
+ /* ENOSR 98 / * No STREAM resources */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOSR] = ENOSR;
+ gf_errno_to_error_array[ENOSR] = GF_ERROR_CODE_NOSR;
+
+ /* ENOSTR 99 / * Not a STREAM */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOSTR] = ENOSTR;
+ gf_errno_to_error_array[ENOSTR] = GF_ERROR_CODE_NOSTR;
+
+/* EPROTO 100 / * Protocol error */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROTO] = EPROTO;
+ gf_errno_to_error_array[EPROTO] = GF_ERROR_CODE_PROTO;
+/* ETIME 101 / * STREAM ioctl timeout */
+ gf_error_to_errno_array[GF_ERROR_CODE_TIME] = ETIME;
+ gf_errno_to_error_array[ETIME] = GF_ERROR_CODE_TIME;
+
+/* This value is only discrete when compiling __DARWIN_UNIX03, or KERNEL */
+/* EOPNOTSUPP 102 / * Operation not supported on socket */
+ gf_error_to_errno_array[GF_ERROR_CODE_OPNOTSUPP] = EOPNOTSUPP;
+ gf_errno_to_error_array[EOPNOTSUPP] = GF_ERROR_CODE_OPNOTSUPP;
+
+/* ENOPOLICY 103 / * No such policy registered */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOPOLICY] = ENOPOLICY;
+ gf_errno_to_error_array[ENOPOLICY] = GF_ERROR_CODE_NOPOLICY;
+
+ return ;
+}
+#endif /* GF_DARWIN_HOST_OS */
+
+#ifdef GF_BSD_HOST_OS
+static void
+init_compat_errno_arrays ()
+{
+ /* Quite a bit of things changed in FreeBSD - current */
+
+ /* EAGAIN 35 / * Try Again */
+ gf_error_to_errno_array[GF_ERROR_CODE_AGAIN] = EAGAIN;
+ gf_errno_to_error_array[EAGAIN] = GF_ERROR_CODE_AGAIN;
+
+ /* EDEADLK 11 / * Resource deadlock would occur */
+ gf_error_to_errno_array[GF_ERROR_CODE_DEADLK] = EDEADLK;
+ gf_errno_to_error_array[EDEADLK] = GF_ERROR_CODE_DEADLK;
+
+ /* EINPROGRESS 36 / * Operation now in progress */
+ gf_error_to_errno_array[GF_ERROR_CODE_INPROGRESS] = EINPROGRESS;
+ gf_errno_to_error_array[EINPROGRESS] = GF_ERROR_CODE_INPROGRESS;
+
+ /* EALREADY 37 / * Operation already in progress */
+ gf_error_to_errno_array[GF_ERROR_CODE_ALREADY] = EALREADY;
+ gf_errno_to_error_array[EALREADY] = GF_ERROR_CODE_ALREADY;
+
+ /* ENOTSOCK 38 / * Socket operation on non-socket */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOTSOCK] = ENOTSOCK;
+ gf_errno_to_error_array[ENOTSOCK] = GF_ERROR_CODE_NOTSOCK;
+
+ /* EDESTADDRREQ 39 / * Destination address required */
+ gf_error_to_errno_array[GF_ERROR_CODE_DESTADDRREQ] = EDESTADDRREQ;
+ gf_errno_to_error_array[EDESTADDRREQ] = GF_ERROR_CODE_DESTADDRREQ;
+
+ /* EMSGSIZE 40 / * Message too long */
+ gf_error_to_errno_array[GF_ERROR_CODE_MSGSIZE] = EMSGSIZE;
+ gf_errno_to_error_array[EMSGSIZE] = GF_ERROR_CODE_MSGSIZE;
+
+ /* EPROTOTYPE 41 / * Protocol wrong type for socket */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROTOTYPE] = EPROTOTYPE;
+ gf_errno_to_error_array[EPROTOTYPE] = GF_ERROR_CODE_PROTOTYPE;
+
+ /* ENOPROTOOPT 42 / * Protocol not available */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOPROTOOPT] = ENOPROTOOPT;
+ gf_errno_to_error_array[ENOPROTOOPT] = GF_ERROR_CODE_NOPROTOOPT;
+
+ /* EPROTONOSUPPORT 43 / * Protocol not supported */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROTONOSUPPORT] = EPROTONOSUPPORT;
+ gf_errno_to_error_array[EPROTONOSUPPORT] = GF_ERROR_CODE_PROTONOSUPPORT;
+
+ /* ESOCKTNOSUPPORT 44 / * Socket type not supported */
+ gf_error_to_errno_array[GF_ERROR_CODE_SOCKTNOSUPPORT] = ESOCKTNOSUPPORT;
+ gf_errno_to_error_array[ESOCKTNOSUPPORT] = GF_ERROR_CODE_SOCKTNOSUPPORT;
+
+ /* EOPNOTSUPP 45 / * Operation not supported */
+ gf_error_to_errno_array[GF_ERROR_CODE_OPNOTSUPP] = EOPNOTSUPP;
+ gf_errno_to_error_array[EOPNOTSUPP] = GF_ERROR_CODE_OPNOTSUPP;
+
+ /* EPFNOSUPPORT 46 / * Protocol family not supported */
+ gf_error_to_errno_array[GF_ERROR_CODE_PFNOSUPPORT] = EPFNOSUPPORT;
+ gf_errno_to_error_array[EPFNOSUPPORT] = GF_ERROR_CODE_PFNOSUPPORT;
+
+ /* EAFNOSUPPORT 47 / * Address family not supported by protocol family */
+ gf_error_to_errno_array[GF_ERROR_CODE_AFNOSUPPORT] = EAFNOSUPPORT;
+ gf_errno_to_error_array[EAFNOSUPPORT] = GF_ERROR_CODE_AFNOSUPPORT;
+
+ /* EADDRINUSE 48 / * Address already in use */
+ gf_error_to_errno_array[GF_ERROR_CODE_ADDRINUSE] = EADDRINUSE;
+ gf_errno_to_error_array[EADDRINUSE] = GF_ERROR_CODE_ADDRINUSE;
+
+ /* EADDRNOTAVAIL 49 / * Can't assign requested address */
+ gf_error_to_errno_array[GF_ERROR_CODE_ADDRNOTAVAIL] = EADDRNOTAVAIL;
+ gf_errno_to_error_array[EADDRNOTAVAIL] = GF_ERROR_CODE_ADDRNOTAVAIL;
+
+ /* ENETDOWN 50 / * Network is down */
+ gf_error_to_errno_array[GF_ERROR_CODE_NETDOWN] = ENETDOWN;
+ gf_errno_to_error_array[ENETDOWN] = GF_ERROR_CODE_NETDOWN;
+
+ /* ENETUNREACH 51 / * Network is unreachable */
+ gf_error_to_errno_array[GF_ERROR_CODE_NETUNREACH] = ENETUNREACH;
+ gf_errno_to_error_array[ENETUNREACH] = GF_ERROR_CODE_NETUNREACH;
+
+ /* ENETRESET 52 / * Network dropped connection on reset */
+ gf_error_to_errno_array[GF_ERROR_CODE_NETRESET] = ENETRESET;
+ gf_errno_to_error_array[ENETRESET] = GF_ERROR_CODE_NETRESET;
+
+ /* ECONNABORTED 53 / * Software caused connection abort */
+ gf_error_to_errno_array[GF_ERROR_CODE_CONNABORTED] = ECONNABORTED;
+ gf_errno_to_error_array[ECONNABORTED] = GF_ERROR_CODE_CONNABORTED;
+
+ /* ECONNRESET 54 / * Connection reset by peer */
+ gf_error_to_errno_array[GF_ERROR_CODE_CONNRESET] = ECONNRESET;
+ gf_errno_to_error_array[ECONNRESET] = GF_ERROR_CODE_CONNRESET;
+
+ /* ENOBUFS 55 / * No buffer space available */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOBUFS] = ENOBUFS;
+ gf_errno_to_error_array[ENOBUFS] = GF_ERROR_CODE_NOBUFS;
+
+ /* EISCONN 56 / * Socket is already connected */
+ gf_error_to_errno_array[GF_ERROR_CODE_ISCONN] = EISCONN;
+ gf_errno_to_error_array[EISCONN] = GF_ERROR_CODE_ISCONN;
+
+ /* ENOTCONN 57 / * Socket is not connected */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOTCONN] = ENOTCONN;
+ gf_errno_to_error_array[ENOTCONN] = GF_ERROR_CODE_NOTCONN;
+
+ /* ESHUTDOWN 58 / * Can't send after socket shutdown */
+ gf_error_to_errno_array[GF_ERROR_CODE_SHUTDOWN] = ESHUTDOWN;
+ gf_errno_to_error_array[ESHUTDOWN] = GF_ERROR_CODE_SHUTDOWN;
+
+ /* ETOOMANYREFS 59 / * Too many references: can't splice */
+ gf_error_to_errno_array[GF_ERROR_CODE_TOOMANYREFS] = ETOOMANYREFS;
+ gf_errno_to_error_array[ETOOMANYREFS] = GF_ERROR_CODE_TOOMANYREFS;
+
+ /* ETIMEDOUT 60 / * Operation timed out */
+ gf_error_to_errno_array[GF_ERROR_CODE_TIMEDOUT] = ETIMEDOUT;
+ gf_errno_to_error_array[ETIMEDOUT] = GF_ERROR_CODE_TIMEDOUT;
+
+ /* ECONNREFUSED 61 / * Connection refused */
+ gf_error_to_errno_array[GF_ERROR_CODE_CONNREFUSED] = ECONNREFUSED;
+ gf_errno_to_error_array[ECONNREFUSED] = GF_ERROR_CODE_CONNREFUSED;
+
+ /* ELOOP 62 / * Too many levels of symbolic links */
+ gf_error_to_errno_array[GF_ERROR_CODE_LOOP] = ELOOP;
+ gf_errno_to_error_array[ELOOP] = GF_ERROR_CODE_LOOP;
+
+ /* ENAMETOOLONG 63 / * File name too long */
+ gf_error_to_errno_array[GF_ERROR_CODE_NAMETOOLONG] = ENAMETOOLONG;
+ gf_errno_to_error_array[ENAMETOOLONG] = GF_ERROR_CODE_NAMETOOLONG;
+
+ /* EHOSTDOWN 64 / * Host is down */
+ gf_error_to_errno_array[GF_ERROR_CODE_HOSTDOWN] = EHOSTDOWN;
+ gf_errno_to_error_array[EHOSTDOWN] = GF_ERROR_CODE_HOSTDOWN;
+
+ /* EHOSTUNREACH 65 / * No route to host */
+ gf_error_to_errno_array[GF_ERROR_CODE_HOSTUNREACH] = EHOSTUNREACH;
+ gf_errno_to_error_array[EHOSTUNREACH] = GF_ERROR_CODE_HOSTUNREACH;
+
+ /* ENOTEMPTY 66 / * Directory not empty */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOTEMPTY] = ENOTEMPTY;
+ gf_errno_to_error_array[ENOTEMPTY] = GF_ERROR_CODE_NOTEMPTY;
+
+ /* EPROCLIM 67 / * Too many processes */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROCLIM] = EPROCLIM;
+ gf_errno_to_error_array[EPROCLIM] = GF_ERROR_CODE_PROCLIM;
+
+ /* EUSERS 68 / * Too many users */
+ gf_error_to_errno_array[GF_ERROR_CODE_USERS] = EUSERS;
+ gf_errno_to_error_array[EUSERS] = GF_ERROR_CODE_USERS;
+
+ /* EDQUOT 69 / * Disc quota exceeded */
+ gf_error_to_errno_array[GF_ERROR_CODE_DQUOT] = EDQUOT;
+ gf_errno_to_error_array[EDQUOT] = GF_ERROR_CODE_DQUOT;
+
+ /* ESTALE 70 / * Stale NFS file handle */
+ gf_error_to_errno_array[GF_ERROR_CODE_STALE] = ESTALE;
+ gf_errno_to_error_array[ESTALE] = GF_ERROR_CODE_STALE;
+
+ /* EREMOTE 71 / * Too many levels of remote in path */
+ gf_error_to_errno_array[GF_ERROR_CODE_REMOTE] = EREMOTE;
+ gf_errno_to_error_array[EREMOTE] = GF_ERROR_CODE_REMOTE;
+
+ /* EBADRPC 72 / * RPC struct is bad */
+ gf_error_to_errno_array[GF_ERROR_CODE_BADRPC] = EBADRPC;
+ gf_errno_to_error_array[EBADRPC] = GF_ERROR_CODE_BADRPC;
+
+ /* ERPCMISMATCH 73 / * RPC version wrong */
+ gf_error_to_errno_array[GF_ERROR_CODE_RPCMISMATCH] = ERPCMISMATCH;
+ gf_errno_to_error_array[ERPCMISMATCH] = GF_ERROR_CODE_RPCMISMATCH;
+
+ /* EPROGUNAVAIL 74 / * RPC prog. not avail */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROGUNAVAIL] = EPROGUNAVAIL;
+ gf_errno_to_error_array[EPROGUNAVAIL] = GF_ERROR_CODE_PROGUNAVAIL;
+
+ /* EPROGMISMATCH 75 / * Program version wrong */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROGMISMATCH] = EPROGMISMATCH;
+ gf_errno_to_error_array[EPROGMISMATCH] = GF_ERROR_CODE_PROGMISMATCH;
+
+ /* EPROCUNAVAIL 76 / * Bad procedure for program */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROCUNAVAIL] = EPROCUNAVAIL;
+ gf_errno_to_error_array[EPROCUNAVAIL] = GF_ERROR_CODE_PROCUNAVAIL;
+
+ /* ENOLCK 77 / * No locks available */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOLCK] = ENOLCK;
+ gf_errno_to_error_array[ENOLCK] = GF_ERROR_CODE_NOLCK;
+
+ /* ENOSYS 78 / * Function not implemented */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOSYS] = ENOSYS;
+ gf_errno_to_error_array[ENOSYS] = GF_ERROR_CODE_NOSYS;
+
+ /* EFTYPE 79 / * Inappropriate file type or format */
+ gf_error_to_errno_array[GF_ERROR_CODE_FTYPE] = EFTYPE;
+ gf_errno_to_error_array[EFTYPE] = GF_ERROR_CODE_FTYPE;
+
+ /* EAUTH 80 / * Authentication error */
+ gf_error_to_errno_array[GF_ERROR_CODE_AUTH] = EAUTH;
+ gf_errno_to_error_array[EAUTH] = GF_ERROR_CODE_AUTH;
+
+ /* ENEEDAUTH 81 / * Need authenticator */
+ gf_error_to_errno_array[GF_ERROR_CODE_NEEDAUTH] = ENEEDAUTH;
+ gf_errno_to_error_array[ENEEDAUTH] = GF_ERROR_CODE_NEEDAUTH;
+
+ /* EIDRM 82 / * Identifier removed */
+ gf_error_to_errno_array[GF_ERROR_CODE_IDRM] = EIDRM;
+ gf_errno_to_error_array[EIDRM] = GF_ERROR_CODE_IDRM;
+
+ /* ENOMSG 83 / * No message of desired type */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOMSG] = ENOMSG;
+ gf_errno_to_error_array[ENOMSG] = GF_ERROR_CODE_NOMSG;
+
+ /* EOVERFLOW 84 / * Value too large to be stored in data type */
+ gf_error_to_errno_array[GF_ERROR_CODE_OVERFLOW] = EOVERFLOW;
+ gf_errno_to_error_array[EOVERFLOW] = GF_ERROR_CODE_OVERFLOW;
+
+ /* ECANCELED 85 / * Operation canceled */
+ gf_error_to_errno_array[GF_ERROR_CODE_CANCELED] = ECANCELED;
+ gf_errno_to_error_array[ECANCELED] = GF_ERROR_CODE_CANCELED;
+
+ /* EILSEQ 86 / * Illegal byte sequence */
+ gf_error_to_errno_array[GF_ERROR_CODE_ILSEQ] = EILSEQ;
+ gf_errno_to_error_array[EILSEQ] = GF_ERROR_CODE_ILSEQ;
+
+ /* ENOATTR 87 / * Attribute not found */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOATTR] = ENOATTR;
+ gf_errno_to_error_array[ENOATTR] = GF_ERROR_CODE_NOATTR;
+
+ /* EDOOFUS 88 / * Programming error */
+ gf_error_to_errno_array[GF_ERROR_CODE_DOOFUS] = EDOOFUS;
+ gf_errno_to_error_array[EDOOFUS] = GF_ERROR_CODE_DOOFUS;
+
+ /* EBADMSG 89 / * Bad message */
+ gf_error_to_errno_array[GF_ERROR_CODE_BADMSG] = EBADMSG;
+ gf_errno_to_error_array[EBADMSG] = GF_ERROR_CODE_BADMSG;
+
+ /* EMULTIHOP 90 / * Multihop attempted */
+ gf_error_to_errno_array[GF_ERROR_CODE_MULTIHOP] = EMULTIHOP;
+ gf_errno_to_error_array[EMULTIHOP] = GF_ERROR_CODE_MULTIHOP;
+
+ /* ENOLINK 91 / * Link has been severed */
+ gf_error_to_errno_array[GF_ERROR_CODE_NOLINK] = ENOLINK;
+ gf_errno_to_error_array[ENOLINK] = GF_ERROR_CODE_NOLINK;
+
+ /* EPROTO 92 / * Protocol error */
+ gf_error_to_errno_array[GF_ERROR_CODE_PROTO] = EPROTO;
+ gf_errno_to_error_array[EPROTO] = GF_ERROR_CODE_PROTO;
+
+
+ return ;
+}
+#endif /* GF_BSD_HOST_OS */
+
+#ifdef GF_LINUX_HOST_OS
+static void
+init_compat_errno_arrays ()
+{
+ /* Things are fine. Everything should work seemlessly on GNU/Linux machines */
+ return ;
+}
+#endif /* GF_LINUX_HOST_OS */
+
+
+static void
+init_errno_arrays ()
+{
+ int i;
+ for (i=0; i < GF_ERROR_CODE_UNKNOWN; i++) {
+ gf_errno_to_error_array[i] = i;
+ gf_error_to_errno_array[i] = i;
+ }
+ /* Now change the order if it needs to be. */
+ init_compat_errno_arrays();
+
+ return;
+}
+
+int32_t
+gf_errno_to_error (int32_t op_errno)
+{
+ if (!gf_compat_errno_init_done) {
+ init_errno_arrays ();
+ gf_compat_errno_init_done = 1;
+ }
+
+ if ((op_errno > GF_ERROR_CODE_SUCCESS) && (op_errno < GF_ERROR_CODE_UNKNOWN))
+ return gf_errno_to_error_array[op_errno];
+
+ return op_errno;
+}
+
+
+int32_t
+gf_error_to_errno (int32_t error)
+{
+ if (!gf_compat_errno_init_done) {
+ init_errno_arrays ();
+ gf_compat_errno_init_done = 1;
+ }
+
+ if ((error > GF_ERROR_CODE_SUCCESS) && (error < GF_ERROR_CODE_UNKNOWN))
+ return gf_error_to_errno_array[error];
+
+ return error;
+}
+
diff --git a/libglusterfs/src/compat-errno.h b/libglusterfs/src/compat-errno.h
new file mode 100644
index 000000000..918df45eb
--- /dev/null
+++ b/libglusterfs/src/compat-errno.h
@@ -0,0 +1,240 @@
+/*
+ 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/>.
+*/
+
+#ifndef __COMPAT_ERRNO_H__
+#define __COMPAT_ERRNO_H__
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+#define GF_ERROR_CODE_SUCCESS 0
+#define GF_ERROR_CODE_UNKNOWN 1024
+#define GF_ERRNO_UNKNOWN 1024
+
+#define GF_ERROR_CODE_PERM 1 /* Operation not permitted */
+#define GF_ERROR_CODE_NOENT 2 /* No such file or directory */
+#define GF_ERROR_CODE_SRCH 3 /* No such process */
+#define GF_ERROR_CODE_INTR 4 /* Interrupted system call */
+#define GF_ERROR_CODE_IO 5 /* I/O error */
+#define GF_ERROR_CODE_NXIO 6 /* No such device or address */
+#define GF_ERROR_CODE_2BIG 7 /* Argument list too long */
+#define GF_ERROR_CODE_NOEXEC 8 /* Exec format error */
+#define GF_ERROR_CODE_BADF 9 /* Bad file number */
+#define GF_ERROR_CODE_CHILD 10 /* No child processes */
+#define GF_ERROR_CODE_AGAIN 11 /* Try again */
+#define GF_ERROR_CODE_NOMEM 12 /* Out of memory */
+#define GF_ERROR_CODE_ACCES 13 /* Permission denied */
+#define GF_ERROR_CODE_FAULT 14 /* Bad address */
+#define GF_ERROR_CODE_NOTBLK 15 /* Block device required */
+#define GF_ERROR_CODE_BUSY 16 /* Device or resource busy */
+#define GF_ERROR_CODE_EXIST 17 /* File exists */
+#define GF_ERROR_CODE_XDEV 18 /* Cross-device link */
+#define GF_ERROR_CODE_NODEV 19 /* No such device */
+#define GF_ERROR_CODE_NOTDIR 20 /* Not a directory */
+#define GF_ERROR_CODE_ISDIR 21 /* Is a directory */
+#define GF_ERROR_CODE_INVAL 22 /* Invalid argument */
+#define GF_ERROR_CODE_NFILE 23 /* File table overflow */
+#define GF_ERROR_CODE_MFILE 24 /* Too many open files */
+#define GF_ERROR_CODE_NOTTY 25 /* Not a typewriter */
+#define GF_ERROR_CODE_TXTBSY 26 /* Text file busy */
+#define GF_ERROR_CODE_FBIG 27 /* File too large */
+#define GF_ERROR_CODE_NOSPC 28 /* No space left on device */
+#define GF_ERROR_CODE_SPIPE 29 /* Illegal seek */
+#define GF_ERROR_CODE_ROFS 30 /* Read-only file system */
+#define GF_ERROR_CODE_MLINK 31 /* Too many links */
+#define GF_ERROR_CODE_PIPE 32 /* Broken pipe */
+#define GF_ERROR_CODE_DOM 33 /* Math argument out of domain of func */
+#define GF_ERROR_CODE_RANGE 34 /* Math result not representable */
+#define GF_ERROR_CODE_DEADLK 35 /* Resource deadlock would occur */
+#define GF_ERROR_CODE_NAMETOOLONG 36 /* File name too long */
+#define GF_ERROR_CODE_NOLCK 37 /* No record locks available */
+#define GF_ERROR_CODE_NOSYS 38 /* Function not implemented */
+#define GF_ERROR_CODE_NOTEMPTY 39 /* Directory not empty */
+#define GF_ERROR_CODE_LOOP 40 /* Too many symbolic links encountered */
+
+#define GF_ERROR_CODE_NOMSG 42 /* No message of desired type */
+#define GF_ERROR_CODE_IDRM 43 /* Identifier removed */
+#define GF_ERROR_CODE_CHRNG 44 /* Channel number out of range */
+#define GF_ERROR_CODE_L2NSYNC 45 /* Level 2 not synchronized */
+#define GF_ERROR_CODE_L3HLT 46 /* Level 3 halted */
+#define GF_ERROR_CODE_L3RST 47 /* Level 3 reset */
+#define GF_ERROR_CODE_LNRNG 48 /* Link number out of range */
+#define GF_ERROR_CODE_UNATCH 49 /* Protocol driver not attached */
+#define GF_ERROR_CODE_NOCSI 50 /* No CSI structure available */
+#define GF_ERROR_CODE_L2HLT 51 /* Level 2 halted */
+#define GF_ERROR_CODE_BADE 52 /* Invalid exchange */
+#define GF_ERROR_CODE_BADR 53 /* Invalid request descriptor */
+#define GF_ERROR_CODE_XFULL 54 /* Exchange full */
+#define GF_ERROR_CODE_NOANO 55 /* No anode */
+#define GF_ERROR_CODE_BADRQC 56 /* Invalid request code */
+#define GF_ERROR_CODE_BADSLT 57 /* Invalid slot */
+#define GF_ERROR_CODE_BFONT 59 /* Bad font file format */
+#define GF_ERROR_CODE_NOSTR 60 /* Device not a stream */
+#define GF_ERROR_CODE_NODATA 61 /* No data available */
+#define GF_ERROR_CODE_TIME 62 /* Timer expired */
+#define GF_ERROR_CODE_NOSR 63 /* Out of streams resources */
+#define GF_ERROR_CODE_NONET 64 /* Machine is not on the network */
+#define GF_ERROR_CODE_NOPKG 65 /* Package not installed */
+#define GF_ERROR_CODE_REMOTE 66 /* Object is remote */
+#define GF_ERROR_CODE_NOLINK 67 /* Link has been severed */
+#define GF_ERROR_CODE_ADV 68 /* Advertise error */
+#define GF_ERROR_CODE_SRMNT 69 /* Srmount error */
+#define GF_ERROR_CODE_COMM 70 /* Communication error on send */
+#define GF_ERROR_CODE_PROTO 71 /* Protocol error */
+#define GF_ERROR_CODE_MULTIHOP 72 /* Multihop attempted */
+#define GF_ERROR_CODE_DOTDOT 73 /* RFS specific error */
+#define GF_ERROR_CODE_BADMSG 74 /* Not a data message */
+#define GF_ERROR_CODE_OVERFLOW 75 /* Value too large for defined data type */
+#define GF_ERROR_CODE_NOTUNIQ 76 /* Name not unique on network */
+#define GF_ERROR_CODE_BADFD 77 /* File descriptor in bad state */
+#define GF_ERROR_CODE_REMCHG 78 /* Remote address changed */
+#define GF_ERROR_CODE_LIBACC 79 /* Can not access a needed shared library */
+#define GF_ERROR_CODE_LIBBAD 80 /* Accessing a corrupted shared library */
+#define GF_ERROR_CODE_LIBSCN 81 /* .lib section in a.out corrupted */
+#define GF_ERROR_CODE_LIBMAX 82 /* Attempting to link in too many shared libraries */
+#define GF_ERROR_CODE_LIBEXEC 83 /* Cannot exec a shared library directly */
+#define GF_ERROR_CODE_ILSEQ 84 /* Illegal byte sequence */
+#define GF_ERROR_CODE_RESTART 85 /* Interrupted system call should be restarted */
+#define GF_ERROR_CODE_STRPIPE 86 /* Streams pipe error */
+#define GF_ERROR_CODE_USERS 87 /* Too many users */
+#define GF_ERROR_CODE_NOTSOCK 88 /* Socket operation on non-socket */
+#define GF_ERROR_CODE_DESTADDRREQ 89 /* Destination address required */
+#define GF_ERROR_CODE_MSGSIZE 90 /* Message too long */
+#define GF_ERROR_CODE_PROTOTYPE 91 /* Protocol wrong type for socket */
+#define GF_ERROR_CODE_NOPROTOOPT 92 /* Protocol not available */
+#define GF_ERROR_CODE_PROTONOSUPPORT 93 /* Protocol not supported */
+#define GF_ERROR_CODE_SOCKTNOSUPPORT 94 /* Socket type not supported */
+#define GF_ERROR_CODE_OPNOTSUPP 95 /* Operation not supported on transport endpoint */
+#define GF_ERROR_CODE_PFNOSUPPORT 96 /* Protocol family not supported */
+#define GF_ERROR_CODE_AFNOSUPPORT 97 /* Address family not supported by protocol */
+#define GF_ERROR_CODE_ADDRINUSE 98 /* Address already in use */
+#define GF_ERROR_CODE_ADDRNOTAVAIL 99 /* Cannot assign requested address */
+#define GF_ERROR_CODE_NETDOWN 100 /* Network is down */
+#define GF_ERROR_CODE_NETUNREACH 101 /* Network is unreachable */
+#define GF_ERROR_CODE_NETRESET 102 /* Network dropped connection because of reset */
+#define GF_ERROR_CODE_CONNABORTED 103 /* Software caused connection abort */
+#define GF_ERROR_CODE_CONNRESET 104 /* Connection reset by peer */
+#define GF_ERROR_CODE_NOBUFS 105 /* No buffer space available */
+#define GF_ERROR_CODE_ISCONN 106 /* Transport endpoint is already connected */
+#define GF_ERROR_CODE_NOTCONN 107 /* Transport endpoint is not connected */
+#define GF_ERROR_CODE_SHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
+#define GF_ERROR_CODE_TOOMANYREFS 109 /* Too many references: cannot splice */
+#define GF_ERROR_CODE_TIMEDOUT 110 /* Connection timed out */
+#define GF_ERROR_CODE_CONNREFUSED 111 /* Connection refused */
+#define GF_ERROR_CODE_HOSTDOWN 112 /* Host is down */
+#define GF_ERROR_CODE_HOSTUNREACH 113 /* No route to host */
+#define GF_ERROR_CODE_ALREADY 114 /* Operation already in progress */
+#define GF_ERROR_CODE_INPROGRESS 115 /* Operation now in progress */
+#define GF_ERROR_CODE_ALREADY 114 /* Operation already in progress */
+#define GF_ERROR_CODE_INPROGRESS 115 /* Operation now in progress */
+#define GF_ERROR_CODE_STALE 116 /* Stale NFS file handle */
+#define GF_ERROR_CODE_UCLEAN 117 /* Structure needs cleaning */
+#define GF_ERROR_CODE_NOTNAM 118 /* Not a XENIX named type file */
+#define GF_ERROR_CODE_NAVAIL 119 /* No XENIX semaphores available */
+#define GF_ERROR_CODE_ISNAM 120 /* Is a named type file */
+#define GF_ERROR_CODE_REMOTEIO 121 /* Remote I/O error */
+#define GF_ERROR_CODE_DQUOT 122 /* Quota exceeded */
+#define GF_ERROR_CODE_NOMEDIUM 123 /* No medium found */
+#define GF_ERROR_CODE_MEDIUMTYPE 124 /* Wrong medium type */
+#define GF_ERROR_CODE_CANCELED 125 /* Operation Canceled */
+#define GF_ERROR_CODE_NOKEY 126 /* Required key not available */
+#define GF_ERROR_CODE_KEYEXPIRED 127 /* Key has expired */
+#define GF_ERROR_CODE_KEYREVOKED 128 /* Key has been revoked */
+#define GF_ERROR_CODE_KEYREJECTED 129 /* Key was rejected by service */
+
+/* for robust mutexes */
+#define GF_ERROR_CODE_OWNERDEAD 130 /* Owner died */
+#define GF_ERROR_CODE_NOTRECOVERABLE 131 /* State not recoverable */
+
+
+
+/* Should never be seen by user programs */
+#define GF_ERROR_CODE_RESTARTSYS 512
+#define GF_ERROR_CODE_RESTARTNOINTR 513
+#define GF_ERROR_CODE_RESTARTNOHAND 514 /* restart if no handler.. */
+#define GF_ERROR_CODE_NOIOCTLCMD 515 /* No ioctl command */
+#define GF_ERROR_CODE_RESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
+
+/* Defined for the NFSv3 protocol */
+#define GF_ERROR_CODE_BADHANDLE 521 /* Illegal NFS file handle */
+#define GF_ERROR_CODE_NOTSYNC 522 /* Update synchronization mismatch */
+#define GF_ERROR_CODE_BADCOOKIE 523 /* Cookie is stale */
+#define GF_ERROR_CODE_NOTSUPP 524 /* Operation is not supported */
+#define GF_ERROR_CODE_TOOSMALL 525 /* Buffer or request is too small */
+#define GF_ERROR_CODE_SERVERFAULT 526 /* An untranslatable error occurred */
+#define GF_ERROR_CODE_BADTYPE 527 /* Type not supported by server */
+#define GF_ERROR_CODE_JUKEBOX 528 /* Request initiated, but will not complete before timeout */
+#define GF_ERROR_CODE_IOCBQUEUED 529 /* iocb queued, will get completion event */
+#define GF_ERROR_CODE_IOCBRETRY 530 /* iocb queued, will trigger a retry */
+
+/* Darwin OS X */
+#define GF_ERROR_CODE_NOPOLICY 701
+#define GF_ERROR_CODE_BADMACHO 702
+#define GF_ERROR_CODE_PWROFF 703
+#define GF_ERROR_CODE_DEVERR 704
+#define GF_ERROR_CODE_BADARCH 705
+#define GF_ERROR_CODE_BADEXEC 706
+#define GF_ERROR_CODE_SHLIBVERS 707
+
+
+
+/* Solaris */
+/* ENOTACTIVE 73 / * Facility is not active */
+#define GF_ERROR_CODE_NOTACTIVE 801
+/* ELOCKUNMAPPED 72 / * locked lock was unmapped */
+#define GF_ERROR_CODE_LOCKUNMAPPED 802
+
+/* BSD system */
+#define GF_ERROR_CODE_PROCLIM 901 /* Too many processes */
+#define GF_ERROR_CODE_BADRPC 902 /* RPC struct is bad */
+#define GF_ERROR_CODE_RPCMISMATCH 903 /* RPC version wrong */
+#define GF_ERROR_CODE_PROGUNAVAIL 904 /* RPC prog. not avail */
+#define GF_ERROR_CODE_PROGMISMATCH 905 /* Program version wrong */
+#define GF_ERROR_CODE_PROCUNAVAIL 905 /* Bad procedure for program */
+#define GF_ERROR_CODE_FTYPE 906 /* Inappropriate file type or format */
+#define GF_ERROR_CODE_AUTH 907 /* Authentication error */
+#define GF_ERROR_CODE_NEEDAUTH 908 /* Need authenticator */
+#define GF_ERROR_CODE_DOOFUS 909 /* Programming error */
+
+#define GF_ERROR_CODE_NOATTR GF_ERROR_CODE_NODATA /* Attribute not found */
+
+/* Either one of enodata or enoattr will be there in system */
+#ifndef ENOATTR
+#define ENOATTR ENODATA
+#endif /* ENOATTR */
+
+#ifndef ENODATA
+#define ENODATA ENOATTR
+#endif /* ENODATA */
+
+#ifndef EBADFD
+#define EBADFD EBADRPC
+#endif /* EBADFD */
+
+/* These functions are defined for all the OS flags, but content will
+ * be different for each OS flag.
+ */
+int32_t gf_errno_to_error (int32_t op_errno);
+int32_t gf_error_to_errno (int32_t error);
+
+#endif /* __COMPAT_ERRNO_H__ */
diff --git a/libglusterfs/src/compat.c b/libglusterfs/src/compat.c
new file mode 100644
index 000000000..71aeb32c7
--- /dev/null
+++ b/libglusterfs/src/compat.c
@@ -0,0 +1,383 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#ifdef GF_SOLARIS_HOST_OS
+#include "logging.h"
+#endif /* GF_SOLARIS_HOST_OS */
+
+#include "compat.h"
+#include "common-utils.h"
+
+#ifdef GF_DARWIN_HOST_OS
+
+#define GF_FINDER_INFO_XATTR "com.apple.FinderInfo"
+#define GF_RESOURCE_FORK_XATTR "com.apple.ResourceFork"
+#define GF_FINDER_INFO_SIZE 32
+
+static const char gf_finder_info_content[GF_FINDER_INFO_SIZE] = {
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+};
+
+
+int32_t
+gf_darwin_compat_listxattr (int len, dict_t *dict, int size)
+{
+ data_t *data = NULL;
+ if (len == -1)
+ len = 0;
+
+ data = dict_get (dict, GF_FINDER_INFO_XATTR);
+ if (!data) {
+ dict_set (dict, GF_FINDER_INFO_XATTR,
+ bin_to_data ((void *)gf_finder_info_content,
+ GF_FINDER_INFO_SIZE));
+ len += strlen (GF_FINDER_INFO_XATTR);
+ }
+
+ data = dict_get (dict, GF_RESOURCE_FORK_XATTR);
+ if (!data) {
+ dict_set (dict, GF_RESOURCE_FORK_XATTR, str_to_data (""));
+ len += strlen (GF_RESOURCE_FORK_XATTR);
+ }
+
+ return len;
+}
+
+int32_t
+gf_darwin_compat_getxattr (const char *key, dict_t *dict)
+{
+ data_t *data = NULL;
+
+ if (strcmp(key, GF_FINDER_INFO_XATTR) == 0) {
+ data = dict_get (dict, GF_FINDER_INFO_XATTR);
+ if (!data) {
+ dict_set (dict, GF_FINDER_INFO_XATTR,
+ bin_to_data ((void *)gf_finder_info_content,
+ GF_FINDER_INFO_SIZE));
+ return GF_FINDER_INFO_SIZE;
+ }
+ return 0;
+ }
+
+ if (strcmp(key, GF_RESOURCE_FORK_XATTR) == 0) {
+ data = dict_get (dict, GF_RESOURCE_FORK_XATTR);
+ if (!data) {
+ /* Always null */
+ dict_set (dict, GF_RESOURCE_FORK_XATTR,
+ str_to_data (""));
+ return 0;
+ }
+ return 0;
+ }
+ return -1;
+}
+
+
+int32_t
+gf_darwin_compat_setxattr (dict_t *dict)
+{
+ data_t *data = NULL;
+
+ data = dict_get (dict, GF_FINDER_INFO_XATTR);
+ if (data)
+ return 0;
+ data = dict_get (dict, GF_RESOURCE_FORK_XATTR);
+ if (data)
+ return 0;
+
+ return -1;
+}
+
+#endif /* DARWIN */
+
+
+#ifdef GF_SOLARIS_HOST_OS
+
+int
+solaris_fsetxattr(int fd,
+ const char* key,
+ const char *value,
+ size_t size,
+ int flags)
+{
+ int attrfd = -1;
+ int ret = 0;
+
+ attrfd = openat (fd, key, flags|O_CREAT|O_WRONLY|O_XATTR, 0777);
+ if (attrfd >= 0) {
+ ftruncate (attrfd, 0);
+ ret = write (attrfd, value, size);
+ close (attrfd);
+ } else {
+ if (errno != ENOENT)
+ gf_log ("libglusterfs", GF_LOG_ERROR,
+ "Couldn't set extended attribute for %d (%d)",
+ fd, errno);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int
+solaris_fgetxattr(int fd,
+ const char* key,
+ char *value,
+ size_t size)
+{
+ int attrfd = -1;
+ int ret = 0;
+
+ attrfd = openat (fd, key, O_RDONLY|O_XATTR);
+ if (attrfd >= 0) {
+ if (size == 0) {
+ struct stat buf;
+ fstat (attrfd, &buf);
+ ret = buf.st_size;
+ } else {
+ ret = read (attrfd, value, size);
+ }
+ close (attrfd);
+ } else {
+ if (errno == ENOENT)
+ errno = ENODATA;
+ if (errno != ENOENT)
+ gf_log ("libglusterfs", GF_LOG_DEBUG,
+ "Couldn't read extended attribute for the file %d (%d)",
+ fd, errno);
+ return -1;
+ }
+
+ return ret;
+}
+
+
+int
+solaris_setxattr(const char *path,
+ const char* key,
+ const char *value,
+ size_t size,
+ int flags)
+{
+ int attrfd = -1;
+ int ret = 0;
+
+ attrfd = attropen (path, key, flags|O_CREAT|O_WRONLY, 0777);
+ if (attrfd >= 0) {
+ ftruncate (attrfd, 0);
+ ret = write (attrfd, value, size);
+ close (attrfd);
+ } else {
+ if (errno != ENOENT)
+ gf_log ("libglusterfs", GF_LOG_ERROR,
+ "Couldn't set extended attribute for %s (%d)",
+ path, errno);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int
+solaris_listxattr(const char *path,
+ char *list,
+ size_t size)
+{
+ int attrdirfd = -1;
+ ssize_t len = 0;
+ DIR *dirptr = NULL;
+ struct dirent *dent = NULL;
+ int newfd = -1;
+
+ attrdirfd = attropen (path, ".", O_RDONLY, 0);
+ if (attrdirfd >= 0) {
+ newfd = dup(attrdirfd);
+ dirptr = fdopendir(newfd);
+ if (dirptr) {
+ while ((dent = readdir(dirptr))) {
+ size_t listlen = strlen(dent->d_name);
+ if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) {
+ /* we don't want "." and ".." here */
+ continue;
+ }
+ if (size == 0) {
+ /* return the current size of the list of extended attribute names*/
+ len += listlen + 1;
+ } else {
+ /* check size and copy entrie + nul into list. */
+ if ((len + listlen + 1) > size) {
+ errno = ERANGE;
+ len = -1;
+ break;
+ } else {
+ strncpy(list + len, dent->d_name, listlen);
+ len += listlen;
+ list[len] = '\0';
+ ++len;
+ }
+ }
+ }
+
+ if (closedir(dirptr) == -1) {
+ close (attrdirfd);
+ return -1;
+ }
+ } else {
+ close (attrdirfd);
+ return -1;
+ }
+ close (attrdirfd);
+ }
+ return len;
+}
+
+int
+solaris_removexattr(const char *path,
+ const char* key)
+{
+ int ret = -1;
+ int attrfd = attropen (path, ".", O_RDONLY, 0);
+ if (attrfd >= 0) {
+ ret = unlinkat (attrfd, key, 0);
+ close (attrfd);
+ } else {
+ if (errno == ENOENT)
+ errno = ENODATA;
+ return -1;
+ }
+
+ return ret;
+}
+
+int
+solaris_getxattr(const char *path,
+ const char* key,
+ char *value,
+ size_t size)
+{
+ int attrfd = -1;
+ int ret = 0;
+
+ attrfd = attropen (path, key, O_RDONLY, 0);
+ if (attrfd >= 0) {
+ if (size == 0) {
+ struct stat buf;
+ fstat (attrfd, &buf);
+ ret = buf.st_size;
+ } else {
+ ret = read (attrfd, value, size);
+ }
+ close (attrfd);
+ } else {
+ if (errno == ENOENT)
+ errno = ENODATA;
+ if (errno != ENOENT)
+ gf_log ("libglusterfs", GF_LOG_DEBUG,
+ "Couldn't read extended attribute for the file %s (%d)",
+ path, errno);
+ return -1;
+ }
+ return ret;
+}
+
+
+int
+asprintf(char **string_ptr, const char *format, ...)
+{
+ va_list arg;
+ char *str;
+ int size;
+ int rv;
+
+ if (!string_ptr || !format)
+ return -1;
+
+ va_start(arg, format);
+ size = vsnprintf(NULL, 0, format, arg);
+ size++;
+ va_start(arg, format);
+ str = MALLOC(size);
+ if (str == NULL) {
+ va_end(arg);
+ /*
+ * Strictly speaking, GNU asprintf doesn't do this,
+ * but the caller isn't checking the return value.
+ */
+ gf_log ("libglusterfs", GF_LOG_CRITICAL, "failed to allocate memory");
+ return -1;
+ }
+ rv = vsnprintf(str, size, format, arg);
+ va_end(arg);
+
+ *string_ptr = str;
+ return (rv);
+}
+
+char* strsep(char** str, const char* delims)
+{
+ char* token;
+
+ if (*str==NULL) {
+ /* No more tokens */
+ return NULL;
+ }
+
+ token=*str;
+ while (**str!='\0') {
+ if (strchr(delims,**str)!=NULL) {
+ **str='\0';
+ (*str)++;
+ return token;
+ }
+ (*str)++;
+ }
+ /* There is no other token */
+ *str=NULL;
+ return token;
+}
+
+#endif /* GF_SOLARIS_HOST_OS */
+
+#ifndef HAVE_STRNLEN
+size_t
+strnlen(const char *string, size_t maxlen)
+{
+ int len = 0;
+ while ((len < maxlen) && string[len])
+ len++;
+ return len;
+}
+#endif /* STRNLEN */
diff --git a/libglusterfs/src/compat.h b/libglusterfs/src/compat.h
new file mode 100644
index 000000000..1e8ccaab1
--- /dev/null
+++ b/libglusterfs/src/compat.h
@@ -0,0 +1,356 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+#ifndef __COMPAT_H__
+#define __COMPAT_H__
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include "dict.h"
+
+#ifndef LLONG_MAX
+#define LLONG_MAX LONG_LONG_MAX /* compat with old gcc */
+#endif /* LLONG_MAX */
+
+
+#ifdef GF_LINUX_HOST_OS
+
+#define UNIX_PATH_MAX 108
+
+#include <sys/un.h>
+#include <linux/limits.h>
+#include <sys/xattr.h>
+#include <endian.h>
+
+
+#ifndef HAVE_LLISTXATTR
+
+/* This part is valid only incase of old glibc which doesn't support
+ * 'llistxattr()' system calls.
+ */
+
+#define lremovexattr(path,key) removexattr(path,key)
+#define llistxattr(path,key,size) listxattr(path,key,size)
+#define lgetxattr(path, key, value, size) getxattr(path,key,value,size)
+#define lsetxattr(path,key,value,size,flags) setxattr(path,key,value,size,flags)
+
+#endif /* HAVE_LLISTXATTR */
+#endif /* GF_LINUX_HOST_OS */
+
+#ifdef GF_BSD_HOST_OS
+/* In case of FreeBSD */
+
+#define UNIX_PATH_MAX 104
+#include <sys/types.h>
+
+#include <sys/un.h>
+#include <sys/endian.h>
+#include <sys/extattr.h>
+#include <limits.h>
+
+#include <libgen.h>
+
+enum {
+ ATTR_CREATE = 1,
+#define XATTR_CREATE ATTR_CREATE
+ ATTR_REPLACE = 2
+#define XATTR_REPLACE ATTR_REPLACE
+};
+
+
+#ifndef sighandler_t
+#define sighandler_t sig_t
+#endif
+
+#ifndef ino64_t
+#define ino64_t ino_t
+#endif
+
+#ifndef EUCLEAN
+#define EUCLEAN 0
+#endif
+
+#include <netinet/in.h>
+#ifndef s6_addr16
+#define s6_addr16 __u6_addr.__u6_addr16
+#endif
+#ifndef s6_addr32
+#define s6_addr32 __u6_addr.__u6_addr32
+#endif
+
+/* Posix dictates NAME_MAX to be used */
+# ifndef NAME_MAX
+# ifdef MAXNAMLEN
+# define NAME_MAX MAXNAMLEN
+# else
+# define NAME_MAX 255
+# endif
+# endif
+
+#define lremovexattr(path,key) extattr_delete_link(path, EXTATTR_NAMESPACE_USER, key)
+#define llistxattr(path,key,size) extattr_list_link(path, EXTATTR_NAMESPACE_USER, key, size)
+#define lgetxattr(path, key, value, size) extattr_get_link(path, EXTATTR_NAMESPACE_USER, key, value, size)
+#define lsetxattr(path,key,value,size,flags) extattr_set_link(path, EXTATTR_NAMESPACE_USER, key, value, size)
+#define fgetxattr(fd,key,value,size) extattr_get_fd(fd, EXTATTR_NAMESPACE_USER, key, value, size)
+#define fsetxattr(fd,key,value,size,flag) extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, key, value, size)
+
+
+#define F_GETLK64 F_GETLK
+#define F_SETLK64 F_SETLK
+#define F_SETLKW64 F_SETLKW
+
+#endif /* GF_BSD_HOST_OS */
+
+#ifdef GF_DARWIN_HOST_OS
+
+#define UNIX_PATH_MAX 104
+#include <sys/types.h>
+
+#include <sys/un.h>
+#include <machine/endian.h>
+#include <sys/xattr.h>
+#include <limits.h>
+
+#include <libgen.h>
+
+
+#if __DARWIN_64_BIT_INO_T == 0
+# error '64 bit ino_t is must for GlusterFS to work, Compile with "CFLAGS=-D__DARWIN_64_BIT_INO_T"'
+#endif /* __DARWIN_64_BIT_INO_T */
+
+
+#if __DARWIN_64_BIT_INO_T == 0
+# error '64 bit ino_t is must for GlusterFS to work, Compile with "CFLAGS=-D__DARWIN_64_BIT_INO_T"'
+#endif /* __DARWIN_64_BIT_INO_T */
+
+#ifndef sighandler_t
+#define sighandler_t sig_t
+#endif
+
+#ifndef EUCLEAN
+#define EUCLEAN 0
+#endif
+
+#include <netinet/in.h>
+#ifndef s6_addr16
+#define s6_addr16 __u6_addr.__u6_addr16
+#endif
+#ifndef s6_addr32
+#define s6_addr32 __u6_addr.__u6_addr32
+#endif
+
+/* Posix dictates NAME_MAX to be used */
+# ifndef NAME_MAX
+# ifdef MAXNAMLEN
+# define NAME_MAX MAXNAMLEN
+# else
+# define NAME_MAX 255
+# endif
+# endif
+
+#define llistxattr(path,key,size) listxattr(path,key,size,XATTR_NOFOLLOW)
+#define lgetxattr(path,key,value,size) getxattr(path,key,value,size,0,XATTR_NOFOLLOW)
+#define lsetxattr(path,key,value,size,flags) setxattr(path,key,value,size,0,flags|XATTR_NOFOLLOW)
+#define lremovexattr(path,key) removexattr(path,key,XATTR_NOFOLLOW)
+#define fgetxattr(path,key,value,size) fgetxattr(path,key,value,size,0,0)
+#define fsetxattr(path,key,value,size,flag) fsetxattr(path,key,value,size,0,flag)
+
+#define F_GETLK64 F_GETLK
+#define F_SETLK64 F_SETLK
+#define F_SETLKW64 F_SETLKW
+
+int32_t gf_darwin_compat_listxattr (int len, dict_t *dict, int size);
+int32_t gf_darwin_compat_getxattr (const char *key, dict_t *dict);
+int32_t gf_darwin_compat_setxattr (dict_t *dict);
+
+#endif /* GF_DARWIN_HOST_OS */
+
+#ifdef GF_SOLARIS_HOST_OS
+
+#define UNIX_PATH_MAX 108
+#define EUCLEAN 117
+
+#include <sys/un.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include <libgen.h>
+#include <sys/mkdev.h>
+
+#ifndef lchmod
+#define lchmod chmod
+#endif
+
+enum {
+ ATTR_CREATE = 1,
+#define XATTR_CREATE ATTR_CREATE
+ ATTR_REPLACE = 2
+#define XATTR_REPLACE ATTR_REPLACE
+};
+
+/* This patch is not present in Solaris 10 and before */
+#ifndef dirfd
+#define dirfd(dirp) ((dirp)->dd_fd)
+#endif
+
+/* Posix dictates NAME_MAX to be used */
+# ifndef NAME_MAX
+# ifdef MAXNAMLEN
+# define NAME_MAX MAXNAMLEN
+# else
+# define NAME_MAX 255
+# endif
+# endif
+
+#include <netinet/in.h>
+#ifndef s6_addr16
+#define S6_ADDR16(x) ((uint16_t*) ((char*)&(x).s6_addr))
+#endif
+#ifndef s6_addr32
+#define s6_addr32 _S6_un._S6_u32
+#endif
+
+#define lremovexattr(path,key) solaris_removexattr(path,key)
+#define llistxattr(path,key,size) solaris_listxattr(path,key,size)
+#define lgetxattr(path,key,value,size) solaris_getxattr(path,key,value,size)
+#define lsetxattr(path,key,value,size,flags) solaris_setxattr(path,key,value,size,flags)
+#define fgetxattr(fd,key,value,size) solaris_fgetxattr(fd,key,value,size)
+#define fsetxattr(fd,key,value,size,flags) solaris_fsetxattr(fd,key,value,size,flags)
+#define lutimes(filename,times) utimes(filename,times)
+
+int asprintf(char **string_ptr, const char *format, ...);
+char* strsep(char** str, const char* delims);
+int solaris_listxattr(const char *path, char *list, size_t size);
+int solaris_removexattr(const char *path, const char* key);
+int solaris_getxattr(const char *path, const char* key,
+ char *value, size_t size);
+int solaris_setxattr(const char *path, const char* key, const char *value,
+ size_t size, int flags);
+int solaris_fgetxattr(int fd, const char* key,
+ char *value, size_t size);
+int solaris_fsetxattr(int fd, const char* key, const char *value,
+ size_t size, int flags);
+
+#endif /* GF_SOLARIS_HOST_OS */
+
+#ifndef HAVE_ARGP
+#include "argp.h"
+#else
+#include <argp.h>
+#endif /* HAVE_ARGP */
+
+#ifndef HAVE_STRNLEN
+size_t strnlen(const char *string, size_t maxlen);
+#endif /* STRNLEN */
+
+#ifndef strdupa
+#define strdupa(s) \
+ (__extension__ \
+ ({ \
+ __const char *__old = (s); \
+ size_t __len = strlen (__old) + 1; \
+ char *__new = (char *) __builtin_alloca (__len); \
+ (char *) memcpy (__new, __old, __len); \
+ }))
+#endif
+
+#define ALIGN(x) (((x) + sizeof (uint64_t) - 1) & ~(sizeof (uint64_t) - 1))
+
+#include <sys/types.h>
+#include <dirent.h>
+
+static inline int32_t
+dirent_size (struct dirent *entry)
+{
+#ifdef GF_BSD_HOST_OS
+ return ALIGN (24 /* FIX MEEEE!!! */ + entry->d_namlen);
+#endif
+#ifdef GF_DARWIN_HOST_OS
+ return ALIGN (24 /* FIX MEEEE!!! */ + entry->d_namlen);
+#endif
+#ifdef GF_LINUX_HOST_OS
+ return ALIGN (24 /* FIX MEEEE!!! */ + entry->d_reclen);
+#endif
+#ifdef GF_SOLARIS_HOST_OS
+ return ALIGN (24 /* FIX MEEEE!!! */ + entry->d_reclen);
+#endif
+}
+
+
+static inline int32_t
+gf_compat_getxattr (const char *key, dict_t *dict)
+{
+#ifdef GF_DARWIN_HOST_OS
+ return gf_darwin_compat_getxattr (key, dict);
+#endif
+ return -1;
+}
+
+
+static inline int32_t
+gf_compat_setxattr (dict_t *dict)
+{
+#ifdef GF_DARWIN_HOST_OS
+ return gf_darwin_compat_setxattr (dict);
+#endif
+ return -1;
+}
+
+
+static inline int32_t
+gf_compat_listxattr (int len, dict_t *dict, int size)
+{
+#ifdef GF_DARWIN_HOST_OS
+ return gf_darwin_compat_listxattr (len, dict, size);
+#endif
+ return len;
+}
+
+
+#ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
+/* Linux, Solaris, Cygwin */
+#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atim.tv_nsec)
+#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctim.tv_nsec)
+#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtim.tv_nsec)
+#define ST_ATIM_NSEC_SET(stbuf, val) ((stbuf)->st_atim.tv_nsec = (val))
+#define ST_MTIM_NSEC_SET(stbuf, val) ((stbuf)->st_mtim.tv_nsec = (val))
+#define ST_CTIM_NSEC_SET(stbuf, val) ((stbuf)->st_ctim.tv_nsec = (val))
+#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC)
+/* FreeBSD, NetBSD */
+#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atimespec.tv_nsec)
+#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctimespec.tv_nsec)
+#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtimespec.tv_nsec)
+#define ST_ATIM_NSEC_SET(stbuf, val) ((stbuf)->st_atimespec.tv_nsec = (val))
+#define ST_MTIM_NSEC_SET(stbuf, val) ((stbuf)->st_mtimespec.tv_nsec = (val))
+#define ST_CTIM_NSEC_SET(stbuf, val) ((stbuf)->st_ctimespec.tv_nsec = (val))
+#else
+#define ST_ATIM_NSEC(stbuf) (0)
+#define ST_CTIM_NSEC(stbuf) (0)
+#define ST_MTIM_NSEC(stbuf) (0)
+#define ST_ATIM_NSEC_SET(stbuf, val) do { } while (0);
+#define ST_MTIM_NSEC_SET(stbuf, val) do { } while (0);
+#define ST_CTIM_NSEC_SET(stbuf, val) do { } while (0);
+#endif
+
+#endif /* __COMPAT_H__ */
diff --git a/libglusterfs/src/defaults.c b/libglusterfs/src/defaults.c
new file mode 100644
index 000000000..575e3d86e
--- /dev/null
+++ b/libglusterfs/src/defaults.c
@@ -0,0 +1,1388 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+/* libglusterfs/src/defaults.c:
+ This file contains functions, which are used to fill the 'fops' and 'mops'
+ structures in the xlator structures, if they are not written. Here, all the
+ function calls are plainly forwared to the first child of the xlator, and
+ all the *_cbk function does plain STACK_UNWIND of the frame, and returns.
+
+ All the functions are plain enough to understand.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "xlator.h"
+
+static int32_t
+default_lookup_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf,
+ dict_t *dict)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ inode,
+ buf,
+ dict);
+ return 0;
+}
+
+int32_t
+default_lookup (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ dict_t *xattr_req)
+{
+ STACK_WIND (frame,
+ default_lookup_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->lookup,
+ loc,
+ xattr_req);
+ return 0;
+}
+
+
+int32_t
+default_forget (xlator_t *this,
+ inode_t *inode)
+{
+ return 0;
+}
+
+static int32_t
+default_stat_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ buf);
+ return 0;
+}
+
+int32_t
+default_stat (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc)
+{
+ STACK_WIND (frame,
+ default_stat_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->stat,
+ loc);
+ return 0;
+}
+
+static int32_t
+default_chmod_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ buf);
+ return 0;
+}
+
+int32_t
+default_chmod (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ mode_t mode)
+{
+ STACK_WIND (frame,
+ default_chmod_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->chmod,
+ loc,
+ mode);
+ return 0;
+}
+
+
+static int32_t
+default_fchmod_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ buf);
+ return 0;
+}
+
+int32_t
+default_fchmod (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ mode_t mode)
+{
+ STACK_WIND (frame,
+ default_fchmod_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->fchmod,
+ fd,
+ mode);
+ return 0;
+}
+
+static int32_t
+default_chown_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ buf);
+ return 0;
+}
+
+int32_t
+default_chown (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ uid_t uid,
+ gid_t gid)
+{
+ STACK_WIND (frame,
+ default_chown_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->chown,
+ loc,
+ uid,
+ gid);
+ return 0;
+}
+
+static int32_t
+default_fchown_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ buf);
+ return 0;
+}
+
+int32_t
+default_fchown (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ uid_t uid,
+ gid_t gid)
+{
+ STACK_WIND (frame,
+ default_fchown_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->fchown,
+ fd,
+ uid,
+ gid);
+ return 0;
+}
+
+static int32_t
+default_truncate_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ buf);
+ return 0;
+}
+
+int32_t
+default_truncate (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ off_t offset)
+{
+ STACK_WIND (frame,
+ default_truncate_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->truncate,
+ loc,
+ offset);
+ return 0;
+}
+
+static int32_t
+default_ftruncate_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ buf);
+ return 0;
+}
+
+int32_t
+default_ftruncate (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ off_t offset)
+{
+ STACK_WIND (frame,
+ default_ftruncate_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->ftruncate,
+ fd,
+ offset);
+ return 0;
+}
+
+int32_t
+default_utimens_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ buf);
+ return 0;
+}
+
+
+int32_t
+default_utimens (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ struct timespec tv[2])
+{
+ STACK_WIND (frame,
+ default_utimens_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->utimens,
+ loc,
+ tv);
+ return 0;
+}
+
+static int32_t
+default_access_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno);
+ return 0;
+}
+
+int32_t
+default_access (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t mask)
+{
+ STACK_WIND (frame,
+ default_access_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->access,
+ loc,
+ mask);
+ return 0;
+}
+
+
+static int32_t
+default_readlink_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ const char *path)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ path);
+ return 0;
+}
+
+int32_t
+default_readlink (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ size_t size)
+{
+ STACK_WIND (frame,
+ default_readlink_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->readlink,
+ loc,
+ size);
+ return 0;
+}
+
+
+static int32_t
+default_mknod_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ inode,
+ buf);
+ return 0;
+}
+
+int32_t
+default_mknod (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ mode_t mode,
+ dev_t rdev)
+{
+ STACK_WIND (frame,
+ default_mknod_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->mknod,
+ loc, mode, rdev);
+ return 0;
+}
+
+static int32_t
+default_mkdir_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ inode,
+ buf);
+ return 0;
+}
+
+int32_t
+default_mkdir (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ mode_t mode)
+{
+ STACK_WIND (frame,
+ default_mkdir_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->mkdir,
+ loc, mode);
+ return 0;
+}
+
+static int32_t
+default_unlink_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ STACK_UNWIND (frame, op_ret, op_errno);
+ return 0;
+}
+
+int32_t
+default_unlink (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc)
+{
+ STACK_WIND (frame,
+ default_unlink_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->unlink,
+ loc);
+ return 0;
+}
+
+static int32_t
+default_rmdir_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno);
+ return 0;
+}
+
+int32_t
+default_rmdir (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc)
+{
+ STACK_WIND (frame,
+ default_rmdir_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->rmdir,
+ loc);
+ return 0;
+}
+
+
+static int32_t
+default_symlink_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf)
+{
+ STACK_UNWIND (frame, op_ret, op_errno, inode, buf);
+ return 0;
+}
+
+int32_t
+default_symlink (call_frame_t *frame,
+ xlator_t *this,
+ const char *linkpath,
+ loc_t *loc)
+{
+ STACK_WIND (frame,
+ default_symlink_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->symlink,
+ linkpath, loc);
+ return 0;
+}
+
+
+static int32_t
+default_rename_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ STACK_UNWIND (frame, op_ret, op_errno, buf);
+ return 0;
+}
+
+int32_t
+default_rename (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *oldloc,
+ loc_t *newloc)
+{
+ STACK_WIND (frame,
+ default_rename_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->rename,
+ oldloc, newloc);
+ return 0;
+}
+
+
+static int32_t
+default_link_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf)
+{
+ STACK_UNWIND (frame, op_ret, op_errno, inode, buf);
+ return 0;
+}
+
+int32_t
+default_link (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *oldloc,
+ loc_t *newloc)
+{
+ STACK_WIND (frame,
+ default_link_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->link,
+ oldloc, newloc);
+ return 0;
+}
+
+
+static int32_t
+default_create_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ fd_t *fd,
+ inode_t *inode,
+ struct stat *buf)
+{
+ STACK_UNWIND (frame, op_ret, op_errno, fd, inode, buf);
+ return 0;
+}
+
+int32_t
+default_create (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t flags,
+ mode_t mode, fd_t *fd)
+{
+ STACK_WIND (frame, default_create_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->create,
+ loc, flags, mode, fd);
+ return 0;
+}
+
+static int32_t
+default_open_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ fd_t *fd)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ fd);
+ return 0;
+}
+
+int32_t
+default_open (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t flags, fd_t *fd)
+{
+ STACK_WIND (frame,
+ default_open_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->open,
+ loc, flags, fd);
+ return 0;
+}
+
+static int32_t
+default_readv_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct iovec *vector,
+ int32_t count,
+ struct stat *stbuf)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ vector,
+ count,
+ stbuf);
+ return 0;
+}
+
+int32_t
+default_readv (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ size_t size,
+ off_t offset)
+{
+ STACK_WIND (frame,
+ default_readv_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->readv,
+ fd,
+ size,
+ offset);
+ return 0;
+}
+
+
+static int32_t
+default_writev_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *stbuf)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ stbuf);
+ return 0;
+}
+
+int32_t
+default_writev (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ struct iovec *vector,
+ int32_t count,
+ off_t off)
+{
+ STACK_WIND (frame,
+ default_writev_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->writev,
+ fd,
+ vector,
+ count,
+ off);
+ return 0;
+}
+
+static int32_t
+default_flush_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno);
+ return 0;
+}
+
+int32_t
+default_flush (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd)
+{
+ STACK_WIND (frame,
+ default_flush_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->flush,
+ fd);
+ return 0;
+}
+
+
+static int32_t
+default_fsync_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno);
+ return 0;
+}
+
+int32_t
+default_fsync (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t flags)
+{
+ STACK_WIND (frame,
+ default_fsync_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->fsync,
+ fd,
+ flags);
+ return 0;
+}
+
+static int32_t
+default_fstat_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ buf);
+ return 0;
+}
+
+int32_t
+default_fstat (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd)
+{
+ STACK_WIND (frame,
+ default_fstat_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->fstat,
+ fd);
+ return 0;
+}
+
+static int32_t
+default_opendir_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ fd_t *fd)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ fd);
+ return 0;
+}
+
+int32_t
+default_opendir (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc, fd_t *fd)
+{
+ STACK_WIND (frame,
+ default_opendir_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->opendir,
+ loc, fd);
+ return 0;
+}
+
+
+static int32_t
+default_getdents_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ dir_entry_t *entries,
+ int32_t count)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ entries,
+ count);
+ return 0;
+}
+
+int32_t
+default_getdents (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ size_t size,
+ off_t offset,
+ int32_t flag)
+{
+ STACK_WIND (frame,
+ default_getdents_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->getdents,
+ fd,
+ size,
+ offset,
+ flag);
+ return 0;
+}
+
+
+static int32_t
+default_setdents_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno);
+ return 0;
+}
+
+int32_t
+default_setdents (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t flags,
+ dir_entry_t *entries,
+ int32_t count)
+{
+ STACK_WIND (frame,
+ default_setdents_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->setdents,
+ fd,
+ flags,
+ entries,
+ count);
+ return 0;
+}
+
+
+static int32_t
+default_fsyncdir_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno);
+ return 0;
+}
+
+int32_t
+default_fsyncdir (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t flags)
+{
+ STACK_WIND (frame,
+ default_fsyncdir_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->fsyncdir,
+ fd,
+ flags);
+ return 0;
+}
+
+
+static int32_t
+default_statfs_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct statvfs *buf)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ buf);
+ return 0;
+}
+
+int32_t
+default_statfs (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc)
+{
+ STACK_WIND (frame,
+ default_statfs_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->statfs,
+ loc);
+ return 0;
+}
+
+
+static int32_t
+default_setxattr_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno);
+ return 0;
+}
+
+int32_t
+default_setxattr (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ dict_t *dict,
+ int32_t flags)
+{
+ STACK_WIND (frame,
+ default_setxattr_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->setxattr,
+ loc,
+ dict,
+ flags);
+ return 0;
+}
+
+static int32_t
+default_getxattr_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ dict_t *dict)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ dict);
+ return 0;
+}
+
+int32_t
+default_getxattr (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ const char *name)
+{
+ STACK_WIND (frame,
+ default_getxattr_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->getxattr,
+ loc,
+ name);
+ return 0;
+}
+
+int32_t
+default_xattrop_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ dict_t *dict)
+{
+ STACK_UNWIND (frame, op_ret, op_errno, dict);
+ return 0;
+}
+
+int32_t
+default_xattrop (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ gf_xattrop_flags_t flags,
+ dict_t *dict)
+{
+ STACK_WIND (frame,
+ default_xattrop_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->xattrop,
+ loc,
+ flags,
+ dict);
+ return 0;
+}
+
+int32_t
+default_fxattrop_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ dict_t *dict)
+{
+ STACK_UNWIND (frame, op_ret, op_errno, dict);
+ return 0;
+}
+
+int32_t
+default_fxattrop (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ gf_xattrop_flags_t flags,
+ dict_t *dict)
+{
+ STACK_WIND (frame,
+ default_fxattrop_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->fxattrop,
+ fd,
+ flags,
+ dict);
+ return 0;
+}
+
+
+static int32_t
+default_removexattr_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno);
+ return 0;
+}
+
+int32_t
+default_removexattr (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ const char *name)
+{
+ STACK_WIND (frame,
+ default_removexattr_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->removexattr,
+ loc,
+ name);
+ return 0;
+}
+
+static int32_t
+default_lk_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct flock *lock)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ lock);
+ return 0;
+}
+
+int32_t
+default_lk (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t cmd,
+ struct flock *lock)
+{
+ STACK_WIND (frame,
+ default_lk_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->lk,
+ fd,
+ cmd,
+ lock);
+ return 0;
+}
+
+
+static int32_t
+default_inodelk_cbk (call_frame_t *frame, void *cookie,
+ xlator_t *this, int32_t op_ret, int32_t op_errno)
+
+{
+ STACK_UNWIND (frame, op_ret, op_errno);
+ return 0;
+}
+
+
+int32_t
+default_inodelk (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, int32_t cmd, struct flock *lock)
+{
+ STACK_WIND (frame,
+ default_inodelk_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->inodelk,
+ loc, cmd, lock);
+ return 0;
+}
+
+
+static int32_t
+default_finodelk_cbk (call_frame_t *frame, void *cookie,
+ xlator_t *this, int32_t op_ret, int32_t op_errno)
+
+{
+ STACK_UNWIND (frame, op_ret, op_errno);
+ return 0;
+}
+
+
+int32_t
+default_finodelk (call_frame_t *frame, xlator_t *this,
+ fd_t *fd, int32_t cmd, struct flock *lock)
+{
+ STACK_WIND (frame,
+ default_finodelk_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->finodelk,
+ fd, cmd, lock);
+ return 0;
+}
+
+
+static int32_t
+default_entrylk_cbk (call_frame_t *frame, void *cookie,
+ xlator_t *this, int32_t op_ret, int32_t op_errno)
+
+{
+ STACK_UNWIND (frame, op_ret, op_errno);
+ return 0;
+}
+
+int32_t
+default_entrylk (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, const char *basename,
+ entrylk_cmd cmd, entrylk_type type)
+{
+ STACK_WIND (frame, default_entrylk_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->entrylk,
+ loc, basename, cmd, type);
+ return 0;
+}
+
+static int32_t
+default_fentrylk_cbk (call_frame_t *frame, void *cookie,
+ xlator_t *this, int32_t op_ret, int32_t op_errno)
+
+{
+ STACK_UNWIND (frame, op_ret, op_errno);
+ return 0;
+}
+
+int32_t
+default_fentrylk (call_frame_t *frame, xlator_t *this,
+ fd_t *fd, const char *basename,
+ entrylk_cmd cmd, entrylk_type type)
+{
+ STACK_WIND (frame, default_fentrylk_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->fentrylk,
+ fd, basename, cmd, type);
+ return 0;
+}
+
+
+/* Management operations */
+
+static int32_t
+default_stats_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct xlator_stats *stats)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ stats);
+ return 0;
+}
+
+
+int32_t
+default_stats (call_frame_t *frame,
+ xlator_t *this,
+ int32_t flags)
+{
+ STACK_WIND (frame,
+ default_stats_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->mops->stats,
+ flags);
+ return 0;
+}
+
+static int32_t
+default_getspec_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ char *spec_data)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ spec_data);
+ return 0;
+}
+
+
+int32_t
+default_getspec (call_frame_t *frame,
+ xlator_t *this,
+ const char *key,
+ int32_t flags)
+{
+ STACK_WIND (frame,
+ default_getspec_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->mops->getspec,
+ key, flags);
+ return 0;
+}
+
+
+static int32_t
+default_checksum_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ uint8_t *file_checksum,
+ uint8_t *dir_checksum)
+{
+ STACK_UNWIND (frame,
+ op_ret,
+ op_errno,
+ file_checksum,
+ dir_checksum);
+ return 0;
+}
+
+
+int32_t
+default_checksum (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t flag)
+{
+ STACK_WIND (frame,
+ default_checksum_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->checksum,
+ loc,
+ flag);
+ return 0;
+}
+
+
+int32_t
+default_readdir_cbk (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ gf_dirent_t *entries)
+{
+ STACK_UNWIND (frame, op_ret, op_errno, entries);
+ return 0;
+}
+
+
+int32_t
+default_readdir (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ size_t size,
+ off_t off)
+{
+ STACK_WIND (frame,
+ default_readdir_cbk,
+ FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->readdir,
+ fd, size, off);
+ return 0;
+}
+
+/* notify */
+int32_t
+default_notify (xlator_t *this,
+ int32_t event,
+ void *data,
+ ...)
+{
+ switch (event)
+ {
+ case GF_EVENT_PARENT_UP:
+ {
+ xlator_list_t *list = this->children;
+
+ while (list)
+ {
+ list->xlator->notify (list->xlator, event, this);
+ list = list->next;
+ }
+ }
+ break;
+ case GF_EVENT_CHILD_DOWN:
+ case GF_EVENT_CHILD_UP:
+ default:
+ {
+ xlator_list_t *parent = this->parents;
+ while (parent) {
+ parent->xlator->notify (parent->xlator, event, this, NULL);
+ parent = parent->next;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int32_t
+default_releasedir (xlator_t *this,
+ fd_t *fd)
+{
+ return 0;
+}
+
+int32_t
+default_release (xlator_t *this,
+ fd_t *fd)
+{
+ return 0;
+}
+
diff --git a/libglusterfs/src/defaults.h b/libglusterfs/src/defaults.h
new file mode 100644
index 000000000..aa15df599
--- /dev/null
+++ b/libglusterfs/src/defaults.h
@@ -0,0 +1,273 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+/* libglusterfs/src/defaults.h:
+ This file contains definition of default fops and mops functions.
+*/
+
+#ifndef _DEFAULTS_H
+#define _DEFAULTS_H
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "xlator.h"
+
+/* Management Operations */
+
+int32_t default_stats (call_frame_t *frame,
+ xlator_t *this,
+ int32_t flags);
+
+int32_t default_getspec (call_frame_t *frame,
+ xlator_t *this,
+ const char *key,
+ int32_t flag);
+
+int32_t default_checksum (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t flag);
+
+
+/* FileSystem operations */
+int32_t default_lookup (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ dict_t *xattr_req);
+
+int32_t default_stat (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc);
+
+int32_t default_fstat (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd);
+
+int32_t default_chmod (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ mode_t mode);
+
+int32_t default_fchmod (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ mode_t mode);
+
+int32_t default_chown (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ uid_t uid,
+ gid_t gid);
+
+int32_t default_fchown (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ uid_t uid,
+ gid_t gid);
+
+int32_t default_truncate (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ off_t offset);
+
+int32_t default_ftruncate (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ off_t offset);
+
+int32_t default_utimens (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ struct timespec tv[2]);
+
+int32_t default_access (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t mask);
+
+int32_t default_readlink (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ size_t size);
+
+int32_t default_mknod (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ mode_t mode,
+ dev_t rdev);
+
+int32_t default_mkdir (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ mode_t mode);
+
+int32_t default_unlink (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc);
+
+int32_t default_rmdir (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc);
+
+int32_t default_symlink (call_frame_t *frame,
+ xlator_t *this,
+ const char *linkpath,
+ loc_t *loc);
+
+int32_t default_rename (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *oldloc,
+ loc_t *newloc);
+
+int32_t default_link (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *oldloc,
+ loc_t *newloc);
+
+int32_t default_create (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t flags,
+ mode_t mode, fd_t *fd);
+
+int32_t default_open (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t flags, fd_t *fd);
+
+int32_t default_readv (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ size_t size,
+ off_t offset);
+
+int32_t default_writev (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ struct iovec *vector,
+ int32_t count,
+ off_t offset);
+
+int32_t default_flush (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd);
+
+int32_t default_fsync (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t datasync);
+
+int32_t default_opendir (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc, fd_t *fd);
+
+int32_t default_getdents (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ size_t size,
+ off_t offset,
+ int32_t flag);
+
+int32_t default_fsyncdir (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t datasync);
+
+int32_t default_statfs (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc);
+
+int32_t default_setxattr (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ dict_t *dict,
+ int32_t flags);
+
+int32_t default_getxattr (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ const char *name);
+
+int32_t default_removexattr (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ const char *name);
+
+int32_t default_lk (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t cmd,
+ struct flock *flock);
+
+int32_t default_inodelk (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, int32_t cmd, struct flock *flock);
+
+int32_t default_finodelk (call_frame_t *frame, xlator_t *this,
+ fd_t *fd, int32_t cmd, struct flock *flock);
+
+int32_t default_entrylk (call_frame_t *frame, xlator_t *this,
+ loc_t *loc, const char *basename,
+ entrylk_cmd cmd, entrylk_type type);
+
+int32_t default_fentrylk (call_frame_t *frame, xlator_t *this,
+ fd_t *fd, const char *basename,
+ entrylk_cmd cmd, entrylk_type type);
+
+int32_t default_readdir (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ size_t size, off_t off);
+
+int32_t default_setdents (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t flags,
+ dir_entry_t *entries,
+ int32_t count);
+
+int32_t default_xattrop (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ gf_xattrop_flags_t flags,
+ dict_t *dict);
+
+int32_t default_fxattrop (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ gf_xattrop_flags_t flags,
+ dict_t *dict);
+
+int32_t default_notify (xlator_t *this,
+ int32_t event,
+ void *data,
+ ...);
+
+int32_t default_forget (xlator_t *this,
+ inode_t *inode);
+
+int32_t default_release (xlator_t *this,
+ fd_t *fd);
+
+int32_t default_releasedir (xlator_t *this,
+ fd_t *fd);
+
+#endif /* _DEFAULTS_H */
diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c
new file mode 100644
index 000000000..eb181f191
--- /dev/null
+++ b/libglusterfs/src/dict.c
@@ -0,0 +1,2243 @@
+/*
+ Copyright (c) 2006, 2007, 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 <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "common-utils.h"
+#include "dict.h"
+#include "hashfn.h"
+#include "logging.h"
+#include "compat.h"
+#include "byte-order.h"
+
+data_pair_t *
+get_new_data_pair ()
+{
+ data_pair_t *data_pair_ptr = NULL;
+
+ data_pair_ptr = (data_pair_t *) CALLOC (1, sizeof (data_pair_t));
+ ERR_ABORT (data_pair_ptr);
+
+ return data_pair_ptr;
+}
+
+data_t *
+get_new_data ()
+{
+ data_t *data = NULL;
+
+ data = (data_t *) CALLOC (1, sizeof (data_t));
+ if (!data) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "calloc () returned NULL");
+ return NULL;
+ }
+
+ LOCK_INIT (&data->lock);
+ return data;
+}
+
+dict_t *
+get_new_dict_full (int size_hint)
+{
+ dict_t *dict = CALLOC (1, sizeof (dict_t));
+
+ if (!dict) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "calloc () returned NULL");
+ return NULL;
+ }
+
+ dict->hash_size = size_hint;
+ dict->members = CALLOC (size_hint, sizeof (data_pair_t *));
+
+ if (!dict->members) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "calloc () returned NULL");
+ return NULL;
+ }
+
+ LOCK_INIT (&dict->lock);
+
+ return dict;
+}
+
+dict_t *
+get_new_dict (void)
+{
+ return get_new_dict_full (1);
+}
+
+dict_t *
+dict_new (void)
+{
+ dict_t *dict = NULL;
+
+ dict = get_new_dict_full(1);
+
+ if (dict)
+ dict_ref (dict);
+
+ return dict;
+}
+
+
+int32_t
+is_data_equal (data_t *one,
+ data_t *two)
+{
+ if (!one || !two || !one->data || !two->data)
+ return 1;
+
+ if (one == two)
+ return 1;
+
+ if (one->len != two->len)
+ return 0;
+
+ if (one->data == two->data)
+ return 1;
+
+ if (memcmp (one->data, two->data, one->len) == 0)
+ return 1;
+
+ return 0;
+}
+
+void
+data_destroy (data_t *data)
+{
+ if (data) {
+ LOCK_DESTROY (&data->lock);
+
+ if (!data->is_static) {
+ if (data->data)
+ FREE (data->data);
+ if (data->vec)
+ FREE (data->vec);
+ }
+
+ data->len = 0xbabababa;
+ if (!data->is_const)
+ FREE (data);
+ }
+}
+
+data_t *
+data_copy (data_t *old)
+{
+ if (!old) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@old is NULL");
+ return NULL;
+ }
+
+ data_t *newdata = (data_t *) CALLOC (1, sizeof (*newdata));
+
+ if (!newdata) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@old is NULL");
+ return NULL;
+ }
+
+ if (old) {
+ newdata->len = old->len;
+ if (old->data)
+ newdata->data = memdup (old->data, old->len);
+ if (old->vec)
+ newdata->vec = memdup (old->vec, old->len * (sizeof (void *) +
+ sizeof (size_t)));
+ if (!old->data && !old->vec) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@newdata->data || @newdata->vec got NULL from CALLOC()");
+ return NULL;
+ }
+ }
+
+ return newdata;
+}
+
+static data_pair_t *
+_dict_lookup (dict_t *this, char *key)
+{
+ if (!this || !key) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@this=%p @key=%p", this, key);
+ return NULL;
+ }
+
+ int hashval = SuperFastHash (key, strlen (key)) % this->hash_size;
+ data_pair_t *pair;
+
+ for (pair = this->members[hashval]; pair != NULL; pair = pair->hash_next) {
+ if (pair->key && !strcmp (pair->key, key))
+ return pair;
+ }
+
+ return NULL;
+}
+
+
+static int32_t
+_dict_set (dict_t *this,
+ char *key,
+ data_t *value)
+{
+ int hashval;
+ data_pair_t *pair;
+ char key_free = 0;
+ int tmp = 0;
+
+ if (!key) {
+ asprintf (&key, "ref:%p", value);
+ key_free = 1;
+ }
+
+ tmp = SuperFastHash (key, strlen (key));
+ hashval = (tmp % this->hash_size);
+ pair = _dict_lookup (this, key);
+
+ if (pair) {
+ data_t *unref_data = pair->value;
+ pair->value = data_ref (value);
+ data_unref (unref_data);
+ if (key_free)
+ FREE (key);
+ /* Indicates duplicate key */
+ return 0;
+ }
+ pair = (data_pair_t *) CALLOC (1, sizeof (*pair));
+ if (!pair) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@pair - NULL returned by CALLOC");
+ return -1;
+ }
+
+ pair->key = (char *) CALLOC (1, strlen (key) + 1);
+ if (!pair->key) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@pair->key - NULL returned by CALLOC");
+ return -1;
+ }
+
+ strcpy (pair->key, key);
+ pair->value = data_ref (value);
+
+ pair->hash_next = this->members[hashval];
+ this->members[hashval] = pair;
+
+ pair->next = this->members_list;
+ pair->prev = NULL;
+ if (this->members_list)
+ this->members_list->prev = pair;
+ this->members_list = pair;
+ this->count++;
+
+ if (key_free)
+ FREE (key);
+ return 0;
+}
+
+int32_t
+dict_set (dict_t *this,
+ char *key,
+ data_t *value)
+{
+ int32_t ret;
+
+ if (!this || !value) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@this=%p @value=%p", this, value);
+ return -1;
+ }
+
+ LOCK (&this->lock);
+
+ ret = _dict_set (this, key, value);
+
+ UNLOCK (&this->lock);
+
+ return ret;
+}
+
+
+data_t *
+dict_get (dict_t *this,
+ char *key)
+{
+ data_pair_t *pair;
+
+ if (!this || !key) {
+ gf_log ("dict", GF_LOG_DEBUG,
+ "@this=%p @key=%p", this, key);
+ return NULL;
+ }
+
+ LOCK (&this->lock);
+
+ pair = _dict_lookup (this, key);
+
+ UNLOCK (&this->lock);
+
+ if (pair)
+ return pair->value;
+
+ return NULL;
+}
+
+void
+dict_del (dict_t *this,
+ char *key)
+{
+ if (!this || !key) {
+ gf_log ("dict", GF_LOG_DEBUG,
+ "@this=%p @key=%p", this, key);
+ return;
+ }
+
+ LOCK (&this->lock);
+
+ int hashval = SuperFastHash (key, strlen (key)) % this->hash_size;
+ data_pair_t *pair = this->members[hashval];
+ data_pair_t *prev = NULL;
+
+ while (pair) {
+ if (strcmp (pair->key, key) == 0) {
+ if (prev)
+ prev->hash_next = pair->hash_next;
+ else
+ this->members[hashval] = pair->hash_next;
+
+ data_unref (pair->value);
+
+ if (pair->prev)
+ pair->prev->next = pair->next;
+ else
+ this->members_list = pair->next;
+
+ if (pair->next)
+ pair->next->prev = pair->prev;
+
+ FREE (pair->key);
+ FREE (pair);
+ this->count--;
+ break;
+ }
+
+ prev = pair;
+ pair = pair->hash_next;
+ }
+
+ UNLOCK (&this->lock);
+
+ return;
+}
+
+void
+dict_destroy (dict_t *this)
+{
+ if (!this) {
+ gf_log ("dict", GF_LOG_DEBUG,
+ "@this=%p", this);
+ return;
+ }
+
+ data_pair_t *pair = this->members_list;
+ data_pair_t *prev = this->members_list;
+
+ LOCK_DESTROY (&this->lock);
+
+ while (prev) {
+ pair = pair->next;
+ data_unref (prev->value);
+ FREE (prev->key);
+ FREE (prev);
+ prev = pair;
+ }
+
+ FREE (this->members);
+
+ if (this->extra_free)
+ FREE (this->extra_free);
+
+ if (!this->is_static)
+ FREE (this);
+
+ return;
+}
+
+void
+dict_unref (dict_t *this)
+{
+ int32_t ref;
+
+ if (!this) {
+ gf_log ("dict", GF_LOG_DEBUG,
+ "@this=%p", this);
+ return;
+ }
+
+ LOCK (&this->lock);
+
+ this->refcount--;
+ ref = this->refcount;
+
+ UNLOCK (&this->lock);
+
+ if (!ref)
+ dict_destroy (this);
+}
+
+dict_t *
+dict_ref (dict_t *this)
+{
+ if (!this) {
+ gf_log ("dict", GF_LOG_DEBUG,
+ "@this=%p", this);
+ return NULL;
+ }
+
+ LOCK (&this->lock);
+
+ this->refcount++;
+
+ UNLOCK (&this->lock);
+
+ return this;
+}
+
+void
+data_unref (data_t *this)
+{
+ int32_t ref;
+
+ if (!this) {
+ gf_log ("dict", GF_LOG_DEBUG,
+ "@this=%p", this);
+ return;
+ }
+
+ LOCK (&this->lock);
+
+ this->refcount--;
+ ref = this->refcount;
+
+ UNLOCK (&this->lock);
+
+ if (!ref)
+ data_destroy (this);
+}
+
+data_t *
+data_ref (data_t *this)
+{
+ if (!this) {
+ gf_log ("dict", GF_LOG_DEBUG,
+ "@this=%p", this);
+ return NULL;
+ }
+
+ LOCK (&this->lock);
+
+ this->refcount++;
+
+ UNLOCK (&this->lock);
+
+ return this;
+}
+
+/*
+ Serialization format:
+ ----
+ Count:8
+ Key_len:8:Value_len:8
+ Key
+ Value
+ .
+ .
+ .
+*/
+
+int32_t
+dict_serialized_length_old (dict_t *this)
+{
+
+ if (!this) {
+ gf_log ("dict", GF_LOG_DEBUG,
+ "@this=%p", this);
+ return -1;
+ }
+
+ int32_t len = 9; /* count + \n */
+ int32_t count = this->count;
+ data_pair_t *pair = this->members_list;
+
+ while (count) {
+ len += 18;
+ len += strlen (pair->key) + 1;
+ if (pair->value->vec) {
+ int i;
+ for (i=0; i<pair->value->len; i++) {
+ len += pair->value->vec[i].iov_len;
+ }
+ } else {
+ len += pair->value->len;
+ }
+ pair = pair->next;
+ count--;
+ }
+
+ return len;
+}
+
+int32_t
+dict_serialize_old (dict_t *this, char *buf)
+{
+ if (!this || !buf) {
+ gf_log ("dict", GF_LOG_DEBUG,
+ "@this=%p @buf=%p", this, buf);
+ return -1;
+ }
+
+ data_pair_t *pair = this->members_list;
+ int32_t count = this->count;
+ uint64_t dcount = this->count;
+
+ // FIXME: magic numbers
+
+ sprintf (buf, "%08"PRIx64"\n", dcount);
+ buf += 9;
+ while (count) {
+ uint64_t keylen = strlen (pair->key) + 1;
+ uint64_t vallen = pair->value->len;
+
+ sprintf (buf, "%08"PRIx64":%08"PRIx64"\n", keylen, vallen);
+ buf += 18;
+ memcpy (buf, pair->key, keylen);
+ buf += keylen;
+ memcpy (buf, pair->value->data, pair->value->len);
+ buf += pair->value->len;
+ pair = pair->next;
+ count--;
+ }
+ return (0);
+}
+
+
+dict_t *
+dict_unserialize_old (char *buf, int32_t size, dict_t **fill)
+{
+ int32_t ret = 0;
+ int32_t cnt = 0;
+
+ if (!buf || fill == NULL || !*fill) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "@buf=%p @fill=%p @*fill=%p", buf, fill, *fill);
+ return NULL;
+ }
+
+ uint64_t count;
+ ret = sscanf (buf, "%"SCNx64"\n", &count);
+ (*fill)->count = 0;
+
+ if (!ret){
+ gf_log ("dict",
+ GF_LOG_ERROR,
+ "sscanf on buf failed");
+ goto err;
+ }
+ buf += 9;
+
+ if (count == 0) {
+ gf_log ("dict",
+ GF_LOG_ERROR,
+ "count == 0");
+ goto err;
+ }
+
+ for (cnt = 0; cnt < count; cnt++) {
+ data_t *value = NULL;
+ char *key = NULL;
+ uint64_t key_len, value_len;
+
+ ret = sscanf (buf, "%"SCNx64":%"SCNx64"\n", &key_len, &value_len);
+ if (ret != 2) {
+ gf_log ("dict",
+ GF_LOG_ERROR,
+ "sscanf for key_len and value_len failed");
+ goto err;
+ }
+ buf += 18;
+
+ key = buf;
+ buf += key_len;
+
+ value = get_new_data ();
+ value->len = value_len;
+ value->data = buf;
+ value->is_static = 1;
+ buf += value_len;
+
+ dict_set (*fill, key, value);
+ }
+
+ goto ret;
+
+err:
+ FREE (*fill);
+ *fill = NULL;
+
+ret:
+ return *fill;
+}
+
+
+int32_t
+dict_iovec_len (dict_t *this)
+{
+ if (!this) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@this=%p", this);
+ return -1;
+ }
+
+ int32_t len = 0;
+ data_pair_t *pair = this->members_list;
+
+ len++; /* initial header */
+ while (pair) {
+ len++; /* pair header */
+ len++; /* key */
+
+ if (pair->value->vec)
+ len += pair->value->len;
+ else
+ len++;
+ pair = pair->next;
+ }
+
+ return len;
+}
+
+int32_t
+dict_to_iovec (dict_t *this,
+ struct iovec *vec,
+ int32_t count)
+{
+ if (!this || !vec) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@this=%p @vec=%p", this, vec);
+ return -1;
+ }
+
+ int32_t i = 0;
+ data_pair_t *pair = this->members_list;
+
+ vec[0].iov_len = 9;
+ if (vec[0].iov_base)
+ sprintf (vec[0].iov_base,
+ "%08"PRIx64"\n",
+ (int64_t)this->count);
+ i++;
+
+ while (pair) {
+ int64_t keylen = strlen (pair->key) + 1;
+ int64_t vallen = 0;
+
+ if (pair->value->vec) {
+ int i;
+
+ for (i=0; i<pair->value->len; i++) {
+ vallen += pair->value->vec[i].iov_len;
+ }
+ } else {
+ vallen = pair->value->len;
+ }
+
+ vec[i].iov_len = 18;
+ if (vec[i].iov_base)
+ sprintf (vec[i].iov_base,
+ "%08"PRIx64":%08"PRIx64"\n",
+ keylen,
+ vallen);
+ i++;
+
+ vec[i].iov_len = keylen;
+ vec[i].iov_base = pair->key;
+ i++;
+
+ if (pair->value->vec) {
+ int k;
+
+ for (k=0; k<pair->value->len; k++) {
+ vec[i].iov_len = pair->value->vec[k].iov_len;
+ vec[i].iov_base = pair->value->vec[k].iov_base;
+ i++;
+ }
+ } else {
+ vec[i].iov_len = pair->value->len;
+ vec[i].iov_base = pair->value->data;
+ i++;
+ }
+
+ pair = pair->next;
+ }
+
+ return 0;
+}
+
+data_t *
+int_to_data (int64_t value)
+{
+ data_t *data = get_new_data ();
+
+ if (!data) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@data - NULL returned by CALLOC");
+ return NULL;
+ }
+
+ asprintf (&data->data, "%"PRId64, value);
+ data->len = strlen (data->data) + 1;
+
+ return data;
+}
+
+data_t *
+data_from_int64 (int64_t value)
+{
+ data_t *data = get_new_data ();
+
+ if (!data) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@data - NULL returned by CALLOC");
+ return NULL;
+ }
+ asprintf (&data->data, "%"PRId64, value);
+ data->len = strlen (data->data) + 1;
+
+ return data;
+}
+
+data_t *
+data_from_int32 (int32_t value)
+{
+ data_t *data = get_new_data ();
+
+ if (!data) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@data - NULL returned by CALLOC");
+ return NULL;
+ }
+ asprintf (&data->data, "%"PRId32, value);
+ data->len = strlen (data->data) + 1;
+
+ return data;
+}
+
+data_t *
+data_from_int16 (int16_t value)
+{
+
+ data_t *data = get_new_data ();
+
+ if (!data) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@data - NULL returned by CALLOC");
+ return NULL;
+ }
+ asprintf (&data->data, "%"PRId16, value);
+ data->len = strlen (data->data) + 1;
+
+ return data;
+}
+
+data_t *
+data_from_int8 (int8_t value)
+{
+
+ data_t *data = get_new_data ();
+
+ if (!data) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@data - NULL returned by CALLOC");
+ return NULL;
+ }
+ asprintf (&data->data, "%d", value);
+ data->len = strlen (data->data) + 1;
+
+ return data;
+}
+
+data_t *
+data_from_uint64 (uint64_t value)
+{
+ data_t *data = get_new_data ();
+
+ if (!data) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@data - NULL returned by CALLOC");
+ return NULL;
+ }
+ asprintf (&data->data, "%"PRIu64, value);
+ data->len = strlen (data->data) + 1;
+
+ return data;
+}
+
+
+data_t *
+data_from_uint32 (uint32_t value)
+{
+ data_t *data = get_new_data ();
+
+ if (!data) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@data - NULL returned by CALLOC");
+ return NULL;
+ }
+ asprintf (&data->data, "%"PRIu32, value);
+ data->len = strlen (data->data) + 1;
+
+ return data;
+}
+
+
+data_t *
+data_from_uint16 (uint16_t value)
+{
+ data_t *data = get_new_data ();
+
+ if (!data) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@data - NULL returned by CALLOC");
+ return NULL;
+ }
+ asprintf (&data->data, "%"PRIu16, value);
+ data->len = strlen (data->data) + 1;
+
+ return data;
+}
+
+
+data_t *
+data_from_ptr (void *value)
+{
+ if (!value) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@value=%p", value);
+ return NULL;
+ }
+
+ data_t *data = get_new_data ();
+
+ if (!data) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@data - NULL returned by CALLOC");
+ return NULL;
+ }
+
+ data->data = value;
+ return data;
+}
+
+data_t *
+data_from_static_ptr (void *value)
+{
+/*
+ this is valid to set 0 as value..
+
+ if (!value) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@value=%p", value);
+ return NULL;
+ }
+*/
+ data_t *data = get_new_data ();
+
+ if (!data) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@data - NULL returned by CALLOC");
+ return NULL;
+ }
+
+ data->is_static = 1;
+ data->data = value;
+
+ return data;
+}
+
+data_t *
+str_to_data (char *value)
+{
+ if (!value) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@value=%p", value);
+ return NULL;
+ }
+ data_t *data = get_new_data ();
+
+ if (!data) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@data - NULL returned by CALLOC");
+ return NULL;
+ }
+ data->len = strlen (value) + 1;
+
+ data->data = value;
+ data->is_static = 1;
+
+ return data;
+}
+
+data_t *
+data_from_dynstr (char *value)
+{
+ if (!value) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@value=%p", value);
+ return NULL;
+ }
+
+ data_t *data = get_new_data ();
+
+ data->len = strlen (value) + 1;
+ data->data = value;
+
+ return data;
+}
+
+data_t *
+data_from_dynptr (void *value, int32_t len)
+{
+ data_t *data = get_new_data ();
+
+ data->len = len;
+ data->data = value;
+
+ return data;
+}
+
+data_t *
+bin_to_data (void *value, int32_t len)
+{
+ if (!value) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@value=%p", value);
+ return NULL;
+ }
+
+ data_t *data = get_new_data ();
+
+ data->is_static = 1;
+ data->len = len;
+ data->data = value;
+
+ return data;
+}
+
+int64_t
+data_to_int64 (data_t *data)
+{
+ if (!data)
+ return -1;
+
+ char *str = alloca (data->len + 1);
+ ERR_ABORT (str);
+ memcpy (str, data->data, data->len);
+ str[data->len] = '\0';
+ return (int64_t) strtoull (str, NULL, 0);
+}
+
+int32_t
+data_to_int32 (data_t *data)
+{
+ if (!data)
+ return -1;
+
+ char *str = alloca (data->len + 1);
+ ERR_ABORT (str);
+ memcpy (str, data->data, data->len);
+ str[data->len] = '\0';
+
+ return strtoul (str, NULL, 0);
+}
+
+int16_t
+data_to_int16 (data_t *data)
+{
+ if (!data)
+ return -1;
+
+ char *str = alloca (data->len + 1);
+ ERR_ABORT (str);
+ memcpy (str, data->data, data->len);
+ str[data->len] = '\0';
+
+ return strtol (str, NULL, 0);
+}
+
+
+int8_t
+data_to_int8 (data_t *data)
+{
+ if (!data)
+ return -1;
+
+ char *str = alloca (data->len + 1);
+ ERR_ABORT (str);
+ memcpy (str, data->data, data->len);
+ str[data->len] = '\0';
+
+ return (int8_t)strtol (str, NULL, 0);
+}
+
+
+uint64_t
+data_to_uint64 (data_t *data)
+{
+ if (!data)
+ return -1;
+ char *str = alloca (data->len + 1);
+ ERR_ABORT (str);
+ memcpy (str, data->data, data->len);
+ str[data->len] = '\0';
+
+ return strtoll (str, NULL, 0);
+}
+
+uint32_t
+data_to_uint32 (data_t *data)
+{
+ if (!data)
+ return -1;
+
+ char *str = alloca (data->len + 1);
+ ERR_ABORT (str);
+ memcpy (str, data->data, data->len);
+ str[data->len] = '\0';
+
+ return strtol (str, NULL, 0);
+}
+
+uint16_t
+data_to_uint16 (data_t *data)
+{
+ if (!data)
+ return -1;
+
+ char *str = alloca (data->len + 1);
+ ERR_ABORT (str);
+ memcpy (str, data->data, data->len);
+ str[data->len] = '\0';
+
+ return strtol (str, NULL, 0);
+}
+
+char *
+data_to_str (data_t *data)
+{
+ if (!data) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@data=%p", data);
+ return NULL;
+ }
+ return data->data;
+}
+
+void *
+data_to_ptr (data_t *data)
+{
+ if (!data) {
+ return NULL;
+ }
+ return data->data;
+}
+
+void *
+data_to_bin (data_t *data)
+{
+ if (!data) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@data=%p", data);
+ return NULL;
+ }
+ return data->data;
+}
+
+void
+dict_foreach (dict_t *dict,
+ void (*fn)(dict_t *this,
+ char *key,
+ data_t *value,
+ void *data),
+ void *data)
+{
+ if (!data) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@data=%p", data);
+ return;
+ }
+
+ data_pair_t *pairs = dict->members_list;
+
+ while (pairs) {
+ fn (dict, pairs->key, pairs->value, data);
+ pairs = pairs->next;
+ }
+}
+
+
+static void
+_copy (dict_t *unused,
+ char *key,
+ data_t *value,
+ void *newdict)
+{
+ dict_set ((dict_t *)newdict, key, (value));
+}
+
+
+dict_t *
+dict_copy (dict_t *dict,
+ dict_t *new)
+{
+ if (!dict) {
+ gf_log ("dict", GF_LOG_CRITICAL,
+ "@data=%p", dict);
+ return NULL;
+ }
+
+ if (!new)
+ new = get_new_dict_full (dict->hash_size);
+
+ dict_foreach (dict, _copy, new);
+
+ return new;
+}
+
+dict_t *
+dict_copy_with_ref (dict_t *dict,
+ dict_t *new)
+{
+ dict_t *local_new = NULL;
+
+ GF_VALIDATE_OR_GOTO("dict", dict, fail);
+
+ if (new == NULL) {
+ local_new = dict_new ();
+ GF_VALIDATE_OR_GOTO("dict", local_new, fail);
+ new = local_new;
+ }
+
+ dict_foreach (dict, _copy, new);
+fail:
+ return new;
+}
+
+/*
+ * !!!!!!! CLEANED UP CODE !!!!!!!
+ */
+
+/**
+ * Common cleaned up interface:
+ *
+ * Return value: 0 success
+ * -val error, val = errno
+ */
+
+
+static int
+dict_get_with_ref (dict_t *this, char *key, data_t **data)
+{
+ data_pair_t * pair = NULL;
+ int ret = -ENOENT;
+
+ if (!this || !key || !data) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ LOCK (&this->lock);
+ {
+ pair = _dict_lookup (this, key);
+ }
+ UNLOCK (&this->lock);
+
+ if (pair) {
+ ret = 0;
+ *data = data_ref (pair->value);
+ }
+
+err:
+ return ret;
+}
+
+static int
+_data_to_ptr (data_t *data, void **val)
+{
+ int ret = 0;
+
+ if (!data) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ *val = data->data;
+err:
+ return ret;
+}
+
+
+static int
+_data_to_int8 (data_t *data, int8_t *val)
+{
+ int ret = 0;
+ char * str = NULL;
+
+ if (!data || !val) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ str = alloca (data->len + 1);
+ if (!str) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ memcpy (str, data->data, data->len);
+ str[data->len] = '\0';
+
+ errno = 0;
+ *val = strtol (str, NULL, 0);
+ if (errno != 0)
+ ret = -errno;
+
+err:
+ return ret;
+}
+
+static int
+_data_to_int16 (data_t *data, int16_t *val)
+{
+ int ret = 0;
+ char * str = NULL;
+
+ if (!data || !val) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ str = alloca (data->len + 1);
+ if (!str) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ memcpy (str, data->data, data->len);
+ str[data->len] = '\0';
+
+ errno = 0;
+ *val = strtol (str, NULL, 0);
+ if (errno != 0)
+ ret = -errno;
+
+err:
+ return ret;
+}
+
+static int
+_data_to_int32 (data_t *data, int32_t *val)
+{
+ int ret = 0;
+ char * str = NULL;
+
+ if (!data || !val) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ str = alloca (data->len + 1);
+ if (!str) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ memcpy (str, data->data, data->len);
+ str[data->len] = '\0';
+
+ errno = 0;
+ *val = strtol (str, NULL, 0);
+ if (errno != 0)
+ ret = -errno;
+
+err:
+ return ret;
+}
+
+static int
+_data_to_int64 (data_t *data, int64_t *val)
+{
+ int ret = 0;
+ char * str = NULL;
+
+ if (!data || !val) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ str = alloca (data->len + 1);
+ if (!str) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ memcpy (str, data->data, data->len);
+ str[data->len] = '\0';
+
+ errno = 0;
+ *val = strtoll (str, NULL, 0);
+ if (errno != 0)
+ ret = -errno;
+
+err:
+ return ret;
+}
+
+static int
+_data_to_uint16 (data_t *data, uint16_t *val)
+{
+ int ret = 0;
+ char * str = NULL;
+
+ if (!data || !val) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ str = alloca (data->len + 1);
+ if (!str) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ memcpy (str, data->data, data->len);
+ str[data->len] = '\0';
+
+ errno = 0;
+ *val = strtoul (str, NULL, 0);
+ if (errno != 0)
+ ret = -errno;
+
+err:
+ return ret;
+}
+
+static int
+_data_to_uint32 (data_t *data, uint32_t *val)
+{
+ int ret = 0;
+ char * str = NULL;
+
+ if (!data || !val) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ str = alloca (data->len + 1);
+ if (!str) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ memcpy (str, data->data, data->len);
+ str[data->len] = '\0';
+
+ errno = 0;
+ *val = strtoul (str, NULL, 0);
+ if (errno != 0)
+ ret = -errno;
+
+err:
+ return ret;
+}
+
+static int
+_data_to_uint64 (data_t *data, uint64_t *val)
+{
+ int ret = 0;
+ char * str = NULL;
+
+ if (!data || !val) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ str = alloca (data->len + 1);
+ if (!str) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ memcpy (str, data->data, data->len);
+ str[data->len] = '\0';
+
+ errno = 0;
+ *val = strtoull (str, NULL, 0);
+ if (errno != 0)
+ ret = -errno;
+
+err:
+ return ret;
+}
+
+int
+dict_get_int8 (dict_t *this, char *key, int8_t *val)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ if (!this || !key || !val) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_get_with_ref (this, key, &data);
+ if (ret != 0) {
+ goto err;
+ }
+
+ ret = _data_to_int8 (data, val);
+
+err:
+ if (data)
+ data_unref (data);
+ return ret;
+}
+
+
+int
+dict_set_int8 (dict_t *this, char *key, int8_t val)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ data = data_from_int8 (val);
+ if (!data) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_set (this, key, data);
+
+err:
+ return ret;
+}
+
+int
+dict_get_int16 (dict_t *this, char *key, int16_t *val)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ if (!this || !key || !val) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_get_with_ref (this, key, &data);
+ if (ret != 0) {
+ goto err;
+ }
+
+ ret = _data_to_int16 (data, val);
+
+err:
+ if (data)
+ data_unref (data);
+ return ret;
+}
+
+
+int
+dict_set_int16 (dict_t *this, char *key, int16_t val)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ data = data_from_int16 (val);
+ if (!data) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_set (this, key, data);
+
+err:
+ return ret;
+}
+
+int
+dict_get_int32 (dict_t *this, char *key, int32_t *val)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ if (!this || !key || !val) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_get_with_ref (this, key, &data);
+ if (ret != 0) {
+ goto err;
+ }
+
+ ret = _data_to_int32 (data, val);
+
+err:
+ if (data)
+ data_unref (data);
+ return ret;
+}
+
+
+int
+dict_set_int32 (dict_t *this, char *key, int32_t val)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ data = data_from_int32 (val);
+ if (!data) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_set (this, key, data);
+
+err:
+ return ret;
+}
+
+int
+dict_get_int64 (dict_t *this, char *key, int64_t *val)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ if (!this || !key || !val) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_get_with_ref (this, key, &data);
+ if (ret != 0) {
+ goto err;
+ }
+
+ ret = _data_to_int64 (data, val);
+
+err:
+ if (data)
+ data_unref (data);
+ return ret;
+}
+
+
+int
+dict_set_int64 (dict_t *this, char *key, int64_t val)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ data = data_from_int64 (val);
+ if (!data) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_set (this, key, data);
+
+err:
+ return ret;
+}
+
+int
+dict_get_uint16 (dict_t *this, char *key, uint16_t *val)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ if (!this || !key || !val) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_get_with_ref (this, key, &data);
+ if (ret != 0) {
+ goto err;
+ }
+
+ ret = _data_to_uint16 (data, val);
+
+err:
+ if (data)
+ data_unref (data);
+ return ret;
+}
+
+
+int
+dict_set_uint16 (dict_t *this, char *key, uint16_t val)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ data = data_from_uint16 (val);
+ if (!data) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_set (this, key, data);
+
+err:
+ return ret;
+}
+
+int
+dict_get_uint32 (dict_t *this, char *key, uint32_t *val)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ if (!this || !key || !val) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_get_with_ref (this, key, &data);
+ if (ret != 0) {
+ goto err;
+ }
+
+ ret = _data_to_uint32 (data, val);
+
+err:
+ if (data)
+ data_unref (data);
+ return ret;
+}
+
+
+int
+dict_set_uint32 (dict_t *this, char *key, uint32_t val)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ data = data_from_uint32 (val);
+ if (!data) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_set (this, key, data);
+
+err:
+ return ret;
+}
+
+int
+dict_get_uint64 (dict_t *this, char *key, uint64_t *val)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ if (!this || !key || !val) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_get_with_ref (this, key, &data);
+ if (ret != 0) {
+ goto err;
+ }
+
+ ret = _data_to_uint64 (data, val);
+
+err:
+ if (data)
+ data_unref (data);
+ return ret;
+}
+
+
+int
+dict_set_uint64 (dict_t *this, char *key, uint64_t val)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ data = data_from_uint64 (val);
+ if (!data) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_set (this, key, data);
+
+err:
+ return ret;
+}
+
+int
+dict_set_static_ptr (dict_t *this, char *key, void *ptr)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ data = data_from_static_ptr (ptr);
+ if (!data) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_set (this, key, data);
+
+err:
+ return ret;
+}
+
+int
+dict_set_dynptr (dict_t *this, char *key, void *ptr, size_t len)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ data = data_from_dynptr (ptr, len);
+ if (!data) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_set (this, key, data);
+
+err:
+ return ret;
+}
+
+int
+dict_get_ptr (dict_t *this, char *key, void **ptr)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ if (!this || !key || !ptr) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_get_with_ref (this, key, &data);
+ if (ret != 0) {
+ goto err;
+ }
+
+ ret = _data_to_ptr (data, ptr);
+ if (ret != 0) {
+ goto err;
+ }
+
+err:
+ if (data)
+ data_unref (data);
+
+ return ret;
+}
+
+int
+dict_set_ptr (dict_t *this, char *key, void *ptr)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ data = data_from_ptr (ptr);
+ if (!data) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_set (this, key, data);
+
+err:
+ return ret;
+}
+
+
+int
+dict_get_str (dict_t *this, char *key, char **str)
+{
+ data_t * data = NULL;
+ int ret = -EINVAL;
+
+ if (!this || !key || !str) {
+ goto err;
+ }
+
+ ret = dict_get_with_ref (this, key, &data);
+ if (ret < 0) {
+ goto err;
+ }
+
+ if (!data || !data->data) {
+ goto err;
+ }
+ *str = data->data;
+
+err:
+ if (data)
+ data_unref (data);
+
+ return ret;
+}
+
+int
+dict_set_str (dict_t *this, char *key, char *str)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ data = str_to_data (str);
+ if (!data) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_set (this, key, data);
+
+err:
+ return ret;
+}
+
+int
+dict_set_dynstr (dict_t *this, char *key, char *str)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ data = data_from_dynstr (str);
+ if (!data) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = dict_set (this, key, data);
+
+err:
+ return ret;
+}
+
+
+int
+dict_get_bin (dict_t *this, char *key, void **bin)
+{
+ data_t * data = NULL;
+ int ret = -EINVAL;
+
+ if (!this || !key || !bin) {
+ goto err;
+ }
+
+ ret = dict_get_with_ref (this, key, &data);
+ if (ret < 0) {
+ goto err;
+ }
+
+ if (!data || !data->data) {
+ goto err;
+ }
+ *bin = data->data;
+
+err:
+ if (data)
+ data_unref (data);
+
+ return ret;
+}
+
+
+int
+dict_set_bin (dict_t *this, char *key, void *ptr, size_t size)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ if (!ptr || (size < 0)) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ data = bin_to_data (ptr, size);
+ if (!data) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ data->data = ptr;
+ data->len = size;
+ data->is_static = 0;
+
+ ret = dict_set (this, key, data);
+
+err:
+ return ret;
+}
+
+
+int
+dict_set_static_bin (dict_t *this, char *key, void *ptr, size_t size)
+{
+ data_t * data = NULL;
+ int ret = 0;
+
+ if (!ptr || (size < 0)) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ data = bin_to_data (ptr, size);
+ if (!data) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ data->data = ptr;
+ data->len = size;
+ data->is_static = 1;
+
+ ret = dict_set (this, key, data);
+
+err:
+ return ret;
+}
+
+/**
+ * Serialization format:
+ * -------- -------- -------- ----------- -------------
+ * | count | key len | val len | key \0| value
+ * ---------------------------------------- -------------
+ * 4 4 4 <key len> <value len>
+ */
+
+#define DICT_HDR_LEN 4
+#define DICT_DATA_HDR_KEY_LEN 4
+#define DICT_DATA_HDR_VAL_LEN 4
+
+/**
+ * dict_serialized_length - return the length of serialized dict
+ *
+ * @this: dict to be serialized
+ * @return: success: len
+ * : failure: -errno
+ */
+
+int
+dict_serialized_length (dict_t *this)
+{
+ int ret = -EINVAL;
+ int count = 0;
+ int len = 0;
+ int i = 0;
+ data_pair_t * pair = NULL;
+
+ if (!this) {
+ gf_log ("dict", GF_LOG_ERROR, "this is null!");
+ goto out;
+ }
+
+ len = DICT_HDR_LEN;
+ count = this->count;
+
+ if (count < 0) {
+ gf_log ("dict", GF_LOG_ERROR, "count (%d) < 0!", count);
+ goto out;
+ }
+
+ pair = this->members_list;
+
+ while (count) {
+ if (!pair) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "less than count data pairs found!");
+ goto out;
+ }
+
+ len += DICT_DATA_HDR_KEY_LEN + DICT_DATA_HDR_VAL_LEN;
+
+ if (!pair->key) {
+ gf_log ("dict", GF_LOG_ERROR, "pair->key is null!");
+ goto out;
+ }
+
+ len += strlen (pair->key) + 1 /* for '\0' */;
+
+ if (!pair->value) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "pair->value is null!");
+ goto out;
+ }
+
+ if (pair->value->vec) {
+ for (i = 0; i < pair->value->len; i++) {
+ if (pair->value->vec[i].iov_len < 0) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "iov_len (%"GF_PRI_SIZET") < 0!",
+ pair->value->vec[i].iov_len);
+ goto out;
+ }
+
+ len += pair->value->vec[i].iov_len;
+ }
+ } else {
+ if (pair->value->len < 0) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "value->len (%d) < 0",
+ pair->value->len);
+ goto out;
+ }
+
+ len += pair->value->len;
+ }
+
+ pair = pair->next;
+ count--;
+ }
+
+ ret = len;
+out:
+ return ret;
+}
+
+/**
+ * dict_serialize - serialize a dictionary into a buffer
+ *
+ * @this: dict to serialize
+ * @buf: buffer to serialize into. This must be
+ * atleast dict_serialized_length (this) large
+ *
+ * @return: success: 0
+ * failure: -errno
+ */
+
+int
+dict_serialize (dict_t *this, char *buf)
+{
+ int ret = -1;
+ data_pair_t * pair = NULL;
+ int32_t count = 0;
+ int32_t keylen = 0;
+ int32_t vallen = 0;
+
+ if (!this) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "this is null!");
+ goto out;
+ }
+ if (!buf) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "buf is null!");
+ goto out;
+ }
+
+ count = this->count;
+ if (count < 0) {
+ gf_log ("dict", GF_LOG_ERROR, "count (%d) < 0!", count);
+ goto out;
+ }
+
+ *(int32_t *) buf = hton32 (count);
+ buf += DICT_HDR_LEN;
+ pair = this->members_list;
+
+ while (count) {
+ if (!pair) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "less than count data pairs found!");
+ goto out;
+ }
+
+ if (!pair->key) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "pair->key is null!");
+ goto out;
+ }
+
+ keylen = strlen (pair->key);
+ *(int32_t *) buf = hton32 (keylen);
+ buf += DICT_DATA_HDR_KEY_LEN;
+
+ if (!pair->value) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "pair->value is null!");
+ goto out;
+ }
+
+ vallen = pair->value->len;
+ *(int32_t *) buf = hton32 (vallen);
+ buf += DICT_DATA_HDR_VAL_LEN;
+
+ memcpy (buf, pair->key, keylen);
+ buf += keylen;
+ *buf++ = '\0';
+
+ if (!pair->value->data) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "pair->value->data is null!");
+ goto out;
+ }
+ memcpy (buf, pair->value->data, vallen);
+ buf += vallen;
+
+ pair = pair->next;
+ count--;
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
+
+/**
+ * dict_unserialize - unserialize a buffer into a dict
+ *
+ * @buf: buf containing serialized dict
+ * @size: size of the @buf
+ * @fill: dict to fill in
+ *
+ * @return: success: 0
+ * failure: -errno
+ */
+
+int32_t
+dict_unserialize (char *orig_buf, int32_t size, dict_t **fill)
+{
+ char *buf = NULL;
+ int ret = -1;
+ int32_t count = 0;
+ int i = 0;
+
+ data_t * value = NULL;
+ char * key = NULL;
+ int32_t keylen = 0;
+ int32_t vallen = 0;
+
+
+ buf = orig_buf;
+
+ if (!buf) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "buf is null!");
+ goto out;
+ }
+
+ if (size == 0) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "size is 0!");
+ goto out;
+ }
+
+ if (!fill) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "fill is null!");
+ goto out;
+ }
+
+ if (!*fill) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "*fill is null!");
+ goto out;
+ }
+
+ if ((buf + DICT_HDR_LEN) > (orig_buf + size)) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "undersized buffer passsed");
+ goto out;
+ }
+
+ count = ntoh32 (*(int32_t *) buf);
+ buf += DICT_HDR_LEN;
+
+ if (count < 0) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "count (%d) <= 0", count);
+ goto out;
+ }
+
+ /* count will be set by the dict_set's below */
+ (*fill)->count = 0;
+
+ for (i = 0; i < count; i++) {
+ if ((buf + DICT_DATA_HDR_KEY_LEN) > (orig_buf + size)) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "undersized buffer passsed");
+ goto out;
+ }
+ keylen = ntoh32 (*(int32_t *) buf);
+ buf += DICT_DATA_HDR_KEY_LEN;
+
+ if ((buf + DICT_DATA_HDR_VAL_LEN) > (orig_buf + size)) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "undersized buffer passsed");
+ goto out;
+ }
+ vallen = ntoh32 (*(int32_t *) buf);
+ buf += DICT_DATA_HDR_VAL_LEN;
+
+ if ((buf + keylen) > (orig_buf + size)) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "undersized buffer passsed");
+ goto out;
+ }
+ key = buf;
+ buf += keylen + 1; /* for '\0' */
+
+ if ((buf + vallen) > (orig_buf + size)) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "undersized buffer passsed");
+ goto out;
+ }
+ value = get_new_data ();
+ value->len = vallen;
+ value->data = buf;
+ value->is_static = 1;
+ buf += vallen;
+
+ dict_set (*fill, key, value);
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
diff --git a/libglusterfs/src/dict.h b/libglusterfs/src/dict.h
new file mode 100644
index 000000000..5c299d039
--- /dev/null
+++ b/libglusterfs/src/dict.h
@@ -0,0 +1,179 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+#ifndef _DICT_H
+#define _DICT_H
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <inttypes.h>
+#include <sys/uio.h>
+#include <pthread.h>
+
+#include "common-utils.h"
+
+typedef struct _data data_t;
+typedef struct _dict dict_t;
+typedef struct _data_pair data_pair_t;
+
+struct _data {
+ unsigned char is_static:1;
+ unsigned char is_const:1;
+ int32_t len;
+ struct iovec *vec;
+ char *data;
+ int32_t refcount;
+ gf_lock_t lock;
+};
+
+struct _data_pair {
+ struct _data_pair *hash_next;
+ struct _data_pair *prev;
+ struct _data_pair *next;
+ data_t *value;
+ char *key;
+};
+
+struct _dict {
+ unsigned char is_static:1;
+ int32_t hash_size;
+ int32_t count;
+ int32_t refcount;
+ data_pair_t **members;
+ data_pair_t *members_list;
+ char *extra_free;
+ gf_lock_t lock;
+};
+
+
+int32_t is_data_equal (data_t *one, data_t *two);
+void data_destroy (data_t *data);
+
+int32_t dict_set (dict_t *this, char *key, data_t *value);
+data_t *dict_get (dict_t *this, char *key);
+void dict_del (dict_t *this, char *key);
+
+int32_t dict_serialized_length (dict_t *dict);
+int32_t dict_serialize (dict_t *dict, char *buf);
+int32_t dict_unserialize (char *buf, int32_t size, dict_t **fill);
+
+int32_t dict_iovec_len (dict_t *dict);
+int32_t dict_to_iovec (dict_t *dict, struct iovec *vec, int32_t count);
+
+void dict_destroy (dict_t *dict);
+void dict_unref (dict_t *dict);
+dict_t *dict_ref (dict_t *dict);
+data_t *data_ref (data_t *data);
+void data_unref (data_t *data);
+
+/*
+ TODO: provide converts for differnt byte sizes, signedness, and void *
+ */
+data_t *int_to_data (int64_t value);
+data_t *str_to_data (char *value);
+data_t *data_from_dynstr (char *value);
+data_t *data_from_dynptr (void *value, int32_t len);
+data_t *bin_to_data (void *value, int32_t len);
+data_t *static_str_to_data (char *value);
+data_t *static_bin_to_data (void *value);
+
+int64_t data_to_int64 (data_t *data);
+int32_t data_to_int32 (data_t *data);
+int16_t data_to_int16 (data_t *data);
+int8_t data_to_int8 (data_t *data);
+
+uint64_t data_to_uint64 (data_t *data);
+uint32_t data_to_uint32 (data_t *data);
+uint16_t data_to_uint16 (data_t *data);
+
+data_t *data_from_ptr (void *value);
+data_t *data_from_static_ptr (void *value);
+
+data_t *data_from_int64 (int64_t value);
+data_t *data_from_int32 (int32_t value);
+data_t *data_from_int16 (int16_t value);
+data_t *data_from_int8 (int8_t value);
+
+data_t *data_from_uint64 (uint64_t value);
+data_t *data_from_uint32 (uint32_t value);
+data_t *data_from_uint16 (uint16_t value);
+
+char *data_to_str (data_t *data);
+void *data_to_bin (data_t *data);
+void *data_to_ptr (data_t *data);
+
+data_t *get_new_data ();
+dict_t *get_new_dict_full (int size_hint);
+dict_t *get_new_dict ();
+
+data_pair_t *get_new_data_pair ();
+
+void dict_foreach (dict_t *this,
+ void (*fn)(dict_t *this,
+ char *key,
+ data_t *value,
+ void *data),
+ void *data);
+
+dict_t *dict_copy (dict_t *this,
+ dict_t *new);
+
+/* CLEANED UP FUNCTIONS DECLARATIONS */
+GF_MUST_CHECK dict_t *dict_new (void);
+dict_t *dict_copy_with_ref (dict_t *this,
+ dict_t *new);
+
+GF_MUST_CHECK int dict_get_int8 (dict_t *this, char *key, int8_t *val);
+GF_MUST_CHECK int dict_set_int8 (dict_t *this, char *key, int8_t val);
+
+GF_MUST_CHECK int dict_get_int16 (dict_t *this, char *key, int16_t *val);
+GF_MUST_CHECK int dict_set_int16 (dict_t *this, char *key, int16_t val);
+
+GF_MUST_CHECK int dict_get_int32 (dict_t *this, char *key, int32_t *val);
+GF_MUST_CHECK int dict_set_int32 (dict_t *this, char *key, int32_t val);
+
+GF_MUST_CHECK int dict_get_int64 (dict_t *this, char *key, int64_t *val);
+GF_MUST_CHECK int dict_set_int64 (dict_t *this, char *key, int64_t val);
+
+GF_MUST_CHECK int dict_get_uint16 (dict_t *this, char *key, uint16_t *val);
+GF_MUST_CHECK int dict_set_uint16 (dict_t *this, char *key, uint16_t val);
+
+GF_MUST_CHECK int dict_get_uint32 (dict_t *this, char *key, uint32_t *val);
+GF_MUST_CHECK int dict_set_uint32 (dict_t *this, char *key, uint32_t val);
+
+GF_MUST_CHECK int dict_get_uint64 (dict_t *this, char *key, uint64_t *val);
+GF_MUST_CHECK int dict_set_uint64 (dict_t *this, char *key, uint64_t val);
+
+GF_MUST_CHECK int dict_set_static_ptr (dict_t *this, char *key, void *ptr);
+GF_MUST_CHECK int dict_get_ptr (dict_t *this, char *key, void **ptr);
+GF_MUST_CHECK int dict_set_ptr (dict_t *this, char *key, void *ptr);
+GF_MUST_CHECK int dict_set_dynptr (dict_t *this, char *key, void *ptr, size_t size);
+
+GF_MUST_CHECK int dict_get_bin (dict_t *this, char *key, void **ptr);
+GF_MUST_CHECK int dict_set_bin (dict_t *this, char *key, void *ptr, size_t size);
+GF_MUST_CHECK int dict_set_static_bin (dict_t *this, char *key, void *ptr, size_t size);
+
+GF_MUST_CHECK int dict_set_str (dict_t *this, char *key, char *str);
+GF_MUST_CHECK int dict_set_dynstr (dict_t *this, char *key, char *str);
+GF_MUST_CHECK int dict_get_str (dict_t *this, char *key, char **str);
+
+#endif
diff --git a/libglusterfs/src/event.c b/libglusterfs/src/event.c
new file mode 100644
index 000000000..f2bbddd20
--- /dev/null
+++ b/libglusterfs/src/event.c
@@ -0,0 +1,978 @@
+/*
+ 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 <sys/poll.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include "logging.h"
+#include "event.h"
+#include "mem-pool.h"
+
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+static int
+event_register_poll (struct event_pool *event_pool, int fd,
+ event_handler_t handler,
+ void *data, int poll_in, int poll_out);
+
+
+static int
+__flush_fd (int fd, int idx, void *data,
+ int poll_in, int poll_out, int poll_err)
+{
+ char buf[64];
+ int ret = -1;
+
+ if (!poll_in)
+ return ret;
+
+ do {
+ ret = read (fd, buf, 64);
+ if (ret == -1 && errno != EAGAIN) {
+ gf_log ("poll", GF_LOG_ERROR,
+ "read on %d returned error (%s)",
+ fd, strerror (errno));
+ }
+ } while (ret == 64);
+
+ return ret;
+}
+
+
+static int
+__event_getindex (struct event_pool *event_pool, int fd, int idx)
+{
+ int ret = -1;
+ int i = 0;
+
+ if (event_pool == NULL) {
+ gf_log ("event", GF_LOG_ERROR, "invalid argument");
+ return -1;
+ }
+
+ if (idx > -1 && idx < event_pool->used) {
+ if (event_pool->reg[idx].fd == fd)
+ ret = idx;
+ }
+
+ for (i=0; ret == -1 && i<event_pool->used; i++) {
+ if (event_pool->reg[i].fd == fd) {
+ ret = i;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+
+static struct event_pool *
+event_pool_new_poll (int count)
+{
+ struct event_pool *event_pool = NULL;
+ int ret = -1;
+
+ event_pool = CALLOC (1, sizeof (*event_pool));
+
+ if (!event_pool)
+ return NULL;
+
+ event_pool->count = count;
+ event_pool->reg = CALLOC (event_pool->count,
+ sizeof (*event_pool->reg));
+
+ if (!event_pool->reg) {
+ gf_log ("poll", GF_LOG_CRITICAL,
+ "failed to allocate event registry");
+ free (event_pool);
+ return NULL;
+ }
+
+ pthread_mutex_init (&event_pool->mutex, NULL);
+
+ ret = pipe (event_pool->breaker);
+
+ if (ret == -1) {
+ gf_log ("poll", GF_LOG_ERROR,
+ "pipe creation failed (%s)", strerror (errno));
+ free (event_pool->reg);
+ free (event_pool);
+ return NULL;
+ }
+
+ ret = fcntl (event_pool->breaker[0], F_SETFL, O_NONBLOCK);
+ if (ret == -1) {
+ gf_log ("poll", GF_LOG_ERROR,
+ "could not set pipe to non blocking mode (%s)",
+ strerror (errno));
+ close (event_pool->breaker[0]);
+ close (event_pool->breaker[1]);
+ event_pool->breaker[0] = event_pool->breaker[1] = -1;
+
+ free (event_pool->reg);
+ free (event_pool);
+ return NULL;
+ }
+
+ ret = fcntl (event_pool->breaker[1], F_SETFL, O_NONBLOCK);
+ if (ret == -1) {
+ gf_log ("poll", GF_LOG_ERROR,
+ "could not set pipe to non blocking mode (%s)",
+ strerror (errno));
+
+ close (event_pool->breaker[0]);
+ close (event_pool->breaker[1]);
+ event_pool->breaker[0] = event_pool->breaker[1] = -1;
+
+ free (event_pool->reg);
+ free (event_pool);
+ return NULL;
+ }
+
+ ret = event_register_poll (event_pool, event_pool->breaker[0],
+ __flush_fd, NULL, 1, 0);
+ if (ret == -1) {
+ gf_log ("poll", GF_LOG_ERROR,
+ "could not register pipe fd with poll event loop");
+ close (event_pool->breaker[0]);
+ close (event_pool->breaker[1]);
+ event_pool->breaker[0] = event_pool->breaker[1] = -1;
+
+ free (event_pool->reg);
+ free (event_pool);
+ return NULL;
+ }
+
+ return event_pool;
+}
+
+
+static int
+event_register_poll (struct event_pool *event_pool, int fd,
+ event_handler_t handler,
+ void *data, int poll_in, int poll_out)
+{
+ int idx = -1;
+
+ if (event_pool == NULL) {
+ gf_log ("event", GF_LOG_ERROR, "invalid argument");
+ return -1;
+ }
+
+ pthread_mutex_lock (&event_pool->mutex);
+ {
+ if (event_pool->count == event_pool->used)
+ {
+ event_pool->count += 256;
+
+ event_pool->reg = realloc (event_pool->reg,
+ event_pool->count *
+ sizeof (*event_pool->reg));
+ }
+
+ idx = event_pool->used++;
+
+ event_pool->reg[idx].fd = fd;
+ event_pool->reg[idx].events = POLLPRI;
+ event_pool->reg[idx].handler = handler;
+ event_pool->reg[idx].data = data;
+
+ switch (poll_in) {
+ case 1:
+ event_pool->reg[idx].events |= POLLIN;
+ break;
+ case 0:
+ event_pool->reg[idx].events &= ~POLLIN;
+ break;
+ case -1:
+ /* do nothing */
+ break;
+ default:
+ gf_log ("poll", GF_LOG_ERROR,
+ "invalid poll_in value %d", poll_in);
+ break;
+ }
+
+ switch (poll_out) {
+ case 1:
+ event_pool->reg[idx].events |= POLLOUT;
+ break;
+ case 0:
+ event_pool->reg[idx].events &= ~POLLOUT;
+ break;
+ case -1:
+ /* do nothing */
+ break;
+ default:
+ gf_log ("poll", GF_LOG_ERROR,
+ "invalid poll_out value %d", poll_in);
+ break;
+ }
+
+ event_pool->changed = 1;
+
+ }
+ pthread_mutex_unlock (&event_pool->mutex);
+
+ return idx;
+}
+
+
+static int
+event_unregister_poll (struct event_pool *event_pool, int fd, int idx_hint)
+{
+ int idx = -1;
+
+ if (event_pool == NULL) {
+ gf_log ("event", GF_LOG_ERROR, "invalid argument");
+ return -1;
+ }
+
+ pthread_mutex_lock (&event_pool->mutex);
+ {
+ idx = __event_getindex (event_pool, fd, idx_hint);
+
+ if (idx == -1) {
+ gf_log ("poll", GF_LOG_ERROR,
+ "index not found for fd=%d (idx_hint=%d)",
+ fd, idx_hint);
+ errno = ENOENT;
+ goto unlock;
+ }
+
+ event_pool->reg[idx] = event_pool->reg[--event_pool->used];
+ event_pool->changed = 1;
+ }
+unlock:
+ pthread_mutex_unlock (&event_pool->mutex);
+
+ return idx;
+}
+
+
+static int
+event_select_on_poll (struct event_pool *event_pool, int fd, int idx_hint,
+ int poll_in, int poll_out)
+{
+ int idx = -1;
+
+ if (event_pool == NULL) {
+ gf_log ("event", GF_LOG_ERROR, "invalid argument");
+ return -1;
+ }
+
+ pthread_mutex_lock (&event_pool->mutex);
+ {
+ idx = __event_getindex (event_pool, fd, idx_hint);
+
+ if (idx == -1) {
+ gf_log ("poll", GF_LOG_ERROR,
+ "index not found for fd=%d (idx_hint=%d)",
+ fd, idx_hint);
+ errno = ENOENT;
+ goto unlock;
+ }
+
+ switch (poll_in) {
+ case 1:
+ event_pool->reg[idx].events |= POLLIN;
+ break;
+ case 0:
+ event_pool->reg[idx].events &= ~POLLIN;
+ break;
+ case -1:
+ /* do nothing */
+ break;
+ default:
+ /* TODO: log error */
+ break;
+ }
+
+ switch (poll_out) {
+ case 1:
+ event_pool->reg[idx].events |= POLLOUT;
+ break;
+ case 0:
+ event_pool->reg[idx].events &= ~POLLOUT;
+ break;
+ case -1:
+ /* do nothing */
+ break;
+ default:
+ /* TODO: log error */
+ break;
+ }
+
+ if (poll_in + poll_out > -2)
+ event_pool->changed = 1;
+ }
+unlock:
+ pthread_mutex_unlock (&event_pool->mutex);
+
+ return idx;
+}
+
+
+static int
+event_dispatch_poll_handler (struct event_pool *event_pool,
+ struct pollfd *ufds, int i)
+{
+ event_handler_t handler = NULL;
+ void *data = NULL;
+ int idx = -1;
+ int ret = 0;
+
+ handler = NULL;
+ data = NULL;
+ idx = -1;
+
+ pthread_mutex_lock (&event_pool->mutex);
+ {
+ idx = __event_getindex (event_pool, ufds[i].fd, i);
+
+ if (idx == -1) {
+ gf_log ("poll", GF_LOG_ERROR,
+ "index not found for fd=%d (idx_hint=%d)",
+ ufds[i].fd, i);
+ goto unlock;
+ }
+
+ handler = event_pool->reg[idx].handler;
+ data = event_pool->reg[idx].data;
+ }
+unlock:
+ pthread_mutex_unlock (&event_pool->mutex);
+
+ if (handler)
+ ret = handler (ufds[i].fd, idx, data,
+ (ufds[i].revents & (POLLIN|POLLPRI)),
+ (ufds[i].revents & (POLLOUT)),
+ (ufds[i].revents & (POLLERR|POLLHUP|POLLNVAL)));
+
+ return ret;
+}
+
+
+static int
+event_dispatch_poll_resize (struct event_pool *event_pool,
+ struct pollfd *ufds, int size)
+{
+ int i = 0;
+
+ pthread_mutex_lock (&event_pool->mutex);
+ {
+ if (event_pool->changed == 0) {
+ goto unlock;
+ }
+
+ if (event_pool->used > event_pool->evcache_size) {
+ if (event_pool->evcache)
+ free (event_pool->evcache);
+
+ event_pool->evcache = ufds = NULL;
+
+ event_pool->evcache_size = event_pool->used;
+
+ ufds = CALLOC (sizeof (struct pollfd),
+ event_pool->evcache_size);
+ event_pool->evcache = ufds;
+ }
+
+ for (i = 0; i < event_pool->used; i++) {
+ ufds[i].fd = event_pool->reg[i].fd;
+ ufds[i].events = event_pool->reg[i].events;
+ ufds[i].revents = 0;
+ }
+
+ size = i;
+ }
+unlock:
+ pthread_mutex_unlock (&event_pool->mutex);
+
+ return size;
+}
+
+
+static int
+event_dispatch_poll (struct event_pool *event_pool)
+{
+ struct pollfd *ufds = NULL;
+ int size = 0;
+ int i = 0;
+ int ret = -1;
+
+
+ if (event_pool == NULL) {
+ gf_log ("event", GF_LOG_ERROR, "invalid argument");
+ return -1;
+ }
+
+ while (1) {
+ size = event_dispatch_poll_resize (event_pool, ufds, size);
+ ufds = event_pool->evcache;
+
+ ret = poll (ufds, size, 1);
+
+ if (ret == 0)
+ /* timeout */
+ continue;
+
+ if (ret == -1 && errno == EINTR)
+ /* sys call */
+ continue;
+
+ for (i = 0; i < size; i++) {
+ if (!ufds[i].revents)
+ continue;
+
+ event_dispatch_poll_handler (event_pool, ufds, i);
+ }
+ }
+
+ return -1;
+}
+
+
+static struct event_ops event_ops_poll = {
+ .new = event_pool_new_poll,
+ .event_register = event_register_poll,
+ .event_select_on = event_select_on_poll,
+ .event_unregister = event_unregister_poll,
+ .event_dispatch = event_dispatch_poll
+};
+
+
+
+#ifdef HAVE_SYS_EPOLL_H
+#include <sys/epoll.h>
+
+
+static struct event_pool *
+event_pool_new_epoll (int count)
+{
+ struct event_pool *event_pool = NULL;
+ int epfd = -1;
+
+ event_pool = CALLOC (1, sizeof (*event_pool));
+
+ if (!event_pool)
+ return NULL;
+
+ event_pool->count = count;
+ event_pool->reg = CALLOC (event_pool->count,
+ sizeof (*event_pool->reg));
+
+ if (!event_pool->reg) {
+ gf_log ("epoll", GF_LOG_CRITICAL,
+ "event registry allocation failed");
+ free (event_pool);
+ return NULL;
+ }
+
+ epfd = epoll_create (count);
+
+ if (epfd == -1) {
+ gf_log ("epoll", GF_LOG_ERROR, "epoll fd creation failed (%s)",
+ strerror (errno));
+ free (event_pool->reg);
+ free (event_pool);
+ return NULL;
+ }
+
+ event_pool->fd = epfd;
+
+ event_pool->count = count;
+
+ pthread_mutex_init (&event_pool->mutex, NULL);
+ pthread_cond_init (&event_pool->cond, NULL);
+
+ return event_pool;
+}
+
+
+int
+event_register_epoll (struct event_pool *event_pool, int fd,
+ event_handler_t handler,
+ void *data, int poll_in, int poll_out)
+{
+ int idx = -1;
+ int ret = -1;
+ struct epoll_event epoll_event = {0, };
+ struct event_data *ev_data = (void *)&epoll_event.data;
+
+
+ if (event_pool == NULL) {
+ gf_log ("event", GF_LOG_ERROR, "invalid argument");
+ return -1;
+ }
+
+ pthread_mutex_lock (&event_pool->mutex);
+ {
+ if (event_pool->count == event_pool->used) {
+ event_pool->count *= 2;
+
+ event_pool->reg = realloc (event_pool->reg,
+ event_pool->count *
+ sizeof (*event_pool->reg));
+
+ if (!event_pool->reg) {
+ gf_log ("epoll", GF_LOG_ERROR,
+ "event registry re-allocation failed");
+ goto unlock;
+ }
+ }
+
+ idx = event_pool->used;
+ event_pool->used++;
+
+ event_pool->reg[idx].fd = fd;
+ event_pool->reg[idx].events = EPOLLPRI;
+ event_pool->reg[idx].handler = handler;
+ event_pool->reg[idx].data = data;
+
+ switch (poll_in) {
+ case 1:
+ event_pool->reg[idx].events |= EPOLLIN;
+ break;
+ case 0:
+ event_pool->reg[idx].events &= ~EPOLLIN;
+ break;
+ case -1:
+ /* do nothing */
+ break;
+ default:
+ gf_log ("epoll", GF_LOG_ERROR,
+ "invalid poll_in value %d", poll_in);
+ break;
+ }
+
+ switch (poll_out) {
+ case 1:
+ event_pool->reg[idx].events |= EPOLLOUT;
+ break;
+ case 0:
+ event_pool->reg[idx].events &= ~EPOLLOUT;
+ break;
+ case -1:
+ /* do nothing */
+ break;
+ default:
+ gf_log ("epoll", GF_LOG_ERROR,
+ "invalid poll_out value %d", poll_in);
+ break;
+ }
+
+ event_pool->changed = 1;
+
+ epoll_event.events = event_pool->reg[idx].events;
+ ev_data->fd = fd;
+ ev_data->idx = idx;
+
+ ret = epoll_ctl (event_pool->fd, EPOLL_CTL_ADD, fd,
+ &epoll_event);
+
+ if (ret == -1) {
+ gf_log ("epoll", GF_LOG_ERROR,
+ "failed to add fd(=%d) to epoll fd(=%d) (%s)",
+ fd, event_pool->fd, strerror (errno));
+ goto unlock;
+ }
+
+ pthread_cond_broadcast (&event_pool->cond);
+ }
+unlock:
+ pthread_mutex_unlock (&event_pool->mutex);
+
+ return ret;
+}
+
+
+static int
+event_unregister_epoll (struct event_pool *event_pool, int fd, int idx_hint)
+{
+ int idx = -1;
+ int ret = -1;
+
+ struct epoll_event epoll_event = {0, };
+ struct event_data *ev_data = (void *)&epoll_event.data;
+ int lastidx = -1;
+
+ if (event_pool == NULL) {
+ gf_log ("event", GF_LOG_ERROR, "invalid argument");
+ return -1;
+ }
+
+ pthread_mutex_lock (&event_pool->mutex);
+ {
+ idx = __event_getindex (event_pool, fd, idx_hint);
+
+ if (idx == -1) {
+ gf_log ("epoll", GF_LOG_ERROR,
+ "index not found for fd=%d (idx_hint=%d)",
+ fd, idx_hint);
+ errno = ENOENT;
+ goto unlock;
+ }
+
+ ret = epoll_ctl (event_pool->fd, EPOLL_CTL_DEL, fd, NULL);
+
+ /* if ret is -1, this array member should never be accessed */
+ /* if it is 0, the array member might be used by idx_cache
+ * in which case the member should not be accessed till
+ * it is reallocated
+ */
+
+ event_pool->reg[idx].fd = -1;
+
+ if (ret == -1) {
+ gf_log ("epoll", GF_LOG_ERROR,
+ "fail to del fd(=%d) from epoll fd(=%d) (%s)",
+ fd, event_pool->fd, strerror (errno));
+ goto unlock;
+ }
+
+ lastidx = event_pool->used - 1;
+ if (lastidx == idx) {
+ event_pool->used--;
+ goto unlock;
+ }
+
+ epoll_event.events = event_pool->reg[lastidx].events;
+ ev_data->fd = event_pool->reg[lastidx].fd;
+ ev_data->idx = idx;
+
+ ret = epoll_ctl (event_pool->fd, EPOLL_CTL_MOD, ev_data->fd,
+ &epoll_event);
+ if (ret == -1) {
+ gf_log ("epoll", GF_LOG_ERROR,
+ "fail to modify fd(=%d) index %d to %d (%s)",
+ ev_data->fd, event_pool->used, idx,
+ strerror (errno));
+ goto unlock;
+ }
+
+ /* just replace the unregistered idx by last one */
+ event_pool->reg[idx] = event_pool->reg[lastidx];
+ event_pool->used--;
+ }
+unlock:
+ pthread_mutex_unlock (&event_pool->mutex);
+
+ return ret;
+}
+
+
+static int
+event_select_on_epoll (struct event_pool *event_pool, int fd, int idx_hint,
+ int poll_in, int poll_out)
+{
+ int idx = -1;
+ int ret = -1;
+
+ struct epoll_event epoll_event = {0, };
+ struct event_data *ev_data = (void *)&epoll_event.data;
+
+
+ if (event_pool == NULL) {
+ gf_log ("event", GF_LOG_ERROR, "invalid argument");
+ return -1;
+ }
+
+ pthread_mutex_lock (&event_pool->mutex);
+ {
+ idx = __event_getindex (event_pool, fd, idx_hint);
+
+ if (idx == -1) {
+ gf_log ("epoll", GF_LOG_ERROR,
+ "index not found for fd=%d (idx_hint=%d)",
+ fd, idx_hint);
+ errno = ENOENT;
+ goto unlock;
+ }
+
+ switch (poll_in) {
+ case 1:
+ event_pool->reg[idx].events |= EPOLLIN;
+ break;
+ case 0:
+ event_pool->reg[idx].events &= ~EPOLLIN;
+ break;
+ case -1:
+ /* do nothing */
+ break;
+ default:
+ gf_log ("epoll", GF_LOG_ERROR,
+ "invalid poll_in value %d", poll_in);
+ break;
+ }
+
+ switch (poll_out) {
+ case 1:
+ event_pool->reg[idx].events |= EPOLLOUT;
+ break;
+ case 0:
+ event_pool->reg[idx].events &= ~EPOLLOUT;
+ break;
+ case -1:
+ /* do nothing */
+ break;
+ default:
+ gf_log ("epoll", GF_LOG_ERROR,
+ "invalid poll_out value %d", poll_in);
+ break;
+ }
+
+ epoll_event.events = event_pool->reg[idx].events;
+ ev_data->fd = fd;
+ ev_data->idx = idx;
+
+ ret = epoll_ctl (event_pool->fd, EPOLL_CTL_MOD, fd,
+ &epoll_event);
+ if (ret == -1) {
+ gf_log ("epoll", GF_LOG_ERROR,
+ "failed to modify fd(=%d) events to %d",
+ fd, epoll_event.events);
+ }
+ }
+unlock:
+ pthread_mutex_unlock (&event_pool->mutex);
+
+ return ret;
+}
+
+
+static int
+event_dispatch_epoll_handler (struct event_pool *event_pool,
+ struct epoll_event *events, int i)
+{
+ struct event_data *event_data = NULL;
+ event_handler_t handler = NULL;
+ void *data = NULL;
+ int idx = -1;
+ int ret = -1;
+
+
+ event_data = (void *)&events[i].data;
+ handler = NULL;
+ data = NULL;
+ idx = -1;
+
+ pthread_mutex_lock (&event_pool->mutex);
+ {
+ idx = __event_getindex (event_pool, event_data->fd,
+ event_data->idx);
+
+ if (idx == -1) {
+ gf_log ("epoll", GF_LOG_ERROR,
+ "index not found for fd(=%d) (idx_hint=%d)",
+ event_data->fd, event_data->idx);
+ goto unlock;
+ }
+
+ handler = event_pool->reg[idx].handler;
+ data = event_pool->reg[idx].data;
+ }
+unlock:
+ pthread_mutex_unlock (&event_pool->mutex);
+
+ if (handler)
+ ret = handler (event_data->fd, event_data->idx, data,
+ (events[i].events & (EPOLLIN|EPOLLPRI)),
+ (events[i].events & (EPOLLOUT)),
+ (events[i].events & (EPOLLERR|EPOLLHUP)));
+ return ret;
+}
+
+
+static int
+event_dispatch_epoll (struct event_pool *event_pool)
+{
+ struct epoll_event *events = NULL;
+ int size = 0;
+ int i = 0;
+ int ret = -1;
+
+
+ if (event_pool == NULL) {
+ gf_log ("event", GF_LOG_ERROR, "invalid argument");
+ return -1;
+ }
+
+ while (1) {
+ pthread_mutex_lock (&event_pool->mutex);
+ {
+ while (event_pool->used == 0)
+ pthread_cond_wait (&event_pool->cond,
+ &event_pool->mutex);
+
+ if (event_pool->used > event_pool->evcache_size) {
+ if (event_pool->evcache)
+ free (event_pool->evcache);
+
+ event_pool->evcache = events = NULL;
+
+ event_pool->evcache_size =
+ event_pool->used + 256;
+
+ events = CALLOC (event_pool->evcache_size,
+ sizeof (struct epoll_event));
+
+ event_pool->evcache = events;
+ }
+ }
+ pthread_mutex_unlock (&event_pool->mutex);
+
+ ret = epoll_wait (event_pool->fd, event_pool->evcache,
+ event_pool->evcache_size, -1);
+
+ if (ret == 0)
+ /* timeout */
+ continue;
+
+ if (ret == -1 && errno == EINTR)
+ /* sys call */
+ continue;
+
+ size = ret;
+
+ for (i = 0; i < size; i++) {
+ if (!events[i].events)
+ continue;
+
+ ret = event_dispatch_epoll_handler (event_pool,
+ events, i);
+ }
+ }
+
+ return -1;
+}
+
+
+static struct event_ops event_ops_epoll = {
+ .new = event_pool_new_epoll,
+ .event_register = event_register_epoll,
+ .event_select_on = event_select_on_epoll,
+ .event_unregister = event_unregister_epoll,
+ .event_dispatch = event_dispatch_epoll
+};
+
+#endif
+
+
+struct event_pool *
+event_pool_new (int count)
+{
+ struct event_pool *event_pool = NULL;
+
+#ifdef HAVE_SYS_EPOLL_H
+ event_pool = event_ops_epoll.new (count);
+
+ if (event_pool) {
+ event_pool->ops = &event_ops_epoll;
+ } else {
+ gf_log ("event", GF_LOG_WARNING,
+ "failing back to poll based event handling");
+ }
+#endif
+
+ if (!event_pool) {
+ event_pool = event_ops_poll.new (count);
+
+ if (event_pool)
+ event_pool->ops = &event_ops_poll;
+ }
+
+ return event_pool;
+}
+
+
+int
+event_register (struct event_pool *event_pool, int fd,
+ event_handler_t handler,
+ void *data, int poll_in, int poll_out)
+{
+ int ret = -1;
+
+ if (event_pool == NULL) {
+ gf_log ("event", GF_LOG_ERROR, "invalid argument");
+ return -1;
+ }
+
+ ret = event_pool->ops->event_register (event_pool, fd, handler, data,
+ poll_in, poll_out);
+ return ret;
+}
+
+
+int
+event_unregister (struct event_pool *event_pool, int fd, int idx)
+{
+ int ret = -1;
+
+ if (event_pool == NULL) {
+ gf_log ("event", GF_LOG_ERROR, "invalid argument");
+ return -1;
+ }
+
+ ret = event_pool->ops->event_unregister (event_pool, fd, idx);
+
+ return ret;
+}
+
+
+int
+event_select_on (struct event_pool *event_pool, int fd, int idx_hint,
+ int poll_in, int poll_out)
+{
+ int ret = -1;
+
+ if (event_pool == NULL) {
+ gf_log ("event", GF_LOG_ERROR, "invalid argument");
+ return -1;
+ }
+
+ ret = event_pool->ops->event_select_on (event_pool, fd, idx_hint,
+ poll_in, poll_out);
+ return ret;
+}
+
+
+int
+event_dispatch (struct event_pool *event_pool)
+{
+ int ret = -1;
+
+ if (event_pool == NULL) {
+ gf_log ("event", GF_LOG_ERROR, "invalid argument");
+ return -1;
+ }
+
+ ret = event_pool->ops->event_dispatch (event_pool);
+
+ return ret;
+}
diff --git a/libglusterfs/src/event.h b/libglusterfs/src/event.h
new file mode 100644
index 000000000..ec80e2a58
--- /dev/null
+++ b/libglusterfs/src/event.h
@@ -0,0 +1,90 @@
+/*
+ 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/>.
+*/
+
+#ifndef _EVENT_H_
+#define _EVENT_H_
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+
+struct event_pool;
+struct event_ops;
+struct event_data {
+ int fd;
+ int idx;
+} __attribute__ ((__packed__));
+
+
+typedef int (*event_handler_t) (int fd, int idx, void *data,
+ int poll_in, int poll_out, int poll_err);
+
+struct event_pool {
+ struct event_ops *ops;
+
+ int fd;
+ int breaker[2];
+
+ int count;
+ struct {
+ int fd;
+ int events;
+ void *data;
+ event_handler_t handler;
+ } *reg;
+
+ int used;
+ int idx_cache;
+ int changed;
+
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+
+ void *evcache;
+ int evcache_size;
+};
+
+struct event_ops {
+ struct event_pool * (*new) (int count);
+
+ int (*event_register) (struct event_pool *event_pool, int fd,
+ event_handler_t handler,
+ void *data, int poll_in, int poll_out);
+
+ int (*event_select_on) (struct event_pool *event_pool, int fd, int idx,
+ int poll_in, int poll_out);
+
+ int (*event_unregister) (struct event_pool *event_pool, int fd, int idx);
+
+ int (*event_dispatch) (struct event_pool *event_pool);
+};
+
+struct event_pool * event_pool_new (int count);
+int event_select_on (struct event_pool *event_pool, int fd, int idx,
+ int poll_in, int poll_out);
+int event_register (struct event_pool *event_pool, int fd,
+ event_handler_t handler,
+ void *data, int poll_in, int poll_out);
+int event_unregister (struct event_pool *event_pool, int fd, int idx);
+int event_dispatch (struct event_pool *event_pool);
+
+#endif /* _EVENT_H_ */
diff --git a/libglusterfs/src/fd.c b/libglusterfs/src/fd.c
new file mode 100644
index 000000000..78c578842
--- /dev/null
+++ b/libglusterfs/src/fd.c
@@ -0,0 +1,611 @@
+/*
+ Copyright (c) 2007, 2008, 2009 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 "fd.h"
+#include "glusterfs.h"
+#include "inode.h"
+#include "dict.h"
+
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+
+static uint32_t
+gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr);
+
+static fd_t *
+_fd_ref (fd_t *fd);
+
+/*
+ Allocate in memory chunks of power of 2 starting from 1024B
+ Assumes fdtable->lock is held
+*/
+static inline uint32_t
+gf_roundup_power_of_two (uint32_t nr)
+{
+ uint32_t result = nr;
+
+ if (nr < 0) {
+ gf_log ("server-protocol/fd",
+ GF_LOG_ERROR,
+ "Negative number passed");
+ return -1;
+ }
+
+ switch (nr) {
+ case 0:
+ case 1:
+ result = 1;
+ break;
+
+ default:
+ {
+ uint32_t cnt = 0, tmp = nr;
+ uint8_t remainder = 0;
+ while (tmp != 1){
+ if (tmp % 2)
+ remainder = 1;
+ tmp /= 2;
+ cnt++;
+ }
+
+ if (remainder)
+ result = 0x1 << (cnt + 1);
+ break;
+ }
+ }
+
+ return result;
+}
+
+static uint32_t
+gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr)
+{
+ fd_t **oldfds = NULL;
+ uint32_t oldmax_fds = -1;
+
+ if (fdtable == NULL || nr < 0)
+ {
+ gf_log ("fd", GF_LOG_ERROR, "invalid argument");
+ return EINVAL;
+ }
+
+ nr /= (1024 / sizeof (fd_t *));
+ nr = gf_roundup_power_of_two (nr + 1);
+ nr *= (1024 / sizeof (fd_t *));
+
+ oldfds = fdtable->fds;
+ oldmax_fds = fdtable->max_fds;
+
+ fdtable->fds = CALLOC (nr, sizeof (fd_t *));
+ ERR_ABORT (fdtable->fds);
+ fdtable->max_fds = nr;
+
+ if (oldfds) {
+ uint32_t cpy = oldmax_fds * sizeof (fd_t *);
+ memcpy (fdtable->fds, oldfds, cpy);
+ }
+
+ FREE (oldfds);
+ return 0;
+}
+
+fdtable_t *
+gf_fd_fdtable_alloc (void)
+{
+ fdtable_t *fdtable = NULL;
+
+ fdtable = CALLOC (1, sizeof (*fdtable));
+ if (!fdtable)
+ return NULL;
+
+ pthread_mutex_init (&fdtable->lock, NULL);
+
+ pthread_mutex_lock (&fdtable->lock);
+ {
+ gf_fd_fdtable_expand (fdtable, 0);
+ }
+ pthread_mutex_unlock (&fdtable->lock);
+
+ return fdtable;
+}
+
+void
+gf_fd_fdtable_destroy (fdtable_t *fdtable)
+{
+
+ int32_t i = 0;
+
+ if (fdtable) {
+ pthread_mutex_lock (&fdtable->lock);
+ {
+ for (i=0; i < fdtable->max_fds; i++) {
+ if (fdtable->fds[i]) {
+ fd_t *fd = fdtable->fds[i];
+
+ fd_unref (fd);
+ }
+ }
+
+ FREE (fdtable->fds);
+ }
+ pthread_mutex_unlock (&fdtable->lock);
+ pthread_mutex_destroy (&fdtable->lock);
+ FREE (fdtable);
+ }
+}
+
+int32_t
+gf_fd_unused_get2 (fdtable_t *fdtable, fd_t *fdptr, int32_t fd)
+{
+ int32_t ret = -1;
+
+ if (fdtable == NULL || fdptr == NULL || fd < 0)
+ {
+ gf_log ("fd", GF_LOG_ERROR, "invalid argument");
+ errno = EINVAL;
+ return -1;
+ }
+
+ pthread_mutex_lock (&fdtable->lock);
+ {
+ while (fdtable->max_fds < fd) {
+ int error = 0;
+ error = gf_fd_fdtable_expand (fdtable, fdtable->max_fds + 1);
+ if (error)
+ {
+ gf_log ("fd.c",
+ GF_LOG_ERROR,
+ "Cannot expand fdtable:%s", strerror (error));
+ goto err;
+ }
+ }
+
+ if (!fdtable->fds[fd])
+ {
+ fdtable->fds[fd] = fdptr;
+ fd_ref (fdptr);
+ ret = fd;
+ }
+ else
+ {
+ gf_log ("fd.c",
+ GF_LOG_ERROR,
+ "Cannot allocate fd %d (slot not empty in fdtable)", fd);
+ }
+ }
+err:
+ pthread_mutex_unlock (&fdtable->lock);
+
+ return ret;
+}
+
+
+int32_t
+gf_fd_unused_get (fdtable_t *fdtable, fd_t *fdptr)
+{
+ int32_t fd = -1, i = 0;
+
+ if (fdtable == NULL || fdptr == NULL)
+ {
+ gf_log ("fd", GF_LOG_ERROR, "invalid argument");
+ return EINVAL;
+ }
+
+ pthread_mutex_lock (&fdtable->lock);
+ {
+ for (i = 0; i<fdtable->max_fds; i++)
+ {
+ if (!fdtable->fds[i])
+ break;
+ }
+
+ if (i < fdtable->max_fds) {
+ fdtable->fds[i] = fdptr;
+ fd = i;
+ } else {
+ int32_t error;
+ error = gf_fd_fdtable_expand (fdtable, fdtable->max_fds + 1);
+ if (error) {
+ gf_log ("server-protocol.c",
+ GF_LOG_ERROR,
+ "Cannot expand fdtable:%s", strerror (error));
+ } else {
+ fdtable->fds[i] = fdptr;
+ fd = i;
+ }
+ }
+ }
+ pthread_mutex_unlock (&fdtable->lock);
+
+ return fd;
+}
+
+
+inline void
+gf_fd_put (fdtable_t *fdtable, int32_t fd)
+{
+ fd_t *fdptr = NULL;
+ if (fdtable == NULL || fd < 0)
+ {
+ gf_log ("fd", GF_LOG_ERROR, "invalid argument");
+ return;
+ }
+
+ if (!(fd < fdtable->max_fds))
+ {
+ gf_log ("fd", GF_LOG_ERROR, "invalid argument");
+ return;
+ }
+
+ pthread_mutex_lock (&fdtable->lock);
+ {
+ fdptr = fdtable->fds[fd];
+ fdtable->fds[fd] = NULL;
+ }
+ pthread_mutex_unlock (&fdtable->lock);
+
+ if (fdptr) {
+ fd_unref (fdptr);
+ }
+}
+
+
+fd_t *
+gf_fd_fdptr_get (fdtable_t *fdtable, int64_t fd)
+{
+ fd_t *fdptr = NULL;
+
+ if (fdtable == NULL || fd < 0)
+ {
+ gf_log ("fd", GF_LOG_ERROR, "invalid argument");
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (!(fd < fdtable->max_fds))
+ {
+ gf_log ("fd", GF_LOG_ERROR, "invalid argument");
+ errno = EINVAL;
+ return NULL;
+ }
+
+ pthread_mutex_lock (&fdtable->lock);
+ {
+ fdptr = fdtable->fds[fd];
+ if (fdptr) {
+ fd_ref (fdptr);
+ }
+ }
+ pthread_mutex_unlock (&fdtable->lock);
+
+ return fdptr;
+}
+
+fd_t *
+_fd_ref (fd_t *fd)
+{
+ ++fd->refcount;
+
+ return fd;
+}
+
+fd_t *
+fd_ref (fd_t *fd)
+{
+ fd_t *refed_fd = NULL;
+
+ if (!fd) {
+ gf_log ("fd", GF_LOG_ERROR, "@fd=%p", fd);
+ return NULL;
+ }
+
+ LOCK (&fd->inode->lock);
+ refed_fd = _fd_ref (fd);
+ UNLOCK (&fd->inode->lock);
+
+ return refed_fd;
+}
+
+fd_t *
+_fd_unref (fd_t *fd)
+{
+ assert (fd->refcount);
+
+ --fd->refcount;
+
+ if (fd->refcount == 0){
+ list_del_init (&fd->inode_list);
+ }
+
+ return fd;
+}
+
+static void
+fd_destroy (fd_t *fd)
+{
+ data_pair_t *pair = NULL;
+ xlator_t *xl = NULL;
+ int i = 0;
+
+ if (fd == NULL){
+ gf_log ("xlator", GF_LOG_ERROR, "invalid arugument");
+ goto out;
+ }
+
+ if (fd->inode == NULL){
+ gf_log ("xlator", GF_LOG_ERROR, "fd->inode is NULL");
+ goto out;
+ }
+ if (!fd->_ctx)
+ goto out;
+
+ if (S_ISDIR (fd->inode->st_mode)) {
+ for (pair = fd->ctx->members_list; pair; pair = pair->next) {
+ /* notify all xlators which have a context */
+ xl = xlator_search_by_name (fd->inode->table->xl,
+ pair->key);
+
+ if (!xl) {
+ gf_log ("fd", GF_LOG_CRITICAL,
+ "fd(%p)->ctx has invalid key(%s)",
+ fd, pair->key);
+ continue;
+ }
+ if (xl->cbks->releasedir) {
+ xl->cbks->releasedir (xl, fd);
+ } else {
+ gf_log ("fd", GF_LOG_CRITICAL,
+ "xlator(%s) in fd(%p) no RELEASE cbk",
+ xl->name, fd);
+ }
+
+ }
+ for (i = 0; i < fd->inode->table->xl->ctx->xl_count; i++) {
+ if (fd->_ctx[i].key) {
+ xl = (xlator_t *)(long)fd->_ctx[i].key;
+ if (xl->cbks->releasedir)
+ xl->cbks->releasedir (xl, fd);
+ }
+ }
+ } else {
+ for (pair = fd->ctx->members_list; pair; pair = pair->next) {
+ /* notify all xlators which have a context */
+ xl = xlator_search_by_name (fd->inode->table->xl,
+ pair->key);
+
+ if (!xl) {
+ gf_log ("fd", GF_LOG_CRITICAL,
+ "fd(%p)->ctx has invalid key(%s)",
+ fd, pair->key);
+ continue;
+ }
+ if (xl->cbks->release) {
+ xl->cbks->release (xl, fd);
+ } else {
+ gf_log ("fd", GF_LOG_CRITICAL,
+ "xlator(%s) in fd(%p) no RELEASE cbk",
+ xl->name, fd);
+ }
+ }
+ for (i = 0; i < fd->inode->table->xl->ctx->xl_count; i++) {
+ if (fd->_ctx[i].key) {
+ xl = (xlator_t *)(long)fd->_ctx[i].key;
+ if (xl->cbks->release)
+ xl->cbks->release (xl, fd);
+ }
+ }
+ }
+
+ FREE (fd->_ctx);
+ inode_unref (fd->inode);
+ fd->inode = (inode_t *)0xaaaaaaaa;
+ dict_destroy (fd->ctx);
+ FREE (fd);
+
+out:
+ return;
+}
+
+void
+fd_unref (fd_t *fd)
+{
+ int32_t refcount = 0;
+
+ if (!fd) {
+ gf_log ("fd.c", GF_LOG_ERROR, "fd is NULL");
+ return;
+ }
+
+ LOCK (&fd->inode->lock);
+ {
+ _fd_unref (fd);
+ refcount = fd->refcount;
+ }
+ UNLOCK (&fd->inode->lock);
+
+ if (refcount == 0) {
+ fd_destroy (fd);
+ }
+
+ return ;
+}
+
+fd_t *
+fd_bind (fd_t *fd)
+{
+ inode_t *inode = fd->inode;
+
+ if (!fd) {
+ gf_log ("fd.c", GF_LOG_ERROR, "fd is NULL");
+ return NULL;
+ }
+
+ LOCK (&inode->lock);
+ {
+ list_add (&fd->inode_list, &inode->fd_list);
+ }
+ UNLOCK (&inode->lock);
+
+ return fd;
+}
+
+fd_t *
+fd_create (inode_t *inode, pid_t pid)
+{
+ fd_t *fd = NULL;
+
+ if (inode == NULL) {
+ gf_log ("fd", GF_LOG_ERROR, "invalid argument");
+ return NULL;
+ }
+
+ fd = CALLOC (1, sizeof (fd_t));
+ ERR_ABORT (fd);
+
+ fd->_ctx = CALLOC (1, (sizeof (struct _fd_ctx) *
+ inode->table->xl->ctx->xl_count));
+ fd->ctx = get_new_dict ();
+ fd->inode = inode_ref (inode);
+ fd->pid = pid;
+ INIT_LIST_HEAD (&fd->inode_list);
+
+ LOCK (&inode->lock);
+ fd = _fd_ref (fd);
+ UNLOCK (&inode->lock);
+
+ return fd;
+}
+
+fd_t *
+fd_lookup (inode_t *inode, pid_t pid)
+{
+ fd_t *fd = NULL;
+ fd_t *iter_fd = NULL;
+
+ LOCK (&inode->lock);
+ {
+ if (list_empty (&inode->fd_list)) {
+ fd = NULL;
+ } else {
+ list_for_each_entry (iter_fd, &inode->fd_list, inode_list) {
+ if (pid) {
+ if (iter_fd->pid == pid) {
+ fd = _fd_ref (iter_fd);
+ break;
+ }
+ } else {
+ fd = _fd_ref (iter_fd);
+ break;
+ }
+ }
+ }
+ }
+ UNLOCK (&inode->lock);
+
+ return fd;
+}
+
+uint8_t
+fd_list_empty (inode_t *inode)
+{
+ uint8_t empty = 0;
+
+ LOCK (&inode->lock);
+ {
+ empty = list_empty (&inode->fd_list);
+ }
+ UNLOCK (&inode->lock);
+
+ return empty;
+}
+
+int
+fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value)
+{
+ int index = 0;
+
+ if (!fd || !xlator)
+ return -1;
+
+ for (index = 0; index < xlator->ctx->xl_count; index++) {
+ if (!fd->_ctx[index].key ||
+ (fd->_ctx[index].key == (uint64_t)(long)xlator))
+ break;
+ }
+
+ if (index == xlator->ctx->xl_count)
+ return -1;
+
+ fd->_ctx[index].key = (uint64_t)(long) xlator;
+ fd->_ctx[index].value = value;
+
+ return 0;
+}
+
+int
+fd_ctx_get (fd_t *fd, xlator_t *xlator, uint64_t *value)
+{
+ int index = 0;
+
+ if (!fd || !xlator)
+ return -1;
+
+ for (index = 0; index < xlator->ctx->xl_count; index++) {
+ if (fd->_ctx[index].key == (uint64_t)(long)xlator)
+ break;
+ }
+
+ if (index == xlator->ctx->xl_count)
+ return -1;
+
+ if (value)
+ *value = fd->_ctx[index].value;
+
+ return 0;
+}
+
+
+int
+fd_ctx_del (fd_t *fd, xlator_t *xlator, uint64_t *value)
+{
+ int index = 0;
+
+ if (!fd || !xlator)
+ return -1;
+
+ for (index = 0; index < xlator->ctx->xl_count; index++) {
+ if (fd->_ctx[index].key == (uint64_t)(long)xlator)
+ break;
+ }
+
+ if (index == xlator->ctx->xl_count)
+ return -1;
+
+ if (value)
+ *value = fd->_ctx[index].value;
+
+ fd->_ctx[index].key = 0;
+ fd->_ctx[index].value = 0;
+
+ return 0;
+}
diff --git a/libglusterfs/src/fd.h b/libglusterfs/src/fd.h
new file mode 100644
index 000000000..8b8effdc3
--- /dev/null
+++ b/libglusterfs/src/fd.h
@@ -0,0 +1,107 @@
+/*
+ Copyright (c) 2007, 2008, 2009 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/>.
+*/
+
+#ifndef _FD_H
+#define _FD_H
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "list.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include "glusterfs.h"
+
+struct _inode;
+struct _dict;
+struct _fd_ctx {
+ uint64_t key;
+ uint64_t value;
+};
+
+struct _fd {
+ pid_t pid;
+ int32_t flags;
+ int32_t refcount;
+ struct list_head inode_list;
+ struct _inode *inode;
+ struct _dict *ctx;
+ struct _fd_ctx *_ctx;
+};
+typedef struct _fd fd_t;
+
+struct _fdtable {
+ int refcount;
+ uint32_t max_fds;
+ pthread_mutex_t lock;
+ fd_t **fds;
+};
+typedef struct _fdtable fdtable_t;
+
+#include "logging.h"
+#include "xlator.h"
+
+inline void
+gf_fd_put (fdtable_t *fdtable, int32_t fd);
+
+fd_t *
+gf_fd_fdptr_get (fdtable_t *fdtable, int64_t fd);
+
+fdtable_t *
+gf_fd_fdtable_alloc (void);
+
+int32_t
+gf_fd_unused_get (fdtable_t *fdtable, fd_t *fdptr);
+
+int32_t
+gf_fd_unused_get2 (fdtable_t *fdtable, fd_t *fdptr, int32_t fd);
+
+void
+gf_fd_fdtable_destroy (fdtable_t *fdtable);
+
+fd_t *
+fd_ref (fd_t *fd);
+
+void
+fd_unref (fd_t *fd);
+
+fd_t *
+fd_create (struct _inode *inode, pid_t pid);
+
+fd_t *
+fd_lookup (struct _inode *inode, pid_t pid);
+
+uint8_t
+fd_list_empty (struct _inode *inode);
+
+fd_t *
+fd_bind (fd_t *fd);
+
+int
+fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value);
+
+int
+fd_ctx_get (fd_t *fd, xlator_t *xlator, uint64_t *value);
+
+int
+fd_ctx_del (fd_t *fd, xlator_t *xlator, uint64_t *value);
+
+#endif /* _FD_H */
diff --git a/libglusterfs/src/gf-dirent.c b/libglusterfs/src/gf-dirent.c
new file mode 100644
index 000000000..28d1ab425
--- /dev/null
+++ b/libglusterfs/src/gf-dirent.c
@@ -0,0 +1,157 @@
+/*
+ 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/>.
+*/
+
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include "compat.h"
+#include "xlator.h"
+#include "byte-order.h"
+
+
+struct gf_dirent_nb {
+ uint64_t d_ino;
+ uint64_t d_off;
+ uint32_t d_len;
+ uint32_t d_type;
+ char d_name[0];
+} __attribute__((packed));
+
+
+int
+gf_dirent_nb_size (gf_dirent_t *entries)
+{
+ return (sizeof (struct gf_dirent_nb) + strlen (entries->d_name) + 1);
+}
+
+
+gf_dirent_t *
+gf_dirent_for_name (const char *name)
+{
+ gf_dirent_t *gf_dirent = NULL;
+
+ /* TODO: use mem-pool */
+ gf_dirent = CALLOC (gf_dirent_size (name), 1);
+ if (!gf_dirent)
+ return NULL;
+
+ INIT_LIST_HEAD (&gf_dirent->list);
+ strcpy (gf_dirent->d_name, name);
+
+ gf_dirent->d_off = 0;
+ gf_dirent->d_ino = -1;
+ gf_dirent->d_type = 0;
+ gf_dirent->d_len = strlen (name);
+
+ return gf_dirent;
+}
+
+
+void
+gf_dirent_free (gf_dirent_t *entries)
+{
+ gf_dirent_t *entry = NULL;
+ gf_dirent_t *tmp = NULL;
+
+ list_for_each_entry_safe (entry, tmp, &entries->list, list) {
+ list_del (&entry->list);
+ FREE (entry);
+ }
+}
+
+
+int
+gf_dirent_serialize (gf_dirent_t *entries, char *buf, size_t buf_size)
+{
+ struct gf_dirent_nb *entry_nb = NULL;
+ gf_dirent_t *entry = NULL;
+ int size = 0;
+ int entry_size = 0;
+
+
+ list_for_each_entry (entry, &entries->list, list) {
+ entry_size = gf_dirent_nb_size (entry);
+
+ if (buf && (size + entry_size <= buf_size)) {
+ entry_nb = (void *) (buf + size);
+
+ entry_nb->d_ino = hton64 (entry->d_ino);
+ entry_nb->d_off = hton64 (entry->d_off);
+ entry_nb->d_len = hton32 (entry->d_len);
+ entry_nb->d_type = hton32 (entry->d_type);
+
+ strcpy (entry_nb->d_name, entry->d_name);
+ }
+ size += entry_size;
+ }
+
+ return size;
+}
+
+
+int
+gf_dirent_unserialize (gf_dirent_t *entries, const char *buf, size_t buf_size)
+{
+ struct gf_dirent_nb *entry_nb = NULL;
+ int remaining_size = 0;
+ int least_dirent_size = 0;
+ int count = 0;
+ gf_dirent_t *entry = NULL;
+ int entry_strlen = 0;
+ int entry_len = 0;
+
+
+ remaining_size = buf_size;
+ least_dirent_size = (sizeof (struct gf_dirent_nb) + 2);
+
+ while (remaining_size >= least_dirent_size) {
+ entry_nb = (void *)(buf + (buf_size - remaining_size));
+
+ entry_strlen = strnlen (entry_nb->d_name, remaining_size);
+ if (entry_strlen == remaining_size) {
+ break;
+ }
+
+ entry_len = sizeof (gf_dirent_t) + entry_strlen + 1;
+ entry = CALLOC (1, entry_len);
+ if (!entry) {
+ break;
+ }
+
+ entry->d_ino = ntoh64 (entry_nb->d_ino);
+ entry->d_off = ntoh64 (entry_nb->d_off);
+ entry->d_len = ntoh32 (entry_nb->d_len);
+ entry->d_type = ntoh32 (entry_nb->d_type);
+ strcpy (entry->d_name, entry_nb->d_name);
+
+ list_add_tail (&entry->list, &entries->list);
+
+ remaining_size -= (sizeof (*entry_nb) + entry_strlen + 1);
+ count++;
+ }
+
+ return count;
+}
diff --git a/libglusterfs/src/gf-dirent.h b/libglusterfs/src/gf-dirent.h
new file mode 100644
index 000000000..fa0a8a625
--- /dev/null
+++ b/libglusterfs/src/gf-dirent.h
@@ -0,0 +1,60 @@
+/*
+ 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/>.
+*/
+
+
+#ifndef _GF_DIRENT_H
+#define _GF_DIRENT_H
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#define gf_dirent_size(name) (sizeof (gf_dirent_t) + strlen (name) + 1)
+
+struct _dir_entry_t {
+ struct _dir_entry_t *next;
+ char *name;
+ char *link;
+ struct stat buf;
+};
+
+
+struct _gf_dirent_t {
+ union {
+ struct list_head list;
+ struct {
+ struct _gf_dirent_t *next;
+ struct _gf_dirent_t *prev;
+ };
+ };
+ uint64_t d_ino;
+ uint64_t d_off;
+ uint32_t d_len;
+ uint32_t d_type;
+ char d_name[0];
+};
+
+
+gf_dirent_t *gf_dirent_for_name (const char *name);
+void gf_dirent_free (gf_dirent_t *entries);
+int gf_dirent_serialize (gf_dirent_t *entries, char *buf, size_t size);
+int gf_dirent_unserialize (gf_dirent_t *entries, const char *buf, size_t size);
+
+#endif /* _GF_DIRENT_H */
diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h
new file mode 100644
index 000000000..76891f5b0
--- /dev/null
+++ b/libglusterfs/src/glusterfs.h
@@ -0,0 +1,277 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+#ifndef _GLUSTERFS_H
+#define _GLUSTERFS_H
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <netdb.h>
+#include <errno.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#include <sys/poll.h>
+#include <pthread.h>
+
+#include "list.h"
+#include "logging.h"
+
+#define GF_YES 1
+#define GF_NO 0
+
+#ifndef O_LARGEFILE
+/* savannah bug #20053, patch for compiling on darwin */
+#define O_LARGEFILE 0
+#endif
+
+#ifndef O_DIRECT
+/* savannah bug #20050, #20052 */
+#define O_DIRECT 0 /* From asm/fcntl.h */
+#endif
+
+#ifndef O_DIRECTORY
+/* FreeBSD does not need O_DIRECTORY */
+#define O_DIRECTORY 0
+#endif
+
+#define ZR_FILE_CONTENT_STR "glusterfs.file."
+#define ZR_FILE_CONTENT_STRLEN 15
+
+#define GLUSTERFS_OPEN_FD_COUNT "glusterfs.open-fd-count"
+
+#define ZR_FILE_CONTENT_REQUEST(key) (!strncmp(key, ZR_FILE_CONTENT_STR, \
+ ZR_FILE_CONTENT_STRLEN))
+
+/* TODO: Should we use PATH-MAX? On some systems it may save space */
+#define ZR_PATH_MAX 4096
+
+/* This is used as the maximum permitted filename length over FS.
+ * If the backend FS supports higher than this, it should be changed.
+ */
+#define ZR_FILENAME_MAX 256
+
+
+/* NOTE: add members ONLY at the end (just before _MAXVALUE) */
+typedef enum {
+ GF_FOP_STAT, /* 0 */
+ GF_FOP_READLINK, /* 1 */
+ GF_FOP_MKNOD, /* 2 */
+ GF_FOP_MKDIR,
+ GF_FOP_UNLINK,
+ GF_FOP_RMDIR, /* 5 */
+ GF_FOP_SYMLINK,
+ GF_FOP_RENAME,
+ GF_FOP_LINK,
+ GF_FOP_CHMOD,
+ GF_FOP_CHOWN, /* 10 */
+ GF_FOP_TRUNCATE,
+ GF_FOP_OPEN,
+ GF_FOP_READ,
+ GF_FOP_WRITE,
+ GF_FOP_STATFS, /* 15 */
+ GF_FOP_FLUSH,
+ GF_FOP_FSYNC,
+ GF_FOP_SETXATTR,
+ GF_FOP_GETXATTR,
+ GF_FOP_REMOVEXATTR,/* 20 */
+ GF_FOP_OPENDIR,
+ GF_FOP_GETDENTS,
+ GF_FOP_FSYNCDIR,
+ GF_FOP_ACCESS,
+ GF_FOP_CREATE, /* 25 */
+ GF_FOP_FTRUNCATE,
+ GF_FOP_FSTAT,
+ GF_FOP_LK,
+ GF_FOP_UTIMENS,
+ GF_FOP_FCHMOD, /* 30 */
+ GF_FOP_FCHOWN,
+ GF_FOP_LOOKUP,
+ GF_FOP_SETDENTS,
+ GF_FOP_READDIR,
+ GF_FOP_INODELK, /* 35 */
+ GF_FOP_FINODELK,
+ GF_FOP_ENTRYLK,
+ GF_FOP_FENTRYLK,
+ GF_FOP_CHECKSUM,
+ GF_FOP_XATTROP, /* 40 */
+ GF_FOP_FXATTROP,
+ GF_FOP_MAXVALUE,
+} glusterfs_fop_t;
+
+/* NOTE: add members ONLY at the end (just before _MAXVALUE) */
+typedef enum {
+ GF_MOP_SETVOLUME, /* 0 */
+ GF_MOP_GETVOLUME, /* 1 */
+ GF_MOP_STATS,
+ GF_MOP_SETSPEC,
+ GF_MOP_GETSPEC,
+ GF_MOP_PING,
+ GF_MOP_MAXVALUE /* 5 */
+} glusterfs_mop_t;
+
+typedef enum {
+ GF_CBK_FORGET, /* 0 */
+ GF_CBK_RELEASE, /* 1 */
+ GF_CBK_RELEASEDIR, /* 2 */
+ GF_CBK_MAXVALUE /* 3 */
+} glusterfs_cbk_t;
+
+typedef enum {
+ GF_OP_TYPE_FOP_REQUEST = 1,
+ GF_OP_TYPE_MOP_REQUEST,
+ GF_OP_TYPE_CBK_REQUEST,
+ GF_OP_TYPE_FOP_REPLY,
+ GF_OP_TYPE_MOP_REPLY,
+ GF_OP_TYPE_CBK_REPLY
+} glusterfs_op_type_t;
+
+/* NOTE: all the miscellaneous flags used by GlusterFS should be listed here */
+typedef enum {
+ GF_LK_GETLK = 0,
+ GF_LK_SETLK,
+ GF_LK_SETLKW,
+} glusterfs_lk_cmds_t;
+
+typedef enum {
+ GF_LK_F_RDLCK = 0,
+ GF_LK_F_WRLCK,
+ GF_LK_F_UNLCK
+} glusterfs_lk_types_t;
+
+typedef enum {
+ GF_LOCK_POSIX,
+ GF_LOCK_INTERNAL
+} gf_lk_domain_t;
+
+typedef enum {
+ ENTRYLK_LOCK,
+ ENTRYLK_UNLOCK,
+ ENTRYLK_LOCK_NB
+} entrylk_cmd;
+
+typedef enum {
+ ENTRYLK_RDLCK,
+ ENTRYLK_WRLCK
+} entrylk_type;
+
+typedef enum {
+ GF_GET_ALL = 1,
+ GF_GET_DIR_ONLY,
+ GF_GET_SYMLINK_ONLY,
+ GF_GET_REGULAR_FILES_ONLY,
+} glusterfs_getdents_flags_t;
+
+typedef enum {
+ GF_XATTROP_ADD_ARRAY,
+} gf_xattrop_flags_t;
+
+#define GF_SET_IF_NOT_PRESENT 0x1 /* default behaviour */
+#define GF_SET_OVERWRITE 0x2 /* Overwrite with the buf given */
+#define GF_SET_DIR_ONLY 0x4
+#define GF_SET_EPOCH_TIME 0x8 /* used by afr dir lookup selfheal */
+
+
+struct _xlator_cmdline_option {
+ struct list_head cmd_args;
+ char *volume;
+ char *key;
+ char *value;
+};
+typedef struct _xlator_cmdline_option xlator_cmdline_option_t;
+
+struct _cmd_args {
+ /* basic options */
+ char *volfile_server;
+ char *volume_file;
+ gf_loglevel_t log_level;
+ char *log_file;
+ /* advanced options */
+ uint32_t volfile_server_port;
+ char *volfile_server_transport;
+ char *pid_file;
+ int no_daemon_mode;
+ char *run_id;
+ int debug_mode;
+ struct list_head xlator_options; /* list of xlator_option_t */
+
+ /* fuse options */
+ int fuse_direct_io_mode_flag;
+ unsigned int fuse_entry_timeout;
+ unsigned int fuse_attribute_timeout;
+ char *volume_name;
+ int non_local; /* Used only by darwin os,
+ used for '-o local' option */
+ char *icon_name; /* This string will appear as
+ Desktop icon name when mounted
+ on darwin */
+ int fuse_nodev;
+ int fuse_nosuid;
+
+ /* key args */
+ char *mount_point;
+ char *volfile_id;
+};
+typedef struct _cmd_args cmd_args_t;
+
+struct _glusterfs_ctx {
+ cmd_args_t cmd_args;
+ char *process_uuid;
+ FILE *specfp;
+ FILE *pidfp;
+ char fin;
+ void *timer;
+ void *ib;
+ void *pool;
+ void *graph;
+ void *top; /* either fuse or server protocol */
+ void *event_pool;
+ pthread_mutex_t lock;
+ int xl_count;
+};
+
+typedef struct _glusterfs_ctx glusterfs_ctx_t;
+
+typedef enum {
+ GF_EVENT_PARENT_UP = 1,
+ GF_EVENT_POLLIN,
+ GF_EVENT_POLLOUT,
+ GF_EVENT_POLLERR,
+ GF_EVENT_CHILD_UP,
+ GF_EVENT_CHILD_DOWN,
+ GF_EVENT_CHILD_CONNECTING,
+ GF_EVENT_TRANSPORT_CLEANUP,
+ GF_EVENT_TRANSPORT_CONNECTED,
+} glusterfs_event_t;
+
+#define GF_MUST_CHECK __attribute__((warn_unused_result))
+
+#endif /* _GLUSTERFS_H */
diff --git a/libglusterfs/src/hashfn.c b/libglusterfs/src/hashfn.c
new file mode 100644
index 000000000..edc49678f
--- /dev/null
+++ b/libglusterfs/src/hashfn.c
@@ -0,0 +1,89 @@
+/*
+ Copyright (c) 2006, 2007, 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 <stdint.h>
+#include <stdlib.h>
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "hashfn.h"
+
+#define get16bits(d) (*((const uint16_t *) (d)))
+
+/*
+ This is apparently the "fastest hash function for strings".
+ Written by Paul Hsieh <http://www.azillionmonkeys.com/qed/hash.html>
+*/
+
+/* In any case make sure, you return 1 */
+
+uint32_t SuperFastHash (const char * data, int32_t len) {
+ uint32_t hash = len, tmp;
+ int32_t rem;
+
+ if (len <= 1 || data == NULL) return 1;
+
+
+ for (;len > 0; len--) {
+ hash ^= data[len];
+
+ return hash;
+ }
+
+ rem = len & 3;
+ len >>= 2;
+
+ /* Main loop */
+ for (;len > 0; len--) {
+ hash += get16bits (data);
+ tmp = (get16bits (data+2) << 11) ^ hash;
+ hash = (hash << 16) ^ tmp;
+ data += 2*sizeof (uint16_t);
+ hash += hash >> 11;
+ }
+
+ /* Handle end cases */
+ switch (rem) {
+ case 3: hash += get16bits (data);
+ hash ^= hash << 16;
+ hash ^= data[sizeof (uint16_t)] << 18;
+ hash += hash >> 11;
+ break;
+ case 2: hash += get16bits (data);
+ hash ^= hash << 11;
+ hash += hash >> 17;
+ break;
+ case 1: hash += *data;
+ hash ^= hash << 10;
+ hash += hash >> 1;
+ }
+
+ /* Force "avalanching" of final 127 bits */
+ hash ^= hash << 3;
+ hash += hash >> 5;
+ hash ^= hash << 4;
+ hash += hash >> 17;
+ hash ^= hash << 25;
+ hash += hash >> 6;
+
+ return hash;
+}
diff --git a/libglusterfs/src/hashfn.h b/libglusterfs/src/hashfn.h
new file mode 100644
index 000000000..13673f6e6
--- /dev/null
+++ b/libglusterfs/src/hashfn.h
@@ -0,0 +1,33 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+#ifndef __HASHFN_H__
+#define __HASHFN_H__
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <stdint.h>
+
+uint32_t SuperFastHash (const char * data, int32_t len);
+
+#endif /* __HASHFN_H__ */
diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c
new file mode 100644
index 000000000..6c527fc75
--- /dev/null
+++ b/libglusterfs/src/inode.c
@@ -0,0 +1,1174 @@
+/*
+ Copyright (c) 2007, 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/>.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "inode.h"
+#include "common-utils.h"
+#include <pthread.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include "list.h"
+#include <time.h>
+#include <assert.h>
+
+/* TODO:
+ move latest accessed dentry to list_head of inode
+*/
+
+static inode_t *
+__inode_unref (inode_t *inode);
+
+static int
+inode_table_prune (inode_table_t *table);
+
+static int
+hash_name (ino_t par,
+ const char *name,
+ int mod)
+{
+ int hash = 0;
+ int ret = 0;
+
+ hash = *name;
+ if (hash) {
+ for (name += 1; *name != '\0'; name++) {
+ hash = (hash << 5) - hash + *name;
+ }
+ }
+ ret = (hash + par) % mod;
+
+ return ret;
+}
+
+
+static int
+hash_inode (ino_t ino,
+ int mod)
+{
+ int hash = 0;
+
+ hash = ino % mod;
+
+ return hash;
+}
+
+
+static void
+__dentry_hash (dentry_t *dentry)
+{
+ inode_table_t *table = NULL;
+ int hash = 0;
+
+ table = dentry->inode->table;
+ hash = hash_name (dentry->parent->ino, dentry->name,
+ table->hashsize);
+
+ list_del_init (&dentry->hash);
+ list_add (&dentry->hash, &table->name_hash[hash]);
+
+ list_del_init (&dentry->parent_list);
+ list_add (&dentry->parent_list, &dentry->parent->child_list);
+
+ gf_log (table->name, GF_LOG_DEBUG,
+ "dentry hashed %s (%"PRId64")",
+ dentry->name, dentry->inode->ino);
+}
+
+
+static int
+__is_dentry_hashed (dentry_t *dentry)
+{
+ return !list_empty (&dentry->hash);
+}
+
+
+static void
+__dentry_unhash (dentry_t *dentry)
+{
+ list_del_init (&dentry->hash);
+
+ gf_log (dentry->inode->table->name, GF_LOG_DEBUG,
+ "dentry unhashed %s (%"PRId64")",
+ dentry->name, dentry->inode->ino);
+}
+
+
+static void
+__dentry_unset (dentry_t *dentry)
+{
+ __dentry_unhash (dentry);
+
+ list_del_init (&dentry->inode_list);
+
+ gf_log (dentry->inode->table->name, GF_LOG_DEBUG,
+ "unset dentry %s (%"PRId64")",
+ dentry->name, dentry->inode->ino);
+
+ if (dentry->name)
+ FREE (dentry->name);
+
+ if (dentry->parent) {
+ list_del_init (&dentry->parent_list);
+ __inode_unref (dentry->parent);
+ dentry->parent = NULL;
+ }
+
+ FREE (dentry);
+}
+
+
+static void
+__inode_unhash (inode_t *inode)
+{
+ list_del_init (&inode->hash);
+}
+
+
+static int
+__is_inode_hashed (inode_t *inode)
+{
+ return !list_empty (&inode->hash);
+}
+
+
+static void
+__inode_hash (inode_t *inode)
+{
+ inode_table_t *table = NULL;
+ int hash = 0;
+
+ table = inode->table;
+ hash = hash_inode (inode->ino, table->hashsize);
+
+ list_del_init (&inode->hash);
+ list_add (&inode->hash, &table->inode_hash[hash]);
+}
+
+
+static inode_t *
+__inode_search (inode_table_t *table,
+ ino_t ino)
+{
+ int hash = 0;
+ inode_t *inode = NULL;
+ inode_t *tmp = NULL;
+
+ hash = hash_inode (ino, table->hashsize);
+
+ list_for_each_entry (tmp, &table->inode_hash[hash], hash) {
+ if (tmp->ino == ino) {
+ inode = tmp;
+ break;
+ }
+ }
+
+ return inode;
+}
+
+
+static dentry_t *
+__dentry_search_for_inode (inode_t *inode,
+ ino_t par,
+ const char *name)
+{
+ dentry_t *dentry = NULL;
+ dentry_t *tmp = NULL;
+
+ list_for_each_entry (tmp, &inode->dentry_list, inode_list) {
+ if (tmp->parent->ino == par && !strcmp (tmp->name, name)) {
+ dentry = tmp;
+ break;
+ }
+ }
+
+ return dentry;
+}
+
+
+static dentry_t *
+__dentry_search (inode_table_t *table,
+ ino_t par,
+ const char *name)
+{
+ int hash = 0;
+ dentry_t *dentry = NULL;
+ dentry_t *tmp = NULL;
+
+ hash = hash_name (par, name, table->hashsize);
+
+ list_for_each_entry (tmp, &table->name_hash[hash], hash) {
+ if (tmp->parent->ino == par && !strcmp (tmp->name, name)) {
+ dentry = tmp;
+ break;
+ }
+ }
+
+ return dentry;
+}
+
+
+static void
+__inode_destroy (inode_t *inode)
+{
+ int index = 0;
+ data_pair_t *pair = NULL;
+ xlator_t *xl = NULL;
+
+ if (!inode->ctx) {
+ goto noctx;
+ }
+ for (pair = inode->ctx->members_list; pair; pair = pair->next) {
+ /* notify all xlators which have a context */
+ xl = xlator_search_by_name (inode->table->xl, pair->key);
+
+ if (!xl) {
+ gf_log (inode->table->name, GF_LOG_CRITICAL,
+ "inode(%"PRId64")->ctx has invalid key(%s)",
+ inode->ino, pair->key);
+ continue;
+ }
+
+ if (xl->cbks->forget)
+ xl->cbks->forget (xl, inode);
+ else
+ gf_log (inode->table->name, GF_LOG_CRITICAL,
+ "xlator(%s) in inode(%"PRId64") no FORGET fop",
+ xl->name, inode->ino);
+ }
+ dict_destroy (inode->ctx);
+
+ if (!inode->_ctx)
+ goto noctx;
+
+ for (index = 0; index < inode->table->xl->ctx->xl_count; index++) {
+ if (inode->_ctx[index].key) {
+ xl = (xlator_t *)(long)inode->_ctx[index].key;
+ if (xl->cbks->forget)
+ xl->cbks->forget (xl, inode);
+ }
+ }
+
+ FREE (inode->_ctx);
+noctx:
+
+ if (inode->ino)
+ gf_log (inode->table->name, GF_LOG_DEBUG,
+ "destroy inode(%"PRId64") [@%p]", inode->ino, inode);
+
+ LOCK_DESTROY (&inode->lock);
+ // memset (inode, 0xb, sizeof (*inode));
+ FREE (inode);
+}
+
+
+static void
+__inode_activate (inode_t *inode)
+{
+ list_move (&inode->list, &inode->table->active);
+ inode->table->active_size++;
+
+ gf_log (inode->table->name, GF_LOG_DEBUG,
+ "activating inode(%"PRId64"), lru=%d/%d active=%d purge=%d",
+ inode->ino, inode->table->lru_size, inode->table->lru_limit,
+ inode->table->active_size, inode->table->purge_size);
+}
+
+
+static void
+__inode_passivate (inode_t *inode)
+{
+ dentry_t *dentry = NULL;
+ dentry_t *t = NULL;
+ inode_table_t *table = NULL;
+
+ table = inode->table;
+
+ list_move_tail (&inode->list, &inode->table->lru);
+ inode->table->lru_size++;
+
+ gf_log (table->name, GF_LOG_DEBUG,
+ "passivating inode(%"PRId64") lru=%d/%d active=%d purge=%d",
+ inode->ino, table->lru_size, table->lru_limit,
+ table->active_size, table->purge_size);
+
+ list_for_each_entry_safe (dentry, t, &inode->dentry_list, inode_list) {
+ if (!__is_dentry_hashed (dentry))
+ __dentry_unset (dentry);
+ }
+}
+
+
+static void
+__inode_retire (inode_t *inode)
+{
+ dentry_t *dentry = NULL;
+ dentry_t *t = NULL;
+ inode_table_t *table = NULL;
+
+ table = inode->table;
+
+ list_move_tail (&inode->list, &inode->table->purge);
+ inode->table->purge_size++;
+
+ gf_log (table->name, GF_LOG_DEBUG,
+ "retiring inode(%"PRId64") lru=%d/%d active=%d purge=%d",
+ inode->ino, table->lru_size, table->lru_limit,
+ table->active_size, table->purge_size);
+
+ __inode_unhash (inode);
+ assert (list_empty (&inode->child_list));
+
+ list_for_each_entry_safe (dentry, t, &inode->dentry_list, inode_list) {
+ __dentry_unset (dentry);
+ }
+}
+
+
+static inode_t *
+__inode_unref (inode_t *inode)
+{
+ if (inode->ino == 1)
+ return inode;
+
+ assert (inode->ref);
+
+ --inode->ref;
+
+ if (!inode->ref) {
+ inode->table->active_size--;
+
+ if (inode->nlookup && __is_inode_hashed (inode))
+ __inode_passivate (inode);
+ else
+ __inode_retire (inode);
+ }
+
+ return inode;
+}
+
+
+static inode_t *
+__inode_ref (inode_t *inode)
+{
+ if (!inode->ref) {
+ inode->table->lru_size--;
+ __inode_activate (inode);
+ }
+ inode->ref++;
+
+ return inode;
+}
+
+
+inode_t *
+inode_unref (inode_t *inode)
+{
+ inode_table_t *table = NULL;
+
+ table = inode->table;
+
+ pthread_mutex_lock (&table->lock);
+ {
+ inode = __inode_unref (inode);
+ }
+ pthread_mutex_unlock (&table->lock);
+
+ inode_table_prune (table);
+
+ return inode;
+}
+
+
+inode_t *
+inode_ref (inode_t *inode)
+{
+ inode_table_t *table = NULL;
+
+ table = inode->table;
+
+ pthread_mutex_lock (&table->lock);
+ {
+ inode = __inode_ref (inode);
+ }
+ pthread_mutex_unlock (&table->lock);
+
+ return inode;
+}
+
+
+static dentry_t *
+__dentry_create (inode_t *inode,
+ inode_t *parent,
+ const char *name)
+{
+ dentry_t *newd = NULL;
+
+ newd = (void *) CALLOC (1, sizeof (*newd));
+
+ INIT_LIST_HEAD (&newd->inode_list);
+ INIT_LIST_HEAD (&newd->parent_list);
+ INIT_LIST_HEAD (&newd->hash);
+
+ list_add (&newd->parent_list, &parent->child_list);
+ newd->parent = __inode_ref (parent);
+ newd->name = strdup (name);
+
+ list_add (&newd->inode_list, &inode->dentry_list);
+ newd->inode = inode;
+
+ return newd;
+}
+
+
+static inode_t *
+__inode_create (inode_table_t *table)
+{
+ inode_t *newi = NULL;
+
+ newi = (void *) CALLOC (1, sizeof (*newi));
+ if (!newi)
+ return NULL;
+
+ newi->table = table;
+
+ LOCK_INIT (&newi->lock);
+
+ INIT_LIST_HEAD (&newi->fd_list);
+ INIT_LIST_HEAD (&newi->list);
+ INIT_LIST_HEAD (&newi->hash);
+ INIT_LIST_HEAD (&newi->dentry_list);
+ INIT_LIST_HEAD (&newi->child_list);
+
+
+ list_add (&newi->list, &table->lru);
+ table->lru_size++;
+
+ newi->_ctx = CALLOC (1, (sizeof (struct _inode_ctx) *
+ table->xl->ctx->xl_count));
+
+ newi->ctx = get_new_dict ();
+ gf_log (table->name, GF_LOG_DEBUG,
+ "create inode(%"PRId64")", newi->ino);
+
+ return newi;
+}
+
+
+inode_t *
+inode_new (inode_table_t *table)
+{
+ inode_t *inode = NULL;
+
+ pthread_mutex_lock (&table->lock);
+ {
+ inode = __inode_create (table);
+ __inode_ref (inode);
+ }
+ pthread_mutex_unlock (&table->lock);
+
+ return inode;
+}
+
+
+static inode_t *
+__inode_lookup (inode_t *inode)
+{
+ inode->nlookup++;
+
+ return inode;
+}
+
+
+static inode_t *
+__inode_forget (inode_t *inode, uint64_t nlookup)
+{
+ assert (inode->nlookup >= nlookup);
+
+ inode->nlookup -= nlookup;
+
+ if (!nlookup)
+ inode->nlookup = 0;
+
+ return inode;
+}
+
+
+inode_t *
+inode_search (inode_table_t *table,
+ ino_t ino,
+ const char *name)
+{
+ inode_t *inode = NULL;
+ dentry_t *dentry = NULL;
+
+ pthread_mutex_lock (&table->lock);
+ {
+ if (!name) {
+ inode = __inode_search (table, ino);
+ } else {
+ dentry = __dentry_search (table, ino, name);
+
+ if (dentry)
+ inode = dentry->inode;
+ }
+
+ if (inode)
+ __inode_ref (inode);
+ }
+ pthread_mutex_unlock (&table->lock);
+
+ return inode;
+}
+
+
+static void
+__copy_dentries (inode_t *oldi, inode_t *newi)
+{
+ dentry_t *dentry = NULL;
+ dentry_t *newd = NULL;
+ dentry_t *tmp = NULL;
+
+ list_for_each_entry (dentry, &oldi->dentry_list, inode_list) {
+ tmp = __dentry_search_for_inode (newi, dentry->parent->ino,
+ dentry->name);
+
+ if (!tmp) {
+ newd = __dentry_create (newi, dentry->parent,
+ dentry->name);
+ } else {
+ newd = tmp;
+ }
+
+ if (__is_dentry_hashed (dentry)) {
+ __dentry_unhash (dentry);
+ __dentry_hash (newd);
+ }
+ }
+}
+
+
+static void
+__adopt_children (inode_t *oldi, inode_t *newi)
+{
+ dentry_t *dentry = NULL;
+
+ list_for_each_entry (dentry, &oldi->child_list, parent_list) {
+ assert (dentry->parent == oldi);
+ __inode_unref (dentry->parent);
+ dentry->parent = __inode_ref (newi);
+ }
+
+ list_splice_init (&oldi->child_list, &newi->child_list);
+}
+
+
+static void
+__inode_replace (inode_t *oldi, inode_t *newi)
+{
+ gf_log (oldi->table->name, GF_LOG_DEBUG,
+ "inode(%"PRId64") replaced (%"PRId64"",
+ oldi->ino, newi->ino);
+
+ __copy_dentries (oldi, newi);
+ __adopt_children (oldi, newi);
+
+ newi->nlookup = oldi->nlookup;
+ newi->generation = oldi->generation;
+
+ oldi->nlookup = 0;
+ oldi->generation = 0;
+
+ __inode_unhash (oldi);
+
+ if (newi->ino == 1)
+ newi->table->root = newi;
+}
+
+
+static inode_t *
+__inode_link (inode_t *inode,
+ inode_t *parent,
+ const char *name,
+ struct stat *stbuf)
+{
+ dentry_t *dentry = NULL;
+ dentry_t *old_dentry = NULL;
+ inode_t *old_inode = NULL;
+ inode_table_t *table = NULL;
+
+ table = inode->table;
+
+ if (inode->ino)
+ assert (inode->ino == stbuf->st_ino);
+
+ inode->ino = stbuf->st_ino;
+ inode->st_mode = stbuf->st_mode;
+
+ old_inode = __inode_search (table, stbuf->st_ino);
+
+ if (old_inode && old_inode != inode) {
+ __inode_ref (old_inode);
+ __inode_replace (old_inode, inode);
+ __inode_unref (old_inode);
+ }
+ __inode_hash (inode);
+
+ if (parent) {
+ dentry = __dentry_search_for_inode (inode, parent->ino, name);
+ if (!dentry) {
+ dentry = __dentry_create (inode, parent, name);
+ }
+
+ old_dentry = __dentry_search (table, parent->ino, name);
+ if (old_dentry) {
+ __dentry_unhash (old_dentry);
+ }
+
+ __dentry_hash (dentry);
+ } else if (inode->ino != 1) {
+ gf_log (table->name, GF_LOG_ERROR,
+ "child (%"PRId64") without a parent :O", inode->ino);
+ }
+
+ return inode;
+}
+
+
+int
+inode_link (inode_t *inode,
+ inode_t *parent,
+ const char *name,
+ struct stat *stbuf)
+{
+ inode_table_t *table = NULL;
+
+ table = inode->table;
+
+ pthread_mutex_lock (&table->lock);
+ {
+ inode = __inode_link (inode, parent, name, stbuf);
+ }
+ pthread_mutex_unlock (&table->lock);
+
+ inode_table_prune (table);
+
+ return 0;
+}
+
+
+int
+inode_lookup (inode_t *inode)
+{
+ inode_table_t *table = NULL;
+ inode_t *lookup_inode = NULL;
+
+ table = inode->table;
+ lookup_inode = inode;
+
+ pthread_mutex_lock (&table->lock);
+ {
+ if (!__is_inode_hashed (inode)) {
+ lookup_inode = __inode_search (table, inode->ino);
+ }
+
+ __inode_lookup (lookup_inode);
+ }
+ pthread_mutex_unlock (&table->lock);
+
+ return 0;
+}
+
+
+int
+inode_forget (inode_t *inode, uint64_t nlookup)
+{
+ inode_table_t *table = NULL;
+ inode_t *forget_inode = NULL;
+
+ table = inode->table;
+ forget_inode = inode;
+
+ pthread_mutex_lock (&table->lock);
+ {
+ if (!__is_inode_hashed (inode)) {
+ forget_inode = __inode_search (table, inode->ino);
+ }
+
+ __inode_forget (forget_inode, nlookup);
+ }
+ pthread_mutex_unlock (&table->lock);
+
+ inode_table_prune (table);
+
+ return 0;
+}
+
+
+static void
+__inode_unlink (inode_t *inode,
+ inode_t *parent,
+ const char *name)
+{
+ dentry_t *dentry = NULL;
+
+ dentry = __dentry_search_for_inode (inode, parent->ino, name);
+
+ /* dentry NULL for corrupted backend */
+ if (dentry)
+ __dentry_unset (dentry);
+}
+
+
+void
+inode_unlink (inode_t *inode,
+ inode_t *parent,
+ const char *name)
+{
+ inode_table_t *table = NULL;
+ inode_t *unlink_inode = NULL;
+
+ table = inode->table;
+ unlink_inode = inode;
+
+ pthread_mutex_lock (&table->lock);
+ {
+ if (!__is_inode_hashed (inode)) {
+ unlink_inode = __inode_search (table, inode->ino);
+ }
+
+ __inode_unlink (unlink_inode, parent, name);
+ }
+ pthread_mutex_unlock (&table->lock);
+
+ inode_table_prune (table);
+}
+
+
+int
+inode_rename (inode_table_t *table,
+ inode_t *srcdir,
+ const char *srcname,
+ inode_t *dstdir,
+ const char *dstname,
+ inode_t *inode,
+ struct stat *stbuf)
+{
+ dentry_t *old_dst = NULL;
+ inode_t *rename_inode = NULL;
+
+ rename_inode = inode;
+
+ pthread_mutex_lock (&table->lock);
+ {
+ if (!__is_inode_hashed (inode)) {
+ rename_inode = __inode_search (table, inode->ino);
+ }
+
+ old_dst = __dentry_search (table, dstdir->ino, dstname);
+ if (old_dst)
+ __dentry_unset (old_dst);
+
+ __inode_unlink (rename_inode, srcdir, srcname);
+ __inode_link (rename_inode, dstdir, dstname, stbuf);
+ }
+ pthread_mutex_unlock (&table->lock);
+
+ inode_table_prune (table);
+
+ return 0;
+}
+
+
+static dentry_t *
+__dentry_search_arbit (inode_t *inode)
+{
+ dentry_t *dentry = NULL;
+ dentry_t *trav = NULL;
+
+ list_for_each_entry (trav, &inode->dentry_list, inode_list) {
+ if (__is_dentry_hashed (trav)) {
+ dentry = trav;
+ break;
+ }
+ }
+
+ if (!dentry) {
+ list_for_each_entry (trav, &inode->dentry_list, inode_list) {
+ dentry = trav;
+ break;
+ }
+ }
+
+ return dentry;
+}
+
+
+inode_t *
+inode_parent (inode_t *inode, ino_t par, const char *name)
+{
+ inode_t *parent = NULL;
+ inode_table_t *table = NULL;
+ dentry_t *dentry = NULL;
+
+ table = inode->table;
+
+ pthread_mutex_lock (&table->lock);
+ {
+ if (par && name) {
+ dentry = __dentry_search_for_inode (inode, par, name);
+ } else {
+ dentry = __dentry_search_arbit (inode);
+ }
+
+ if (dentry)
+ parent = __inode_ref (dentry->parent);
+ }
+ pthread_mutex_unlock (&table->lock);
+
+ return parent;
+}
+
+
+int32_t
+inode_path (inode_t *inode,
+ const char *name,
+ char **bufp)
+{
+ inode_table_t *table = NULL;
+ dentry_t *trav = NULL;
+ size_t i = 0, size = 0;
+ int64_t ret = 0;
+ int len = 0;
+ char *buf = NULL;
+
+ table = inode->table;
+
+ pthread_mutex_lock (&table->lock);
+ {
+ for (trav = __dentry_search_arbit (inode); trav;
+ trav = __dentry_search_arbit (trav->parent)) {
+ i ++; /* "/" */
+ i += strlen (trav->name);
+ }
+
+ if ((inode->ino != 1) &&
+ (i == 0)) {
+ gf_log (table->name, GF_LOG_DEBUG,
+ "no dentry for non-root inode %"PRId64,
+ inode->ino);
+ ret = -ENOENT;
+ goto unlock;
+ }
+
+ if (name) {
+ i++;
+ i += strlen (name);
+ }
+
+ ret = i;
+ size = i + 1;
+ buf = CALLOC (size, sizeof (char));
+ if (buf) {
+
+ buf[size - 1] = 0;
+
+ if (name) {
+ len = strlen (name);
+ strncpy (buf + (i - len), name, len);
+ buf[i-len-1] = '/';
+ i -= (len + 1);
+ }
+
+ for (trav = __dentry_search_arbit (inode); trav;
+ trav = __dentry_search_arbit (trav->parent)) {
+ len = strlen (trav->name);
+ strncpy (buf + (i - len), trav->name, len);
+ buf[i-len-1] = '/';
+ i -= (len + 1);
+ }
+ *bufp = buf;
+ } else {
+ gf_log (table->name, GF_LOG_ERROR,
+ "out of memory");
+ ret = -ENOMEM;
+ }
+ }
+unlock:
+ pthread_mutex_unlock (&table->lock);
+
+ if (inode->ino == 1 && !name) {
+ ret = 1;
+ if (buf) {
+ FREE (buf);
+ }
+ buf = CALLOC (ret + 1, sizeof (char));
+ if (buf) {
+ strcpy (buf, "/");
+ *bufp = buf;
+ } else {
+ gf_log (table->name, GF_LOG_ERROR,
+ "out of memory");
+ ret = -ENOMEM;
+ }
+ }
+
+ return ret;
+}
+
+static int
+inode_table_prune (inode_table_t *table)
+{
+ int ret = 0;
+ struct list_head purge = {0, };
+ inode_t *del = NULL;
+ inode_t *tmp = NULL;
+ inode_t *entry = NULL;
+
+
+ INIT_LIST_HEAD (&purge);
+
+ pthread_mutex_lock (&table->lock);
+ {
+ while (table->lru_limit
+ && table->lru_size > (table->lru_limit)) {
+
+ entry = list_entry (table->lru.next, inode_t, list);
+
+ table->lru_size--;
+ __inode_retire (entry);
+
+ ret++;
+ }
+
+ list_splice_init (&table->purge, &purge);
+ table->purge_size = 0;
+ }
+ pthread_mutex_unlock (&table->lock);
+
+ {
+ list_for_each_entry_safe (del, tmp, &purge, list) {
+ list_del_init (&del->list);
+ __inode_forget (del, 0);
+ __inode_destroy (del);
+ }
+ }
+
+ return ret;
+}
+
+
+static void
+__inode_table_init_root (inode_table_t *table)
+{
+ inode_t *root = NULL;
+ struct stat stbuf = {0, };
+
+ root = __inode_create (table);
+
+ stbuf.st_ino = 1;
+ stbuf.st_mode = S_IFDIR|0755;
+
+ __inode_link (root, NULL, NULL, &stbuf);
+ table->root = root;
+}
+
+
+inode_table_t *
+inode_table_new (size_t lru_limit, xlator_t *xl)
+{
+ inode_table_t *new = NULL;
+ int i = 0;
+
+
+ new = (void *)calloc (1, sizeof (*new));
+ if (!new)
+ return NULL;
+
+ gf_log (xl->name, GF_LOG_DEBUG,
+ "creating new inode table with lru_limit=%"GF_PRI_SIZET"", lru_limit);
+
+ new->xl = xl;
+
+ new->lru_limit = lru_limit;
+
+ new->hashsize = 14057; /* TODO: Random Number?? */
+
+ new->inode_hash = (void *)calloc (new->hashsize,
+ sizeof (struct list_head));
+ if (!new->inode_hash) {
+ FREE (new);
+ return NULL;
+ }
+
+ new->name_hash = (void *)calloc (new->hashsize,
+ sizeof (struct list_head));
+ if (!new->name_hash) {
+ FREE (new->inode_hash);
+ FREE (new);
+ return NULL;
+ }
+
+ for (i=0; i<new->hashsize; i++) {
+ INIT_LIST_HEAD (&new->inode_hash[i]);
+ }
+
+
+ for (i=0; i<new->hashsize; i++) {
+ INIT_LIST_HEAD (&new->name_hash[i]);
+ }
+
+ INIT_LIST_HEAD (&new->active);
+ INIT_LIST_HEAD (&new->lru);
+ INIT_LIST_HEAD (&new->purge);
+
+ asprintf (&new->name, "%s/inode", xl->name);
+
+ __inode_table_init_root (new);
+
+ pthread_mutex_init (&new->lock, NULL);
+
+ return new;
+}
+
+
+inode_t *
+inode_from_path (inode_table_t *itable, const char *path)
+{
+ inode_t *inode = NULL;
+ inode_t *parent = NULL;
+ inode_t *root = NULL;
+ inode_t *curr = NULL;
+ char *pathname = NULL;
+ char *component = NULL, *next_component = NULL;
+ char *strtokptr = NULL;
+
+ /* top-down approach */
+ root = itable->root;
+ parent = inode_ref (root);
+ pathname = strdup (path);
+ component = strtok_r (pathname, "/", &strtokptr);
+
+ if (component == NULL)
+ /* root inode */
+ inode = inode_ref (parent);
+
+ while (component) {
+ curr = inode_search (itable, parent->ino, component);
+
+ if (curr == NULL) {
+ component = strtok_r (NULL, "/", &strtokptr);
+ break;
+ }
+
+ next_component = strtok_r (NULL, "/", &strtokptr);
+
+ if (next_component) {
+ inode_unref (parent);
+ parent = curr;
+ curr = NULL;
+ } else {
+ inode = curr;
+ }
+
+ component = next_component;
+ }
+
+ if (parent)
+ inode_unref (parent);
+
+ if (pathname)
+ free (pathname);
+
+ return inode;
+}
+
+int
+inode_ctx_put (inode_t *inode, xlator_t *xlator, uint64_t value)
+{
+ int index = 0;
+
+ if (!inode || !xlator)
+ return -1;
+
+ for (index = 0; index < xlator->ctx->xl_count; index++) {
+ if (!inode->_ctx[index].key ||
+ (inode->_ctx[index].key == (uint64_t)(long)xlator))
+ break;
+ }
+
+ if (index == xlator->ctx->xl_count)
+ return -1;
+
+ inode->_ctx[index].key = (uint64_t)(long) xlator;
+ inode->_ctx[index].value = value;
+
+ return 0;
+}
+
+int
+inode_ctx_get (inode_t *inode, xlator_t *xlator, uint64_t *value)
+{
+ int index = 0;
+
+ if (!inode || !xlator)
+ return -1;
+
+ for (index = 0; index < xlator->ctx->xl_count; index++) {
+ if (inode->_ctx[index].key == (uint64_t)(long)xlator)
+ break;
+ }
+
+ if (index == xlator->ctx->xl_count)
+ return -1;
+
+ if (value)
+ *value = inode->_ctx[index].value;
+
+ return 0;
+}
+
+
+int
+inode_ctx_del (inode_t *inode, xlator_t *xlator, uint64_t *value)
+{
+ int index = 0;
+
+ if (!inode || !xlator)
+ return -1;
+
+ for (index = 0; index < xlator->ctx->xl_count; index++) {
+ if (inode->_ctx[index].key == (uint64_t)(long)xlator)
+ break;
+ }
+
+ if (index == xlator->ctx->xl_count)
+ return -1;
+
+ if (value)
+ *value = inode->_ctx[index].value;
+
+ inode->_ctx[index].key = 0;
+ inode->_ctx[index].value = 0;
+
+ return 0;
+}
diff --git a/libglusterfs/src/inode.h b/libglusterfs/src/inode.h
new file mode 100644
index 000000000..67490f0ee
--- /dev/null
+++ b/libglusterfs/src/inode.h
@@ -0,0 +1,160 @@
+/*
+ Copyright (c) 2007, 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/>.
+*/
+
+#ifndef _INODE_H
+#define _INODE_H
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include <sys/types.h>
+
+struct _inode_table;
+typedef struct _inode_table inode_table_t;
+
+struct _inode;
+typedef struct _inode inode_t;
+
+struct _dentry;
+typedef struct _dentry dentry_t;
+
+#include "list.h"
+#include "xlator.h"
+
+
+struct _inode_table {
+ pthread_mutex_t lock;
+ size_t hashsize; /* bucket size of inode hash and dentry hash */
+ char *name; /* name of the inode table, just for gf_log() */
+ inode_t *root; /* root directory inode, with number 1 */
+ xlator_t *xl; /* xlator to be called to do purge */
+ uint32_t lru_limit; /* maximum LRU cache size */
+ struct list_head *inode_hash; /* buckets for inode hash table */
+ struct list_head *name_hash; /* buckets for dentry hash table */
+ struct list_head active; /* list of inodes currently active (in an fop) */
+ uint32_t active_size; /* count of inodes in active list */
+ struct list_head lru; /* list of inodes recently used.
+ lru.next most recent */
+ uint32_t lru_size; /* count of inodes in lru list */
+ struct list_head purge; /* list of inodes to be purged soon */
+ uint32_t purge_size; /* count of inodes in purge list */
+};
+
+
+struct _dentry {
+ struct list_head inode_list; /* list of dentries of inode */
+ struct list_head hash; /* hash table pointers */
+ struct list_head parent_list; /* list of dentries under the parent */
+ inode_t *inode; /* inode of this directory entry */
+ char *name; /* name of the directory entry */
+ inode_t *parent; /* directory of the entry */
+};
+
+//#define ZR_INODE_CTX_VALUE_LEN 2
+struct _inode_ctx {
+ uint64_t key;
+ uint64_t value;
+ //uint64_t value[ZR_INODE_CTX_VALUE_LEN];
+};
+
+struct _inode {
+ inode_table_t *table; /* the table this inode belongs to */
+ gf_lock_t lock;
+ uint64_t nlookup;
+ uint64_t generation;
+ uint32_t ref; /* reference count on this inode */
+ ino_t ino; /* inode number in the storage (persistent) */
+ dict_t *ctx; /* per xlator private */
+ mode_t st_mode; /* what kind of file */
+ struct list_head fd_list; /* list of open files on this inode */
+ struct list_head dentry_list; /* list of directory entries for this inode */
+ struct list_head child_list; /* list of directory entries under this inode */
+ struct list_head hash; /* hash table pointers */
+ struct list_head list; /* active/lru/purge */
+
+ struct _inode_ctx *_ctx; /* replacement for dict_t *(inode->ctx) */
+};
+
+
+inode_table_t *
+inode_table_new (size_t lru_limit, xlator_t *xl);
+
+inode_t *
+inode_new (inode_table_t *table);
+
+inode_t *
+inode_search (inode_table_t *table, ino_t ino, const char *name);
+
+int
+inode_link (inode_t *inode, inode_t *parent,
+ const char *name, struct stat *stbuf);
+
+void
+inode_unlink (inode_t *inode,
+ inode_t *parent,
+ const char *name);
+
+inode_t *
+inode_parent (inode_t *inode, ino_t par, const char *name);
+
+inode_t *
+inode_ref (inode_t *inode);
+
+inode_t *
+inode_unref (inode_t *inode);
+
+int
+inode_lookup (inode_t *inode);
+
+int
+inode_forget (inode_t *inode,
+ uint64_t nlookup);
+
+int
+inode_rename (inode_table_t *table,
+ inode_t *olddir,
+ const char *oldname,
+ inode_t *newdir,
+ const char *newname,
+ inode_t *inode,
+ struct stat *stbuf);
+
+
+int32_t
+inode_path (inode_t *inode,
+ const char *name,
+ char **bufp);
+
+inode_t *
+inode_from_path (inode_table_t *table,
+ const char *path);
+
+int
+inode_ctx_put (inode_t *inode, xlator_t *xlator, uint64_t value);
+
+int
+inode_ctx_get (inode_t *inode, xlator_t *xlator, uint64_t *value);
+
+int
+inode_ctx_del (inode_t *inode, xlator_t *xlator, uint64_t *value);
+
+#endif /* _INODE_H */
diff --git a/libglusterfs/src/list.h b/libglusterfs/src/list.h
new file mode 100644
index 000000000..0d862f09c
--- /dev/null
+++ b/libglusterfs/src/list.h
@@ -0,0 +1,154 @@
+/*
+ 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/>.
+*/
+
+#ifndef _LLIST_H
+#define _LLIST_H
+
+
+struct list_head {
+ struct list_head *next;
+ struct list_head *prev;
+};
+
+
+#define INIT_LIST_HEAD(head) do { \
+ (head)->next = (head)->prev = head; \
+ } while (0)
+
+
+static inline void
+list_add (struct list_head *new, struct list_head *head)
+{
+ new->prev = head;
+ new->next = head->next;
+
+ new->prev->next = new;
+ new->next->prev = new;
+}
+
+
+static inline void
+list_add_tail (struct list_head *new, struct list_head *head)
+{
+ new->next = head;
+ new->prev = head->prev;
+
+ new->prev->next = new;
+ new->next->prev = new;
+}
+
+
+static inline void
+list_del (struct list_head *old)
+{
+ old->prev->next = old->next;
+ old->next->prev = old->prev;
+
+ old->next = (void *)0xbabebabe;
+ old->prev = (void *)0xcafecafe;
+}
+
+
+static inline void
+list_del_init (struct list_head *old)
+{
+ old->prev->next = old->next;
+ old->next->prev = old->prev;
+
+ old->next = old;
+ old->prev = old;
+}
+
+
+static inline void
+list_move (struct list_head *list, struct list_head *head)
+{
+ list_del (list);
+ list_add (list, head);
+}
+
+
+static inline void
+list_move_tail (struct list_head *list, struct list_head *head)
+{
+ list_del (list);
+ list_add_tail (list, head);
+}
+
+
+static inline int
+list_empty (struct list_head *head)
+{
+ return (head->next == head);
+}
+
+
+static inline void
+__list_splice (struct list_head *list, struct list_head *head)
+{
+ (list->prev)->next = (head->next);
+ (head->next)->prev = (list->prev);
+
+ (head)->next = (list->next);
+ (list->next)->prev = (head);
+}
+
+
+static inline void
+list_splice (struct list_head *list, struct list_head *head)
+{
+ if (list_empty (list))
+ return;
+
+ __list_splice (list, head);
+}
+
+
+static inline void
+list_splice_init (struct list_head *list, struct list_head *head)
+{
+ if (list_empty (list))
+ return;
+
+ __list_splice (list, head);
+ INIT_LIST_HEAD (list);
+}
+
+
+#define list_entry(ptr, type, member) \
+ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+#endif /* _LLIST_H */
diff --git a/libglusterfs/src/locking.h b/libglusterfs/src/locking.h
new file mode 100644
index 000000000..c5c5163d1
--- /dev/null
+++ b/libglusterfs/src/locking.h
@@ -0,0 +1,49 @@
+/*
+ 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/>.
+*/
+
+#ifndef _LOCKING_H
+#define _LOCKING_H
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+
+#if HAVE_SPINLOCK
+#define LOCK_INIT(x) pthread_spin_init (x, 0)
+#define LOCK(x) pthread_spin_lock (x)
+#define TRY_LOCK(x) pthread_spin_trylock (x)
+#define UNLOCK(x) pthread_spin_unlock (x)
+#define LOCK_DESTROY(x) pthread_spin_destroy (x)
+
+typedef pthread_spinlock_t gf_lock_t;
+#else
+#define LOCK_INIT(x) pthread_mutex_init (x, 0)
+#define LOCK(x) pthread_mutex_lock (x)
+#define TRY_LOCK(x) pthread_mutex_trylock (x)
+#define UNLOCK(x) pthread_mutex_unlock (x)
+#define LOCK_DESTROY(x) pthread_mutex_destroy (x)
+
+typedef pthread_mutex_t gf_lock_t;
+#endif /* HAVE_SPINLOCK */
+
+
+#endif /* _LOCKING_H */
diff --git a/libglusterfs/src/logging.c b/libglusterfs/src/logging.c
new file mode 100644
index 000000000..c0b10edca
--- /dev/null
+++ b/libglusterfs/src/logging.c
@@ -0,0 +1,207 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+#include <locale.h>
+#include <string.h>
+#include <stdlib.h>
+#include "logging.h"
+
+
+static pthread_mutex_t logfile_mutex;
+static char *filename = NULL;
+static uint8_t logrotate = 0;
+
+static FILE *logfile = NULL;
+static gf_loglevel_t loglevel = GF_LOG_MAX;
+
+gf_loglevel_t gf_log_loglevel; /* extern'd */
+FILE *gf_log_logfile;
+
+
+void
+gf_log_logrotate (int signum)
+{
+ logrotate = 1;
+}
+
+
+gf_loglevel_t
+gf_log_get_loglevel (void)
+{
+ return loglevel;
+}
+
+
+void
+gf_log_set_loglevel (gf_loglevel_t level)
+{
+ gf_log_loglevel = loglevel = level;
+}
+
+
+void
+gf_log_fini (void)
+{
+ pthread_mutex_destroy (&logfile_mutex);
+}
+
+
+int
+gf_log_init (const char *file)
+{
+ if (!file){
+ fprintf (stderr, "gf_log_init: no filename specified\n");
+ return -1;
+ }
+
+ pthread_mutex_init (&logfile_mutex, NULL);
+
+ filename = strdup (file);
+ if (!filename) {
+ fprintf (stderr, "gf_log_init: strdup error\n");
+ return -1;
+ }
+
+ logfile = fopen (file, "a");
+ if (!logfile){
+ fprintf (stderr,
+ "gf_log_init: failed to open logfile \"%s\" (%s)\n",
+ file,
+ strerror (errno));
+ return -1;
+ }
+
+ gf_log_logfile = logfile;
+
+ return 0;
+}
+
+
+void
+gf_log_lock (void)
+{
+ pthread_mutex_lock (&logfile_mutex);
+}
+
+
+void
+gf_log_unlock (void)
+{
+ pthread_mutex_unlock (&logfile_mutex);
+}
+
+
+void
+gf_log_cleanup (void)
+{
+ pthread_mutex_destroy (&logfile_mutex);
+}
+
+
+int
+_gf_log (const char *domain, const char *file, const char *function, int line,
+ gf_loglevel_t level, const char *fmt, ...)
+{
+ const char *basename = NULL;
+ FILE *new_logfile = NULL;
+ va_list ap;
+ time_t utime = 0;
+ struct tm *tm = NULL;
+ char timestr[256];
+ static char *level_strings[] = {"N", /* NONE */
+ "T", /* TRACE */
+ "C", /* CRITICAL */
+ "E", /* ERROR */
+ "W", /* WARNING */
+ "N", /* TRACE (GF_LOG_NORMAL) */
+ "D", /* DEBUG */
+ ""};
+
+ if (!domain || !file || !function || !fmt) {
+ fprintf (stderr,
+ "logging: %s:%s():%d: invalid argument\n",
+ __FILE__, __PRETTY_FUNCTION__, __LINE__);
+ return -1;
+ }
+
+ if (!logfile) {
+ fprintf (stderr, "no logfile set\n");
+ return (-1);
+ }
+
+ if (logrotate) {
+ logrotate = 0;
+
+ new_logfile = fopen (filename, "a");
+ if (!new_logfile) {
+ gf_log ("logrotate", GF_LOG_CRITICAL,
+ "failed to open logfile %s (%s)",
+ filename, strerror (errno));
+ goto log;
+ }
+
+ fclose (logfile);
+ gf_log_logfile = logfile = new_logfile;
+ }
+
+log:
+ utime = time (NULL);
+ tm = localtime (&utime);
+
+ if (level > loglevel) {
+ goto out;
+ }
+
+ pthread_mutex_lock (&logfile_mutex);
+ {
+ va_start (ap, fmt);
+
+ strftime (timestr, 256, "%Y-%m-%d %H:%M:%S", tm);
+
+ basename = strrchr (file, '/');
+ if (basename)
+ basename++;
+ else
+ basename = file;
+
+ fprintf (logfile, "%s %s [%s:%d:%s] %s: ",
+ timestr, level_strings[level],
+ basename, line, function,
+ domain);
+
+ vfprintf (logfile, fmt, ap);
+ va_end (ap);
+ fprintf (logfile, "\n");
+ fflush (logfile);
+ }
+ pthread_mutex_unlock (&logfile_mutex);
+
+out:
+ return (0);
+}
diff --git a/libglusterfs/src/logging.h b/libglusterfs/src/logging.h
new file mode 100644
index 000000000..7a0deb6e8
--- /dev/null
+++ b/libglusterfs/src/logging.h
@@ -0,0 +1,132 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+
+#ifndef __LOGGING_H__
+#define __LOGGING_H__
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+
+#define GF_PRI_FSBLK PRId64
+#define GF_PRI_BLKSIZE "ld"
+#if GF_LINUX_HOST_OS
+
+# if __WORDSIZE == 64
+# define GF_PRI_SIZET "lu"
+# define GF_PRI_NLINK "lu"
+# else
+# define GF_PRI_SIZET "u"
+# define GF_PRI_NLINK "u"
+# endif /* __WORDSIZE */
+
+#elif GF_DARWIN_HOST_OS
+
+/* Noticed that size_t and ino_t are different on OSX, need to fix the warnings */
+# define GF_PRI_SIZET "lu"
+# define GF_PRI_NLINK "u"
+
+# undef GF_PRI_FSBLK
+# define GF_PRI_FSBLK "u"
+
+# undef GF_PRI_BLKSIZE
+# define GF_PRI_BLKSIZE "u"
+
+# if __DARWIN_64_BIT_INO_T == 0
+# error '64 bit ino_t is must for GlusterFS to work, Compile with "CFLAGS=-D__DARWIN_64_BIT_INO_T"'
+# endif /* __DARWIN_64_BIT_INO_T */
+
+#else /* !LINUX && !DARWIN */
+
+/* BSD and Solaris : Change as per testing there.. */
+# define GF_PRI_SIZET "lu"
+# define GF_PRI_NLINK "u"
+
+#endif /* LINUX_OS */
+
+#define GF_PRI_DEV GF_PRI_FSBLK
+
+typedef enum {
+ GF_LOG_NONE,
+ GF_LOG_TRACE,
+ GF_LOG_CRITICAL, /* fatal errors */
+ GF_LOG_ERROR, /* major failures (not necessarily fatal) */
+ GF_LOG_WARNING, /* info about normal operation */
+ GF_LOG_INFO, /* Normal information */
+#define GF_LOG_NORMAL GF_LOG_INFO
+ GF_LOG_DEBUG, /* all other junk */
+} gf_loglevel_t;
+
+#define GF_LOG_MAX GF_LOG_DEBUG
+
+extern gf_loglevel_t gf_log_loglevel;
+
+#define gf_log(dom, levl, fmt...) do { \
+ if (levl <= gf_log_loglevel) \
+ _gf_log (dom, __FILE__, __FUNCTION__, __LINE__, \
+ levl, ##fmt); \
+ if (0) { \
+ printf (fmt); \
+ } \
+} while (0)
+
+/* Log once in GF_UNIVERSAL_ANSWER times */
+#define GF_LOG_OCCASIONALLY(var, args...) if (!(var++%GF_UNIVERSAL_ANSWER)) { \
+ gf_log (args); \
+ }
+
+
+void
+gf_log_logrotate (int signum);
+
+int gf_log_init (const char *filename);
+
+int
+_gf_log (const char *domain, const char *file, const char *function,
+ int32_t line, gf_loglevel_t level, const char *fmt, ...);
+
+void gf_log_lock (void);
+void gf_log_unlock (void);
+
+gf_loglevel_t
+gf_log_get_loglevel (void);
+void
+gf_log_set_loglevel (gf_loglevel_t level);
+
+#define GF_DEBUG(xl, format, args...) \
+ gf_log ((xl)->name, GF_LOG_DEBUG, format, ##args)
+#define GF_INFO(xl, format, args...) \
+ gf_log ((xl)->name, GF_LOG_INFO, format, ##args)
+#define GF_WARNING(xl, format, args...) \
+ gf_log ((xl)->name, GF_LOG_WARNING, format, ##args)
+#define GF_ERROR(xl, format, args...) \
+ gf_log ((xl)->name, GF_LOG_ERROR, format, ##args)
+
+#define GF_TRACE(xl, args...) do { \
+ if ((xl)->trace) \
+ _gf_log ((xl)->name, __FILE__, __FUNCTION__, \
+ __LINE__, GF_LOG_TRACE, ##args); \
+ } while(0); \
+
+#endif /* __LOGGING_H__ */
diff --git a/libglusterfs/src/mem-pool.c b/libglusterfs/src/mem-pool.c
new file mode 100644
index 000000000..c3646f350
--- /dev/null
+++ b/libglusterfs/src/mem-pool.c
@@ -0,0 +1,174 @@
+/*
+ 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 "mem-pool.h"
+#include "logging.h"
+#include <stdlib.h>
+
+
+#define GF_MEM_POOL_PAD_BOUNDRY 16
+
+
+struct mem_pool *
+mem_pool_new_fn (unsigned long sizeof_type,
+ unsigned long count)
+{
+ struct mem_pool *mem_pool = NULL;
+ int pad = 0;
+ unsigned long padded_sizeof_type = 0;
+ void *pool = NULL;
+ int i = 0;
+ struct list_head *list = NULL;
+
+ if (!sizeof_type || !count) {
+ gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument");
+ return NULL;
+ }
+
+ pad = GF_MEM_POOL_PAD_BOUNDRY -
+ (sizeof_type % GF_MEM_POOL_PAD_BOUNDRY);
+ padded_sizeof_type = sizeof_type + pad;
+
+ mem_pool = CALLOC (sizeof (*mem_pool), 1);
+ if (!mem_pool)
+ return NULL;
+
+ LOCK_INIT (&mem_pool->lock);
+ INIT_LIST_HEAD (&mem_pool->list);
+
+ mem_pool->padded_sizeof_type = padded_sizeof_type;
+ mem_pool->cold_count = count;
+
+ pool = CALLOC (count, sizeof_type + pad);
+ if (!pool)
+ return NULL;
+
+ for (i = 0; i < count; i++) {
+ list = pool + (i * (sizeof_type + pad));
+ INIT_LIST_HEAD (list);
+ list_add_tail (list, &mem_pool->list);
+ }
+
+ mem_pool->pool = pool;
+ mem_pool->pool_end = pool + (count * (sizeof_type + pad));
+
+ return mem_pool;
+}
+
+
+void *
+mem_get (struct mem_pool *mem_pool)
+{
+ struct list_head *list = NULL;
+ void *ptr = NULL;
+
+ if (!mem_pool) {
+ gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument");
+ return NULL;
+ }
+
+ LOCK (&mem_pool->lock);
+ {
+ if (mem_pool->cold_count) {
+ list = mem_pool->list.next;
+ list_del (list);
+
+ mem_pool->hot_count++;
+ mem_pool->cold_count--;
+
+ ptr = list;
+ }
+ }
+ UNLOCK (&mem_pool->lock);
+
+ if (ptr == NULL) {
+ ptr = MALLOC (mem_pool->padded_sizeof_type);
+
+ if (!ptr) {
+ return NULL;
+ }
+
+ LOCK (&mem_pool->lock);
+ {
+ mem_pool->hot_count ++;
+ }
+ UNLOCK (&mem_pool->lock);
+ }
+
+ return ptr;
+}
+
+
+static int
+__is_member (struct mem_pool *pool, void *ptr)
+{
+ if (!pool || !ptr) {
+ gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument");
+ return -1;
+ }
+
+ if (ptr < pool->pool || ptr >= pool->pool_end)
+ return 0;
+
+ if ((ptr - pool->pool) % pool->padded_sizeof_type)
+ return -1;
+
+ return 1;
+}
+
+
+void
+mem_put (struct mem_pool *pool, void *ptr)
+{
+ struct list_head *list = NULL;
+
+ if (!pool || !ptr) {
+ gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument");
+ return;
+ }
+
+ list = ptr;
+
+ LOCK (&pool->lock);
+ {
+ pool->hot_count--;
+
+ switch (__is_member (pool, ptr))
+ {
+ case 1:
+ pool->cold_count++;
+ list_add (list, &pool->list);
+ break;
+ case -1:
+ /* log error */
+ abort ();
+ break;
+ case 0:
+ free (ptr);
+ break;
+ default:
+ /* log error */
+ break;
+ }
+ }
+ UNLOCK (&pool->lock);
+
+ if (ptr)
+ free (ptr);
+}
diff --git a/libglusterfs/src/mem-pool.h b/libglusterfs/src/mem-pool.h
new file mode 100644
index 000000000..b36c24477
--- /dev/null
+++ b/libglusterfs/src/mem-pool.h
@@ -0,0 +1,54 @@
+/*
+ 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/>.
+*/
+
+#ifndef _MEM_POOL_H_
+#define _MEM_POOL_H_
+
+#include "list.h"
+#include "locking.h"
+
+
+#define MALLOC(size) malloc(size)
+#define CALLOC(size,cnt) calloc(size,cnt)
+
+#define FREE(ptr) \
+ if (ptr != NULL) { \
+ free ((void *)ptr); \
+ ptr = (void *)0xeeeeeeee; \
+ }
+
+struct mem_pool {
+ struct list_head list;
+ int hot_count;
+ int cold_count;
+ gf_lock_t lock;
+ unsigned long padded_sizeof_type;
+ void *pool;
+ void *pool_end;
+};
+
+struct mem_pool *
+mem_pool_new_fn (unsigned long sizeof_type, unsigned long count);
+
+#define mem_pool_new(type,count) mem_pool_new_fn (sizeof(type), count)
+
+void mem_put (struct mem_pool *pool, void *ptr);
+void *mem_get (struct mem_pool *pool);
+
+#endif /* _MEM_POOL_H */
diff --git a/libglusterfs/src/protocol.h b/libglusterfs/src/protocol.h
new file mode 100644
index 000000000..4ba869dee
--- /dev/null
+++ b/libglusterfs/src/protocol.h
@@ -0,0 +1,777 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+#ifndef _PROTOCOL_H
+#define _PROTOCOL_H
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <inttypes.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "byte-order.h"
+
+
+struct gf_stat {
+ uint64_t ino;
+ uint64_t size;
+ uint64_t blocks;
+ uint32_t dev;
+ uint32_t rdev;
+ uint32_t mode;
+ uint32_t nlink;
+ uint32_t uid;
+ uint32_t gid;
+ uint32_t blksize;
+ uint32_t atime;
+ uint32_t atime_nsec;
+ uint32_t mtime;
+ uint32_t mtime_nsec;
+ uint32_t ctime;
+ uint32_t ctime_nsec;
+} __attribute__((packed));
+
+
+static inline void
+gf_stat_to_stat (struct gf_stat *gf_stat, struct stat *stat)
+{
+ stat->st_dev = ntoh32 (gf_stat->dev);
+ stat->st_ino = ntoh64 (gf_stat->ino);
+ stat->st_mode = ntoh32 (gf_stat->mode);
+ stat->st_nlink = ntoh32 (gf_stat->nlink);
+ stat->st_uid = ntoh32 (gf_stat->uid);
+ stat->st_gid = ntoh32 (gf_stat->gid);
+ stat->st_rdev = ntoh32 (gf_stat->rdev);
+ stat->st_size = ntoh64 (gf_stat->size);
+ stat->st_blksize = ntoh32 (gf_stat->blksize);
+ stat->st_blocks = ntoh64 (gf_stat->blocks);
+ stat->st_atime = ntoh32 (gf_stat->atime);
+ stat->st_mtime = ntoh32 (gf_stat->mtime);
+ stat->st_ctime = ntoh32 (gf_stat->ctime);
+ /* TODO: handle nsec */
+}
+
+
+static inline void
+gf_stat_from_stat (struct gf_stat *gf_stat, struct stat *stat)
+{
+ gf_stat->dev = hton32 (stat->st_dev);
+ gf_stat->ino = hton64 (stat->st_ino);
+ gf_stat->mode = hton32 (stat->st_mode);
+ gf_stat->nlink = hton32 (stat->st_nlink);
+ gf_stat->uid = hton32 (stat->st_uid);
+ gf_stat->gid = hton32 (stat->st_gid);
+ gf_stat->rdev = hton32 (stat->st_rdev);
+ gf_stat->size = hton64 (stat->st_size);
+ gf_stat->blksize = hton32 (stat->st_blksize);
+ gf_stat->blocks = hton64 (stat->st_blocks);
+ gf_stat->atime = hton32 (stat->st_atime);
+ gf_stat->mtime = hton32 (stat->st_mtime);
+ gf_stat->ctime = hton32 (stat->st_ctime);
+ /* TODO: handle nsec */
+}
+
+
+struct gf_statfs {
+ uint64_t bsize;
+ uint64_t frsize;
+ uint64_t blocks;
+ uint64_t bfree;
+ uint64_t bavail;
+ uint64_t files;
+ uint64_t ffree;
+ uint64_t favail;
+ uint64_t fsid;
+ uint64_t flag;
+ uint64_t namemax;
+} __attribute__((packed));
+
+
+static inline void
+gf_statfs_to_statfs (struct gf_statfs *gf_stat, struct statvfs *stat)
+{
+ stat->f_bsize = ntoh64 (gf_stat->bsize);
+ stat->f_frsize = ntoh64 (gf_stat->frsize);
+ stat->f_blocks = ntoh64 (gf_stat->blocks);
+ stat->f_bfree = ntoh64 (gf_stat->bfree);
+ stat->f_bavail = ntoh64 (gf_stat->bavail);
+ stat->f_files = ntoh64 (gf_stat->files);
+ stat->f_ffree = ntoh64 (gf_stat->ffree);
+ stat->f_favail = ntoh64 (gf_stat->favail);
+ stat->f_fsid = ntoh64 (gf_stat->fsid);
+ stat->f_flag = ntoh64 (gf_stat->flag);
+ stat->f_namemax = ntoh64 (gf_stat->namemax);
+}
+
+
+static inline void
+gf_statfs_from_statfs (struct gf_statfs *gf_stat, struct statvfs *stat)
+{
+ gf_stat->bsize = hton64 (stat->f_bsize);
+ gf_stat->frsize = hton64 (stat->f_frsize);
+ gf_stat->blocks = hton64 (stat->f_blocks);
+ gf_stat->bfree = hton64 (stat->f_bfree);
+ gf_stat->bavail = hton64 (stat->f_bavail);
+ gf_stat->files = hton64 (stat->f_files);
+ gf_stat->ffree = hton64 (stat->f_ffree);
+ gf_stat->favail = hton64 (stat->f_favail);
+ gf_stat->fsid = hton64 (stat->f_fsid);
+ gf_stat->flag = hton64 (stat->f_flag);
+ gf_stat->namemax = hton64 (stat->f_namemax);
+}
+
+
+struct gf_flock {
+ uint16_t type;
+ uint16_t whence;
+ uint64_t start;
+ uint64_t len;
+ uint32_t pid;
+} __attribute__((packed));
+
+
+static inline void
+gf_flock_to_flock (struct gf_flock *gf_flock, struct flock *flock)
+{
+ flock->l_type = ntoh16 (gf_flock->type);
+ flock->l_whence = ntoh16 (gf_flock->whence);
+ flock->l_start = ntoh64 (gf_flock->start);
+ flock->l_len = ntoh64 (gf_flock->len);
+ flock->l_pid = ntoh32 (gf_flock->pid);
+}
+
+
+static inline void
+gf_flock_from_flock (struct gf_flock *gf_flock, struct flock *flock)
+{
+ gf_flock->type = hton16 (flock->l_type);
+ gf_flock->whence = hton16 (flock->l_whence);
+ gf_flock->start = hton64 (flock->l_start);
+ gf_flock->len = hton64 (flock->l_len);
+ gf_flock->pid = hton32 (flock->l_pid);
+}
+
+
+struct gf_timespec {
+ uint32_t tv_sec;
+ uint32_t tv_nsec;
+} __attribute__((packed));
+
+
+static inline void
+gf_timespec_to_timespec (struct gf_timespec *gf_ts, struct timespec *ts)
+{
+
+ ts[0].tv_sec = ntoh32 (gf_ts[0].tv_sec);
+ ts[0].tv_nsec = ntoh32 (gf_ts[0].tv_nsec);
+ ts[1].tv_sec = ntoh32 (gf_ts[1].tv_sec);
+ ts[1].tv_nsec = ntoh32 (gf_ts[1].tv_nsec);
+}
+
+
+static inline void
+gf_timespec_from_timespec (struct gf_timespec *gf_ts, struct timespec *ts)
+{
+ gf_ts[0].tv_sec = hton32 (ts[0].tv_sec);
+ gf_ts[0].tv_nsec = hton32 (ts[0].tv_nsec);
+ gf_ts[1].tv_sec = hton32 (ts[1].tv_sec);
+ gf_ts[1].tv_nsec = hton32 (ts[1].tv_nsec);
+}
+
+
+typedef struct {
+ uint64_t ino;
+ char path[0]; /* NULL terminated */
+} __attribute__((packed)) gf_fop_stat_req_t;;
+typedef struct {
+ struct gf_stat stat;
+} __attribute__((packed)) gf_fop_stat_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ uint32_t size;
+ char path[0]; /* NULL terminated */
+} __attribute__((packed)) gf_fop_readlink_req_t;
+typedef struct {
+ char path[0]; /* NULL terminated */
+} __attribute__((packed)) gf_fop_readlink_rsp_t;
+
+
+typedef struct {
+ uint64_t par;
+ uint64_t dev;
+ uint32_t mode;
+ char path[0]; /* NULL terminated */
+ char bname[0]; /* NULL terminated */
+} __attribute__((packed)) gf_fop_mknod_req_t;
+typedef struct {
+ struct gf_stat stat;
+} __attribute__((packed)) gf_fop_mknod_rsp_t;
+
+
+typedef struct {
+ uint64_t par;
+ uint32_t mode;
+ char path[0]; /* NULL terminated */
+ char bname[0]; /* NULL terminated */
+} __attribute__((packed)) gf_fop_mkdir_req_t;
+typedef struct {
+ struct gf_stat stat;
+} __attribute__((packed)) gf_fop_mkdir_rsp_t;
+
+
+typedef struct {
+ uint64_t par;
+ char path[0]; /* NULL terminated */
+ char bname[0]; /* NULL terminated */
+} __attribute__((packed)) gf_fop_unlink_req_t;
+typedef struct {
+} __attribute__((packed)) gf_fop_unlink_rsp_t;
+
+
+typedef struct {
+ uint64_t par;
+ char path[0];
+ char bname[0]; /* NULL terminated */
+} __attribute__((packed)) gf_fop_rmdir_req_t;
+typedef struct {
+} __attribute__((packed)) gf_fop_rmdir_rsp_t;
+
+
+typedef struct {
+ uint64_t par;
+ char path[0];
+ char bname[0];
+ char linkname[0];
+} __attribute__((packed)) gf_fop_symlink_req_t;
+typedef struct {
+ struct gf_stat stat;
+}__attribute__((packed)) gf_fop_symlink_rsp_t;
+
+
+typedef struct {
+ uint64_t oldpar;
+ uint64_t newpar;
+ char oldpath[0];
+ char oldbname[0]; /* NULL terminated */
+ char newpath[0];
+ char newbname[0]; /* NULL terminated */
+} __attribute__((packed)) gf_fop_rename_req_t;
+typedef struct {
+ struct gf_stat stat;
+} __attribute__((packed)) gf_fop_rename_rsp_t;
+
+
+typedef struct {
+ uint64_t oldino;
+ uint64_t newpar;
+ char oldpath[0];
+ char newpath[0];
+ char newbname[0];
+}__attribute__((packed)) gf_fop_link_req_t;
+typedef struct {
+ struct gf_stat stat;
+} __attribute__((packed)) gf_fop_link_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ uint32_t mode;
+ char path[0];
+} __attribute__((packed)) gf_fop_chmod_req_t;
+typedef struct {
+ struct gf_stat stat;
+} __attribute__((packed)) gf_fop_chmod_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ uint32_t uid;
+ uint32_t gid;
+ char path[0];
+} __attribute__((packed)) gf_fop_chown_req_t;
+typedef struct {
+ struct gf_stat stat;
+} __attribute__((packed)) gf_fop_chown_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ uint64_t offset;
+ char path[0];
+} __attribute__((packed)) gf_fop_truncate_req_t;
+typedef struct {
+ struct gf_stat stat;
+} __attribute__((packed)) gf_fop_truncate_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ uint32_t flags;
+ char path[0];
+} __attribute__((packed)) gf_fop_open_req_t;
+typedef struct {
+ int64_t fd;
+} __attribute__((packed)) gf_fop_open_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ int64_t fd;
+ uint64_t offset;
+ uint32_t size;
+} __attribute__((packed)) gf_fop_read_req_t;
+typedef struct {
+ struct gf_stat stat;
+ char buf[0];
+} __attribute__((packed)) gf_fop_read_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ int64_t fd;
+ uint64_t offset;
+ uint32_t size;
+} __attribute__((packed)) gf_fop_write_req_t;
+typedef struct {
+ struct gf_stat stat;
+} __attribute__((packed)) gf_fop_write_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ char path[0];
+} __attribute__((packed)) gf_fop_statfs_req_t;
+typedef struct {
+ struct gf_statfs statfs;
+} __attribute__((packed)) gf_fop_statfs_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ int64_t fd;
+} __attribute__((packed)) gf_fop_flush_req_t;
+typedef struct { } __attribute__((packed)) gf_fop_flush_rsp_t;
+
+
+typedef struct fsync_req {
+ uint64_t ino;
+ int64_t fd;
+ uint32_t data;
+} __attribute__((packed)) gf_fop_fsync_req_t;
+typedef struct {
+} __attribute__((packed)) gf_fop_fsync_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ uint32_t flags;
+ uint32_t dict_len;
+ char dict[0];
+ char path[0];
+} __attribute__((packed)) gf_fop_setxattr_req_t;
+typedef struct { } __attribute__((packed)) gf_fop_setxattr_rsp_t;
+
+typedef struct {
+ uint64_t ino;
+ uint32_t flags;
+ uint32_t dict_len;
+ char dict[0];
+ char path[0];
+} __attribute__((packed)) gf_fop_xattrop_req_t;
+
+typedef struct {
+ uint32_t dict_len;
+ char dict[0];
+} __attribute__((packed)) gf_fop_xattrop_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ int64_t fd;
+ uint32_t flags;
+ uint32_t dict_len;
+ char dict[0];
+} __attribute__((packed)) gf_fop_fxattrop_req_t;
+
+typedef struct {
+ uint32_t dict_len;
+ char dict[0];
+} __attribute__((packed)) gf_fop_fxattrop_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ uint32_t namelen;
+ char path[0];
+ char name[0];
+} __attribute__((packed)) gf_fop_getxattr_req_t;
+typedef struct {
+ uint32_t dict_len;
+ char dict[0];
+} __attribute__((packed)) gf_fop_getxattr_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ char path[0];
+ char name[0];
+} __attribute__((packed)) gf_fop_removexattr_req_t;
+typedef struct { } __attribute__((packed)) gf_fop_removexattr_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ char path[0];
+} __attribute__((packed)) gf_fop_opendir_req_t;
+typedef struct {
+ int64_t fd;
+} __attribute__((packed)) gf_fop_opendir_rsp_t;
+
+
+typedef struct fsyncdir_req {
+ uint64_t ino;
+ int64_t fd;
+ int32_t data;
+} __attribute__((packed)) gf_fop_fsyncdir_req_t;
+typedef struct {
+} __attribute__((packed)) gf_fop_fsyncdir_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ int64_t fd;
+ uint64_t offset;
+ uint32_t size;
+} __attribute__((packed)) gf_fop_readdir_req_t;
+typedef struct {
+ uint32_t size;
+ char buf[0];
+} __attribute__((packed)) gf_fop_readdir_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ uint32_t mask;
+ char path[0];
+} __attribute__((packed)) gf_fop_access_req_t;
+typedef struct {
+} __attribute__((packed)) gf_fop_access_rsp_t;
+
+
+typedef struct {
+ uint64_t par;
+ uint32_t flags;
+ uint32_t mode;
+ char path[0];
+ char bname[0];
+} __attribute__((packed)) gf_fop_create_req_t;
+typedef struct {
+ struct gf_stat stat;
+ uint64_t fd;
+} __attribute__((packed)) gf_fop_create_rsp_t;
+
+
+
+typedef struct {
+ uint64_t ino;
+ int64_t fd;
+ uint64_t offset;
+} __attribute__((packed)) gf_fop_ftruncate_req_t;
+typedef struct {
+ struct gf_stat stat;
+} __attribute__((packed)) gf_fop_ftruncate_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ int64_t fd;
+} __attribute__((packed)) gf_fop_fstat_req_t;
+typedef struct {
+ struct gf_stat stat;
+} __attribute__((packed)) gf_fop_fstat_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ int64_t fd;
+ uint32_t cmd;
+ uint32_t type;
+ struct gf_flock flock;
+} __attribute__((packed)) gf_fop_lk_req_t;
+typedef struct {
+ struct gf_flock flock;
+} __attribute__((packed)) gf_fop_lk_rsp_t;
+
+typedef struct {
+ uint64_t ino;
+ uint32_t cmd;
+ uint32_t type;
+ struct gf_flock flock;
+ char path[0];
+} __attribute__((packed)) gf_fop_inodelk_req_t;
+typedef struct {
+} __attribute__((packed)) gf_fop_inodelk_rsp_t;
+
+typedef struct {
+ uint64_t ino;
+ int64_t fd;
+ uint32_t cmd;
+ uint32_t type;
+ struct gf_flock flock;
+} __attribute__((packed)) gf_fop_finodelk_req_t;
+typedef struct {
+} __attribute__((packed)) gf_fop_finodelk_rsp_t;
+
+typedef struct {
+ uint64_t ino;
+ uint32_t cmd;
+ uint32_t type;
+ uint64_t namelen;
+ char path[0];
+ char name[0];
+} __attribute__((packed)) gf_fop_entrylk_req_t;
+typedef struct {
+} __attribute__((packed)) gf_fop_entrylk_rsp_t;
+
+typedef struct {
+ uint64_t ino;
+ int64_t fd;
+ uint32_t cmd;
+ uint32_t type;
+ uint64_t namelen;
+ char name[0];
+} __attribute__((packed)) gf_fop_fentrylk_req_t;
+typedef struct {
+} __attribute__((packed)) gf_fop_fentrylk_rsp_t;
+
+typedef struct {
+ uint64_t ino;
+ struct gf_timespec tv[2];
+ char path[0];
+} __attribute__((packed)) gf_fop_utimens_req_t;
+typedef struct {
+ struct gf_stat stat;
+} __attribute__((packed)) gf_fop_utimens_rsp_t;
+
+typedef struct {
+ uint64_t ino;
+ uint64_t fd;
+ uint32_t mode;
+} __attribute__((packed)) gf_fop_fchmod_req_t;
+typedef struct {
+ struct gf_stat stat;
+} __attribute__((packed)) gf_fop_fchmod_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ int64_t fd;
+ uint32_t uid;
+ uint32_t gid;
+} __attribute__((packed)) gf_fop_fchown_req_t;
+typedef struct {
+ struct gf_stat stat;
+} __attribute__((packed)) gf_fop_fchown_rsp_t;
+
+
+typedef struct {
+ uint64_t ino; /* NOTE: used only in case of 'root' lookup */
+ uint64_t par;
+ uint32_t flags;
+ uint32_t dictlen;
+ char path[0];
+ char bname[0];
+ char dict[0];
+} __attribute__((packed)) gf_fop_lookup_req_t;
+typedef struct {
+ struct gf_stat stat;
+ uint32_t dict_len;
+ char dict[0];
+} __attribute__((packed)) gf_fop_lookup_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ int64_t fd;
+ uint32_t flags;
+ uint32_t count;
+ char buf[0];
+} __attribute__((packed)) gf_fop_setdents_req_t;
+typedef struct { } __attribute__((packed)) gf_fop_setdents_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ int64_t fd;
+ uint64_t offset;
+ uint32_t size;
+ uint32_t flags;
+} __attribute__((packed)) gf_fop_getdents_req_t;
+typedef struct {
+ uint32_t count;
+ char buf[0];
+} __attribute__((packed)) gf_fop_getdents_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ uint32_t flag;
+ char path[0];
+} __attribute__((packed)) gf_fop_checksum_req_t;
+typedef struct {
+ unsigned char fchecksum[0];
+ unsigned char dchecksum[0];
+} __attribute__((packed)) gf_fop_checksum_rsp_t;
+
+
+typedef struct {
+ char name[0];
+} __attribute__((packed)) gf_mop_lock_req_t;
+typedef struct {} __attribute__((packed)) gf_mop_lock_rsp_t;
+
+typedef struct {
+ char name[0];
+} __attribute__((packed)) gf_mop_unlock_req_t;
+typedef struct {} __attribute__((packed)) gf_mop_unlock_rsp_t;
+
+typedef struct {
+ char pattern[0];
+} __attribute__((packed)) gf_mop_listlocks_req_t;
+typedef struct {} __attribute__((packed)) gf_mop_listlocks_rsp_t;
+
+typedef struct {
+ uint32_t flags;
+} __attribute__((packed)) gf_mop_stats_req_t;
+typedef struct {
+ char buf[0];
+} __attribute__((packed)) gf_mop_stats_rsp_t;
+
+typedef struct {
+ uint32_t flags;
+ uint32_t keylen;
+ char key[0];
+} __attribute__((packed)) gf_mop_getspec_req_t;
+typedef struct {
+ char spec[0];
+} __attribute__((packed)) gf_mop_getspec_rsp_t;
+
+
+typedef struct {
+ uint32_t dict_len;
+ char buf[0];
+} __attribute__((packed)) gf_mop_setvolume_req_t;
+typedef struct {
+ uint32_t dict_len;
+ char buf[0];
+} __attribute__((packed)) gf_mop_setvolume_rsp_t;
+
+
+typedef struct {
+} __attribute__((packed)) gf_mop_ping_req_t;
+typedef struct {
+} __attribute__((packed)) gf_mop_ping_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ int64_t fd;
+} __attribute__((packed)) gf_cbk_releasedir_req_t;
+typedef struct {
+} __attribute__((packed)) gf_cbk_releasedir_rsp_t;
+
+
+typedef struct {
+ uint64_t ino;
+ int64_t fd;
+} __attribute__((packed)) gf_cbk_release_req_t;
+typedef struct {
+} __attribute__((packed)) gf_cbk_release_rsp_t;
+
+
+typedef struct {
+ uint32_t count;
+ uint64_t ino_array[0];
+} __attribute__((packed)) gf_cbk_forget_req_t;
+typedef struct { } __attribute__((packed)) gf_cbk_forget_rsp_t;
+
+
+typedef struct {
+ uint32_t pid;
+ uint32_t uid;
+ uint32_t gid;
+} __attribute__ ((packed)) gf_hdr_req_t;
+
+
+typedef struct {
+ uint32_t op_ret;
+ uint32_t op_errno;
+} __attribute__ ((packed)) gf_hdr_rsp_t;
+
+
+typedef struct {
+ uint64_t callid;
+ uint32_t type;
+ uint32_t op;
+ uint32_t size;
+ union {
+ gf_hdr_req_t req;
+ gf_hdr_rsp_t rsp;
+ } __attribute__ ((packed));
+} __attribute__ ((packed)) gf_hdr_common_t;
+
+
+static inline gf_hdr_common_t *
+__gf_hdr_new (int size)
+{
+ gf_hdr_common_t *hdr = NULL;
+
+ /* TODO: use mem-pool */
+ hdr = CALLOC (sizeof (gf_hdr_common_t) + size, 1);
+
+ if (!hdr) {
+ return NULL;
+ }
+
+ hdr->size = hton32 (size);
+
+ return hdr;
+}
+
+
+#define gf_hdr_len(type, x) (sizeof (gf_hdr_common_t) + sizeof (*type) + x)
+#define gf_hdr_new(type, x) __gf_hdr_new (sizeof (*type) + x)
+
+
+static inline void *
+gf_param (gf_hdr_common_t *hdr)
+{
+ return ((void *)hdr) + sizeof (*hdr);
+}
+
+#endif
diff --git a/libglusterfs/src/revision.h b/libglusterfs/src/revision.h
new file mode 100644
index 000000000..30742cd5e
--- /dev/null
+++ b/libglusterfs/src/revision.h
@@ -0,0 +1 @@
+#define GLUSTERFS_REPOSITORY_REVISION "glusterfs--mainline--3.0--patch-928"
diff --git a/libglusterfs/src/scheduler.c b/libglusterfs/src/scheduler.c
new file mode 100644
index 000000000..3478a9385
--- /dev/null
+++ b/libglusterfs/src/scheduler.c
@@ -0,0 +1,80 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <dlfcn.h>
+#include <netdb.h>
+#include "xlator.h"
+#include "scheduler.h"
+#include "list.h"
+
+struct sched_ops *
+get_scheduler (xlator_t *xl, const char *name)
+{
+ struct sched_ops *tmp_sched = NULL;
+ volume_opt_list_t *vol_opt = NULL;
+ char *sched_file = NULL;
+ void *handle = NULL;
+
+ if (name == NULL) {
+ gf_log ("scheduler", GF_LOG_ERROR,
+ "'name' not specified, EINVAL");
+ return NULL;
+ }
+
+ asprintf (&sched_file, "%s/%s.so", SCHEDULERDIR, name);
+
+ gf_log ("scheduler", GF_LOG_DEBUG,
+ "attempt to load file %s.so", name);
+
+ handle = dlopen (sched_file, RTLD_LAZY);
+ if (!handle) {
+ gf_log ("scheduler", GF_LOG_ERROR,
+ "dlopen(%s): %s", sched_file, dlerror ());
+ return NULL;
+ }
+
+ tmp_sched = dlsym (handle, "sched");
+ if (!tmp_sched) {
+ gf_log ("scheduler", GF_LOG_ERROR,
+ "dlsym(sched) on %s", dlerror ());
+ return NULL;
+ }
+
+ vol_opt = CALLOC (1, sizeof (volume_opt_list_t));
+ vol_opt->given_opt = dlsym (handle, "options");
+ if (vol_opt->given_opt == NULL) {
+ gf_log ("scheduler", GF_LOG_DEBUG,
+ "volume option validation not specified");
+ } else {
+ list_add_tail (&vol_opt->list, &xl->volume_options);
+ if (validate_xlator_volume_options (xl, vol_opt->given_opt)
+ == -1) {
+ gf_log ("scheduler", GF_LOG_ERROR,
+ "volume option validation failed");
+ return NULL;
+ }
+ }
+
+ return tmp_sched;
+}
diff --git a/libglusterfs/src/scheduler.h b/libglusterfs/src/scheduler.h
new file mode 100644
index 000000000..5ff1a624f
--- /dev/null
+++ b/libglusterfs/src/scheduler.h
@@ -0,0 +1,40 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+#ifndef _SCHEDULER_H
+#define _SCHEDULER_H
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "xlator.h"
+
+struct sched_ops {
+ int32_t (*init) (xlator_t *this);
+ void (*fini) (xlator_t *this);
+ void (*update) (xlator_t *this);
+ xlator_t *(*schedule) (xlator_t *this, const void *path);
+ void (*notify) (xlator_t *xl, int32_t event, void *data);
+};
+
+extern struct sched_ops *get_scheduler (xlator_t *xl, const char *name);
+
+#endif /* _SCHEDULER_H */
diff --git a/libglusterfs/src/spec.l b/libglusterfs/src/spec.l
new file mode 100644
index 000000000..0345730b2
--- /dev/null
+++ b/libglusterfs/src/spec.l
@@ -0,0 +1,94 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+
+%x STRING
+%option prefix="yy"
+%option yylineno
+%{
+
+#define YYSTYPE char *
+#include "xlator.h"
+#include "y.tab.h"
+#include <string.h>
+#define START_STRSIZE 32
+
+static char *text;
+static int text_asize;
+static int text_size;
+
+void new_string(void)
+{
+ text = malloc(START_STRSIZE);
+ text_asize = START_STRSIZE;
+ text_size = 0;
+ *text = 0;
+}
+
+void append_string(const char *str, int size)
+{
+ int new_size = text_size + size + 1;
+ if (new_size > text_asize) {
+ new_size += START_STRSIZE - 1;
+ new_size &= -START_STRSIZE;
+ text = realloc(text, new_size);
+ text_asize = new_size;
+ }
+ memcpy(text + text_size, str, size);
+ text_size += size;
+ text[text_size] = 0;
+}
+
+void alloc_string(const char *str, int size)
+{
+ text = malloc(size + 1);
+ memcpy(text, str, size);
+ text[size] = 0;
+}
+
+%}
+
+VOLUME [v][o][l][u][m][e]
+END [e][n][d]
+SUB [s][u][b]
+OPTION [o][p][t][i][o][n]
+TYPE [t][y][p][e]
+%%
+\#.* ;
+{VOLUME} return SECTION_BEGIN;
+{TYPE} return TYPE;
+{END}[-]{VOLUME} return SECTION_END;
+{SUB}{VOLUME}[Ss] return SUBSECTION;
+{OPTION} return OPTION;
+\" BEGIN(STRING);
+<STRING>{
+ [^\n\"\\]* { append_string (yytext, yyleng); }
+ \\. { append_string (yytext + 1, yyleng - 1); }
+ \" {
+ if (0) {
+ yyunput (0, NULL);
+ }
+ BEGIN (INITIAL);
+ yylval = text;
+ return STRING_TOK;
+ }
+}
+[^ \t\r\n\"\\]+ { yylval = strdup (yytext) ; return ID; }
+[ \t\r\n]+ ;
+%%
diff --git a/libglusterfs/src/spec.y b/libglusterfs/src/spec.y
new file mode 100644
index 000000000..c6491e28d
--- /dev/null
+++ b/libglusterfs/src/spec.y
@@ -0,0 +1,613 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+
+%token SECTION_BEGIN SECTION_END OPTION NEWLINE SUBSECTION ID WHITESPACE COMMENT TYPE STRING_TOK
+%name-prefix="yy"
+
+%{
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+#include "xlator.h"
+#include "logging.h"
+
+static int new_section (char *name);
+static int section_type (char *type);
+static int section_option (char *key, char *value);
+static int section_sub (char *sub);
+static int section_end (void);
+static void sub_error (void);
+static void type_error (void);
+static void option_error (void);
+
+#define YYSTYPE char *
+#define GF_CMD_BUFFER_LEN (32 * GF_UNIT_KB)
+
+int yyerror (const char *);
+int yylex ();
+%}
+
+
+%%
+SECTIONS: SECTION | SECTIONS SECTION;
+
+SECTION: SECTION_HEADER SECTION_DATA SECTION_FOOTER;
+SECTION_HEADER: SECTION_BEGIN WORD {if( -1 == new_section ($2)) { YYABORT; } };
+SECTION_FOOTER: SECTION_END {if( -1 == section_end ()) { YYABORT; } };
+
+SECTION_DATA: TYPE_LINE OPTIONS_LINE SUBSECTION_LINE OPTIONS_LINE |
+ TYPE_LINE SUBSECTION_LINE OPTIONS_LINE |
+ TYPE_LINE OPTIONS_LINE SUBSECTION_LINE |
+ TYPE_LINE SUBSECTION_LINE |
+ TYPE_LINE OPTIONS_LINE |
+ OPTIONS_LINE SUBSECTION_LINE OPTIONS_LINE | /* error case */
+ OPTIONS_LINE; /* error case */
+
+TYPE_LINE: TYPE WORD {if ( -1 == section_type ($2)) { YYABORT; }} | TYPE { type_error(); YYABORT; };
+
+SUBSECTION_LINE: SUBSECTION WORDS | SUBSECTION { sub_error (); YYABORT; };
+
+OPTIONS_LINE: OPTION_LINE | OPTIONS_LINE OPTION_LINE;
+
+OPTION_LINE: OPTION WORD WORD {if(-1 == section_option($2,$3)){YYABORT;} } |
+ OPTION WORD { option_error (); YYABORT; } |
+ OPTION { option_error (); YYABORT; };
+
+WORDS: WORD {if (-1 == section_sub ($1)) {YYABORT; } } | WORDS WORD { if (-1 == section_sub ($2)) { YYABORT; } };
+WORD: ID | STRING_TOK ;
+%%
+
+xlator_t *complete_tree = NULL;
+xlator_t *tree = NULL;
+glusterfs_ctx_t *gctx;
+
+static void
+type_error (void)
+{
+ extern int yylineno;
+
+ fprintf (stderr, "volume %s, before line %d: specify which 'type' "
+ "you need\n",
+ complete_tree->name, yylineno);
+ gf_log ("parser", GF_LOG_ERROR,
+ "volume %s, before line %d: specify which 'type' you need",
+ complete_tree->name, yylineno);
+ return;
+}
+
+static void
+sub_error (void)
+{
+ extern int yylineno;
+
+ fprintf (stderr, "volume %s, before line %d: specify what all "
+ "'subvolumes' you need for volume\n",
+ complete_tree->name, yylineno);
+ gf_log ("parser", GF_LOG_ERROR,
+ "volume %s, before line %d: specify what all 'subvolumes' "
+ "you need for volume",
+ complete_tree->name, yylineno);
+ return;
+}
+
+static void
+option_error (void)
+{
+ extern int yylineno;
+
+ fprintf (stderr, "volume %s, before line %d: you need to specify "
+ "<key> <value> pair for 'option' token\n",
+ complete_tree->name, yylineno);
+ gf_log ("parser", GF_LOG_ERROR,
+ "volume %s, before line %d: you need to specify <key> "
+ "<value> pair for 'option' token",
+ complete_tree->name, yylineno);
+ return;
+}
+
+static int
+cut_tree (xlator_t *tree)
+{
+ xlator_t *trav = tree, *prev = tree;
+
+ if (!tree) {
+ gf_log ("parser", GF_LOG_DEBUG, "Translator tree not found");
+ return -1;
+ }
+
+ gf_log ("parser", GF_LOG_DEBUG, "Failed to build translator graph");
+
+ while (prev) {
+ trav = prev->next;
+ dict_destroy (prev->options);
+ FREE (prev->name);
+ FREE (prev);
+ prev = trav;
+ }
+
+ return 0;
+}
+
+
+static int
+new_section (char *name)
+{
+ extern int yylineno;
+ xlator_t *trav = complete_tree;
+ xlator_t *node = (void *) calloc (1, sizeof (*node));
+
+ if (!name) {
+ gf_log ("parser", GF_LOG_DEBUG,
+ "invalid argument name '%s'", name);
+ return -1;
+ }
+
+ while (trav) {
+ if (!strcmp (name, trav->name)) {
+ fprintf (stderr,
+ "line %d: volume '%s' defined again\n",
+ yylineno, name);
+ gf_log ("parser", GF_LOG_ERROR,
+ "line %d: volume '%s' defined again",
+ yylineno, name);
+ return -1;
+ }
+ trav = trav->next;
+ }
+
+ node->ctx = gctx;
+ node->name = name;
+ node->next = complete_tree;
+ if (complete_tree)
+ complete_tree->prev = node;
+ node->options = get_new_dict ();
+ complete_tree = node;
+
+ tree = node;
+ gf_log ("parser", GF_LOG_DEBUG, "New node for '%s'", name);
+
+ return 0;
+}
+
+static int
+section_type (char *type)
+{
+ extern int yylineno;
+ int32_t ret = -1;
+ if (!type) {
+ gf_log ("parser", GF_LOG_DEBUG, "invalid argument type");
+ return -1;
+ }
+
+ ret = xlator_set_type (tree, type);
+ if (ret) {
+ fprintf (stderr, "volume '%s', line %d: type '%s' is not "
+ "valid or not found on this machine\n",
+ complete_tree->name, yylineno, type);
+ gf_log ("parser", GF_LOG_ERROR,
+ "volume '%s', line %d: type '%s' is not valid or "
+ "not found on this machine",
+ complete_tree->name, yylineno, type);
+ return -1;
+ }
+ gf_log ("parser", GF_LOG_DEBUG, "Type:%s:%s", tree->name, type);
+
+ return 0;
+}
+
+
+static int
+section_option (char *key, char *value)
+{
+ extern int yylineno;
+
+ int ret = 0;
+
+ if (!key || !value){
+ fprintf (stderr, "invalid argument\n");
+ gf_log ("parser", GF_LOG_ERROR, "invalid argument");
+ return -1;
+ }
+
+ ret = dict_set (tree->options, key, str_to_data (value));
+
+ if (ret == 1) {
+ gf_log ("parser", GF_LOG_ERROR,
+ "volume '%s', line %d: duplicate entry "
+ "('option %s') present",
+ tree->name, yylineno, key);
+ return -1;
+ }
+ gf_log ("parser", GF_LOG_DEBUG, "Option:%s:%s:%s",
+ tree->name, key, value);
+
+ return 0;
+}
+
+static int
+section_sub (char *sub)
+{
+ extern int yylineno;
+ xlator_t *trav = complete_tree;
+ xlator_list_t *xlchild, *tmp, *xlparent;
+
+ if (!sub) {
+ fprintf (stderr, "invalid subvolumes argument\n");
+ gf_log ("parser", GF_LOG_ERROR, "invalid subvolumes argument");
+ return -1;
+ }
+
+ while (trav) {
+ if (!strcmp (sub, trav->name))
+ break;
+ trav = trav->next;
+ }
+ if (!trav) {
+ fprintf (stderr,
+ "volume '%s', line %d: subvolume '%s' is not "
+ "defined prior to usage\n",
+ complete_tree->name, yylineno, sub);
+ gf_log ("parser", GF_LOG_ERROR,
+ "volume '%s', line %d: subvolume '%s' is not defined "
+ "prior to usage",
+ complete_tree->name, yylineno, sub);
+ return -1;
+ }
+
+ if (trav == tree) {
+ fprintf (stderr, "volume '%s', line %d: has '%s' itself as "
+ "subvolume\n",
+ complete_tree->name, yylineno, sub);
+ gf_log ("parser", GF_LOG_ERROR,
+ "volume '%s', line %d: has '%s' itself as subvolume",
+ complete_tree->name, yylineno, sub);
+ return -1;
+ }
+
+ xlparent = (void *) calloc (1, sizeof (*xlparent));
+ xlparent->xlator = tree;
+
+ tmp = trav->parents;
+ if (tmp == NULL) {
+ trav->parents = xlparent;
+ } else {
+ while (tmp->next)
+ tmp = tmp->next;
+ tmp->next = xlparent;
+ }
+
+ xlchild = (void *) calloc (1, sizeof(*xlchild));
+ xlchild->xlator = trav;
+
+ tmp = tree->children;
+ if (tmp == NULL) {
+ tree->children = xlchild;
+ } else {
+ while (tmp->next)
+ tmp = tmp->next;
+ tmp->next = xlchild;
+ }
+
+ gf_log ("parser", GF_LOG_DEBUG, "child:%s->%s", tree->name, sub);
+
+ return 0;
+}
+
+static int
+section_end (void)
+{
+ if (!tree->fops || !tree->mops) {
+ fprintf (stderr,
+ "\"type\" not specified for volume %s\n", tree->name);
+ gf_log ("parser", GF_LOG_ERROR,
+ "\"type\" not specified for volume %s", tree->name);
+ return -1;
+ }
+ gf_log ("parser", GF_LOG_DEBUG, "end:%s", tree->name);
+
+ tree = NULL;
+ return 0;
+}
+
+int
+yywrap ()
+{
+ return 1;
+}
+
+int
+yyerror (const char *str)
+{
+ extern char *yytext;
+ extern int yylineno;
+
+ if (complete_tree && complete_tree->name)
+ {
+ if (!strcmp (yytext, "volume"))
+ {
+ fprintf (stderr,
+ "'end-volume' not defined for volume '%s'\n",
+ complete_tree->name);
+ gf_log ("parser", GF_LOG_ERROR,
+ "'end-volume' not defined for volume '%s'",
+ complete_tree->name);
+ }
+ else if (!strcmp (yytext, "type"))
+ {
+ fprintf (stderr, "line %d: duplicate 'type' defined "
+ "for volume '%s'",
+ yylineno, complete_tree->name);
+ gf_log ("parser", GF_LOG_ERROR,
+ "line %d: duplicate 'type' defined for "
+ "volume '%s'",
+ yylineno, complete_tree->name);
+ }
+ else if (!strcmp (yytext, "subvolumes"))
+ {
+ fprintf (stderr, "line %d: duplicate 'subvolumes' "
+ "defined for volume '%s'",
+ yylineno, complete_tree->name);
+ gf_log ("parser", GF_LOG_ERROR,
+ "line %d: duplicate 'subvolumes' defined for "
+ "volume '%s'",
+ yylineno, complete_tree->name);
+ }
+ else if (tree)
+ {
+ fprintf (stderr,
+ "syntax error: line %d (volume '%s'): \"%s\""
+ "\nallowed tokens are 'volume', 'type', "
+ "'subvolumes', 'option', 'end-volume'",
+ yylineno, complete_tree->name,
+ yytext);
+
+ gf_log ("parser", GF_LOG_ERROR,
+ "syntax error: line %d (volume '%s'): \"%s\""
+ "\nallowed tokens are 'volume', 'type', "
+ "'subvolumes', 'option', 'end-volume'()",
+ yylineno, complete_tree->name,
+ yytext);
+ }
+ else
+ {
+ fprintf (stderr,
+ "syntax error: line %d (just after volume "
+ "'%s'): \"%s\"\n(%s)",
+ yylineno, complete_tree->name,
+ yytext,
+ "allowed tokens are 'volume', 'type', "
+ "'subvolumes', 'option', 'end-volume'");
+ gf_log ("parser", GF_LOG_ERROR,
+ "syntax error: line %d (just after volume "
+ "'%s'): \"%s\"\n(%s)",
+ yylineno, complete_tree->name,
+ yytext,
+ "allowed tokens are 'volume', 'type', "
+ "'subvolumes', 'option', 'end-volume'");
+ }
+ }
+ else
+ {
+ fprintf (stderr,
+ "syntax error in line %d: \"%s\" \n"
+ "(allowed tokens are 'volume', 'type', "
+ "'subvolumes', 'option', 'end-volume')\n",
+ yylineno, yytext);
+ gf_log ("parser", GF_LOG_ERROR,
+ "syntax error in line %d: \"%s\" \n"
+ "(allowed tokens are 'volume', 'type', "
+ "'subvolumes', 'option', 'end-volume')\n",
+ yylineno, yytext);
+ }
+
+ cut_tree (tree);
+ complete_tree = NULL;
+ return 0;
+}
+
+static int
+execute_cmd (char *cmd, char *result, int size)
+{
+ FILE *fpp = NULL;
+ int ret = 0;
+
+ fpp = popen (cmd, "r");
+ if (!fpp)
+ {
+ gf_log ("parser", GF_LOG_ERROR, "%s: failed to popen", cmd);
+ return -1;
+ }
+
+ if (!fgets (result, GF_UNIT_KB, fpp))
+ {
+ gf_log ("parser", GF_LOG_ERROR, "failed to read output of cmd (%s)", cmd);
+ pclose (fpp);
+ return -1;
+ }
+
+ ret = strlen (result);
+ result[ret - 1] = '\0';
+ ret--;
+ pclose (fpp);
+
+ return ret;
+}
+
+static int
+find_and_execute_cmds (char *src, char *dst)
+{
+ char escaped = 0;
+ char *cmd = NULL;
+ char in_backtick = 0;
+ int size = 0, ret = 0;
+
+ if (!src || !dst) {
+ ret = -1;
+ goto out;
+ }
+
+ while (*src) {
+ if (*src == '`' && !escaped) {
+ if (in_backtick) {
+ *src = '\0';
+ ret = execute_cmd (cmd, dst, GF_UNIT_KB);
+ if (ret < 0) {
+ ret = -1;
+ size = -1;
+ goto out;
+ }
+
+ dst += ret;
+ size += ret;
+ } else {
+ cmd = src + 1;
+ }
+
+ in_backtick = !in_backtick;
+ } else if (!in_backtick) {
+ *dst++ = *src;
+ size++;
+ }
+
+ if (*src == '\\') {
+ escaped = !escaped;
+ } else {
+ escaped = 0;
+ }
+
+ src++;
+ }
+
+out:
+ return size;
+}
+
+
+static int
+parse_backtick (FILE *srcfp, FILE *dstfp)
+{
+ char srcbuf[8 * GF_UNIT_KB] = {0, };
+ char *dstbuf = NULL;
+ int ret = 0;
+ int size = 0;
+
+ dstbuf = calloc (32 * GF_UNIT_KB, 1);
+
+ fseek (srcfp, 0L, SEEK_SET);
+ fseek (dstfp, 0L, SEEK_SET);
+
+ while (!feof (srcfp)) {
+ if (fgets (srcbuf, 8 * GF_UNIT_KB, srcfp) == NULL) {
+ break;
+ }
+
+ size = find_and_execute_cmds (srcbuf, dstbuf);
+ if (size < 0) {
+ ret = -1;
+ break;
+ }
+ fwrite (dstbuf, size, 1, dstfp);
+ }
+
+ fseek (srcfp, 0L, SEEK_SET);
+ fseek (dstfp, 0L, SEEK_SET);
+ FREE (dstbuf);
+ return ret;
+}
+
+extern FILE *yyin;
+xlator_t *
+file_to_xlator_tree (glusterfs_ctx_t *ctx,
+ FILE *fp)
+{
+ int32_t ret = 0;
+ xlator_t *tmp_tree = NULL;
+ FILE *tmp_file = NULL;
+ int fd = -1, tmp_fd = -1;
+ struct stat stbuf = {0, };
+ char *buffer = NULL;
+
+ tmp_file = tmpfile ();
+ if (NULL == tmp_file) {
+ gf_log ("parser", GF_LOG_ERROR,
+ "cannot create temparory file");
+ return NULL;
+ }
+
+ fd = fileno (fp);
+ if (fd == -1) {
+ gf_log ("parser", GF_LOG_ERROR,
+ "cannot get file descriptor from volume specification file stream pointer");
+ fclose (tmp_file);
+ return NULL;
+ }
+
+ ret = fstat (fd, &stbuf);
+ if (ret == -1) {
+ gf_log ("parser", GF_LOG_ERROR,
+ "getting the size of volume specification file failed");
+ fclose (tmp_file);
+ return NULL;
+ }
+
+ buffer = calloc (stbuf.st_size + GF_CMD_BUFFER_LEN, 1);
+
+ tmp_fd = fileno (tmp_file);
+ if (!mmap (buffer, stbuf.st_size + GF_CMD_BUFFER_LEN,
+ PROT_NONE, 0, tmp_fd, 0)) {
+ gf_log ("parser", GF_LOG_ERROR,
+ "mmap of volume specification file failed");
+ fclose (tmp_file);
+ FREE (buffer);
+ return NULL;
+ }
+
+ ret = parse_backtick (fp, tmp_file);
+ if (ret < 0) {
+ gf_log ("parser", GF_LOG_ERROR,
+ "parsing of backticks failed");
+ fclose (tmp_file);
+ FREE (buffer);
+ return NULL;
+ }
+
+ gctx = ctx;
+ yyin = tmp_file;
+ ret = yyparse ();
+
+ fclose (tmp_file);
+ FREE (buffer);
+
+ if (1 == ret) {
+ gf_log ("parser", GF_LOG_DEBUG,
+ "parsing of volfile failed, please review it "
+ "once more");
+ tree = complete_tree = NULL;
+ return NULL;
+ }
+
+ tmp_tree = complete_tree;
+ tree = complete_tree = NULL;
+
+ return tmp_tree;
+}
diff --git a/libglusterfs/src/stack.h b/libglusterfs/src/stack.h
new file mode 100644
index 000000000..f014a4a27
--- /dev/null
+++ b/libglusterfs/src/stack.h
@@ -0,0 +1,266 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+/*
+ This file defines MACROS and static inlines used to emulate a function
+ call over asynchronous communication with remote server
+*/
+
+#ifndef _STACK_H
+#define _STACK_H
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+struct _call_stack_t;
+typedef struct _call_stack_t call_stack_t;
+struct _call_frame_t;
+typedef struct _call_frame_t call_frame_t;
+struct _call_pool_t;
+typedef struct _call_pool_t call_pool_t;
+
+#include "xlator.h"
+#include "dict.h"
+#include "list.h"
+#include "common-utils.h"
+
+
+typedef int32_t (*ret_fn_t) (call_frame_t *frame,
+ call_frame_t *prev_frame,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ ...);
+
+struct _call_pool_t {
+ union {
+ struct list_head all_frames;
+ struct {
+ call_stack_t *next_call;
+ call_stack_t *prev_call;
+ } all_stacks;
+ };
+ int64_t cnt;
+ gf_lock_t lock;
+};
+
+struct _call_frame_t {
+ call_stack_t *root; /* stack root */
+ call_frame_t *parent; /* previous BP */
+ call_frame_t *next;
+ call_frame_t *prev; /* maintainence list */
+ void *local; /* local variables */
+ xlator_t *this; /* implicit object */
+ ret_fn_t ret; /* op_return address */
+ int32_t ref_count;
+ gf_lock_t lock;
+ void *cookie; /* unique cookie */
+};
+
+struct _call_stack_t {
+ union {
+ struct list_head all_frames;
+ struct {
+ call_stack_t *next_call;
+ call_stack_t *prev_call;
+ };
+ };
+ call_pool_t *pool;
+ void *trans;
+ uint64_t unique;
+ void *state; /* pointer to request state */
+ uid_t uid;
+ gid_t gid;
+ pid_t pid;
+ call_frame_t frames;
+ dict_t *req_refs;
+ dict_t *rsp_refs;
+
+ int32_t op;
+ int8_t type;
+};
+
+
+static inline void
+FRAME_DESTROY (call_frame_t *frame)
+{
+ if (frame->next)
+ frame->next->prev = frame->prev;
+ if (frame->prev)
+ frame->prev->next = frame->next;
+ if (frame->local)
+ FREE (frame->local);
+ LOCK_DESTROY (&frame->lock);
+ FREE (frame);
+}
+
+
+static inline void
+STACK_DESTROY (call_stack_t *stack)
+{
+ LOCK (&stack->pool->lock);
+ {
+ list_del_init (&stack->all_frames);
+ stack->pool->cnt--;
+ }
+ UNLOCK (&stack->pool->lock);
+
+ if (stack->frames.local)
+ FREE (stack->frames.local);
+
+ LOCK_DESTROY (&stack->frames.lock);
+
+ while (stack->frames.next) {
+ FRAME_DESTROY (stack->frames.next);
+ }
+ FREE (stack);
+}
+
+
+#define cbk(x) cbk_##x
+
+
+/* make a call */
+#define STACK_WIND(frame, rfn, obj, fn, params ...) \
+ do { \
+ call_frame_t *_new = NULL; \
+ \
+ _new = CALLOC (1, sizeof (call_frame_t)); \
+ ERR_ABORT (_new); \
+ typeof(fn##_cbk) tmp_cbk = rfn; \
+ _new->root = frame->root; \
+ _new->next = frame->root->frames.next; \
+ _new->prev = &frame->root->frames; \
+ if (frame->root->frames.next) \
+ frame->root->frames.next->prev = _new; \
+ frame->root->frames.next = _new; \
+ _new->this = obj; \
+ _new->ret = (ret_fn_t) tmp_cbk; \
+ _new->parent = frame; \
+ _new->cookie = _new; \
+ LOCK_INIT (&_new->lock); \
+ frame->ref_count++; \
+ \
+ fn (_new, obj, params); \
+ } while (0)
+
+
+/* make a call with a cookie */
+#define STACK_WIND_COOKIE(frame, rfn, cky, obj, fn, params ...) \
+ do { \
+ call_frame_t *_new = CALLOC (1, \
+ sizeof (call_frame_t)); \
+ ERR_ABORT (_new); \
+ typeof(fn##_cbk) tmp_cbk = rfn; \
+ _new->root = frame->root; \
+ _new->next = frame->root->frames.next; \
+ _new->prev = &frame->root->frames; \
+ if (frame->root->frames.next) \
+ frame->root->frames.next->prev = _new; \
+ frame->root->frames.next = _new; \
+ _new->this = obj; \
+ _new->ret = (ret_fn_t) tmp_cbk; \
+ _new->parent = frame; \
+ _new->cookie = cky; \
+ LOCK_INIT (&_new->lock); \
+ frame->ref_count++; \
+ fn##_cbk = rfn; \
+ \
+ fn (_new, obj, params); \
+ } while (0)
+
+
+/* return from function */
+#define STACK_UNWIND(frame, params ...) \
+ do { \
+ ret_fn_t fn = frame->ret; \
+ call_frame_t *_parent = frame->parent; \
+ _parent->ref_count--; \
+ fn (_parent, frame->cookie, _parent->this, params); \
+ } while (0)
+
+
+static inline call_frame_t *
+copy_frame (call_frame_t *frame)
+{
+ call_stack_t *newstack = NULL;
+ call_stack_t *oldstack = NULL;
+
+ if (!frame) {
+ return NULL;
+ }
+
+ newstack = (void *) CALLOC (1, sizeof (*newstack));
+ oldstack = frame->root;
+
+ newstack->uid = oldstack->uid;
+ newstack->gid = oldstack->gid;
+ newstack->pid = oldstack->pid;
+ newstack->unique = oldstack->unique;
+
+ newstack->frames.this = frame->this;
+ newstack->frames.root = newstack;
+ newstack->pool = oldstack->pool;
+
+ LOCK_INIT (&newstack->frames.lock);
+
+ LOCK (&oldstack->pool->lock);
+ {
+ list_add (&newstack->all_frames, &oldstack->all_frames);
+ newstack->pool->cnt++;
+
+ }
+ UNLOCK (&oldstack->pool->lock);
+
+ return &newstack->frames;
+}
+
+static inline call_frame_t *
+create_frame (xlator_t *xl, call_pool_t *pool)
+{
+ call_stack_t *stack = NULL;
+
+ if (!xl || !pool) {
+ return NULL;
+ }
+
+ stack = CALLOC (1, sizeof (*stack));
+ if (!stack)
+ return NULL;
+
+ stack->pool = pool;
+ stack->frames.root = stack;
+ stack->frames.this = xl;
+
+ LOCK (&pool->lock);
+ {
+ list_add (&stack->all_frames, &pool->all_frames);
+ pool->cnt++;
+ }
+ UNLOCK (&pool->lock);
+
+ LOCK_INIT (&stack->frames.lock);
+
+ return &stack->frames;
+}
+
+
+#endif /* _STACK_H */
diff --git a/libglusterfs/src/timer.c b/libglusterfs/src/timer.c
new file mode 100644
index 000000000..a6dbaaa83
--- /dev/null
+++ b/libglusterfs/src/timer.c
@@ -0,0 +1,220 @@
+/*
+ Copyright (c) 2007, 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/>.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "timer.h"
+#include "logging.h"
+#include "common-utils.h"
+
+#define TS(tv) ((((unsigned long long) tv.tv_sec) * 1000000) + (tv.tv_usec))
+
+gf_timer_t *
+gf_timer_call_after (glusterfs_ctx_t *ctx,
+ struct timeval delta,
+ gf_timer_cbk_t cbk,
+ void *data)
+{
+ gf_timer_registry_t *reg = NULL;
+ gf_timer_t *event = NULL;
+ gf_timer_t *trav = NULL;
+ unsigned long long at = 0L;
+
+ if (ctx == NULL)
+ {
+ gf_log ("timer", GF_LOG_ERROR, "invalid argument");
+ return NULL;
+ }
+
+ reg = gf_timer_registry_init (ctx);
+
+ if (!reg) {
+ gf_log ("timer", GF_LOG_ERROR, "!reg");
+ return NULL;
+ }
+
+ event = CALLOC (1, sizeof (*event));
+ if (!event) {
+ gf_log ("timer", GF_LOG_CRITICAL, "Not enough memory");
+ return NULL;
+ }
+ gettimeofday (&event->at, NULL);
+ event->at.tv_usec = ((event->at.tv_usec + delta.tv_usec) % 1000000);
+ event->at.tv_sec += ((event->at.tv_usec + delta.tv_usec) / 1000000);
+ event->at.tv_sec += delta.tv_sec;
+ at = TS (event->at);
+ event->cbk = cbk;
+ event->data = data;
+ pthread_mutex_lock (&reg->lock);
+ {
+ trav = reg->active.prev;
+ while (trav != &reg->active) {
+ if (TS (trav->at) < at)
+ break;
+ trav = trav->prev;
+ }
+ event->prev = trav;
+ event->next = event->prev->next;
+ event->prev->next = event;
+ event->next->prev = event;
+ }
+ pthread_mutex_unlock (&reg->lock);
+ return event;
+}
+
+int32_t
+gf_timer_call_stale (gf_timer_registry_t *reg,
+ gf_timer_t *event)
+{
+ if (reg == NULL || event == NULL)
+ {
+ gf_log ("timer", GF_LOG_ERROR, "invalid argument");
+ return 0;
+ }
+
+ event->next->prev = event->prev;
+ event->prev->next = event->next;
+ event->next = &reg->stale;
+ event->prev = event->next->prev;
+ event->next->prev = event;
+ event->prev->next = event;
+
+ return 0;
+}
+
+int32_t
+gf_timer_call_cancel (glusterfs_ctx_t *ctx,
+ gf_timer_t *event)
+{
+ gf_timer_registry_t *reg = NULL;
+
+ if (ctx == NULL || event == NULL)
+ {
+ gf_log ("timer", GF_LOG_ERROR, "invalid argument");
+ return 0;
+ }
+
+ reg = gf_timer_registry_init (ctx);
+ if (!reg) {
+ gf_log ("timer", GF_LOG_ERROR, "!reg");
+ return 0;
+ }
+
+ pthread_mutex_lock (&reg->lock);
+ {
+ event->next->prev = event->prev;
+ event->prev->next = event->next;
+ }
+ pthread_mutex_unlock (&reg->lock);
+
+ FREE (event);
+ return 0;
+}
+
+void *
+gf_timer_proc (void *ctx)
+{
+ gf_timer_registry_t *reg = NULL;
+
+ if (ctx == NULL)
+ {
+ gf_log ("timer", GF_LOG_ERROR, "invalid argument");
+ return NULL;
+ }
+
+ reg = gf_timer_registry_init (ctx);
+ if (!reg) {
+ gf_log ("timer", GF_LOG_ERROR, "!reg");
+ return NULL;
+ }
+
+ while (!reg->fin) {
+ unsigned long long now;
+ struct timeval now_tv;
+ gf_timer_t *event = NULL;
+
+ gettimeofday (&now_tv, NULL);
+ now = TS (now_tv);
+ while (1) {
+ unsigned long long at;
+ char need_cbk = 0;
+
+ pthread_mutex_lock (&reg->lock);
+ {
+ event = reg->active.next;
+ at = TS (event->at);
+ if (event != &reg->active && now >= at) {
+ need_cbk = 1;
+ gf_timer_call_stale (reg, event);
+ }
+ }
+ pthread_mutex_unlock (&reg->lock);
+ if (need_cbk)
+ event->cbk (event->data);
+
+ else
+ break;
+ }
+ usleep (1000000);
+ }
+
+ pthread_mutex_lock (&reg->lock);
+ {
+ while (reg->active.next != &reg->active) {
+ gf_timer_call_cancel (ctx, reg->active.next);
+ }
+
+ while (reg->stale.next != &reg->stale) {
+ gf_timer_call_cancel (ctx, reg->stale.next);
+ }
+ }
+ pthread_mutex_unlock (&reg->lock);
+ pthread_mutex_destroy (&reg->lock);
+ FREE (((glusterfs_ctx_t *)ctx)->timer);
+
+ return NULL;
+}
+
+gf_timer_registry_t *
+gf_timer_registry_init (glusterfs_ctx_t *ctx)
+{
+ if (ctx == NULL)
+ {
+ gf_log ("timer", GF_LOG_ERROR, "invalid argument");
+ return NULL;
+ }
+
+ if (!ctx->timer) {
+ gf_timer_registry_t *reg = NULL;
+
+ ctx->timer = reg = CALLOC (1, sizeof (*reg));
+ ERR_ABORT (reg);
+ pthread_mutex_init (&reg->lock, NULL);
+ reg->active.next = &reg->active;
+ reg->active.prev = &reg->active;
+ reg->stale.next = &reg->stale;
+ reg->stale.prev = &reg->stale;
+
+ pthread_create (&reg->th, NULL, gf_timer_proc, ctx);
+ }
+ return ctx->timer;
+}
diff --git a/libglusterfs/src/timer.h b/libglusterfs/src/timer.h
new file mode 100644
index 000000000..5152900f3
--- /dev/null
+++ b/libglusterfs/src/timer.h
@@ -0,0 +1,68 @@
+/*
+ Copyright (c) 2007, 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/>.
+*/
+
+#ifndef _TIMER_H
+#define _TIMER_H
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "glusterfs.h"
+#include <sys/time.h>
+#include <pthread.h>
+
+typedef void (*gf_timer_cbk_t) (void *);
+
+struct _gf_timer {
+ struct _gf_timer *next, *prev;
+ struct timeval at;
+ gf_timer_cbk_t cbk;
+ void *data;
+};
+
+struct _gf_timer_registry {
+ pthread_t th;
+ char fin;
+ struct _gf_timer stale;
+ struct _gf_timer active;
+ pthread_mutex_t lock;
+};
+
+typedef struct _gf_timer gf_timer_t;
+typedef struct _gf_timer_registry gf_timer_registry_t;
+
+gf_timer_t *
+gf_timer_call_after (glusterfs_ctx_t *ctx,
+ struct timeval delta,
+ gf_timer_cbk_t cbk,
+ void *data);
+
+int32_t
+gf_timer_call_cancel (glusterfs_ctx_t *ctx,
+ gf_timer_t *event);
+
+void *
+gf_timer_proc (void *data);
+
+gf_timer_registry_t *
+gf_timer_registry_init (glusterfs_ctx_t *ctx);
+
+#endif /* _TIMER_H */
diff --git a/libglusterfs/src/transport.c b/libglusterfs/src/transport.c
new file mode 100644
index 000000000..8bd4ff010
--- /dev/null
+++ b/libglusterfs/src/transport.c
@@ -0,0 +1,339 @@
+/*
+ Copyright (c) 2006, 2007, 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 <dlfcn.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/poll.h>
+#include <fnmatch.h>
+#include <stdint.h>
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "logging.h"
+#include "transport.h"
+#include "glusterfs.h"
+#include "xlator.h"
+#include "list.h"
+
+
+transport_t *
+transport_load (dict_t *options,
+ xlator_t *xl)
+{
+ struct transport *trans = NULL, *return_trans = NULL;
+ char *addr_family = NULL;
+ char *name = NULL;
+ void *handle = NULL;
+ char *type = NULL;
+ char str[] = "ERROR";
+ int32_t ret = -1;
+ int8_t is_tcp = 0, is_unix = 0, is_ibsdp = 0;
+ volume_opt_list_t *vol_opt = NULL;
+
+ GF_VALIDATE_OR_GOTO("transport", options, fail);
+ GF_VALIDATE_OR_GOTO("transport", xl, fail);
+
+ trans = CALLOC (1, sizeof (struct transport));
+ GF_VALIDATE_OR_GOTO("transport", trans, fail);
+
+ trans->xl = xl;
+ type = str;
+
+ /* Backward compatibility */
+ ret = dict_get_str (options, "transport-type", &type);
+ if (ret < 0) {
+ ret = dict_set_str (options, "transport-type", "socket");
+ if (ret < 0)
+ gf_log ("dict", GF_LOG_DEBUG,
+ "setting transport-type failed");
+ ret = dict_get_str (options, "transport.address-family",
+ &addr_family);
+ if (ret < 0) {
+ ret = dict_get_str (options, "address-family",
+ &addr_family);
+ }
+
+ if (ret < 0) {
+ ret = dict_set_str (options,
+ "transport.address-family",
+ "inet");
+ if (ret < 0) {
+ gf_log ("dict", GF_LOG_ERROR,
+ "setting address-family failed");
+ }
+ }
+
+ gf_log ("transport", GF_LOG_WARNING,
+ "missing 'option transport-type'. defaulting to "
+ "\"socket\" (%s)", addr_family?addr_family:"inet");
+ } else {
+ {
+ /* Backword compatibility to handle * /client,
+ * * /server.
+ */
+ char *tmp = strchr (type, '/');
+ if (tmp)
+ *tmp = '\0';
+ }
+
+ is_tcp = strcmp (type, "tcp");
+ is_unix = strcmp (type, "unix");
+ is_ibsdp = strcmp (type, "ib-sdp");
+ if ((is_tcp == 0) ||
+ (is_unix == 0) ||
+ (is_ibsdp == 0)) {
+ if (is_tcp == 0)
+ ret = dict_set_str (options,
+ "transport.address-family",
+ "inet");
+ if (is_unix == 0)
+ ret = dict_set_str (options,
+ "transport.address-family",
+ "unix");
+ if (is_ibsdp == 0)
+ ret = dict_set_str (options,
+ "transport.address-family",
+ "inet-sdp");
+
+ if (ret < 0)
+ gf_log ("dict", GF_LOG_DEBUG,
+ "setting address-family failed");
+
+ ret = dict_set_str (options,
+ "transport-type", "socket");
+ if (ret < 0)
+ gf_log ("dict", GF_LOG_DEBUG,
+ "setting transport-type failed");
+ }
+ }
+
+ ret = dict_get_str (options, "transport-type", &type);
+ if (ret < 0) {
+ FREE (trans);
+ gf_log ("transport", GF_LOG_ERROR,
+ "'option transport-type <xx>' missing in volume '%s'",
+ xl->name);
+ goto fail;
+ }
+
+ asprintf (&name, "%s/%s.so", TRANSPORTDIR, type);
+ gf_log ("transport", GF_LOG_DEBUG,
+ "attempt to load file %s", name);
+
+ handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL);
+ if (handle == NULL) {
+ gf_log ("transport", GF_LOG_ERROR, "%s", dlerror ());
+ gf_log ("transport", GF_LOG_ERROR,
+ "volume '%s': transport-type '%s' is not valid or "
+ "not found on this machine",
+ xl->name, type);
+ FREE (name);
+ FREE (trans);
+ goto fail;
+ }
+ FREE (name);
+
+ trans->ops = dlsym (handle, "tops");
+ if (trans->ops == NULL) {
+ gf_log ("transport", GF_LOG_ERROR,
+ "dlsym (transport_ops) on %s", dlerror ());
+ FREE (trans);
+ goto fail;
+ }
+
+ trans->init = dlsym (handle, "init");
+ if (trans->init == NULL) {
+ gf_log ("transport", GF_LOG_ERROR,
+ "dlsym (gf_transport_init) on %s", dlerror ());
+ FREE (trans);
+ goto fail;
+ }
+
+ trans->fini = dlsym (handle, "fini");
+ if (trans->fini == NULL) {
+ gf_log ("transport", GF_LOG_ERROR,
+ "dlsym (gf_transport_fini) on %s", dlerror ());
+ FREE (trans);
+ goto fail;
+ }
+
+ vol_opt = CALLOC (1, sizeof (volume_opt_list_t));
+ vol_opt->given_opt = dlsym (handle, "options");
+ if (vol_opt->given_opt == NULL) {
+ gf_log ("transport", GF_LOG_DEBUG,
+ "volume option validation not specified");
+ } else {
+ list_add_tail (&vol_opt->list, &xl->volume_options);
+ if (-1 ==
+ validate_xlator_volume_options (xl,
+ vol_opt->given_opt)) {
+ gf_log ("transport", GF_LOG_ERROR,
+ "volume option validation failed");
+ FREE (trans);
+ goto fail;
+ }
+ }
+
+ ret = trans->init (trans);
+ if (ret != 0) {
+ gf_log ("transport", GF_LOG_ERROR,
+ "'%s' initialization failed", type);
+ FREE (trans);
+ goto fail;
+ }
+
+ pthread_mutex_init (&trans->lock, NULL);
+ return_trans = trans;
+fail:
+ return return_trans;
+}
+
+
+int32_t
+transport_submit (transport_t *this, char *buf, int32_t len,
+ struct iovec *vector, int count, dict_t *refs)
+{
+ int32_t ret = -1;
+
+ GF_VALIDATE_OR_GOTO("transport", this, fail);
+ GF_VALIDATE_OR_GOTO("transport", this->ops, fail);
+
+ ret = this->ops->submit (this, buf, len, vector, count, refs);
+fail:
+ return ret;
+}
+
+
+int32_t
+transport_connect (transport_t *this)
+{
+ int ret = -1;
+
+ GF_VALIDATE_OR_GOTO("transport", this, fail);
+
+ ret = this->ops->connect (this);
+fail:
+ return ret;
+}
+
+
+int32_t
+transport_listen (transport_t *this)
+{
+ int ret = -1;
+
+ GF_VALIDATE_OR_GOTO("transport", this, fail);
+
+ ret = this->ops->listen (this);
+fail:
+ return ret;
+}
+
+
+int32_t
+transport_disconnect (transport_t *this)
+{
+ int32_t ret = -1;
+
+ GF_VALIDATE_OR_GOTO("transport", this, fail);
+
+ ret = this->ops->disconnect (this);
+fail:
+ return ret;
+}
+
+
+int32_t
+transport_destroy (transport_t *this)
+{
+ int32_t ret = -1;
+
+ GF_VALIDATE_OR_GOTO("transport", this, fail);
+
+ if (this->fini)
+ this->fini (this);
+
+ pthread_mutex_destroy (&this->lock);
+ FREE (this);
+fail:
+ return ret;
+}
+
+
+transport_t *
+transport_ref (transport_t *this)
+{
+ transport_t *return_this = NULL;
+
+ GF_VALIDATE_OR_GOTO("transport", this, fail);
+
+ pthread_mutex_lock (&this->lock);
+ {
+ this->refcount ++;
+ }
+ pthread_mutex_unlock (&this->lock);
+
+ return_this = this;
+fail:
+ return return_this;
+}
+
+
+int32_t
+transport_receive (transport_t *this, char **hdr_p, size_t *hdrlen_p,
+ char **buf_p, size_t *buflen_p)
+{
+ int32_t ret = -1;
+
+ GF_VALIDATE_OR_GOTO("transport", this, fail);
+
+ ret = this->ops->receive (this, hdr_p, hdrlen_p, buf_p, buflen_p);
+fail:
+ return ret;
+}
+
+
+int32_t
+transport_unref (transport_t *this)
+{
+ int32_t refcount = 0;
+ int32_t ret = -1;
+
+ GF_VALIDATE_OR_GOTO("transport", this, fail);
+
+ pthread_mutex_lock (&this->lock);
+ {
+ refcount = --this->refcount;
+ }
+ pthread_mutex_unlock (&this->lock);
+
+ if (refcount == 0) {
+ this->xl->notify (this->xl, GF_EVENT_TRANSPORT_CLEANUP, this);
+ transport_destroy (this);
+ }
+
+ ret = 0;
+fail:
+ return ret;
+}
+
diff --git a/libglusterfs/src/transport.h b/libglusterfs/src/transport.h
new file mode 100644
index 000000000..be5c8b5df
--- /dev/null
+++ b/libglusterfs/src/transport.h
@@ -0,0 +1,85 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+#ifndef __TRANSPORT_H__
+#define __TRANSPORT_H__
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <inttypes.h>
+
+struct transport_ops;
+typedef struct transport transport_t;
+
+#include "xlator.h"
+#include "dict.h"
+#include "compat.h"
+
+typedef struct peer_info {
+ struct sockaddr_storage sockaddr;
+ socklen_t sockaddr_len;
+ char identifier[UNIX_PATH_MAX];
+}peer_info_t;
+
+struct transport {
+ struct transport_ops *ops;
+ void *private;
+ void *xl_private;
+ pthread_mutex_t lock;
+ int32_t refcount;
+
+ xlator_t *xl;
+ void *dnscache;
+ data_t *buf;
+ int32_t (*init) (transport_t *this);
+ void (*fini) (transport_t *this);
+ /* int (*notify) (transport_t *this, int event, void *data); */
+ peer_info_t peerinfo;
+ peer_info_t myinfo;
+};
+
+struct transport_ops {
+ int32_t (*receive) (transport_t *this, char **hdr_p, size_t *hdrlen_p,
+ char **buf_p, size_t *buflen_p);
+ int32_t (*submit) (transport_t *this, char *buf, int len,
+ struct iovec *vector, int count, dict_t *refs);
+ int32_t (*connect) (transport_t *this);
+ int32_t (*listen) (transport_t *this);
+ int32_t (*disconnect) (transport_t *this);
+};
+
+
+int32_t transport_listen (transport_t *this);
+int32_t transport_connect (transport_t *this);
+int32_t transport_disconnect (transport_t *this);
+int32_t transport_notify (transport_t *this, int event);
+int32_t transport_submit (transport_t *this, char *buf, int len,
+ struct iovec *vector, int count, dict_t *refs);
+int32_t transport_receive (transport_t *this, char **hdr_p, size_t *hdrlen_p,
+ char **buf_p, size_t *buflen_p);
+int32_t transport_destroy (transport_t *this);
+
+transport_t *transport_load (dict_t *options, xlator_t *xl);
+transport_t *transport_ref (transport_t *trans);
+int32_t transport_unref (transport_t *trans);
+
+#endif /* __TRANSPORT_H__ */
diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c
new file mode 100644
index 000000000..2b17cc7f6
--- /dev/null
+++ b/libglusterfs/src/xlator.c
@@ -0,0 +1,728 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include "xlator.h"
+#include <dlfcn.h>
+#include <netdb.h>
+#include <fnmatch.h>
+#include "defaults.h"
+
+
+#define SET_DEFAULT_FOP(fn) do { \
+ if (!xl->fops->fn) \
+ xl->fops->fn = default_##fn; \
+ } while (0)
+
+#define SET_DEFAULT_MOP(fn) do { \
+ if (!xl->mops->fn) \
+ xl->mops->fn = default_##fn; \
+ } while (0)
+
+#define SET_DEFAULT_CBK(fn) do { \
+ if (!xl->cbks->fn) \
+ xl->cbks->fn = default_##fn; \
+ } while (0)
+
+
+static void
+fill_defaults (xlator_t *xl)
+{
+ if (xl == NULL) {
+ gf_log ("xlator", GF_LOG_ERROR, "invalid argument");
+ return;
+ }
+
+ SET_DEFAULT_FOP (create);
+ SET_DEFAULT_FOP (open);
+ SET_DEFAULT_FOP (stat);
+ SET_DEFAULT_FOP (readlink);
+ SET_DEFAULT_FOP (mknod);
+ SET_DEFAULT_FOP (mkdir);
+ SET_DEFAULT_FOP (unlink);
+ SET_DEFAULT_FOP (rmdir);
+ SET_DEFAULT_FOP (symlink);
+ SET_DEFAULT_FOP (rename);
+ SET_DEFAULT_FOP (link);
+ SET_DEFAULT_FOP (chmod);
+ SET_DEFAULT_FOP (chown);
+ SET_DEFAULT_FOP (truncate);
+ SET_DEFAULT_FOP (utimens);
+ SET_DEFAULT_FOP (readv);
+ SET_DEFAULT_FOP (writev);
+ SET_DEFAULT_FOP (statfs);
+ SET_DEFAULT_FOP (flush);
+ SET_DEFAULT_FOP (fsync);
+ SET_DEFAULT_FOP (setxattr);
+ SET_DEFAULT_FOP (getxattr);
+ SET_DEFAULT_FOP (removexattr);
+ SET_DEFAULT_FOP (opendir);
+ SET_DEFAULT_FOP (readdir);
+ SET_DEFAULT_FOP (fsyncdir);
+ SET_DEFAULT_FOP (access);
+ SET_DEFAULT_FOP (ftruncate);
+ SET_DEFAULT_FOP (fstat);
+ SET_DEFAULT_FOP (lk);
+ SET_DEFAULT_FOP (inodelk);
+ SET_DEFAULT_FOP (finodelk);
+ SET_DEFAULT_FOP (entrylk);
+ SET_DEFAULT_FOP (fentrylk);
+ SET_DEFAULT_FOP (lookup);
+ SET_DEFAULT_FOP (fchown);
+ SET_DEFAULT_FOP (fchmod);
+ SET_DEFAULT_FOP (setdents);
+ SET_DEFAULT_FOP (getdents);
+ SET_DEFAULT_FOP (checksum);
+ SET_DEFAULT_FOP (xattrop);
+ SET_DEFAULT_FOP (fxattrop);
+
+ SET_DEFAULT_MOP (stats);
+
+ SET_DEFAULT_CBK (release);
+ SET_DEFAULT_CBK (releasedir);
+ SET_DEFAULT_CBK (forget);
+
+ if (!xl->notify)
+ xl->notify = default_notify;
+
+ return;
+}
+
+int
+_volume_option_value_validate (xlator_t *xl,
+ data_pair_t *pair,
+ volume_option_t *opt)
+{
+ int i = 0;
+ int ret = -1;
+ uint64_t input_size = 0;
+ long long inputll = 0;
+
+ /* Key is valid, validate the option */
+ switch (opt->type) {
+ case GF_OPTION_TYPE_PATH:
+ {
+ /* Make sure the given path is valid */
+ if (pair->value->data[0] != '/') {
+ gf_log (xl->name, GF_LOG_WARNING,
+ "option %s %s: '%s' is not an "
+ "absolute path name",
+ pair->key, pair->value->data,
+ pair->value->data);
+ }
+ ret = 0;
+ }
+ break;
+ case GF_OPTION_TYPE_INT:
+ {
+ /* Check the range */
+ if (gf_string2longlong (pair->value->data,
+ &inputll) != 0) {
+ gf_log (xl->name, GF_LOG_ERROR,
+ "invalid number format \"%s\" in "
+ "\"option %s\"",
+ pair->value->data, pair->key);
+ goto out;
+ }
+
+ if ((opt->min == 0) && (opt->max == 0)) {
+ gf_log (xl->name, GF_LOG_DEBUG,
+ "no range check required for "
+ "'option %s %s'",
+ pair->key, pair->value->data);
+ ret = 0;
+ break;
+ }
+ if ((inputll < opt->min) ||
+ (inputll > opt->max)) {
+ gf_log (xl->name, GF_LOG_WARNING,
+ "'%lld' in 'option %s %s' is out of "
+ "range [%"PRId64" - %"PRId64"]",
+ inputll, pair->key,
+ pair->value->data,
+ opt->min, opt->max);
+ }
+ ret = 0;
+ }
+ break;
+ case GF_OPTION_TYPE_SIZET:
+ {
+ /* Check the range */
+ if (gf_string2bytesize (pair->value->data,
+ &input_size) != 0) {
+ gf_log (xl->name, GF_LOG_ERROR,
+ "invalid size format \"%s\" in "
+ "\"option %s\"",
+ pair->value->data, pair->key);
+ goto out;
+ }
+
+ if ((opt->min == 0) && (opt->max == 0)) {
+ gf_log (xl->name, GF_LOG_DEBUG,
+ "no range check required for "
+ "'option %s %s'",
+ pair->key, pair->value->data);
+ ret = 0;
+ break;
+ }
+ if ((input_size < opt->min) ||
+ (input_size > opt->max)) {
+ gf_log (xl->name, GF_LOG_ERROR,
+ "'%"PRId64"' in 'option %s %s' is "
+ "out of range [%"PRId64" - %"PRId64"]",
+ input_size, pair->key,
+ pair->value->data,
+ opt->min, opt->max);
+ }
+ ret = 0;
+ }
+ break;
+ case GF_OPTION_TYPE_BOOL:
+ {
+ /* Check if the value is one of
+ '0|1|on|off|no|yes|true|false|enable|disable' */
+ gf_boolean_t bool_value;
+ if (gf_string2boolean (pair->value->data,
+ &bool_value) != 0) {
+ gf_log (xl->name, GF_LOG_ERROR,
+ "option %s %s: '%s' is not a valid "
+ "boolean value",
+ pair->key, pair->value->data,
+ pair->value->data);
+ goto out;
+ }
+ ret = 0;
+ }
+ break;
+ case GF_OPTION_TYPE_XLATOR:
+ {
+ /* Check if the value is one of the xlators */
+ xlator_t *xlopt = xl;
+ while (xlopt->prev)
+ xlopt = xlopt->prev;
+
+ while (xlopt) {
+ if (strcmp (pair->value->data,
+ xlopt->name) == 0) {
+ ret = 0;
+ break;
+ }
+ xlopt = xlopt->next;
+ }
+ if (!xlopt) {
+ gf_log (xl->name, GF_LOG_ERROR,
+ "option %s %s: '%s' is not a "
+ "valid volume name",
+ pair->key, pair->value->data,
+ pair->value->data);
+ }
+ ret = 0;
+ }
+ break;
+ case GF_OPTION_TYPE_STR:
+ {
+ /* Check if the '*str' is valid */
+ if (!opt->value) {
+ ret = 0;
+ goto out;
+ }
+
+ for (i = 0; (i < ZR_OPTION_MAX_ARRAY_SIZE) &&
+ opt->value[i]; i++) {
+ if (strcasecmp (opt->value[i],
+ pair->value->data) == 0) {
+ ret = 0;
+ break;
+ }
+ }
+
+ if ((i == ZR_OPTION_MAX_ARRAY_SIZE)
+ || ((i < ZR_OPTION_MAX_ARRAY_SIZE)
+ && (!opt->value[i]))) {
+ /* enter here only if
+ * 1. reached end of opt->value array and haven't validated input
+ * OR
+ * 2. valid input list is less than ZR_OPTION_MAX_ARRAY_SIZE and
+ * input has not matched all possible input values.
+ */
+ char given_array[4096] = {0,};
+ for (i = 0; (i < ZR_OPTION_MAX_ARRAY_SIZE) &&
+ opt->value[i]; i++) {
+ strcat (given_array, opt->value[i]);
+ strcat (given_array, ", ");
+ }
+
+ gf_log (xl->name, GF_LOG_ERROR,
+ "option %s %s: '%s' is not valid "
+ "(possible options are %s)",
+ pair->key, pair->value->data,
+ pair->value->data, given_array);
+
+ goto out;
+ }
+ }
+ break;
+ case GF_OPTION_TYPE_PERCENT:
+ {
+ uint32_t percent = 0;
+
+ /* Check if the value is valid percentage */
+ if (gf_string2percent (pair->value->data,
+ &percent) != 0) {
+ gf_log (xl->name, GF_LOG_ERROR,
+ "invalid percent format \"%s\" "
+ "in \"option %s\"",
+ pair->value->data, pair->key);
+ goto out;
+ }
+
+ if ((percent < 0) || (percent > 100)) {
+ gf_log (xl->name, GF_LOG_ERROR,
+ "'%d' in 'option %s %s' is out of "
+ "range [0 - 100]",
+ percent, pair->key,
+ pair->value->data);
+ }
+ ret = 0;
+ }
+ break;
+ case GF_OPTION_TYPE_TIME:
+ {
+ uint32_t input_time = 0;
+
+ /* Check if the value is valid percentage */
+ if (gf_string2time (pair->value->data,
+ &input_time) != 0) {
+ gf_log (xl->name,
+ GF_LOG_ERROR,
+ "invalid time format \"%s\" in "
+ "\"option %s\"",
+ pair->value->data, pair->key);
+ goto out;
+ }
+
+ if ((opt->min == 0) && (opt->max == 0)) {
+ gf_log (xl->name, GF_LOG_DEBUG,
+ "no range check required for "
+ "'option %s %s'",
+ pair->key, pair->value->data);
+ ret = 0;
+ goto out;
+ }
+ if ((input_time < opt->min) ||
+ (input_time > opt->max)) {
+ gf_log (xl->name, GF_LOG_ERROR,
+ "'%"PRIu32"' in 'option %s %s' is "
+ "out of range [%"PRId64" - %"PRId64"]",
+ input_time, pair->key,
+ pair->value->data,
+ opt->min, opt->max);
+ }
+ ret = 0;
+ }
+ break;
+ case GF_OPTION_TYPE_ANY:
+ /* NO CHECK */
+ ret = 0;
+ break;
+ }
+
+ out:
+ return ret;
+}
+
+int
+validate_xlator_volume_options (xlator_t *xl, volume_option_t *opt)
+{
+ int i = 0;
+ int ret = -1;
+ int index = 0;
+ volume_option_t *trav = NULL;
+ data_pair_t *pairs = NULL;
+
+ if (!opt) {
+ ret = 0;
+ goto out;
+ }
+
+ /* First search for not supported options, if any report error */
+ pairs = xl->options->members_list;
+ while (pairs) {
+ ret = -1;
+ for (index = 0;
+ opt[index].key && opt[index].key[0] ; index++) {
+ trav = &(opt[index]);
+ for (i = 0 ;
+ (i < ZR_VOLUME_MAX_NUM_KEY) &&
+ trav->key[i]; i++) {
+ /* Check if the key is valid */
+ if (fnmatch (trav->key[i],
+ pairs->key, FNM_NOESCAPE) == 0) {
+ ret = 0;
+ break;
+ }
+ }
+ if (!ret) {
+ if (i) {
+ gf_log (xl->name, GF_LOG_WARNING,
+ "option '%s' is deprecated, "
+ "preferred is '%s', continuing"
+ " with correction",
+ trav->key[i], trav->key[0]);
+ /* TODO: some bytes lost */
+ pairs->key = strdup (trav->key[0]);
+ }
+ break;
+ }
+ }
+ if (!ret) {
+ ret = _volume_option_value_validate (xl, pairs, trav);
+ if (-1 == ret) {
+ goto out;
+ }
+ }
+
+ pairs = pairs->next;
+ }
+
+ ret = 0;
+ out:
+ return ret;
+}
+
+int32_t
+xlator_set_type (xlator_t *xl,
+ const char *type)
+{
+ char *name = NULL;
+ void *handle = NULL;
+ volume_opt_list_t *vol_opt = NULL;
+
+ if (xl == NULL || type == NULL) {
+ gf_log ("xlator", GF_LOG_ERROR, "invalid argument");
+ return -1;
+ }
+
+ xl->type = strdup (type);
+
+ asprintf (&name, "%s/%s.so", XLATORDIR, type);
+
+ gf_log ("xlator", GF_LOG_DEBUG, "attempt to load file %s", name);
+
+ handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL);
+ if (!handle) {
+ gf_log ("xlator", GF_LOG_ERROR, "%s", dlerror ());
+ return -1;
+ }
+
+ if (!(xl->fops = dlsym (handle, "fops"))) {
+ gf_log ("xlator", GF_LOG_ERROR, "dlsym(fops) on %s",
+ dlerror ());
+ return -1;
+ }
+
+ if (!(xl->mops = dlsym (handle, "mops"))) {
+ gf_log ("xlator", GF_LOG_ERROR, "dlsym(mops) on %s",
+ dlerror ());
+ return -1;
+ }
+
+ if (!(xl->cbks = dlsym (handle, "cbks"))) {
+ gf_log ("xlator", GF_LOG_ERROR, "dlsym(cbks) on %s",
+ dlerror ());
+ return -1;
+ }
+
+ if (!(xl->init = dlsym (handle, "init"))) {
+ gf_log ("xlator", GF_LOG_ERROR, "dlsym(init) on %s",
+ dlerror ());
+ return -1;
+ }
+
+ if (!(xl->fini = dlsym (handle, "fini"))) {
+ gf_log ("xlator", GF_LOG_ERROR, "dlsym(fini) on %s",
+ dlerror ());
+ return -1;
+ }
+
+ if (!(xl->notify = dlsym (handle, "notify"))) {
+ gf_log ("xlator", GF_LOG_DEBUG,
+ "dlsym(notify) on %s -- neglecting", dlerror ());
+ }
+
+ INIT_LIST_HEAD (&xl->volume_options);
+
+ vol_opt = CALLOC (1, sizeof (volume_opt_list_t));
+
+ if (!(vol_opt->given_opt = dlsym (handle, "options"))) {
+ dlerror ();
+ gf_log (xl->name, GF_LOG_DEBUG,
+ "strict option validation not enforced -- neglecting");
+ }
+ list_add_tail (&vol_opt->list, &xl->volume_options);
+
+ fill_defaults (xl);
+
+ FREE (name);
+ return 0;
+}
+
+
+void
+xlator_foreach (xlator_t *this,
+ void (*fn)(xlator_t *each,
+ void *data),
+ void *data)
+{
+ xlator_t *first = NULL;
+
+ if (this == NULL || fn == NULL || data == NULL) {
+ gf_log ("xlator", GF_LOG_ERROR, "invalid argument");
+ return;
+ }
+
+ first = this;
+
+ while (first->prev)
+ first = first->prev;
+
+ while (first) {
+ fn (first, data);
+ first = first->next;
+ }
+}
+
+
+xlator_t *
+xlator_search_by_name (xlator_t *any, const char *name)
+{
+ xlator_t *search = NULL;
+
+ if (any == NULL || name == NULL) {
+ gf_log ("xlator", GF_LOG_ERROR, "invalid argument");
+ return NULL;
+ }
+
+ search = any;
+
+ while (search->prev)
+ search = search->prev;
+
+ while (search) {
+ if (!strcmp (search->name, name))
+ break;
+ search = search->next;
+ }
+
+ return search;
+}
+
+
+static int32_t
+xlator_init_rec (xlator_t *xl)
+{
+ xlator_list_t *trav = NULL;
+ int32_t ret = 0;
+
+ if (xl == NULL) {
+ gf_log ("xlator", GF_LOG_ERROR, "invalid argument");
+ return 0;
+ }
+
+ trav = xl->children;
+
+ while (trav) {
+ ret = 0;
+ ret = xlator_init_rec (trav->xlator);
+ if (ret != 0)
+ break;
+ gf_log (trav->xlator->name, GF_LOG_DEBUG,
+ "Initialization done");
+ trav = trav->next;
+ }
+
+ if (!ret && !xl->ready) {
+ ret = -1;
+ if (xl->init) {
+ ret = xl->init (xl);
+ if (ret) {
+ gf_log ("xlator", GF_LOG_ERROR,
+ "initialization of volume '%s' failed,"
+ " review your volfile again",
+ xl->name);
+ } else {
+ xl->init_succeeded = 1;
+ }
+ } else {
+ gf_log (xl->name, GF_LOG_ERROR, "No init() found");
+ }
+ /* This 'xl' is checked */
+ xl->ready = 1;
+ }
+
+ return ret;
+}
+
+
+int32_t
+xlator_tree_init (xlator_t *xl)
+{
+ xlator_t *top = NULL;
+ int32_t ret = 0;
+
+ if (xl == NULL) {
+ gf_log ("xlator", GF_LOG_ERROR, "invalid argument");
+ return 0;
+ }
+
+ top = xl;
+/*
+ while (top->parents)
+ top = top->parents->xlator;
+*/
+ ret = xlator_init_rec (top);
+
+ if (ret == 0 && top->notify) {
+ top->notify (top, GF_EVENT_PARENT_UP, NULL);
+ }
+
+ return ret;
+}
+
+
+static void
+xlator_fini_rec (xlator_t *xl)
+{
+ xlator_list_t *trav = NULL;
+
+ if (xl == NULL) {
+ gf_log ("xlator", GF_LOG_ERROR, "invalid argument");
+ return;
+ }
+
+ trav = xl->children;
+
+ while (trav) {
+ if (!trav->xlator->init_succeeded) {
+ break;
+ }
+
+ xlator_fini_rec (trav->xlator);
+ gf_log (trav->xlator->name, GF_LOG_DEBUG, "fini done");
+ trav = trav->next;
+ }
+
+ if (xl->init_succeeded) {
+ if (xl->fini) {
+ xl->fini (xl);
+ } else {
+ gf_log (xl->name, GF_LOG_ERROR, "No fini() found");
+ }
+ xl->init_succeeded = 0;
+ }
+}
+
+
+void
+xlator_tree_fini (xlator_t *xl)
+{
+ xlator_t *top = NULL;
+
+ if (xl == NULL) {
+ gf_log ("xlator", GF_LOG_ERROR, "invalid argument");
+ return;
+ }
+
+ top = xl;
+ xlator_fini_rec (top);
+}
+
+
+int
+xlator_tree_free (xlator_t *tree)
+{
+ xlator_t *trav = tree, *prev = tree;
+
+ if (!tree) {
+ gf_log ("parser", GF_LOG_ERROR, "Translator tree not found");
+ return -1;
+ }
+
+ while (prev) {
+ trav = prev->next;
+ dict_destroy (prev->options);
+ FREE (prev->name);
+ FREE (prev->type);
+ FREE (prev);
+ prev = trav;
+ }
+
+ return 0;
+}
+
+
+void
+loc_wipe (loc_t *loc)
+{
+ if (loc->inode) {
+ inode_unref (loc->inode);
+ loc->inode = NULL;
+ }
+ if (loc->path) {
+ FREE (loc->path);
+ loc->path = NULL;
+ }
+
+ if (loc->parent) {
+ inode_unref (loc->parent);
+ loc->parent = NULL;
+ }
+}
+
+
+int
+loc_copy (loc_t *dst, loc_t *src)
+{
+ int ret = -1;
+
+ dst->ino = src->ino;
+
+ if (src->inode)
+ dst->inode = inode_ref (src->inode);
+
+ if (src->parent)
+ dst->parent = inode_ref (src->parent);
+
+ dst->path = strdup (src->path);
+
+ if (!dst->path)
+ goto out;
+
+ dst->name = strrchr (dst->path, '/');
+ if (dst->name)
+ dst->name++;
+
+ ret = 0;
+out:
+ return ret;
+}
diff --git a/libglusterfs/src/xlator.h b/libglusterfs/src/xlator.h
new file mode 100644
index 000000000..eadc9fd1a
--- /dev/null
+++ b/libglusterfs/src/xlator.h
@@ -0,0 +1,842 @@
+/*
+ Copyright (c) 2006, 2007, 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/>.
+*/
+
+#ifndef _XLATOR_H
+#define _XLATOR_H
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+
+#include "glusterfs.h"
+#include "logging.h"
+#include "common-utils.h"
+#include "dict.h"
+#include "compat.h"
+#include "list.h"
+
+#define FIRST_CHILD(xl) (xl->children->xlator)
+
+struct _xlator;
+typedef struct _xlator xlator_t;
+struct _dir_entry_t;
+typedef struct _dir_entry_t dir_entry_t;
+struct _gf_dirent_t;
+typedef struct _gf_dirent_t gf_dirent_t;
+struct _loc;
+typedef struct _loc loc_t;
+
+
+typedef int32_t (*event_notify_fn_t) (xlator_t *this,
+ int32_t event,
+ void *data,
+ ...);
+
+#include "list.h"
+#include "gf-dirent.h"
+#include "stack.h"
+#include "inode.h"
+#include "fd.h"
+
+struct _loc {
+ const char *path;
+ const char *name;
+ ino_t ino;
+ inode_t *inode;
+ inode_t *parent;
+};
+
+
+struct xlator_stats {
+ uint64_t nr_files; /* Number of files open via this xlator */
+ uint64_t free_disk; /* Mega bytes */
+ uint64_t total_disk_size; /* Mega Bytes */
+ uint64_t disk_usage; /* Mega bytes */
+ uint64_t disk_speed; /* MHz or Mbps */
+ uint64_t nr_clients; /* Number of client nodes */
+ uint64_t write_usage;
+ uint64_t read_usage; /* add more stats here */
+};
+
+
+
+typedef int32_t (*mop_stats_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct xlator_stats *stats);
+
+typedef int32_t (*mop_getspec_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ char *spec_data);
+
+typedef int32_t (*fop_checksum_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ uint8_t *file_checksum,
+ uint8_t *dir_checksum);
+
+typedef int32_t (*mop_setvolume_t) (call_frame_t *frame,
+ xlator_t *this,
+ const char *volume);
+
+typedef int32_t (*mop_stats_t) (call_frame_t *frame,
+ xlator_t *this,
+ int32_t flags);
+
+typedef int32_t (*mop_getspec_t) (call_frame_t *frame,
+ xlator_t *this,
+ const char *key,
+ int32_t flag);
+
+typedef int32_t (*fop_checksum_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t flag);
+
+struct xlator_mops {
+ mop_stats_t stats;
+ mop_getspec_t getspec;
+
+ mop_stats_cbk_t stats_cbk;
+ mop_getspec_cbk_t getspec_cbk;
+};
+
+
+typedef int32_t (*fop_lookup_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf,
+ dict_t *xattr);
+
+typedef int32_t (*fop_stat_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+
+typedef int32_t (*fop_fstat_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+
+typedef int32_t (*fop_chmod_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+
+typedef int32_t (*fop_fchmod_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+
+typedef int32_t (*fop_chown_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+
+typedef int32_t (*fop_fchown_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+
+typedef int32_t (*fop_truncate_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+
+typedef int32_t (*fop_ftruncate_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+
+typedef int32_t (*fop_utimens_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+
+typedef int32_t (*fop_access_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno);
+
+typedef int32_t (*fop_readlink_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ const char *path);
+
+typedef int32_t (*fop_mknod_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf);
+
+typedef int32_t (*fop_mkdir_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf);
+
+typedef int32_t (*fop_unlink_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno);
+
+typedef int32_t (*fop_rmdir_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno);
+
+typedef int32_t (*fop_symlink_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf);
+
+typedef int32_t (*fop_rename_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *buf);
+
+typedef int32_t (*fop_link_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ inode_t *inode,
+ struct stat *buf);
+
+typedef int32_t (*fop_create_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ fd_t *fd,
+ inode_t *inode,
+ struct stat *buf);
+
+typedef int32_t (*fop_open_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ fd_t *fd);
+
+typedef int32_t (*fop_readv_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct iovec *vector,
+ int32_t count,
+ struct stat *stbuf);
+
+typedef int32_t (*fop_writev_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct stat *stbuf);
+
+typedef int32_t (*fop_flush_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno);
+
+typedef int32_t (*fop_fsync_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno);
+
+typedef int32_t (*fop_opendir_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ fd_t *fd);
+
+typedef int32_t (*fop_getdents_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ dir_entry_t *entries,
+ int32_t count);
+
+typedef int32_t (*fop_fsyncdir_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno);
+
+typedef int32_t (*fop_statfs_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct statvfs *buf);
+
+typedef int32_t (*fop_setxattr_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno);
+
+typedef int32_t (*fop_getxattr_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ dict_t *dict);
+
+typedef int32_t (*fop_removexattr_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno);
+
+typedef int32_t (*fop_lk_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ struct flock *flock);
+
+typedef int32_t (*fop_inodelk_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno);
+
+typedef int32_t (*fop_finodelk_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno);
+
+typedef int32_t (*fop_entrylk_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno);
+
+typedef int32_t (*fop_fentrylk_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno);
+
+typedef int32_t (*fop_setdents_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno);
+
+typedef int32_t (*fop_readdir_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ gf_dirent_t *entries);
+
+typedef int32_t (*fop_xattrop_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ dict_t *xattr);
+
+typedef int32_t (*fop_fxattrop_cbk_t) (call_frame_t *frame,
+ void *cookie,
+ xlator_t *this,
+ int32_t op_ret,
+ int32_t op_errno,
+ dict_t *xattr);
+
+typedef int32_t (*fop_lookup_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ dict_t *xattr_req);
+
+typedef int32_t (*fop_stat_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc);
+
+typedef int32_t (*fop_fstat_t) (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd);
+
+typedef int32_t (*fop_chmod_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ mode_t mode);
+
+typedef int32_t (*fop_fchmod_t) (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ mode_t mode);
+
+typedef int32_t (*fop_chown_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ uid_t uid,
+ gid_t gid);
+
+typedef int32_t (*fop_fchown_t) (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ uid_t uid,
+ gid_t gid);
+
+typedef int32_t (*fop_truncate_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ off_t offset);
+
+typedef int32_t (*fop_ftruncate_t) (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ off_t offset);
+
+typedef int32_t (*fop_utimens_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ struct timespec tv[2]);
+
+typedef int32_t (*fop_access_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t mask);
+
+typedef int32_t (*fop_readlink_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ size_t size);
+
+typedef int32_t (*fop_mknod_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ mode_t mode,
+ dev_t rdev);
+
+typedef int32_t (*fop_mkdir_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ mode_t mode);
+
+typedef int32_t (*fop_unlink_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc);
+
+typedef int32_t (*fop_rmdir_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc);
+
+typedef int32_t (*fop_symlink_t) (call_frame_t *frame,
+ xlator_t *this,
+ const char *linkname,
+ loc_t *loc);
+
+typedef int32_t (*fop_rename_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *oldloc,
+ loc_t *newloc);
+
+typedef int32_t (*fop_link_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *oldloc,
+ loc_t *newloc);
+
+typedef int32_t (*fop_create_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t flags,
+ mode_t mode,
+ fd_t *fd);
+
+typedef int32_t (*fop_open_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t flags,
+ fd_t *fd);
+
+typedef int32_t (*fop_readv_t) (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ size_t size,
+ off_t offset);
+
+typedef int32_t (*fop_writev_t) (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ struct iovec *vector,
+ int32_t count,
+ off_t offset);
+
+typedef int32_t (*fop_flush_t) (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd);
+
+typedef int32_t (*fop_fsync_t) (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t datasync);
+
+typedef int32_t (*fop_opendir_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ fd_t *fd);
+
+typedef int32_t (*fop_getdents_t) (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ size_t size,
+ off_t offset,
+ int32_t flag);
+
+typedef int32_t (*fop_fsyncdir_t) (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t datasync);
+
+typedef int32_t (*fop_statfs_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc);
+
+typedef int32_t (*fop_setxattr_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ dict_t *dict,
+ int32_t flags);
+
+typedef int32_t (*fop_getxattr_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ const char *name);
+
+typedef int32_t (*fop_removexattr_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ const char *name);
+
+typedef int32_t (*fop_lk_t) (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t cmd,
+ struct flock *flock);
+
+typedef int32_t (*fop_inodelk_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ int32_t cmd,
+ struct flock *flock);
+
+typedef int32_t (*fop_finodelk_t) (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t cmd,
+ struct flock *flock);
+
+typedef int32_t (*fop_entrylk_t) (call_frame_t *frame,
+ xlator_t *this, loc_t *loc,
+ const char *basename, entrylk_cmd cmd,
+ entrylk_type type);
+
+typedef int32_t (*fop_fentrylk_t) (call_frame_t *frame,
+ xlator_t *this, fd_t *fd,
+ const char *basename, entrylk_cmd cmd,
+ entrylk_type type);
+
+typedef int32_t (*fop_setdents_t) (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ int32_t flags,
+ dir_entry_t *entries,
+ int32_t count);
+
+typedef int32_t (*fop_readdir_t) (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ size_t size,
+ off_t offset);
+
+typedef int32_t (*fop_xattrop_t) (call_frame_t *frame,
+ xlator_t *this,
+ loc_t *loc,
+ gf_xattrop_flags_t optype,
+ dict_t *xattr);
+
+typedef int32_t (*fop_fxattrop_t) (call_frame_t *frame,
+ xlator_t *this,
+ fd_t *fd,
+ gf_xattrop_flags_t optype,
+ dict_t *xattr);
+
+struct xlator_fops {
+ fop_lookup_t lookup;
+ fop_stat_t stat;
+ fop_fstat_t fstat;
+ fop_chmod_t chmod;
+ fop_fchmod_t fchmod;
+ fop_chown_t chown;
+ fop_fchown_t fchown;
+ fop_truncate_t truncate;
+ fop_ftruncate_t ftruncate;
+ fop_utimens_t utimens;
+ fop_access_t access;
+ fop_readlink_t readlink;
+ fop_mknod_t mknod;
+ fop_mkdir_t mkdir;
+ fop_unlink_t unlink;
+ fop_rmdir_t rmdir;
+ fop_symlink_t symlink;
+ fop_rename_t rename;
+ fop_link_t link;
+ fop_create_t create;
+ fop_open_t open;
+ fop_readv_t readv;
+ fop_writev_t writev;
+ fop_flush_t flush;
+ fop_fsync_t fsync;
+ fop_opendir_t opendir;
+ fop_readdir_t readdir;
+ fop_fsyncdir_t fsyncdir;
+ fop_statfs_t statfs;
+ fop_setxattr_t setxattr;
+ fop_getxattr_t getxattr;
+ fop_removexattr_t removexattr;
+ fop_lk_t lk;
+ fop_inodelk_t inodelk;
+ fop_finodelk_t finodelk;
+ fop_entrylk_t entrylk;
+ fop_fentrylk_t fentrylk;
+ fop_setdents_t setdents;
+ fop_getdents_t getdents;
+ fop_checksum_t checksum;
+ fop_xattrop_t xattrop;
+ fop_fxattrop_t fxattrop;
+
+ /* these entries are used for a typechecking hack in STACK_WIND _only_ */
+ fop_lookup_cbk_t lookup_cbk;
+ fop_stat_cbk_t stat_cbk;
+ fop_fstat_cbk_t fstat_cbk;
+ fop_chmod_cbk_t chmod_cbk;
+ fop_fchmod_cbk_t fchmod_cbk;
+ fop_chown_cbk_t chown_cbk;
+ fop_fchown_cbk_t fchown_cbk;
+ fop_truncate_cbk_t truncate_cbk;
+ fop_ftruncate_cbk_t ftruncate_cbk;
+ fop_utimens_cbk_t utimens_cbk;
+ fop_access_cbk_t access_cbk;
+ fop_readlink_cbk_t readlink_cbk;
+ fop_mknod_cbk_t mknod_cbk;
+ fop_mkdir_cbk_t mkdir_cbk;
+ fop_unlink_cbk_t unlink_cbk;
+ fop_rmdir_cbk_t rmdir_cbk;
+ fop_symlink_cbk_t symlink_cbk;
+ fop_rename_cbk_t rename_cbk;
+ fop_link_cbk_t link_cbk;
+ fop_create_cbk_t create_cbk;
+ fop_open_cbk_t open_cbk;
+ fop_readv_cbk_t readv_cbk;
+ fop_writev_cbk_t writev_cbk;
+ fop_flush_cbk_t flush_cbk;
+ fop_fsync_cbk_t fsync_cbk;
+ fop_opendir_cbk_t opendir_cbk;
+ fop_readdir_cbk_t readdir_cbk;
+ fop_fsyncdir_cbk_t fsyncdir_cbk;
+ fop_statfs_cbk_t statfs_cbk;
+ fop_setxattr_cbk_t setxattr_cbk;
+ fop_getxattr_cbk_t getxattr_cbk;
+ fop_removexattr_cbk_t removexattr_cbk;
+ fop_lk_cbk_t lk_cbk;
+ fop_inodelk_cbk_t inodelk_cbk;
+ fop_finodelk_cbk_t finodelk_cbk;
+ fop_entrylk_cbk_t entrylk_cbk;
+ fop_fentrylk_cbk_t fentrylk_cbk;
+ fop_setdents_cbk_t setdents_cbk;
+ fop_getdents_cbk_t getdents_cbk;
+ fop_checksum_cbk_t checksum_cbk;
+ fop_xattrop_cbk_t xattrop_cbk;
+ fop_fxattrop_cbk_t fxattrop_cbk;
+};
+
+typedef int32_t (*cbk_forget_t) (xlator_t *this,
+ inode_t *inode);
+
+typedef int32_t (*cbk_release_t) (xlator_t *this,
+ fd_t *fd);
+
+struct xlator_cbks {
+ cbk_forget_t forget;
+ cbk_release_t release;
+ cbk_release_t releasedir;
+};
+
+typedef struct xlator_list {
+ xlator_t *xlator;
+ struct xlator_list *next;
+} xlator_list_t;
+
+/* Add possible new type of option you may need */
+typedef enum {
+ GF_OPTION_TYPE_ANY = 0,
+ GF_OPTION_TYPE_STR,
+ GF_OPTION_TYPE_INT,
+ GF_OPTION_TYPE_SIZET,
+ GF_OPTION_TYPE_PERCENT,
+ GF_OPTION_TYPE_BOOL,
+ GF_OPTION_TYPE_XLATOR,
+ GF_OPTION_TYPE_PATH,
+ GF_OPTION_TYPE_TIME,
+} volume_option_type_t;
+
+#define ZR_VOLUME_MAX_NUM_KEY 4
+#define ZR_OPTION_MAX_ARRAY_SIZE 64
+
+/* Each translator should define this structure */
+typedef struct volume_options {
+ char *key[ZR_VOLUME_MAX_NUM_KEY];
+ /* different key, same meaning */
+ volume_option_type_t type;
+ int64_t min; /* -1 means no range */
+ int64_t max; /* -1 means no range */
+ char *value[ZR_OPTION_MAX_ARRAY_SIZE];
+ /* If specified, will check for one of
+ the value from this array */
+ char *description; /* about the key */
+} volume_option_t;
+
+typedef struct vol_opt_list {
+ struct list_head list;
+ volume_option_t *given_opt;
+} volume_opt_list_t;
+
+struct _xlator {
+ /* Built during parsing */
+ char *name;
+ char *type;
+ xlator_t *next;
+ xlator_t *prev;
+ xlator_list_t *parents;
+ xlator_list_t *children;
+ dict_t *options;
+
+ /* Set after doing dlopen() */
+ struct xlator_fops *fops;
+ struct xlator_mops *mops;
+ struct xlator_cbks *cbks;
+ struct list_head volume_options; /* list of volume_option_t */
+
+ void (*fini) (xlator_t *this);
+ int32_t (*init) (xlator_t *this);
+ event_notify_fn_t notify;
+
+ /* Misc */
+ glusterfs_ctx_t *ctx;
+ inode_table_t *itable;
+ char ready;
+ char trace;
+ char init_succeeded;
+ void *private;
+};
+
+int validate_xlator_volume_options (xlator_t *xl, volume_option_t *opt);
+
+int32_t xlator_set_type (xlator_t *xl, const char *type);
+
+xlator_t *file_to_xlator_tree (glusterfs_ctx_t *ctx,
+ FILE *fp);
+
+
+int32_t xlator_tree_init (xlator_t *xl);
+int32_t xlator_tree_free (xlator_t *xl);
+
+void xlator_tree_fini (xlator_t *xl);
+
+void xlator_foreach (xlator_t *this,
+ void (*fn) (xlator_t *each,
+ void *data),
+ void *data);
+
+xlator_t *xlator_search_by_name (xlator_t *any, const char *name);
+
+void inode_destroy_notify (inode_t *inode, const char *xlname);
+
+int loc_copy (loc_t *dst, loc_t *src);
+#define loc_dup(src, dst) loc_copy(dst, src)
+void loc_wipe (loc_t *loc);
+
+#define GF_STAT_PRINT_FMT_STR "%"PRIx64",%"PRIx64",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx64",%"PRIx64",%"PRIx32",%"PRIx64",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32"\n"
+
+#define GF_STAT_SCAN_FMT_STR "%"SCNx64",%"SCNx64",%"SCNx32",%"SCNx32",%"SCNx32",%"SCNx32",%"SCNx64",%"SCNx64",%"SCNx32",%"SCNx64",%"SCNx32",%"SCNx32",%"SCNx32",%"SCNx32",%"SCNx32",%"SCNx32"\n"
+
+#define GF_STATFS_PRINT_FMT_STR "%"PRIx32",%"PRIx32",%"PRIx64",%"PRIx64",%"PRIx64",%"PRIx64",%"PRIx64",%"PRIx64",%"PRIx32",%"PRIx32",%"PRIx32"\n"
+
+#define GF_STATFS_SCAN_FMT_STR "%"SCNx32",%"SCNx32",%"SCNx64",%"SCNx64",%"SCNx64",%"SCNx64",%"SCNx64",%"SCNx64",%"SCNx32",%"SCNx32",%"SCNx32"\n"
+
+#endif /* _XLATOR_H */
+