diff options
Diffstat (limited to 'libglusterfs/src')
46 files changed, 21719 insertions, 0 deletions
diff --git a/libglusterfs/src/Makefile.am b/libglusterfs/src/Makefile.am new file mode 100644 index 00000000000..16e6717de9e --- /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 00000000000..69cc8d99c2b --- /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 00000000000..3d9b78527a3 --- /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 00000000000..b0cf90b09e7 --- /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 00000000000..cd735725960 --- /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 00000000000..12e94a15803 --- /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 00000000000..616c7a8ce68 --- /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 00000000000..2016b51ebcb --- /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 00000000000..a4a6c710675 --- /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 00000000000..918df45ebc6 --- /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 00000000000..71aeb32c780 --- /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 00000000000..1e8ccaab127 --- /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 00000000000..575e3d86e40 --- /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 00000000000..aa15df59945 --- /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 00000000000..eb181f191c3 --- /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 00000000000..5c299d039e6 --- /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 00000000000..f2bbddd2041 --- /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 00000000000..ec80e2a58ba --- /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 00000000000..78c57884247 --- /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 00000000000..8b8effdc335 --- /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 00000000000..28d1ab42595 --- /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 00000000000..fa0a8a6251d --- /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 00000000000..76891f5b05f --- /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 00000000000..edc49678fc5 --- /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 00000000000..13673f6e6f1 --- /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 00000000000..6c527fc75a3 --- /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 00000000000..67490f0ee2d --- /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 00000000000..0d862f09c3f --- /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 00000000000..c5c5163d1f3 --- /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 00000000000..c0b10edcad5 --- /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 00000000000..7a0deb6e85a --- /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 00000000000..c3646f35023 --- /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 00000000000..b36c24477ed --- /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 00000000000..4ba869dee3a --- /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 00000000000..30742cd5eaf --- /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 00000000000..3478a938584 --- /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 00000000000..5ff1a624ff3 --- /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 00000000000..0345730b2a3 --- /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 00000000000..c6491e28d7f --- /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 00000000000..f014a4a27ac --- /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 00000000000..a6dbaaa838f --- /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 (®->lock); +        { +                trav = reg->active.prev; +                while (trav != ®->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 (®->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 = ®->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 (®->lock); +        { +                event->next->prev = event->prev; +                event->prev->next = event->next; +        } +        pthread_mutex_unlock (®->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 (®->lock); +                        { +                                event = reg->active.next; +                                at = TS (event->at); +                                if (event != ®->active && now >= at) { +                                        need_cbk = 1; +                                        gf_timer_call_stale (reg, event); +                                } +                        } +                        pthread_mutex_unlock (®->lock); +                        if (need_cbk) +                                event->cbk (event->data); + +                        else +                                break; +                } +                usleep (1000000); +        } + +        pthread_mutex_lock (®->lock); +        { +                while (reg->active.next != ®->active) { +                        gf_timer_call_cancel (ctx, reg->active.next); +                } + +                while (reg->stale.next != ®->stale) { +                        gf_timer_call_cancel (ctx, reg->stale.next); +                } +        } +        pthread_mutex_unlock (®->lock); +        pthread_mutex_destroy (®->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 (®->lock, NULL); +                reg->active.next = ®->active; +                reg->active.prev = ®->active; +                reg->stale.next = ®->stale; +                reg->stale.prev = ®->stale; + +                pthread_create (®->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 00000000000..5152900f3eb --- /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 00000000000..8bd4ff010a4 --- /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 00000000000..be5c8b5dfd0 --- /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 00000000000..2b17cc7f677 --- /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 00000000000..eadc9fd1a6f --- /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 */ +  | 
