diff options
Diffstat (limited to 'libglusterfs')
47 files changed, 21722 insertions, 0 deletions
diff --git a/libglusterfs/Makefile.am b/libglusterfs/Makefile.am new file mode 100644 index 000000000..d471a3f92 --- /dev/null +++ b/libglusterfs/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src + +CLEANFILES = diff --git a/libglusterfs/src/Makefile.am b/libglusterfs/src/Makefile.am new file mode 100644 index 000000000..16e6717de --- /dev/null +++ b/libglusterfs/src/Makefile.am @@ -0,0 +1,21 @@ +libglusterfs_la_CFLAGS = -fPIC -Wall -g -shared -nostartfiles $(GF_CFLAGS) $(GF_DARWIN_LIBGLUSTERFS_CFLAGS) + +libglusterfs_la_CPPFLAGS = -D_FILE_OFFSET_BITS=64 -D__USE_FILE_OFFSET64 -D_GNU_SOURCE -DXLATORDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator\" -DSCHEDULERDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/scheduler\" -DTRANSPORTDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/transport\" -D$(GF_HOST_OS) -DLIBDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/auth\" + +libglusterfs_la_LIBADD = @LEXLIB@ + +lib_LTLIBRARIES = libglusterfs.la + +libglusterfs_la_SOURCES = dict.c spec.lex.c y.tab.c xlator.c logging.c hashfn.c defaults.c scheduler.c common-utils.c transport.c timer.c inode.c call-stub.c compat.c authenticate.c fd.c compat-errno.c event.c mem-pool.c gf-dirent.c + +noinst_HEADERS = common-utils.h defaults.h dict.h glusterfs.h hashfn.h logging.h protocol.h scheduler.h xlator.h transport.h stack.h timer.h list.h inode.h call-stub.h compat.h authenticate.h fd.h revision.h compat-errno.h event.h mem-pool.h byte-order.h gf-dirent.h locking.h + +EXTRA_DIST = spec.l spec.y + +spec.lex.c: spec.l y.tab.h + $(LEX) -t $(srcdir)/spec.l > $@ + +y.tab.c y.tab.h: spec.y + $(YACC) -d $(srcdir)/spec.y + +CLEANFILES = spec.lex.c y.tab.c y.tab.h diff --git a/libglusterfs/src/authenticate.c b/libglusterfs/src/authenticate.c new file mode 100644 index 000000000..69cc8d99c --- /dev/null +++ b/libglusterfs/src/authenticate.c @@ -0,0 +1,240 @@ +/* + Copyright (c) 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include <stdio.h> +#include <dlfcn.h> +#include <errno.h> +#include "authenticate.h" + +static void +init (dict_t *this, + char *key, + data_t *value, + void *data) +{ + void *handle = NULL; + char *auth_file = NULL; + auth_handle_t *auth_handle = NULL; + auth_fn_t authenticate = NULL; + int *error = NULL; + + /* It gets over written */ + error = data; + + if (!strncasecmp (key, "ip", strlen ("ip"))) { + gf_log ("authenticate", GF_LOG_ERROR, + "AUTHENTICATION MODULE \"IP\" HAS BEEN REPLACED " + "BY \"ADDR\""); + dict_set (this, key, data_from_dynptr (NULL, 0)); + /* TODO: 1.3.x backword compatibility */ + // *error = -1; + // return; + key = "addr"; + } + + asprintf (&auth_file, "%s/%s.so", LIBDIR, key); + handle = dlopen (auth_file, RTLD_LAZY); + if (!handle) { + gf_log ("authenticate", GF_LOG_ERROR, "dlopen(%s): %s\n", + auth_file, dlerror ()); + dict_set (this, key, data_from_dynptr (NULL, 0)); + FREE (auth_file); + *error = -1; + return; + } + FREE (auth_file); + + authenticate = dlsym (handle, "gf_auth"); + if (!authenticate) { + gf_log ("authenticate", GF_LOG_ERROR, + "dlsym(gf_auth) on %s\n", dlerror ()); + dict_set (this, key, data_from_dynptr (NULL, 0)); + *error = -1; + return; + } + + auth_handle = CALLOC (1, sizeof (*auth_handle)); + if (!auth_handle) { + gf_log ("authenticate", GF_LOG_ERROR, "Out of memory"); + dict_set (this, key, data_from_dynptr (NULL, 0)); + *error = -1; + return; + } + auth_handle->vol_opt = CALLOC (1, sizeof (volume_opt_list_t)); + auth_handle->vol_opt->given_opt = dlsym (handle, "options"); + if (auth_handle->vol_opt->given_opt == NULL) { + gf_log ("authenticate", GF_LOG_DEBUG, + "volume option validation not specified"); + } + + auth_handle->authenticate = authenticate; + auth_handle->handle = handle; + + dict_set (this, key, + data_from_dynptr (auth_handle, sizeof (*auth_handle))); +} + +static void +fini (dict_t *this, + char *key, + data_t *value, + void *data) +{ + auth_handle_t *handle = data_to_ptr (value); + if (handle) { + dlclose (handle->handle); + } +} + +int32_t +gf_auth_init (xlator_t *xl, dict_t *auth_modules) +{ + int ret = 0; + auth_handle_t *handle = NULL; + data_pair_t *pair = NULL; + dict_foreach (auth_modules, init, &ret); + if (!ret) { + pair = auth_modules->members_list; + while (pair) { + handle = data_to_ptr (pair->value); + if (handle) { + list_add_tail (&(handle->vol_opt->list), + &(xl->volume_options)); + if (-1 == + validate_xlator_volume_options (xl, + handle->vol_opt->given_opt)) { + gf_log ("authenticate", GF_LOG_ERROR, + "volume option validation " + "failed"); + ret = -1; + } + } + pair = pair->next; + } + } + if (ret) { + gf_log (xl->name, GF_LOG_ERROR, "authentication init failed"); + dict_foreach (auth_modules, fini, &ret); + ret = -1; + } + return ret; +} + +static dict_t *__input_params; +static dict_t *__config_params; + +void +map (dict_t *this, + char *key, + data_t *value, + void *data) +{ + dict_t *res = data; + auth_fn_t authenticate; + auth_handle_t *handle = NULL; + + if (value && (handle = data_to_ptr (value)) && + (authenticate = handle->authenticate)) { + dict_set (res, key, + int_to_data (authenticate (__input_params, + __config_params))); + } else { + dict_set (res, key, int_to_data (AUTH_DONT_CARE)); + } +} + +void +reduce (dict_t *this, + char *key, + data_t *value, + void *data) +{ + int64_t val = 0; + int64_t *res = data; + if (!data) + return; + + val = data_to_int64 (value); + switch (val) + { + case AUTH_ACCEPT: + if (AUTH_DONT_CARE == *res) + *res = AUTH_ACCEPT; + break; + + case AUTH_REJECT: + *res = AUTH_REJECT; + break; + + case AUTH_DONT_CARE: + break; + } +} + + +auth_result_t +gf_authenticate (dict_t *input_params, + dict_t *config_params, + dict_t *auth_modules) +{ + dict_t *results = NULL; + int64_t result = AUTH_DONT_CARE; + + results = get_new_dict (); + __input_params = input_params; + __config_params = config_params; + + dict_foreach (auth_modules, map, results); + + dict_foreach (results, reduce, &result); + if (AUTH_DONT_CARE == result) { + data_t *peerinfo_data = dict_get (input_params, "peer-info"); + char *name = NULL; + + if (peerinfo_data) { + peer_info_t *peerinfo = data_to_ptr (peerinfo_data); + name = peerinfo->identifier; + } + + gf_log ("auth", GF_LOG_ERROR, + "no authentication module is interested in " + "accepting remote-client %s", name); + result = AUTH_REJECT; + } + + dict_destroy (results); + return result; +} + +void +gf_auth_fini (dict_t *auth_modules) +{ + int32_t dummy; + + dict_foreach (auth_modules, fini, &dummy); +} diff --git a/libglusterfs/src/authenticate.h b/libglusterfs/src/authenticate.h new file mode 100644 index 000000000..3d9b78527 --- /dev/null +++ b/libglusterfs/src/authenticate.h @@ -0,0 +1,61 @@ +/* + Copyright (c) 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _AUTHENTICATE_H +#define _AUTHENTICATE_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include <stdio.h> +#include <fnmatch.h> +#include "dict.h" +#include "compat.h" +#include "list.h" +#include "transport.h" +#include "xlator.h" + +typedef enum { + AUTH_ACCEPT, + AUTH_REJECT, + AUTH_DONT_CARE +} auth_result_t; + +typedef auth_result_t (*auth_fn_t) (dict_t *input_params, + dict_t *config_params); + +typedef struct { + void *handle; + auth_fn_t authenticate; + volume_opt_list_t *vol_opt; +} auth_handle_t; + +auth_result_t gf_authenticate (dict_t *input_params, + dict_t *config_params, + dict_t *auth_modules); +int32_t gf_auth_init (xlator_t *xl, dict_t *auth_modules); +void gf_auth_fini (dict_t *auth_modules); + +#endif /* _AUTHENTICATE_H */ diff --git a/libglusterfs/src/byte-order.h b/libglusterfs/src/byte-order.h new file mode 100644 index 000000000..b0cf90b09 --- /dev/null +++ b/libglusterfs/src/byte-order.h @@ -0,0 +1,150 @@ +/* + Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _BYTE_ORDER_H +#define _BYTE_ORDER_H + +#include <inttypes.h> + +#define LS1 0x00ffU +#define MS1 0xff00U +#define LS2 0x0000ffffU +#define MS2 0xffff0000U +#define LS4 0x00000000ffffffffULL +#define MS4 0xffffffff00000000ULL + + +static uint16_t (*hton16) (uint16_t); +static uint32_t (*hton32) (uint32_t); +static uint64_t (*hton64) (uint64_t); + +#define ntoh16 hton16 +#define ntoh32 hton32 +#define ntoh64 hton64 + +#define do_swap2(x) (((x&LS1) << 8)|(((x&MS1) >> 8))) +#define do_swap4(x) ((do_swap2(x&LS2) << 16)|(do_swap2((x&MS2) >> 16))) +#define do_swap8(x) ((do_swap4(x&LS4) << 32)|(do_swap4((x&MS4) >> 32))) + + +static inline uint16_t +__swap16 (uint16_t x) +{ + return do_swap2(x); +} + + +static inline uint32_t +__swap32 (uint32_t x) +{ + return do_swap4(x); +} + + +static inline uint64_t +__swap64 (uint64_t x) +{ + return do_swap8(x); +} + + +static inline uint16_t +__noswap16 (uint16_t x) +{ + return do_swap2(x); +} + + +static inline uint32_t +__noswap32 (uint32_t x) +{ + return do_swap4(x); +} + + +static inline uint64_t +__noswap64 (uint64_t x) +{ + return do_swap8(x); +} + + +static inline uint16_t +__byte_order_init16 (uint16_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + hton16 = __swap16; + hton32 = __swap32; + hton64 = __swap64; + } else { + hton16 = __noswap16; + hton32 = __noswap32; + hton64 = __noswap64; + } + + return hton16 (i); +} + + +static inline uint32_t +__byte_order_init32 (uint32_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + hton16 = __swap16; + hton32 = __swap32; + hton64 = __swap64; + } else { + hton16 = __noswap16; + hton32 = __noswap32; + hton64 = __noswap64; + } + + return hton32 (i); +} + + +static inline uint64_t +__byte_order_init64 (uint64_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + hton16 = __swap16; + hton32 = __swap32; + hton64 = __swap64; + } else { + hton16 = __noswap16; + hton32 = __noswap32; + hton64 = __noswap64; + } + + return hton64 (i); +} + + +static uint16_t (*hton16) (uint16_t) = __byte_order_init16; +static uint32_t (*hton32) (uint32_t) = __byte_order_init32; +static uint64_t (*hton64) (uint64_t) = __byte_order_init64; + + +#endif /* _BYTE_ORDER_H */ diff --git a/libglusterfs/src/call-stub.c b/libglusterfs/src/call-stub.c new file mode 100644 index 000000000..cd7357259 --- /dev/null +++ b/libglusterfs/src/call-stub.c @@ -0,0 +1,3822 @@ +/* + Copyright (c) 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "call-stub.h" + + +static call_stub_t * +stub_new (call_frame_t *frame, + char wind, + glusterfs_fop_t fop) +{ + call_stub_t *new = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + new = CALLOC (1, sizeof (*new)); + GF_VALIDATE_OR_GOTO ("call-stub", new, out); + + new->frame = frame; + new->wind = wind; + new->fop = fop; + + INIT_LIST_HEAD (&new->list); +out: + return new; +} + + +call_stub_t * +fop_lookup_stub (call_frame_t *frame, + fop_lookup_t fn, + loc_t *loc, + dict_t *xattr_req) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_LOOKUP); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.lookup.fn = fn; + + if (xattr_req) + stub->args.lookup.xattr_req = dict_ref (xattr_req); + + loc_copy (&stub->args.lookup.loc, loc); +out: + return stub; +} + + +call_stub_t * +fop_lookup_cbk_stub (call_frame_t *frame, + fop_lookup_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf, + dict_t *dict) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_LOOKUP); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.lookup_cbk.fn = fn; + stub->args.lookup_cbk.op_ret = op_ret; + stub->args.lookup_cbk.op_errno = op_errno; + if (inode) + stub->args.lookup_cbk.inode = inode_ref (inode); + if (buf) + stub->args.lookup_cbk.buf = *buf; + if (dict) + stub->args.lookup_cbk.dict = dict_ref (dict); +out: + return stub; +} + + + +call_stub_t * +fop_stat_stub (call_frame_t *frame, + fop_stat_t fn, + loc_t *loc) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_STAT); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.stat.fn = fn; + loc_copy (&stub->args.stat.loc, loc); +out: + return stub; +} + + +call_stub_t * +fop_stat_cbk_stub (call_frame_t *frame, + fop_stat_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_STAT); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.stat_cbk.fn = fn; + stub->args.stat_cbk.op_ret = op_ret; + stub->args.stat_cbk.op_errno = op_errno; + if (op_ret == 0) + stub->args.stat_cbk.buf = *buf; +out: + return stub; +} + + +call_stub_t * +fop_fstat_stub (call_frame_t *frame, + fop_fstat_t fn, + fd_t *fd) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 1, GF_FOP_FSTAT); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.fstat.fn = fn; + + if (fd) + stub->args.fstat.fd = fd_ref (fd); +out: + return stub; +} + + +call_stub_t * +fop_fstat_cbk_stub (call_frame_t *frame, + fop_fstat_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_FSTAT); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.fstat_cbk.fn = fn; + stub->args.fstat_cbk.op_ret = op_ret; + stub->args.fstat_cbk.op_errno = op_errno; + if (buf) + stub->args.fstat_cbk.buf = *buf; +out: + return stub; +} + + +call_stub_t * +fop_chmod_stub (call_frame_t *frame, + fop_chmod_t fn, + loc_t *loc, + mode_t mode) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_CHMOD); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.chmod.fn = fn; + loc_copy (&stub->args.chmod.loc, loc); + stub->args.chmod.mode = mode; +out: + return stub; +} + + +call_stub_t * +fop_chmod_cbk_stub (call_frame_t *frame, + fop_chmod_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_CHMOD); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.chmod_cbk.fn = fn; + stub->args.chmod_cbk.op_ret = op_ret; + stub->args.chmod_cbk.op_errno = op_errno; + if (buf) + stub->args.chmod_cbk.buf = *buf; +out: + return stub; +} + + +call_stub_t * +fop_fchmod_stub (call_frame_t *frame, + fop_fchmod_t fn, + fd_t *fd, + mode_t mode) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 1, GF_FOP_FCHMOD); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.fchmod.fn = fn; + if (fd) + stub->args.fchmod.fd = fd_ref (fd); + stub->args.fchmod.mode = mode; +out: + return stub; +} + + +call_stub_t * +fop_fchmod_cbk_stub (call_frame_t *frame, + fop_fchmod_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_FCHMOD); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.fchmod_cbk.fn = fn; + stub->args.fchmod_cbk.op_ret = op_ret; + stub->args.fchmod_cbk.op_errno = op_errno; + if (buf) + stub->args.fchmod_cbk.buf = *buf; +out: + return stub; +} + + +call_stub_t * +fop_chown_stub (call_frame_t *frame, + fop_chown_t fn, + loc_t *loc, + uid_t uid, + gid_t gid) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_CHOWN); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.chown.fn = fn; + loc_copy (&stub->args.chown.loc, loc); + stub->args.chown.uid = uid; + stub->args.chown.gid = gid; +out: + return stub; +} + + +call_stub_t * +fop_chown_cbk_stub (call_frame_t *frame, + fop_chown_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_CHOWN); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.chown_cbk.fn = fn; + stub->args.chown_cbk.op_ret = op_ret; + stub->args.chown_cbk.op_errno = op_errno; + if (buf) + stub->args.chown_cbk.buf = *buf; +out: + return stub; +} + + +call_stub_t * +fop_fchown_stub (call_frame_t *frame, + fop_fchown_t fn, + fd_t *fd, + uid_t uid, + gid_t gid) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 1, GF_FOP_FCHOWN); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.fchown.fn = fn; + if (fd) + stub->args.fchown.fd = fd_ref (fd); + stub->args.fchown.uid = uid; + stub->args.fchown.gid = gid; +out: + return stub; +} + + +call_stub_t * +fop_fchown_cbk_stub (call_frame_t *frame, + fop_fchown_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_FCHOWN); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.fchown_cbk.fn = fn; + stub->args.fchown_cbk.op_ret = op_ret; + stub->args.fchown_cbk.op_errno = op_errno; + if (buf) + stub->args.fchown_cbk.buf = *buf; +out: + return stub; +} + + +/* truncate */ + +call_stub_t * +fop_truncate_stub (call_frame_t *frame, + fop_truncate_t fn, + loc_t *loc, + off_t off) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_TRUNCATE); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.truncate.fn = fn; + loc_copy (&stub->args.truncate.loc, loc); + stub->args.truncate.off = off; +out: + return stub; +} + + +call_stub_t * +fop_truncate_cbk_stub (call_frame_t *frame, + fop_truncate_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_TRUNCATE); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.truncate_cbk.fn = fn; + stub->args.truncate_cbk.op_ret = op_ret; + stub->args.truncate_cbk.op_errno = op_errno; + if (buf) + stub->args.truncate_cbk.buf = *buf; +out: + return stub; +} + + +call_stub_t * +fop_ftruncate_stub (call_frame_t *frame, + fop_ftruncate_t fn, + fd_t *fd, + off_t off) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 1, GF_FOP_FTRUNCATE); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.ftruncate.fn = fn; + if (fd) + stub->args.ftruncate.fd = fd_ref (fd); + + stub->args.ftruncate.off = off; +out: + return stub; +} + + +call_stub_t * +fop_ftruncate_cbk_stub (call_frame_t *frame, + fop_ftruncate_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_FTRUNCATE); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.ftruncate_cbk.fn = fn; + stub->args.ftruncate_cbk.op_ret = op_ret; + stub->args.ftruncate_cbk.op_errno = op_errno; + if (buf) + stub->args.ftruncate_cbk.buf = *buf; +out: + return stub; +} + + +call_stub_t * +fop_utimens_stub (call_frame_t *frame, + fop_utimens_t fn, + loc_t *loc, + struct timespec tv[2]) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_UTIMENS); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.utimens.fn = fn; + loc_copy (&stub->args.utimens.loc, loc); + stub->args.utimens.tv[0] = tv[0]; + stub->args.utimens.tv[1] = tv[1]; +out: + return stub; +} + + +call_stub_t * +fop_utimens_cbk_stub (call_frame_t *frame, + fop_utimens_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_UTIMENS); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.utimens_cbk.fn = fn; + stub->args.utimens_cbk.op_ret = op_ret; + stub->args.utimens_cbk.op_errno = op_errno; + if (buf) + stub->args.utimens_cbk.buf = *buf; +out: + return stub; +} + + +call_stub_t * +fop_access_stub (call_frame_t *frame, + fop_access_t fn, + loc_t *loc, + int32_t mask) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_ACCESS); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.access.fn = fn; + loc_copy (&stub->args.access.loc, loc); + stub->args.access.mask = mask; +out: + return stub; +} + + +call_stub_t * +fop_access_cbk_stub (call_frame_t *frame, + fop_access_cbk_t fn, + int32_t op_ret, + int32_t op_errno) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_ACCESS); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.access_cbk.fn = fn; + stub->args.access_cbk.op_ret = op_ret; + stub->args.access_cbk.op_errno = op_errno; +out: + return stub; +} + + +call_stub_t * +fop_readlink_stub (call_frame_t *frame, + fop_readlink_t fn, + loc_t *loc, + size_t size) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_READLINK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.readlink.fn = fn; + loc_copy (&stub->args.readlink.loc, loc); + stub->args.readlink.size = size; +out: + return stub; +} + + +call_stub_t * +fop_readlink_cbk_stub (call_frame_t *frame, + fop_readlink_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + const char *path) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_READLINK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.readlink_cbk.fn = fn; + stub->args.readlink_cbk.op_ret = op_ret; + stub->args.readlink_cbk.op_errno = op_errno; + if (path) + stub->args.readlink_cbk.buf = strdup (path); +out: + return stub; +} + + +call_stub_t * +fop_mknod_stub (call_frame_t *frame, + fop_mknod_t fn, + loc_t *loc, + mode_t mode, + dev_t rdev) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_MKNOD); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.mknod.fn = fn; + loc_copy (&stub->args.mknod.loc, loc); + stub->args.mknod.mode = mode; + stub->args.mknod.rdev = rdev; +out: + return stub; +} + + +call_stub_t * +fop_mknod_cbk_stub (call_frame_t *frame, + fop_mknod_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_MKNOD); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.mknod_cbk.fn = fn; + stub->args.mknod_cbk.op_ret = op_ret; + stub->args.mknod_cbk.op_errno = op_errno; + if (inode) + stub->args.mknod_cbk.inode = inode_ref (inode); + if (buf) + stub->args.mknod_cbk.buf = *buf; +out: + return stub; +} + + +call_stub_t * +fop_mkdir_stub (call_frame_t *frame, + fop_mkdir_t fn, + loc_t *loc, + mode_t mode) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_MKDIR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.mkdir.fn = fn; + loc_copy (&stub->args.mkdir.loc, loc); + stub->args.mkdir.mode = mode; +out: + return stub; +} + + +call_stub_t * +fop_mkdir_cbk_stub (call_frame_t *frame, + fop_mkdir_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_MKDIR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.mkdir_cbk.fn = fn; + stub->args.mkdir_cbk.op_ret = op_ret; + stub->args.mkdir_cbk.op_errno = op_errno; + if (inode) + stub->args.mkdir_cbk.inode = inode_ref (inode); + if (buf) + stub->args.mkdir_cbk.buf = *buf; +out: + return stub; +} + + +call_stub_t * +fop_unlink_stub (call_frame_t *frame, + fop_unlink_t fn, + loc_t *loc) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_UNLINK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.unlink.fn = fn; + loc_copy (&stub->args.unlink.loc, loc); +out: + return stub; +} + + +call_stub_t * +fop_unlink_cbk_stub (call_frame_t *frame, + fop_unlink_cbk_t fn, + int32_t op_ret, + int32_t op_errno) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_UNLINK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.unlink_cbk.fn = fn; + stub->args.unlink_cbk.op_ret = op_ret; + stub->args.unlink_cbk.op_errno = op_errno; +out: + return stub; +} + + + +call_stub_t * +fop_rmdir_stub (call_frame_t *frame, + fop_rmdir_t fn, + loc_t *loc) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_RMDIR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.rmdir.fn = fn; + loc_copy (&stub->args.rmdir.loc, loc); +out: + return stub; +} + + +call_stub_t * +fop_rmdir_cbk_stub (call_frame_t *frame, + fop_rmdir_cbk_t fn, + int32_t op_ret, + int32_t op_errno) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_RMDIR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.rmdir_cbk.fn = fn; + stub->args.rmdir_cbk.op_ret = op_ret; + stub->args.rmdir_cbk.op_errno = op_errno; +out: + return stub; +} + + +call_stub_t * +fop_symlink_stub (call_frame_t *frame, + fop_symlink_t fn, + const char *linkname, + loc_t *loc) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + GF_VALIDATE_OR_GOTO ("call-stub", linkname, out); + + stub = stub_new (frame, 1, GF_FOP_SYMLINK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.symlink.fn = fn; + stub->args.symlink.linkname = strdup (linkname); + loc_copy (&stub->args.symlink.loc, loc); +out: + return stub; +} + + +call_stub_t * +fop_symlink_cbk_stub (call_frame_t *frame, + fop_symlink_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_SYMLINK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.symlink_cbk.fn = fn; + stub->args.symlink_cbk.op_ret = op_ret; + stub->args.symlink_cbk.op_errno = op_errno; + if (inode) + stub->args.symlink_cbk.inode = inode_ref (inode); + if (buf) + stub->args.symlink_cbk.buf = *buf; +out: + return stub; +} + + +call_stub_t * +fop_rename_stub (call_frame_t *frame, + fop_rename_t fn, + loc_t *oldloc, + loc_t *newloc) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", oldloc, out); + GF_VALIDATE_OR_GOTO ("call-stub", newloc, out); + + stub = stub_new (frame, 1, GF_FOP_RENAME); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.rename.fn = fn; + loc_copy (&stub->args.rename.old, oldloc); + loc_copy (&stub->args.rename.new, newloc); +out: + return stub; +} + + +call_stub_t * +fop_rename_cbk_stub (call_frame_t *frame, + fop_rename_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_RENAME); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.rename_cbk.fn = fn; + stub->args.rename_cbk.op_ret = op_ret; + stub->args.rename_cbk.op_errno = op_errno; + if (buf) + stub->args.rename_cbk.buf = *buf; +out: + return stub; +} + + +call_stub_t * +fop_link_stub (call_frame_t *frame, + fop_link_t fn, + loc_t *oldloc, + loc_t *newloc) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", oldloc, out); + GF_VALIDATE_OR_GOTO ("call-stub", newloc, out); + + stub = stub_new (frame, 1, GF_FOP_LINK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.link.fn = fn; + loc_copy (&stub->args.link.oldloc, oldloc); + loc_copy (&stub->args.link.newloc, newloc); + +out: + return stub; +} + + +call_stub_t * +fop_link_cbk_stub (call_frame_t *frame, + fop_link_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_LINK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.link_cbk.fn = fn; + stub->args.link_cbk.op_ret = op_ret; + stub->args.link_cbk.op_errno = op_errno; + if (inode) + stub->args.link_cbk.inode = inode_ref (inode); + if (buf) + stub->args.link_cbk.buf = *buf; +out: + return stub; +} + + +call_stub_t * +fop_create_stub (call_frame_t *frame, + fop_create_t fn, + loc_t *loc, + int32_t flags, + mode_t mode, fd_t *fd) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_CREATE); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.create.fn = fn; + loc_copy (&stub->args.create.loc, loc); + stub->args.create.flags = flags; + stub->args.create.mode = mode; + if (fd) + stub->args.create.fd = fd_ref (fd); +out: + return stub; +} + + +call_stub_t * +fop_create_cbk_stub (call_frame_t *frame, + fop_create_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + fd_t *fd, + inode_t *inode, + struct stat *buf) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_CREATE); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.create_cbk.fn = fn; + stub->args.create_cbk.op_ret = op_ret; + stub->args.create_cbk.op_errno = op_errno; + if (fd) + stub->args.create_cbk.fd = fd_ref (fd); + if (inode) + stub->args.create_cbk.inode = inode_ref (inode); + if (buf) + stub->args.create_cbk.buf = *buf; +out: + return stub; +} + + +call_stub_t * +fop_open_stub (call_frame_t *frame, + fop_open_t fn, + loc_t *loc, + int32_t flags, fd_t *fd) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_OPEN); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.open.fn = fn; + loc_copy (&stub->args.open.loc, loc); + stub->args.open.flags = flags; + if (fd) + stub->args.open.fd = fd_ref (fd); +out: + return stub; +} + + +call_stub_t * +fop_open_cbk_stub (call_frame_t *frame, + fop_open_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + fd_t *fd) + +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_OPEN); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.open_cbk.fn = fn; + stub->args.open_cbk.op_ret = op_ret; + stub->args.open_cbk.op_errno = op_errno; + if (fd) + stub->args.open_cbk.fd = fd_ref (fd); +out: + return stub; +} + + +call_stub_t * +fop_readv_stub (call_frame_t *frame, + fop_readv_t fn, + fd_t *fd, + size_t size, + off_t off) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 1, GF_FOP_READ); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.readv.fn = fn; + if (fd) + stub->args.readv.fd = fd_ref (fd); + stub->args.readv.size = size; + stub->args.readv.off = off; +out: + return stub; +} + + +call_stub_t * +fop_readv_cbk_stub (call_frame_t *frame, + fop_readv_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct iovec *vector, + int32_t count, + struct stat *stbuf) + +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_READ); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.readv_cbk.fn = fn; + stub->args.readv_cbk.op_ret = op_ret; + stub->args.readv_cbk.op_errno = op_errno; + if (op_ret >= 0) { + stub->args.readv_cbk.vector = iov_dup (vector, count); + stub->args.readv_cbk.count = count; + stub->args.readv_cbk.stbuf = *stbuf; + stub->args.readv_cbk.rsp_refs = + dict_ref (frame->root->rsp_refs); + } +out: + return stub; +} + + +call_stub_t * +fop_writev_stub (call_frame_t *frame, + fop_writev_t fn, + fd_t *fd, + struct iovec *vector, + int32_t count, + off_t off) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", vector, out); + + stub = stub_new (frame, 1, GF_FOP_WRITE); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.writev.fn = fn; + if (fd) + stub->args.writev.fd = fd_ref (fd); + stub->args.writev.vector = iov_dup (vector, count); + stub->args.writev.count = count; + stub->args.writev.off = off; + + if (frame->root->req_refs) + stub->args.writev.req_refs = dict_ref (frame->root->req_refs); +out: + return stub; +} + + +call_stub_t * +fop_writev_cbk_stub (call_frame_t *frame, + fop_writev_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *stbuf) + +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_WRITE); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.writev_cbk.fn = fn; + stub->args.writev_cbk.op_ret = op_ret; + stub->args.writev_cbk.op_errno = op_errno; + if (op_ret >= 0) + stub->args.writev_cbk.stbuf = *stbuf; +out: + return stub; +} + + + +call_stub_t * +fop_flush_stub (call_frame_t *frame, + fop_flush_t fn, + fd_t *fd) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 1, GF_FOP_FLUSH); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.flush.fn = fn; + if (fd) + stub->args.flush.fd = fd_ref (fd); +out: + return stub; +} + + +call_stub_t * +fop_flush_cbk_stub (call_frame_t *frame, + fop_flush_cbk_t fn, + int32_t op_ret, + int32_t op_errno) + +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_FLUSH); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.flush_cbk.fn = fn; + stub->args.flush_cbk.op_ret = op_ret; + stub->args.flush_cbk.op_errno = op_errno; +out: + return stub; +} + + + + +call_stub_t * +fop_fsync_stub (call_frame_t *frame, + fop_fsync_t fn, + fd_t *fd, + int32_t datasync) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 1, GF_FOP_FSYNC); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.fsync.fn = fn; + if (fd) + stub->args.fsync.fd = fd_ref (fd); + stub->args.fsync.datasync = datasync; +out: + return stub; +} + + +call_stub_t * +fop_fsync_cbk_stub (call_frame_t *frame, + fop_fsync_cbk_t fn, + int32_t op_ret, + int32_t op_errno) + +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_FSYNC); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.fsync_cbk.fn = fn; + stub->args.fsync_cbk.op_ret = op_ret; + stub->args.fsync_cbk.op_errno = op_errno; +out: + return stub; +} + + +call_stub_t * +fop_opendir_stub (call_frame_t *frame, + fop_opendir_t fn, + loc_t *loc, fd_t *fd) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_OPENDIR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.opendir.fn = fn; + loc_copy (&stub->args.opendir.loc, loc); + if (stub->args.opendir.fd) + stub->args.opendir.fd = fd_ref (fd); +out: + return stub; +} + + +call_stub_t * +fop_opendir_cbk_stub (call_frame_t *frame, + fop_opendir_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + fd_t *fd) + +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_OPENDIR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.opendir_cbk.fn = fn; + stub->args.opendir_cbk.op_ret = op_ret; + stub->args.opendir_cbk.op_errno = op_errno; + + if (fd) + stub->args.opendir_cbk.fd = fd_ref (fd); +out: + return stub; +} + + +call_stub_t * +fop_getdents_stub (call_frame_t *frame, + fop_getdents_t fn, + fd_t *fd, + size_t size, + off_t off, + int32_t flag) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 1, GF_FOP_GETDENTS); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.getdents.fn = fn; + stub->args.getdents.size = size; + stub->args.getdents.off = off; + if (fd) + stub->args.getdents.fd = fd_ref (fd); + stub->args.getdents.flag = flag; +out: + return stub; +} + + +call_stub_t * +fop_getdents_cbk_stub (call_frame_t *frame, + fop_getdents_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + dir_entry_t *entries, + int32_t count) + +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_GETDENTS); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.getdents_cbk.fn = fn; + stub->args.getdents_cbk.op_ret = op_ret; + stub->args.getdents_cbk.op_errno = op_errno; + if (op_ret >= 0) { + stub->args.getdents_cbk.entries.next = entries->next; + /* FIXME: are entries not needed in the caller after + * creating stub? */ + entries->next = NULL; + } + + stub->args.getdents_cbk.count = count; +out: + return stub; +} + + + +call_stub_t * +fop_fsyncdir_stub (call_frame_t *frame, + fop_fsyncdir_t fn, + fd_t *fd, + int32_t datasync) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 1, GF_FOP_FSYNCDIR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.fsyncdir.fn = fn; + if (fd) + stub->args.fsyncdir.fd = fd_ref (fd); + stub->args.fsyncdir.datasync = datasync; +out: + return stub; +} + + +call_stub_t * +fop_fsyncdir_cbk_stub (call_frame_t *frame, + fop_fsyncdir_cbk_t fn, + int32_t op_ret, + int32_t op_errno) + +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_FSYNCDIR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.fsyncdir_cbk.fn = fn; + stub->args.fsyncdir_cbk.op_ret = op_ret; + stub->args.fsyncdir_cbk.op_errno = op_errno; +out: + return stub; +} + + +call_stub_t * +fop_statfs_stub (call_frame_t *frame, + fop_statfs_t fn, + loc_t *loc) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_STATFS); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.statfs.fn = fn; + loc_copy (&stub->args.statfs.loc, loc); +out: + return stub; +} + + +call_stub_t * +fop_statfs_cbk_stub (call_frame_t *frame, + fop_statfs_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct statvfs *buf) + +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_STATFS); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.statfs_cbk.fn = fn; + stub->args.statfs_cbk.op_ret = op_ret; + stub->args.statfs_cbk.op_errno = op_errno; + if (op_ret == 0) + stub->args.statfs_cbk.buf = *buf; +out: + return stub; +} + + +call_stub_t * +fop_setxattr_stub (call_frame_t *frame, + fop_setxattr_t fn, + loc_t *loc, + dict_t *dict, + int32_t flags) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_SETXATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.setxattr.fn = fn; + loc_copy (&stub->args.setxattr.loc, loc); + /* TODO */ + if (dict) + stub->args.setxattr.dict = dict_ref (dict); + stub->args.setxattr.flags = flags; +out: + return stub; +} + + +call_stub_t * +fop_setxattr_cbk_stub (call_frame_t *frame, + fop_setxattr_cbk_t fn, + int32_t op_ret, + int32_t op_errno) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_SETXATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.setxattr_cbk.fn = fn; + stub->args.setxattr_cbk.op_ret = op_ret; + stub->args.setxattr_cbk.op_errno = op_errno; +out: + return stub; +} + +call_stub_t * +fop_getxattr_stub (call_frame_t *frame, + fop_getxattr_t fn, + loc_t *loc, + const char *name) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_GETXATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.getxattr.fn = fn; + loc_copy (&stub->args.getxattr.loc, loc); + + if (name) + stub->args.getxattr.name = strdup (name); +out: + return stub; +} + + +call_stub_t * +fop_getxattr_cbk_stub (call_frame_t *frame, + fop_getxattr_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + dict_t *dict) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_GETXATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.getxattr_cbk.fn = fn; + stub->args.getxattr_cbk.op_ret = op_ret; + stub->args.getxattr_cbk.op_errno = op_errno; + /* TODO */ + if (dict) + stub->args.getxattr_cbk.dict = dict_ref (dict); +out: + return stub; +} + +call_stub_t * +fop_removexattr_stub (call_frame_t *frame, + fop_removexattr_t fn, + loc_t *loc, + const char *name) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + GF_VALIDATE_OR_GOTO ("call-stub", name, out); + + stub = stub_new (frame, 1, GF_FOP_REMOVEXATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.removexattr.fn = fn; + loc_copy (&stub->args.removexattr.loc, loc); + stub->args.removexattr.name = strdup (name); +out: + return stub; +} + + +call_stub_t * +fop_removexattr_cbk_stub (call_frame_t *frame, + fop_removexattr_cbk_t fn, + int32_t op_ret, + int32_t op_errno) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_REMOVEXATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.removexattr_cbk.fn = fn; + stub->args.removexattr_cbk.op_ret = op_ret; + stub->args.removexattr_cbk.op_errno = op_errno; +out: + return stub; +} + + +call_stub_t * +fop_lk_stub (call_frame_t *frame, + fop_lk_t fn, + fd_t *fd, + int32_t cmd, + struct flock *lock) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", lock, out); + + stub = stub_new (frame, 1, GF_FOP_LK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.lk.fn = fn; + if (fd) + stub->args.lk.fd = fd_ref (fd); + stub->args.lk.cmd = cmd; + stub->args.lk.lock = *lock; +out: + return stub; +} + + +call_stub_t * +fop_lk_cbk_stub (call_frame_t *frame, + fop_lk_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct flock *lock) + +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_LK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.lk_cbk.fn = fn; + stub->args.lk_cbk.op_ret = op_ret; + stub->args.lk_cbk.op_errno = op_errno; + if (op_ret == 0) + stub->args.lk_cbk.lock = *lock; +out: + return stub; +} + +call_stub_t * +fop_inodelk_stub (call_frame_t *frame, fop_inodelk_t fn, + loc_t *loc, int32_t cmd, struct flock *lock) +{ + call_stub_t *stub = NULL; + + if (!frame || !lock) + return NULL; + + stub = stub_new (frame, 1, GF_FOP_INODELK); + if (!stub) + return NULL; + + stub->args.inodelk.fn = fn; + + loc_copy (&stub->args.inodelk.loc, loc); + stub->args.inodelk.cmd = cmd; + stub->args.inodelk.lock = *lock; + + return stub; +} + +call_stub_t * +fop_inodelk_cbk_stub (call_frame_t *frame, fop_inodelk_cbk_t fn, + int32_t op_ret, int32_t op_errno) +{ + call_stub_t *stub = NULL; + + if (!frame) + return NULL; + + stub = stub_new (frame, 0, GF_FOP_INODELK); + if (!stub) + return NULL; + + stub->args.inodelk_cbk.fn = fn; + stub->args.inodelk_cbk.op_ret = op_ret; + stub->args.inodelk_cbk.op_errno = op_errno; + + return stub; +} + + +call_stub_t * +fop_finodelk_stub (call_frame_t *frame, fop_finodelk_t fn, + fd_t *fd, int32_t cmd, struct flock *lock) +{ + call_stub_t *stub = NULL; + + if (!frame || !lock) + return NULL; + + stub = stub_new (frame, 1, GF_FOP_FINODELK); + if (!stub) + return NULL; + + stub->args.finodelk.fn = fn; + + if (fd) + stub->args.finodelk.fd = fd_ref (fd); + stub->args.finodelk.cmd = cmd; + stub->args.finodelk.lock = *lock; + + return stub; +} + + +call_stub_t * +fop_finodelk_cbk_stub (call_frame_t *frame, fop_inodelk_cbk_t fn, + int32_t op_ret, int32_t op_errno) +{ + call_stub_t *stub = NULL; + + if (!frame) + return NULL; + + stub = stub_new (frame, 0, GF_FOP_FINODELK); + if (!stub) + return NULL; + + stub->args.finodelk_cbk.fn = fn; + stub->args.finodelk_cbk.op_ret = op_ret; + stub->args.finodelk_cbk.op_errno = op_errno; + + return stub; +} + + +call_stub_t * +fop_entrylk_stub (call_frame_t *frame, fop_entrylk_t fn, + loc_t *loc, const char *name, + entrylk_cmd cmd, entrylk_type type) +{ + call_stub_t *stub = NULL; + + if (!frame) + return NULL; + + stub = stub_new (frame, 1, GF_FOP_ENTRYLK); + if (!stub) + return NULL; + + stub->args.entrylk.fn = fn; + loc_copy (&stub->args.entrylk.loc, loc); + + stub->args.entrylk.cmd = cmd; + stub->args.entrylk.type = type; + if (name) + stub->args.entrylk.name = strdup (name); + + return stub; +} + +call_stub_t * +fop_entrylk_cbk_stub (call_frame_t *frame, fop_entrylk_cbk_t fn, + int32_t op_ret, int32_t op_errno) +{ + call_stub_t *stub = NULL; + + if (!frame) + return NULL; + + stub = stub_new (frame, 0, GF_FOP_ENTRYLK); + if (!stub) + return NULL; + + stub->args.entrylk_cbk.fn = fn; + stub->args.entrylk_cbk.op_ret = op_ret; + stub->args.entrylk_cbk.op_errno = op_errno; + + return stub; +} + + +call_stub_t * +fop_fentrylk_stub (call_frame_t *frame, fop_fentrylk_t fn, + fd_t *fd, const char *name, + entrylk_cmd cmd, entrylk_type type) +{ + call_stub_t *stub = NULL; + + if (!frame) + return NULL; + + stub = stub_new (frame, 1, GF_FOP_FENTRYLK); + if (!stub) + return NULL; + + stub->args.fentrylk.fn = fn; + + if (fd) + stub->args.fentrylk.fd = fd_ref (fd); + stub->args.fentrylk.cmd = cmd; + stub->args.fentrylk.type = type; + if (name) + stub->args.fentrylk.name = strdup (name); + + return stub; +} + +call_stub_t * +fop_fentrylk_cbk_stub (call_frame_t *frame, fop_fentrylk_cbk_t fn, + int32_t op_ret, int32_t op_errno) +{ + call_stub_t *stub = NULL; + + if (!frame) + return NULL; + + stub = stub_new (frame, 0, GF_FOP_FENTRYLK); + if (!stub) + return NULL; + + stub->args.fentrylk_cbk.fn = fn; + stub->args.fentrylk_cbk.op_ret = op_ret; + stub->args.fentrylk_cbk.op_errno = op_errno; + + return stub; +} + + +call_stub_t * +fop_setdents_stub (call_frame_t *frame, + fop_setdents_t fn, + fd_t *fd, + int32_t flags, + dir_entry_t *entries, + int32_t count) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 1, GF_FOP_SETDENTS); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + if (fd) + stub->args.setdents.fd = fd_ref (fd); + stub->args.setdents.fn = fn; + stub->args.setdents.flags = flags; + stub->args.setdents.count = count; + if (entries) { + stub->args.setdents.entries.next = entries->next; + entries->next = NULL; + } +out: + return stub; +} + +call_stub_t * +fop_setdents_cbk_stub (call_frame_t *frame, + fop_setdents_cbk_t fn, + int32_t op_ret, + int32_t op_errno) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_SETDENTS); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.setdents_cbk.fn = fn; + stub->args.setdents_cbk.op_ret = op_ret; + stub->args.setdents_cbk.op_errno = op_errno; +out: + return stub; + +} + +call_stub_t * +fop_readdir_cbk_stub (call_frame_t *frame, + fop_readdir_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + gf_dirent_t *entries) +{ + call_stub_t *stub = NULL; + gf_dirent_t *stub_entry = NULL, *entry = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_READDIR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.readdir_cbk.fn = fn; + stub->args.readdir_cbk.op_ret = op_ret; + stub->args.readdir_cbk.op_errno = op_errno; + INIT_LIST_HEAD (&stub->args.readdir_cbk.entries.list); + + if (op_ret > 0) { + list_for_each_entry (entry, &entries->list, list) { + stub_entry = gf_dirent_for_name (entry->d_name); + ERR_ABORT (stub_entry); + stub_entry->d_off = entry->d_off; + stub_entry->d_ino = entry->d_ino; + + list_add_tail (&stub_entry->list, + &stub->args.readdir_cbk.entries.list); + } + } +out: + return stub; +} + +call_stub_t * +fop_readdir_stub (call_frame_t *frame, + fop_readdir_t fn, + fd_t *fd, + size_t size, + off_t off) +{ + call_stub_t *stub = NULL; + + stub = stub_new (frame, 1, GF_FOP_READDIR); + stub->args.readdir.fn = fn; + stub->args.readdir.fd = fd_ref (fd); + stub->args.readdir.size = size; + stub->args.readdir.off = off; + + return stub; +} +call_stub_t * +fop_checksum_stub (call_frame_t *frame, + fop_checksum_t fn, + loc_t *loc, + int32_t flags) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + + stub = stub_new (frame, 1, GF_FOP_CHECKSUM); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.checksum.fn = fn; + loc_copy (&stub->args.checksum.loc, loc); + stub->args.checksum.flags = flags; +out: + return stub; +} + + +call_stub_t * +fop_checksum_cbk_stub (call_frame_t *frame, + fop_checksum_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + uint8_t *file_checksum, + uint8_t *dir_checksum) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_CHECKSUM); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.checksum_cbk.fn = fn; + stub->args.checksum_cbk.op_ret = op_ret; + stub->args.checksum_cbk.op_errno = op_errno; + if (op_ret >= 0) + { + stub->args.checksum_cbk.file_checksum = + memdup (file_checksum, ZR_FILENAME_MAX); + + stub->args.checksum_cbk.dir_checksum = + memdup (dir_checksum, ZR_FILENAME_MAX); + } +out: + return stub; +} + + +call_stub_t * +fop_xattrop_cbk_stub (call_frame_t *frame, + fop_xattrop_cbk_t fn, + int32_t op_ret, + int32_t op_errno) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_XATTROP); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->args.xattrop_cbk.fn = fn; + stub->args.xattrop_cbk.op_ret = op_ret; + stub->args.xattrop_cbk.op_errno = op_errno; + +out: + return stub; +} + + +call_stub_t * +fop_fxattrop_cbk_stub (call_frame_t *frame, + fop_fxattrop_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + dict_t *xattr) +{ + call_stub_t *stub = NULL; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 1, GF_FOP_FXATTROP); + stub->args.fxattrop_cbk.fn = fn; + stub->args.fxattrop_cbk.op_ret = op_ret; + stub->args.fxattrop_cbk.op_errno = op_errno; + if (xattr) + stub->args.fxattrop_cbk.xattr = dict_ref (xattr); + +out: + return stub; +} + + +call_stub_t * +fop_xattrop_stub (call_frame_t *frame, + fop_xattrop_t fn, + loc_t *loc, + gf_xattrop_flags_t optype, + dict_t *xattr) +{ + call_stub_t *stub = NULL; + + if (!frame || !xattr) + return NULL; + + stub = stub_new (frame, 1, GF_FOP_XATTROP); + if (!stub) + return NULL; + + stub->args.xattrop.fn = fn; + + loc_copy (&stub->args.xattrop.loc, loc); + + stub->args.xattrop.optype = optype; + stub->args.xattrop.xattr = dict_ref (xattr); + + return stub; +} + +call_stub_t * +fop_fxattrop_stub (call_frame_t *frame, + fop_fxattrop_t fn, + fd_t *fd, + gf_xattrop_flags_t optype, + dict_t *xattr) +{ + call_stub_t *stub = NULL; + + if (!frame || !xattr) + return NULL; + + stub = stub_new (frame, 1, GF_FOP_FXATTROP); + if (!stub) + return NULL; + + stub->args.fxattrop.fn = fn; + + stub->args.fxattrop.fd = fd_ref (fd); + + stub->args.fxattrop.optype = optype; + stub->args.fxattrop.xattr = dict_ref (xattr); + + return stub; +} + + +static void +call_resume_wind (call_stub_t *stub) +{ + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + switch (stub->fop) { + case GF_FOP_OPEN: + { + stub->args.open.fn (stub->frame, + stub->frame->this, + &stub->args.open.loc, + stub->args.open.flags, stub->args.open.fd); + break; + } + case GF_FOP_CREATE: + { + stub->args.create.fn (stub->frame, + stub->frame->this, + &stub->args.create.loc, + stub->args.create.flags, + stub->args.create.mode, + stub->args.create.fd); + break; + } + case GF_FOP_STAT: + { + stub->args.stat.fn (stub->frame, + stub->frame->this, + &stub->args.stat.loc); + break; + } + case GF_FOP_READLINK: + { + stub->args.readlink.fn (stub->frame, + stub->frame->this, + &stub->args.readlink.loc, + stub->args.readlink.size); + break; + } + + case GF_FOP_MKNOD: + { + stub->args.mknod.fn (stub->frame, + stub->frame->this, + &stub->args.mknod.loc, + stub->args.mknod.mode, + stub->args.mknod.rdev); + } + break; + + case GF_FOP_MKDIR: + { + stub->args.mkdir.fn (stub->frame, + stub->frame->this, + &stub->args.mkdir.loc, + stub->args.mkdir.mode); + } + break; + + case GF_FOP_UNLINK: + { + stub->args.unlink.fn (stub->frame, + stub->frame->this, + &stub->args.unlink.loc); + } + break; + + case GF_FOP_RMDIR: + { + stub->args.rmdir.fn (stub->frame, + stub->frame->this, + &stub->args.rmdir.loc); + } + break; + + case GF_FOP_SYMLINK: + { + stub->args.symlink.fn (stub->frame, + stub->frame->this, + stub->args.symlink.linkname, + &stub->args.symlink.loc); + } + break; + + case GF_FOP_RENAME: + { + stub->args.rename.fn (stub->frame, + stub->frame->this, + &stub->args.rename.old, + &stub->args.rename.new); + } + break; + + case GF_FOP_LINK: + { + stub->args.link.fn (stub->frame, + stub->frame->this, + &stub->args.link.oldloc, + &stub->args.link.newloc); + } + break; + + case GF_FOP_CHMOD: + { + stub->args.chmod.fn (stub->frame, + stub->frame->this, + &stub->args.chmod.loc, + stub->args.chmod.mode); + } + break; + + case GF_FOP_CHOWN: + { + stub->args.chown.fn (stub->frame, + stub->frame->this, + &stub->args.chown.loc, + stub->args.chown.uid, + stub->args.chown.gid); + break; + } + case GF_FOP_TRUNCATE: + { + stub->args.truncate.fn (stub->frame, + stub->frame->this, + &stub->args.truncate.loc, + stub->args.truncate.off); + break; + } + + case GF_FOP_READ: + { + stub->args.readv.fn (stub->frame, + stub->frame->this, + stub->args.readv.fd, + stub->args.readv.size, + stub->args.readv.off); + break; + } + + case GF_FOP_WRITE: + { + stub->args.writev.fn (stub->frame, + stub->frame->this, + stub->args.writev.fd, + stub->args.writev.vector, + stub->args.writev.count, + stub->args.writev.off); + break; + } + + case GF_FOP_STATFS: + { + stub->args.statfs.fn (stub->frame, + stub->frame->this, + &stub->args.statfs.loc); + break; + } + case GF_FOP_FLUSH: + { + stub->args.flush.fn (stub->frame, + stub->frame->this, + stub->args.flush.fd); + break; + } + + case GF_FOP_FSYNC: + { + stub->args.fsync.fn (stub->frame, + stub->frame->this, + stub->args.fsync.fd, + stub->args.fsync.datasync); + break; + } + + case GF_FOP_SETXATTR: + { + stub->args.setxattr.fn (stub->frame, + stub->frame->this, + &stub->args.setxattr.loc, + stub->args.setxattr.dict, + stub->args.setxattr.flags); + break; + } + + case GF_FOP_GETXATTR: + { + stub->args.getxattr.fn (stub->frame, + stub->frame->this, + &stub->args.getxattr.loc, + stub->args.getxattr.name); + break; + } + + case GF_FOP_REMOVEXATTR: + { + stub->args.removexattr.fn (stub->frame, + stub->frame->this, + &stub->args.removexattr.loc, + stub->args.removexattr.name); + break; + } + + case GF_FOP_OPENDIR: + { + stub->args.opendir.fn (stub->frame, + stub->frame->this, + &stub->args.opendir.loc, + stub->args.opendir.fd); + break; + } + + case GF_FOP_GETDENTS: + { + stub->args.getdents.fn (stub->frame, + stub->frame->this, + stub->args.getdents.fd, + stub->args.getdents.size, + stub->args.getdents.off, + stub->args.getdents.flag); + break; + } + + case GF_FOP_FSYNCDIR: + { + stub->args.fsyncdir.fn (stub->frame, + stub->frame->this, + stub->args.fsyncdir.fd, + stub->args.fsyncdir.datasync); + break; + } + + case GF_FOP_ACCESS: + { + stub->args.access.fn (stub->frame, + stub->frame->this, + &stub->args.access.loc, + stub->args.access.mask); + break; + } + + case GF_FOP_FTRUNCATE: + { + stub->args.ftruncate.fn (stub->frame, + stub->frame->this, + stub->args.ftruncate.fd, + stub->args.ftruncate.off); + break; + } + + case GF_FOP_FSTAT: + { + stub->args.fstat.fn (stub->frame, + stub->frame->this, + stub->args.fstat.fd); + break; + } + + case GF_FOP_LK: + { + stub->args.lk.fn (stub->frame, + stub->frame->this, + stub->args.lk.fd, + stub->args.lk.cmd, + &stub->args.lk.lock); + break; + } + + case GF_FOP_INODELK: + { + stub->args.inodelk.fn (stub->frame, + stub->frame->this, + &stub->args.inodelk.loc, + stub->args.inodelk.cmd, + &stub->args.inodelk.lock); + break; + } + + case GF_FOP_FINODELK: + { + stub->args.finodelk.fn (stub->frame, + stub->frame->this, + stub->args.finodelk.fd, + stub->args.finodelk.cmd, + &stub->args.finodelk.lock); + break; + } + + case GF_FOP_ENTRYLK: + { + stub->args.entrylk.fn (stub->frame, + stub->frame->this, + &stub->args.entrylk.loc, + stub->args.entrylk.name, + stub->args.entrylk.cmd, + stub->args.entrylk.type); + break; + } + + case GF_FOP_FENTRYLK: + { + stub->args.fentrylk.fn (stub->frame, + stub->frame->this, + stub->args.fentrylk.fd, + stub->args.fentrylk.name, + stub->args.fentrylk.cmd, + stub->args.fentrylk.type); + break; + } + + case GF_FOP_UTIMENS: + { + stub->args.utimens.fn (stub->frame, + stub->frame->this, + &stub->args.utimens.loc, + stub->args.utimens.tv); + break; + } + + + break; + case GF_FOP_FCHMOD: + { + stub->args.fchmod.fn (stub->frame, + stub->frame->this, + stub->args.fchmod.fd, + stub->args.fchmod.mode); + break; + } + + case GF_FOP_FCHOWN: + { + stub->args.fchown.fn (stub->frame, + stub->frame->this, + stub->args.fchown.fd, + stub->args.fchown.uid, + stub->args.fchown.gid); + break; + } + + case GF_FOP_LOOKUP: + { + stub->args.lookup.fn (stub->frame, + stub->frame->this, + &stub->args.lookup.loc, + stub->args.lookup.xattr_req); + break; + } + + case GF_FOP_SETDENTS: + { + stub->args.setdents.fn (stub->frame, + stub->frame->this, + stub->args.setdents.fd, + stub->args.setdents.flags, + &stub->args.setdents.entries, + stub->args.setdents.count); + break; + } + + case GF_FOP_CHECKSUM: + { + stub->args.checksum.fn (stub->frame, + stub->frame->this, + &stub->args.checksum.loc, + stub->args.checksum.flags); + break; + } + case GF_FOP_READDIR: + { + stub->args.readdir.fn (stub->frame, + stub->frame->this, + stub->args.readdir.fd, + stub->args.readdir.size, + stub->args.readdir.off); + break; + } + case GF_FOP_XATTROP: + { + stub->args.xattrop.fn (stub->frame, + stub->frame->this, + &stub->args.xattrop.loc, + stub->args.xattrop.optype, + stub->args.xattrop.xattr); + + break; + } + case GF_FOP_FXATTROP: + { + stub->args.fxattrop.fn (stub->frame, + stub->frame->this, + stub->args.fxattrop.fd, + stub->args.fxattrop.optype, + stub->args.fxattrop.xattr); + + break; + } + default: + { + gf_log ("call-stub", + GF_LOG_DEBUG, + "Invalid value of FOP"); + } + break; + } +out: + return; +} + + + +static void +call_resume_unwind (call_stub_t *stub) +{ + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + switch (stub->fop) { + case GF_FOP_OPEN: + { + if (!stub->args.open_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.open_cbk.op_ret, + stub->args.open_cbk.op_errno, + stub->args.open_cbk.fd); + else + stub->args.open_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.open_cbk.op_ret, + stub->args.open_cbk.op_errno, + stub->args.open_cbk.fd); + break; + } + + case GF_FOP_CREATE: + { + if (!stub->args.create_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.create_cbk.op_ret, + stub->args.create_cbk.op_errno, + stub->args.create_cbk.fd, + stub->args.create_cbk.inode, + &stub->args.create_cbk.buf); + else + stub->args.create_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.create_cbk.op_ret, + stub->args.create_cbk.op_errno, + stub->args.create_cbk.fd, + stub->args.create_cbk.inode, + &stub->args.create_cbk.buf); + + break; + } + + case GF_FOP_STAT: + { + if (!stub->args.stat_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.stat_cbk.op_ret, + stub->args.stat_cbk.op_errno, + &stub->args.stat_cbk.buf); + else + stub->args.stat_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.stat_cbk.op_ret, + stub->args.stat_cbk.op_errno, + &stub->args.stat_cbk.buf); + + break; + } + + case GF_FOP_READLINK: + { + if (!stub->args.readlink_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.readlink_cbk.op_ret, + stub->args.readlink_cbk.op_errno, + stub->args.readlink_cbk.buf); + else + stub->args.readlink_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.readlink_cbk.op_ret, + stub->args.readlink_cbk.op_errno, + stub->args.readlink_cbk.buf); + + break; + } + + case GF_FOP_MKNOD: + { + if (!stub->args.mknod_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.mknod_cbk.op_ret, + stub->args.mknod_cbk.op_errno, + stub->args.mknod_cbk.inode, + &stub->args.mknod_cbk.buf); + else + stub->args.mknod_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.mknod_cbk.op_ret, + stub->args.mknod_cbk.op_errno, + stub->args.mknod_cbk.inode, + &stub->args.mknod_cbk.buf); + break; + } + + case GF_FOP_MKDIR: + { + if (!stub->args.mkdir_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.mkdir_cbk.op_ret, + stub->args.mkdir_cbk.op_errno, + stub->args.mkdir_cbk.inode, + &stub->args.mkdir_cbk.buf); + else + stub->args.mkdir_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.mkdir_cbk.op_ret, + stub->args.mkdir_cbk.op_errno, + stub->args.mkdir_cbk.inode, + &stub->args.mkdir_cbk.buf); + + if (stub->args.mkdir_cbk.inode) + inode_unref (stub->args.mkdir_cbk.inode); + + break; + } + + case GF_FOP_UNLINK: + { + if (!stub->args.unlink_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.unlink_cbk.op_ret, + stub->args.unlink_cbk.op_errno); + else + stub->args.unlink_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.unlink_cbk.op_ret, + stub->args.unlink_cbk.op_errno); + break; + } + + case GF_FOP_RMDIR: + { + if (!stub->args.rmdir_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.rmdir_cbk.op_ret, + stub->args.rmdir_cbk.op_errno); + else + stub->args.unlink_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.rmdir_cbk.op_ret, + stub->args.rmdir_cbk.op_errno); + break; + } + + case GF_FOP_SYMLINK: + { + if (!stub->args.symlink_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.symlink_cbk.op_ret, + stub->args.symlink_cbk.op_errno, + stub->args.symlink_cbk.inode, + &stub->args.symlink_cbk.buf); + else + stub->args.symlink_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.symlink_cbk.op_ret, + stub->args.symlink_cbk.op_errno, + stub->args.symlink_cbk.inode, + &stub->args.symlink_cbk.buf); + } + break; + + case GF_FOP_RENAME: + { +#if 0 + if (!stub->args.rename_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.rename_cbk.op_ret, + stub->args.rename_cbk.op_errno, + &stub->args.rename_cbk.buf); + else + stub->args.rename_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.rename_cbk.op_ret, + stub->args.rename_cbk.op_errno, + &stub->args.rename_cbk.buf); +#endif + break; + } + + case GF_FOP_LINK: + { + if (!stub->args.link_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.link_cbk.op_ret, + stub->args.link_cbk.op_errno, + stub->args.link_cbk.inode, + &stub->args.link_cbk.buf); + else + stub->args.link_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.link_cbk.op_ret, + stub->args.link_cbk.op_errno, + stub->args.link_cbk.inode, + &stub->args.link_cbk.buf); + break; + } + + case GF_FOP_CHMOD: + { + if (!stub->args.chmod_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.chmod_cbk.op_ret, + stub->args.chmod_cbk.op_errno, + &stub->args.chmod_cbk.buf); + else + stub->args.chmod_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.chmod_cbk.op_ret, + stub->args.chmod_cbk.op_errno, + &stub->args.chmod_cbk.buf); + break; + } + + case GF_FOP_CHOWN: + { + if (!stub->args.chown_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.chown_cbk.op_ret, + stub->args.chown_cbk.op_errno, + &stub->args.chown_cbk.buf); + else + stub->args.chown_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.chown_cbk.op_ret, + stub->args.chown_cbk.op_errno, + &stub->args.chown_cbk.buf); + break; + } + + case GF_FOP_TRUNCATE: + { + if (!stub->args.truncate_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.truncate_cbk.op_ret, + stub->args.truncate_cbk.op_errno, + &stub->args.truncate_cbk.buf); + else + stub->args.truncate_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.truncate_cbk.op_ret, + stub->args.truncate_cbk.op_errno, + &stub->args.truncate_cbk.buf); + break; + } + + case GF_FOP_READ: + { + if (!stub->args.readv_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.readv_cbk.op_ret, + stub->args.readv_cbk.op_errno, + stub->args.readv_cbk.vector, + stub->args.readv_cbk.count, + &stub->args.readv_cbk.stbuf); + else + stub->args.readv_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.readv_cbk.op_ret, + stub->args.readv_cbk.op_errno, + stub->args.readv_cbk.vector, + stub->args.readv_cbk.count, + &stub->args.readv_cbk.stbuf); + } + break; + + case GF_FOP_WRITE: + { + if (!stub->args.writev_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.writev_cbk.op_ret, + stub->args.writev_cbk.op_errno, + &stub->args.writev_cbk.stbuf); + else + stub->args.writev_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.writev_cbk.op_ret, + stub->args.writev_cbk.op_errno, + &stub->args.writev_cbk.stbuf); + break; + } + + case GF_FOP_STATFS: + { + if (!stub->args.statfs_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.statfs_cbk.op_ret, + stub->args.statfs_cbk.op_errno, + &(stub->args.statfs_cbk.buf)); + else + stub->args.statfs_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.statfs_cbk.op_ret, + stub->args.statfs_cbk.op_errno, + &(stub->args.statfs_cbk.buf)); + } + break; + + case GF_FOP_FLUSH: + { + if (!stub->args.flush_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.flush_cbk.op_ret, + stub->args.flush_cbk.op_errno); + else + stub->args.flush_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.flush_cbk.op_ret, + stub->args.flush_cbk.op_errno); + + break; + } + + case GF_FOP_FSYNC: + { + if (!stub->args.fsync_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.fsync_cbk.op_ret, + stub->args.fsync_cbk.op_errno); + else + stub->args.fsync_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.fsync_cbk.op_ret, + stub->args.fsync_cbk.op_errno); + break; + } + + case GF_FOP_SETXATTR: + { + if (!stub->args.setxattr_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.setxattr_cbk.op_ret, + stub->args.setxattr_cbk.op_errno); + + else + stub->args.setxattr_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.setxattr_cbk.op_ret, + stub->args.setxattr_cbk.op_errno); + + break; + } + + case GF_FOP_GETXATTR: + { + if (!stub->args.getxattr_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.getxattr_cbk.op_ret, + stub->args.getxattr_cbk.op_errno, + stub->args.getxattr_cbk.dict); + else + stub->args.getxattr_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.getxattr_cbk.op_ret, + stub->args.getxattr_cbk.op_errno, + stub->args.getxattr_cbk.dict); + break; + } + + case GF_FOP_REMOVEXATTR: + { + if (!stub->args.removexattr_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.removexattr_cbk.op_ret, + stub->args.removexattr_cbk.op_errno); + else + stub->args.removexattr_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.removexattr_cbk.op_ret, + stub->args.removexattr_cbk.op_errno); + + break; + } + + case GF_FOP_OPENDIR: + { + if (!stub->args.opendir_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.opendir_cbk.op_ret, + stub->args.opendir_cbk.op_errno, + stub->args.opendir_cbk.fd); + else + stub->args.opendir_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.opendir_cbk.op_ret, + stub->args.opendir_cbk.op_errno, + stub->args.opendir_cbk.fd); + break; + } + + case GF_FOP_GETDENTS: + { + if (!stub->args.getdents_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.getdents_cbk.op_ret, + stub->args.getdents_cbk.op_errno, + &stub->args.getdents_cbk.entries, + stub->args.getdents_cbk.count); + else + stub->args.getdents_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.getdents_cbk.op_ret, + stub->args.getdents_cbk.op_errno, + &stub->args.getdents_cbk.entries, + stub->args.getdents_cbk.count); + break; + } + + case GF_FOP_FSYNCDIR: + { + if (!stub->args.fsyncdir_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.fsyncdir_cbk.op_ret, + stub->args.fsyncdir_cbk.op_errno); + else + stub->args.fsyncdir_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.fsyncdir_cbk.op_ret, + stub->args.fsyncdir_cbk.op_errno); + break; + } + + case GF_FOP_ACCESS: + { + if (!stub->args.access_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.access_cbk.op_ret, + stub->args.access_cbk.op_errno); + else + stub->args.access_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.access_cbk.op_ret, + stub->args.access_cbk.op_errno); + + break; + } + + case GF_FOP_FTRUNCATE: + { + if (!stub->args.ftruncate_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.ftruncate_cbk.op_ret, + stub->args.ftruncate_cbk.op_errno, + &stub->args.ftruncate_cbk.buf); + else + stub->args.ftruncate_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.ftruncate_cbk.op_ret, + stub->args.ftruncate_cbk.op_errno, + &stub->args.ftruncate_cbk.buf); + break; + } + + case GF_FOP_FSTAT: + { + if (!stub->args.fstat_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.fstat_cbk.op_ret, + stub->args.fstat_cbk.op_errno, + &stub->args.fstat_cbk.buf); + else + stub->args.fstat_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.fstat_cbk.op_ret, + stub->args.fstat_cbk.op_errno, + &stub->args.fstat_cbk.buf); + + break; + } + + case GF_FOP_LK: + { + if (!stub->args.lk_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.lk_cbk.op_ret, + stub->args.lk_cbk.op_errno, + &stub->args.lk_cbk.lock); + else + stub->args.lk_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.lk_cbk.op_ret, + stub->args.lk_cbk.op_errno, + &stub->args.lk_cbk.lock); + break; + } + + case GF_FOP_INODELK: + { + if (!stub->args.inodelk_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.inodelk_cbk.op_ret, + stub->args.inodelk_cbk.op_errno); + + else + stub->args.inodelk_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.inodelk_cbk.op_ret, + stub->args.inodelk_cbk.op_errno); + break; + } + + case GF_FOP_FINODELK: + { + if (!stub->args.finodelk_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.finodelk_cbk.op_ret, + stub->args.finodelk_cbk.op_errno); + + else + stub->args.finodelk_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.finodelk_cbk.op_ret, + stub->args.finodelk_cbk.op_errno); + break; + } + + case GF_FOP_ENTRYLK: + { + if (!stub->args.entrylk_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.entrylk_cbk.op_ret, + stub->args.entrylk_cbk.op_errno); + + else + stub->args.entrylk_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.entrylk_cbk.op_ret, + stub->args.entrylk_cbk.op_errno); + break; + } + + case GF_FOP_FENTRYLK: + { + if (!stub->args.fentrylk_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.fentrylk_cbk.op_ret, + stub->args.fentrylk_cbk.op_errno); + + else + stub->args.fentrylk_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.fentrylk_cbk.op_ret, + stub->args.fentrylk_cbk.op_errno); + break; + } + + case GF_FOP_UTIMENS: + { + if (!stub->args.utimens_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.utimens_cbk.op_ret, + stub->args.utimens_cbk.op_errno, + &stub->args.utimens_cbk.buf); + else + stub->args.utimens_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.utimens_cbk.op_ret, + stub->args.utimens_cbk.op_errno, + &stub->args.utimens_cbk.buf); + + break; + } + + + break; + case GF_FOP_FCHMOD: + { + if (!stub->args.fchmod_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.fchmod_cbk.op_ret, + stub->args.fchmod_cbk.op_errno, + &stub->args.fchmod_cbk.buf); + else + stub->args.fchmod_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.fchmod_cbk.op_ret, + stub->args.fchmod_cbk.op_errno, + &stub->args.fchmod_cbk.buf); + break; + } + + case GF_FOP_FCHOWN: + { + if (!stub->args.fchown_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.fchown_cbk.op_ret, + stub->args.fchown_cbk.op_errno, + &stub->args.fchown_cbk.buf); + else + stub->args.fchown_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.fchown_cbk.op_ret, + stub->args.fchown_cbk.op_errno, + &stub->args.fchown_cbk.buf); + break; + } + + case GF_FOP_LOOKUP: + { + if (!stub->args.lookup_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.lookup_cbk.op_ret, + stub->args.lookup_cbk.op_errno, + stub->args.lookup_cbk.inode, + &stub->args.lookup_cbk.buf, + stub->args.lookup_cbk.dict); + else + stub->args.lookup_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.lookup_cbk.op_ret, + stub->args.lookup_cbk.op_errno, + stub->args.lookup_cbk.inode, + &stub->args.lookup_cbk.buf, + stub->args.lookup_cbk.dict); + /* FIXME NULL should not be passed */ + + if (stub->args.lookup_cbk.dict) + dict_unref (stub->args.lookup_cbk.dict); + if (stub->args.lookup_cbk.inode) + inode_unref (stub->args.lookup_cbk.inode); + + break; + } + case GF_FOP_SETDENTS: + { + if (!stub->args.setdents_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.setdents_cbk.op_ret, + stub->args.setdents_cbk.op_errno); + else + stub->args.setdents_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.setdents_cbk.op_ret, + stub->args.setdents_cbk.op_errno); + break; + } + + case GF_FOP_CHECKSUM: + { + if (!stub->args.checksum_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.checksum_cbk.op_ret, + stub->args.checksum_cbk.op_errno, + stub->args.checksum_cbk.file_checksum, + stub->args.checksum_cbk.dir_checksum); + else + stub->args.checksum_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.checksum_cbk.op_ret, + stub->args.checksum_cbk.op_errno, + stub->args.checksum_cbk.file_checksum, + stub->args.checksum_cbk.dir_checksum); + if (stub->args.checksum_cbk.op_ret >= 0) + { + FREE (stub->args.checksum_cbk.file_checksum); + FREE (stub->args.checksum_cbk.dir_checksum); + } + + break; + } + + case GF_FOP_READDIR: + { + if (!stub->args.readdir_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.readdir_cbk.op_ret, + stub->args.readdir_cbk.op_errno, + &stub->args.readdir_cbk.entries); + else + stub->args.readdir_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.readdir_cbk.op_ret, + stub->args.readdir_cbk.op_errno, + &stub->args.readdir_cbk.entries); + + if (stub->args.readdir_cbk.op_ret > 0) + gf_dirent_free (&stub->args.readdir_cbk.entries); + + break; + } + + case GF_FOP_XATTROP: + { + if (!stub->args.xattrop_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.xattrop_cbk.op_ret, + stub->args.xattrop_cbk.op_errno); + else + stub->args.xattrop_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.xattrop_cbk.op_ret, + stub->args.xattrop_cbk.op_errno, + stub->args.xattrop_cbk.xattr); + + if (stub->args.xattrop_cbk.xattr) + dict_unref (stub->args.xattrop_cbk.xattr); + + break; + } + case GF_FOP_FXATTROP: + { + if (!stub->args.fxattrop_cbk.fn) + STACK_UNWIND (stub->frame, + stub->args.fxattrop_cbk.op_ret, + stub->args.fxattrop_cbk.op_errno); + else + stub->args.fxattrop_cbk.fn (stub->frame, + stub->frame->cookie, + stub->frame->this, + stub->args.fxattrop_cbk.op_ret, + stub->args.fxattrop_cbk.op_errno, + stub->args.fxattrop_cbk.xattr); + + if (stub->args.fxattrop_cbk.xattr) + dict_unref (stub->args.fxattrop_cbk.xattr); + + break; + } + case GF_FOP_MAXVALUE: + { + gf_log ("call-stub", + GF_LOG_DEBUG, + "Invalid value of FOP"); + } + break; + } +out: + return; +} + + +static void +call_stub_destroy_wind (call_stub_t *stub) +{ + switch (stub->fop) { + case GF_FOP_OPEN: + { + loc_wipe (&stub->args.open.loc); + if (stub->args.open.fd) + fd_unref (stub->args.open.fd); + break; + } + case GF_FOP_CREATE: + { + loc_wipe (&stub->args.create.loc); + if (stub->args.create.fd) + fd_unref (stub->args.create.fd); + break; + } + case GF_FOP_STAT: + { + loc_wipe (&stub->args.stat.loc); + break; + } + case GF_FOP_READLINK: + { + loc_wipe (&stub->args.readlink.loc); + break; + } + + case GF_FOP_MKNOD: + { + loc_wipe (&stub->args.mknod.loc); + } + break; + + case GF_FOP_MKDIR: + { + loc_wipe (&stub->args.mkdir.loc); + } + break; + + case GF_FOP_UNLINK: + { + loc_wipe (&stub->args.unlink.loc); + } + break; + + case GF_FOP_RMDIR: + { + loc_wipe (&stub->args.rmdir.loc); + } + break; + + case GF_FOP_SYMLINK: + { + FREE (stub->args.symlink.linkname); + loc_wipe (&stub->args.symlink.loc); + } + break; + + case GF_FOP_RENAME: + { + loc_wipe (&stub->args.rename.old); + loc_wipe (&stub->args.rename.new); + } + break; + + case GF_FOP_LINK: + { + loc_wipe (&stub->args.link.oldloc); + loc_wipe (&stub->args.link.newloc); + } + break; + + case GF_FOP_CHMOD: + { + loc_wipe (&stub->args.chmod.loc); + } + break; + + case GF_FOP_CHOWN: + { + loc_wipe (&stub->args.chown.loc); + break; + } + case GF_FOP_TRUNCATE: + { + loc_wipe (&stub->args.truncate.loc); + break; + } + + case GF_FOP_READ: + { + if (stub->args.readv.fd) + fd_unref (stub->args.readv.fd); + break; + } + + case GF_FOP_WRITE: + { + dict_t *refs = stub->args.writev.req_refs; + if (stub->args.writev.fd) + fd_unref (stub->args.writev.fd); + FREE (stub->args.writev.vector); + if (refs) + dict_unref (refs); + break; + } + + case GF_FOP_STATFS: + { + loc_wipe (&stub->args.statfs.loc); + break; + } + case GF_FOP_FLUSH: + { + if (stub->args.flush.fd) + fd_unref (stub->args.flush.fd); + break; + } + + case GF_FOP_FSYNC: + { + if (stub->args.fsync.fd) + fd_unref (stub->args.fsync.fd); + break; + } + + case GF_FOP_SETXATTR: + { + loc_wipe (&stub->args.setxattr.loc); + if (stub->args.setxattr.dict) + dict_unref (stub->args.setxattr.dict); + break; + } + + case GF_FOP_GETXATTR: + { + if (stub->args.getxattr.name) + FREE (stub->args.getxattr.name); + loc_wipe (&stub->args.getxattr.loc); + break; + } + + case GF_FOP_REMOVEXATTR: + { + loc_wipe (&stub->args.removexattr.loc); + FREE (stub->args.removexattr.name); + break; + } + + case GF_FOP_OPENDIR: + { + loc_wipe (&stub->args.opendir.loc); + if (stub->args.opendir.fd) + fd_unref (stub->args.opendir.fd); + break; + } + + case GF_FOP_GETDENTS: + { + if (stub->args.getdents.fd) + fd_unref (stub->args.getdents.fd); + break; + } + + case GF_FOP_FSYNCDIR: + { + if (stub->args.fsyncdir.fd) + fd_unref (stub->args.fsyncdir.fd); + break; + } + + case GF_FOP_ACCESS: + { + loc_wipe (&stub->args.access.loc); + break; + } + + case GF_FOP_FTRUNCATE: + { + if (stub->args.ftruncate.fd) + fd_unref (stub->args.ftruncate.fd); + break; + } + + case GF_FOP_FSTAT: + { + if (stub->args.fstat.fd) + fd_unref (stub->args.fstat.fd); + break; + } + + case GF_FOP_LK: + { + if (stub->args.lk.fd) + fd_unref (stub->args.lk.fd); + break; + } + + case GF_FOP_INODELK: + { + loc_wipe (&stub->args.inodelk.loc); + break; + } + case GF_FOP_FINODELK: + { + if (stub->args.finodelk.fd) + fd_unref (stub->args.finodelk.fd); + break; + } + case GF_FOP_ENTRYLK: + { + if (stub->args.entrylk.name) + FREE (stub->args.entrylk.name); + loc_wipe (&stub->args.entrylk.loc); + break; + } + case GF_FOP_FENTRYLK: + { + if (stub->args.fentrylk.name) + FREE (stub->args.fentrylk.name); + + if (stub->args.fentrylk.fd) + fd_unref (stub->args.fentrylk.fd); + break; + } + case GF_FOP_UTIMENS: + { + loc_wipe (&stub->args.utimens.loc); + break; + } + break; + case GF_FOP_FCHMOD: + { + if (stub->args.fchmod.fd) + fd_unref (stub->args.fchmod.fd); + break; + } + + case GF_FOP_FCHOWN: + { + if (stub->args.fchown.fd) + fd_unref (stub->args.fchown.fd); + break; + } + + case GF_FOP_LOOKUP: + { + loc_wipe (&stub->args.lookup.loc); + if (stub->args.lookup.xattr_req) + dict_unref (stub->args.lookup.xattr_req); + break; + } + + case GF_FOP_SETDENTS: + { + dir_entry_t *entry, *next; + if (stub->args.setdents.fd) + fd_unref (stub->args.setdents.fd); + entry = stub->args.setdents.entries.next; + while (entry) { + next = entry->next; + FREE (entry->name); + FREE (entry); + entry = next; + } + break; + } + + case GF_FOP_CHECKSUM: + { + loc_wipe (&stub->args.checksum.loc); + break; + } + break; + case GF_FOP_READDIR: + { + if (stub->args.readdir.fd) + fd_unref (stub->args.readdir.fd); + break; + } + case GF_FOP_XATTROP: + { + loc_wipe (&stub->args.xattrop.loc); + dict_unref (stub->args.xattrop.xattr); + break; + } + case GF_FOP_FXATTROP: + { + if (stub->args.fxattrop.fd) + fd_unref (stub->args.fxattrop.fd); + dict_unref (stub->args.xattrop.xattr); + break; + } + case GF_FOP_MAXVALUE: + { + gf_log ("call-stub", + GF_LOG_DEBUG, + "Invalid value of FOP"); + } + break; + default: + break; + } +} + + +static void +call_stub_destroy_unwind (call_stub_t *stub) +{ + switch (stub->fop) { + case GF_FOP_OPEN: + { + if (stub->args.open_cbk.fd) + fd_unref (stub->args.open_cbk.fd); + } + break; + + case GF_FOP_CREATE: + { + if (stub->args.create_cbk.fd) + fd_unref (stub->args.create_cbk.fd); + + if (stub->args.create_cbk.inode) + inode_unref (stub->args.create_cbk.inode); + } + break; + + case GF_FOP_STAT: + break; + + case GF_FOP_READLINK: + { + if (stub->args.readlink_cbk.buf) + FREE (stub->args.readlink_cbk.buf); + } + break; + + case GF_FOP_MKNOD: + { + if (stub->args.mknod_cbk.inode) + inode_unref (stub->args.mknod_cbk.inode); + } + break; + + case GF_FOP_MKDIR: + { + if (stub->args.mkdir_cbk.inode) + inode_unref (stub->args.mkdir_cbk.inode); + } + break; + + case GF_FOP_UNLINK: + break; + + case GF_FOP_RMDIR: + break; + + case GF_FOP_SYMLINK: + { + if (stub->args.symlink_cbk.inode) + inode_unref (stub->args.symlink_cbk.inode); + } + break; + + case GF_FOP_RENAME: + break; + + case GF_FOP_LINK: + { + if (stub->args.link_cbk.inode) + inode_unref (stub->args.link_cbk.inode); + } + break; + + case GF_FOP_CHMOD: + break; + + case GF_FOP_CHOWN: + break; + + case GF_FOP_TRUNCATE: + break; + + case GF_FOP_READ: + { + if (stub->args.readv_cbk.op_ret >= 0) { + dict_t *refs = stub->args.readv_cbk.rsp_refs; + FREE (stub->args.readv_cbk.vector); + + if (refs) { + dict_unref (refs); + } + } + } + break; + + case GF_FOP_WRITE: + break; + + case GF_FOP_STATFS: + break; + + case GF_FOP_FLUSH: + break; + + case GF_FOP_FSYNC: + break; + + case GF_FOP_SETXATTR: + break; + + case GF_FOP_GETXATTR: + { + if (stub->args.getxattr_cbk.dict) + dict_unref (stub->args.getxattr_cbk.dict); + } + break; + + case GF_FOP_REMOVEXATTR: + break; + + case GF_FOP_OPENDIR: + { + if (stub->args.opendir_cbk.fd) + fd_unref (stub->args.opendir_cbk.fd); + } + break; + + case GF_FOP_GETDENTS: + { + dir_entry_t *tmp = NULL, *entries = NULL; + + entries = &stub->args.getdents_cbk.entries; + if (stub->args.getdents_cbk.op_ret >= 0) { + while (entries->next) { + tmp = entries->next; + entries->next = entries->next->next; + FREE (tmp->name); + FREE (tmp); + } + } + } + break; + + case GF_FOP_FSYNCDIR: + break; + + case GF_FOP_ACCESS: + break; + + case GF_FOP_FTRUNCATE: + break; + + case GF_FOP_FSTAT: + break; + + case GF_FOP_LK: + break; + + case GF_FOP_INODELK: + break; + + case GF_FOP_FINODELK: + break; + + case GF_FOP_ENTRYLK: + break; + + case GF_FOP_FENTRYLK: + break; + + case GF_FOP_UTIMENS: + break; + + case GF_FOP_FCHMOD: + break; + + case GF_FOP_FCHOWN: + break; + + case GF_FOP_LOOKUP: + { + if (stub->args.lookup_cbk.inode) + inode_unref (stub->args.lookup_cbk.inode); + + if (stub->args.lookup_cbk.dict) + dict_unref (stub->args.lookup_cbk.dict); + } + break; + + case GF_FOP_SETDENTS: + break; + + case GF_FOP_CHECKSUM: + { + if (stub->args.checksum_cbk.op_ret >= 0) { + FREE (stub->args.checksum_cbk.file_checksum); + FREE (stub->args.checksum_cbk.dir_checksum); + } + } + break; + + case GF_FOP_READDIR: + { + if (stub->args.readdir_cbk.op_ret > 0) { + gf_dirent_free (&stub->args.readdir_cbk.entries); + } + } + break; + + case GF_FOP_XATTROP: + { + if (stub->args.xattrop_cbk.xattr) + dict_unref (stub->args.xattrop_cbk.xattr); + } + break; + + case GF_FOP_FXATTROP: + { + if (stub->args.fxattrop_cbk.xattr) + dict_unref (stub->args.fxattrop_cbk.xattr); + } + break; + + case GF_FOP_MAXVALUE: + { + gf_log ("call-stub", + GF_LOG_DEBUG, + "Invalid value of FOP"); + } + break; + + default: + break; + } +} + + +void +call_stub_destroy (call_stub_t *stub) +{ + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + if (stub->wind) { + call_stub_destroy_wind (stub); + } else { + call_stub_destroy_unwind (stub); + } + + FREE (stub); +out: + return; +} + +void +call_resume (call_stub_t *stub) +{ + errno = EINVAL; + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + list_del_init (&stub->list); + + if (stub->wind) + call_resume_wind (stub); + else + call_resume_unwind (stub); + + call_stub_destroy (stub); +out: + return; +} + + diff --git a/libglusterfs/src/call-stub.h b/libglusterfs/src/call-stub.h new file mode 100644 index 000000000..12e94a158 --- /dev/null +++ b/libglusterfs/src/call-stub.h @@ -0,0 +1,1104 @@ +/* + Copyright (c) 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CALL_STUB_H_ +#define _CALL_STUB_H_ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "xlator.h" +#include "stack.h" +#include "list.h" + +typedef struct { + struct list_head list; + char wind; + call_frame_t *frame; + glusterfs_fop_t fop; + + union { + /* lookup */ + struct { + fop_lookup_t fn; + loc_t loc; + dict_t *xattr_req; + } lookup; + struct { + fop_lookup_cbk_t fn; + int32_t op_ret, op_errno; + inode_t *inode; + struct stat buf; + dict_t *dict; + } lookup_cbk; + + /* stat */ + struct { + fop_stat_t fn; + loc_t loc; + } stat; + struct { + fop_stat_cbk_t fn; + int32_t op_ret, op_errno; + struct stat buf; + } stat_cbk; + + /* fstat */ + struct { + fop_fstat_t fn; + fd_t *fd; + } fstat; + struct { + fop_fstat_cbk_t fn; + int32_t op_ret, op_errno; + struct stat buf; + } fstat_cbk; + + /* chmod */ + struct { + fop_chmod_t fn; + loc_t loc; + mode_t mode; + } chmod; + struct { + fop_chmod_cbk_t fn; + int32_t op_ret, op_errno; + struct stat buf; + } chmod_cbk; + + /* fchmod */ + struct { + fop_fchmod_t fn; + fd_t *fd; + mode_t mode; + } fchmod; + struct { + fop_fchmod_cbk_t fn; + int32_t op_ret, op_errno; + struct stat buf; + } fchmod_cbk; + + /* chown */ + struct { + fop_chown_t fn; + loc_t loc; + uid_t uid; + gid_t gid; + } chown; + struct { + fop_chown_cbk_t fn; + int32_t op_ret, op_errno; + struct stat buf; + } chown_cbk; + + /* fchown */ + struct { + fop_fchown_t fn; + fd_t *fd; + uid_t uid; + gid_t gid; + } fchown; + struct { + fop_fchown_cbk_t fn; + int32_t op_ret, op_errno; + struct stat buf; + } fchown_cbk; + + /* truncate */ + struct { + fop_truncate_t fn; + loc_t loc; + off_t off; + } truncate; + struct { + fop_truncate_cbk_t fn; + int32_t op_ret, op_errno; + struct stat buf; + } truncate_cbk; + + /* ftruncate */ + struct { + fop_ftruncate_t fn; + fd_t *fd; + off_t off; + } ftruncate; + struct { + fop_ftruncate_cbk_t fn; + int32_t op_ret, op_errno; + struct stat buf; + } ftruncate_cbk; + + /* utimens */ + struct { + fop_utimens_t fn; + loc_t loc; + struct timespec tv[2]; + } utimens; + struct { + fop_utimens_cbk_t fn; + int32_t op_ret, op_errno; + struct stat buf; + } utimens_cbk; + + /* access */ + struct { + fop_access_t fn; + loc_t loc; + int32_t mask; + } access; + struct { + fop_access_cbk_t fn; + int32_t op_ret, op_errno; + } access_cbk; + + /* readlink */ + struct { + fop_readlink_t fn; + loc_t loc; + size_t size; + } readlink; + struct { + fop_readlink_cbk_t fn; + int32_t op_ret, op_errno; + const char *buf; + } readlink_cbk; + + /* mknod */ + struct { + fop_mknod_t fn; + loc_t loc; + mode_t mode; + dev_t rdev; + } mknod; + struct { + fop_mknod_cbk_t fn; + int32_t op_ret, op_errno; + inode_t *inode; + struct stat buf; + } mknod_cbk; + + /* mkdir */ + struct { + fop_mkdir_t fn; + loc_t loc; + mode_t mode; + } mkdir; + struct { + fop_mkdir_cbk_t fn; + int32_t op_ret, op_errno; + inode_t *inode; + struct stat buf; + } mkdir_cbk; + + /* unlink */ + struct { + fop_unlink_t fn; + loc_t loc; + } unlink; + struct { + fop_unlink_cbk_t fn; + int32_t op_ret, op_errno; + } unlink_cbk; + + /* rmdir */ + struct { + fop_rmdir_t fn; + loc_t loc; + } rmdir; + struct { + fop_rmdir_cbk_t fn; + int32_t op_ret, op_errno; + } rmdir_cbk; + + /* symlink */ + struct { + fop_symlink_t fn; + const char *linkname; + loc_t loc; + } symlink; + struct { + fop_symlink_cbk_t fn; + int32_t op_ret, op_errno; + inode_t *inode; + struct stat buf; + } symlink_cbk; + + /* rename */ + struct { + fop_rename_t fn; + loc_t old; + loc_t new; + } rename; + struct { + fop_rename_cbk_t fn; + int32_t op_ret, op_errno; + struct stat buf; + } rename_cbk; + + /* link */ + struct { + fop_link_t fn; + loc_t oldloc; + loc_t newloc; + } link; + struct { + fop_link_cbk_t fn; + int32_t op_ret, op_errno; + inode_t *inode; + struct stat buf; + } link_cbk; + + /* create */ + struct { + fop_create_t fn; + loc_t loc; + int32_t flags; + mode_t mode; + fd_t *fd; + } create; + struct { + fop_create_cbk_t fn; + int32_t op_ret, op_errno; + fd_t *fd; + inode_t *inode; + struct stat buf; + } create_cbk; + + /* open */ + struct { + fop_open_t fn; + loc_t loc; + int32_t flags; + fd_t *fd; + } open; + struct { + fop_open_cbk_t fn; + int32_t op_ret, op_errno; + fd_t *fd; + } open_cbk; + + /* readv */ + struct { + fop_readv_t fn; + fd_t *fd; + size_t size; + off_t off; + } readv; + struct { + fop_readv_cbk_t fn; + int32_t op_ret; + int32_t op_errno; + struct iovec *vector; + int32_t count; + struct stat stbuf; + dict_t *rsp_refs; + } readv_cbk; + + /* writev */ + struct { + fop_writev_t fn; + fd_t *fd; + struct iovec *vector; + int32_t count; + off_t off; + dict_t *req_refs; + } writev; + struct { + fop_writev_cbk_t fn; + int32_t op_ret, op_errno; + struct stat stbuf; + } writev_cbk; + + /* flush */ + struct { + fop_flush_t fn; + fd_t *fd; + } flush; + struct { + fop_flush_cbk_t fn; + int32_t op_ret, op_errno; + } flush_cbk; + + /* fsync */ + struct { + fop_fsync_t fn; + fd_t *fd; + int32_t datasync; + } fsync; + struct { + fop_fsync_cbk_t fn; + int32_t op_ret, op_errno; + } fsync_cbk; + + /* opendir */ + struct { + fop_opendir_t fn; + loc_t loc; + fd_t *fd; + } opendir; + struct { + fop_opendir_cbk_t fn; + int32_t op_ret, op_errno; + fd_t *fd; + } opendir_cbk; + + /* getdents */ + struct { + fop_getdents_t fn; + fd_t *fd; + size_t size; + off_t off; + int32_t flag; + } getdents; + struct { + fop_getdents_cbk_t fn; + int32_t op_ret; + int32_t op_errno; + dir_entry_t entries; + int32_t count; + } getdents_cbk; + + /* setdents */ + struct { + fop_setdents_t fn; + fd_t *fd; + int32_t flags; + dir_entry_t entries; + int32_t count; + } setdents; + struct { + fop_setdents_cbk_t fn; + int32_t op_ret; + int32_t op_errno; + } setdents_cbk; + + /* fsyncdir */ + struct { + fop_fsyncdir_t fn; + fd_t *fd; + int32_t datasync; + } fsyncdir; + struct { + fop_fsyncdir_cbk_t fn; + int32_t op_ret, op_errno; + } fsyncdir_cbk; + + /* statfs */ + struct { + fop_statfs_t fn; + loc_t loc; + } statfs; + struct { + fop_statfs_cbk_t fn; + int32_t op_ret, op_errno; + struct statvfs buf; + } statfs_cbk; + + /* setxattr */ + struct { + fop_setxattr_t fn; + loc_t loc; + dict_t *dict; + int32_t flags; + } setxattr; + struct { + fop_setxattr_cbk_t fn; + int32_t op_ret, op_errno; + } setxattr_cbk; + + /* getxattr */ + struct { + fop_getxattr_t fn; + loc_t loc; + const char *name; + } getxattr; + struct { + fop_getxattr_cbk_t fn; + int32_t op_ret, op_errno; + dict_t *dict; + } getxattr_cbk; + + /* removexattr */ + struct { + fop_removexattr_t fn; + loc_t loc; + const char *name; + } removexattr; + struct { + fop_removexattr_cbk_t fn; + int32_t op_ret, op_errno; + } removexattr_cbk; + + /* lk */ + struct { + fop_lk_t fn; + fd_t *fd; + int32_t cmd; + struct flock lock; + } lk; + struct { + fop_lk_cbk_t fn; + int32_t op_ret, op_errno; + struct flock lock; + } lk_cbk; + + /* inodelk */ + struct { + fop_inodelk_t fn; + loc_t loc; + int32_t cmd; + struct flock lock; + } inodelk; + + struct { + fop_inodelk_cbk_t fn; + int32_t op_ret, op_errno; + } inodelk_cbk; + + /* finodelk */ + struct { + fop_finodelk_t fn; + fd_t *fd; + int32_t cmd; + struct flock lock; + } finodelk; + + struct { + fop_finodelk_cbk_t fn; + int32_t op_ret, op_errno; + } finodelk_cbk; + + /* entrylk */ + struct { + fop_entrylk_t fn; + loc_t loc; + const char *name; + entrylk_cmd cmd; + entrylk_type type; + } entrylk; + + struct { + fop_entrylk_cbk_t fn; + int32_t op_ret, op_errno; + } entrylk_cbk; + + /* fentrylk */ + struct { + fop_fentrylk_t fn; + fd_t *fd; + const char *name; + entrylk_cmd cmd; + entrylk_type type; + } fentrylk; + + struct { + fop_fentrylk_cbk_t fn; + int32_t op_ret, op_errno; + } fentrylk_cbk; + + /* readdir */ + struct { + fop_readdir_t fn; + fd_t *fd; + size_t size; + off_t off; + } readdir; + struct { + fop_readdir_cbk_t fn; + int32_t op_ret, op_errno; + gf_dirent_t entries; + } readdir_cbk; + + /* checksum */ + struct { + fop_checksum_t fn; + loc_t loc; + int32_t flags; + } checksum; + struct { + fop_checksum_cbk_t fn; + int32_t op_ret, op_errno; + uint8_t *file_checksum; + uint8_t *dir_checksum; + } checksum_cbk; + + /* xattrop */ + struct { + fop_xattrop_t fn; + loc_t loc; + gf_xattrop_flags_t optype; + dict_t *xattr; + } xattrop; + struct { + fop_xattrop_cbk_t fn; + int32_t op_ret; + int32_t op_errno; + dict_t *xattr; + } xattrop_cbk; + + /* fxattrop */ + struct { + fop_fxattrop_t fn; + fd_t *fd; + gf_xattrop_flags_t optype; + dict_t *xattr; + } fxattrop; + struct { + fop_fxattrop_cbk_t fn; + int32_t op_ret; + int32_t op_errno; + dict_t *xattr; + } fxattrop_cbk; + } args; +} call_stub_t; + +call_stub_t * +fop_lookup_stub (call_frame_t *frame, + fop_lookup_t fn, + loc_t *loc, + dict_t *xattr_req); + +call_stub_t * +fop_lookup_cbk_stub (call_frame_t *frame, + fop_lookup_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf, + dict_t *dict); +call_stub_t * +fop_stat_stub (call_frame_t *frame, + fop_stat_t fn, + loc_t *loc); +call_stub_t * +fop_stat_cbk_stub (call_frame_t *frame, + fop_stat_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); +call_stub_t * +fop_fstat_stub (call_frame_t *frame, + fop_fstat_t fn, + fd_t *fd); +call_stub_t * +fop_fstat_cbk_stub (call_frame_t *frame, + fop_fstat_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); +call_stub_t * +fop_chmod_stub (call_frame_t *frame, + fop_chmod_t fn, + loc_t *loc, + mode_t mode); +call_stub_t * +fop_chmod_cbk_stub (call_frame_t *frame, + fop_chmod_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); +call_stub_t * +fop_fchmod_stub (call_frame_t *frame, + fop_fchmod_t fn, + fd_t *fd, + mode_t mode); +call_stub_t * +fop_fchmod_cbk_stub (call_frame_t *frame, + fop_fchmod_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); +call_stub_t * +fop_chown_stub (call_frame_t *frame, + fop_chown_t fn, + loc_t *loc, + uid_t uid, + gid_t gid); + +call_stub_t * +fop_chown_cbk_stub (call_frame_t *frame, + fop_chown_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); + +call_stub_t * +fop_fchown_stub (call_frame_t *frame, + fop_fchown_t fn, + fd_t *fd, + uid_t uid, + gid_t gid); + +call_stub_t * +fop_fchown_cbk_stub (call_frame_t *frame, + fop_fchown_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); + +call_stub_t * +fop_truncate_stub (call_frame_t *frame, + fop_truncate_t fn, + loc_t *loc, + off_t off); + +call_stub_t * +fop_truncate_cbk_stub (call_frame_t *frame, + fop_truncate_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); + +call_stub_t * +fop_ftruncate_stub (call_frame_t *frame, + fop_ftruncate_t fn, + fd_t *fd, + off_t off); + +call_stub_t * +fop_ftruncate_cbk_stub (call_frame_t *frame, + fop_ftruncate_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); + +call_stub_t * +fop_utimens_stub (call_frame_t *frame, + fop_utimens_t fn, + loc_t *loc, + struct timespec tv[2]); + +call_stub_t * +fop_utimens_cbk_stub (call_frame_t *frame, + fop_utimens_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); + +call_stub_t * +fop_access_stub (call_frame_t *frame, + fop_access_t fn, + loc_t *loc, + int32_t mask); + +call_stub_t * +fop_access_cbk_stub (call_frame_t *frame, + fop_access_cbk_t fn, + int32_t op_ret, + int32_t op_errno); + +call_stub_t * +fop_readlink_stub (call_frame_t *frame, + fop_readlink_t fn, + loc_t *loc, + size_t size); + +call_stub_t * +fop_readlink_cbk_stub (call_frame_t *frame, + fop_readlink_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + const char *path); + +call_stub_t * +fop_mknod_stub (call_frame_t *frame, + fop_mknod_t fn, + loc_t *loc, + mode_t mode, + dev_t rdev); + +call_stub_t * +fop_mknod_cbk_stub (call_frame_t *frame, + fop_mknod_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf); + +call_stub_t * +fop_mkdir_stub (call_frame_t *frame, + fop_mkdir_t fn, + loc_t *loc, + mode_t mode); + +call_stub_t * +fop_mkdir_cbk_stub (call_frame_t *frame, + fop_mkdir_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf); + +call_stub_t * +fop_unlink_stub (call_frame_t *frame, + fop_unlink_t fn, + loc_t *loc); + +call_stub_t * +fop_unlink_cbk_stub (call_frame_t *frame, + fop_unlink_cbk_t fn, + int32_t op_ret, + int32_t op_errno); + +call_stub_t * +fop_rmdir_stub (call_frame_t *frame, + fop_rmdir_t fn, + loc_t *loc); + +call_stub_t * +fop_rmdir_cbk_stub (call_frame_t *frame, + fop_rmdir_cbk_t fn, + int32_t op_ret, + int32_t op_errno); + +call_stub_t * +fop_symlink_stub (call_frame_t *frame, + fop_symlink_t fn, + const char *linkname, + loc_t *loc); + +call_stub_t * +fop_symlink_cbk_stub (call_frame_t *frame, + fop_symlink_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf); + +call_stub_t * +fop_rename_stub (call_frame_t *frame, + fop_rename_t fn, + loc_t *oldloc, + loc_t *newloc); + +call_stub_t * +fop_rename_cbk_stub (call_frame_t *frame, + fop_rename_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); + +call_stub_t * +fop_link_stub (call_frame_t *frame, + fop_link_t fn, + loc_t *oldloc, + loc_t *newloc); + +call_stub_t * +fop_link_cbk_stub (call_frame_t *frame, + fop_link_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf); + +call_stub_t * +fop_create_stub (call_frame_t *frame, + fop_create_t fn, + loc_t *loc, + int32_t flags, + mode_t mode, fd_t *fd); + +call_stub_t * +fop_create_cbk_stub (call_frame_t *frame, + fop_create_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + fd_t *fd, + inode_t *inode, + struct stat *buf); + +call_stub_t * +fop_open_stub (call_frame_t *frame, + fop_open_t fn, + loc_t *loc, + int32_t flags, + fd_t *fd); + +call_stub_t * +fop_open_cbk_stub (call_frame_t *frame, + fop_open_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + fd_t *fd); + +call_stub_t * +fop_readv_stub (call_frame_t *frame, + fop_readv_t fn, + fd_t *fd, + size_t size, + off_t off); + +call_stub_t * +fop_readv_cbk_stub (call_frame_t *frame, + fop_readv_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct iovec *vector, + int32_t count, + struct stat *stbuf); + +call_stub_t * +fop_writev_stub (call_frame_t *frame, + fop_writev_t fn, + fd_t *fd, + struct iovec *vector, + int32_t count, + off_t off); + +call_stub_t * +fop_writev_cbk_stub (call_frame_t *frame, + fop_writev_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct stat *stbuf); + +call_stub_t * +fop_flush_stub (call_frame_t *frame, + fop_flush_t fn, + fd_t *fd); + +call_stub_t * +fop_flush_cbk_stub (call_frame_t *frame, + fop_flush_cbk_t fn, + int32_t op_ret, + int32_t op_errno); + +call_stub_t * +fop_fsync_stub (call_frame_t *frame, + fop_fsync_t fn, + fd_t *fd, + int32_t datasync); + +call_stub_t * +fop_fsync_cbk_stub (call_frame_t *frame, + fop_fsync_cbk_t fn, + int32_t op_ret, + int32_t op_errno); + +call_stub_t * +fop_opendir_stub (call_frame_t *frame, + fop_opendir_t fn, + loc_t *loc, fd_t *fd); + +call_stub_t * +fop_opendir_cbk_stub (call_frame_t *frame, + fop_opendir_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + fd_t *fd); + +call_stub_t * +fop_getdents_stub (call_frame_t *frame, + fop_getdents_t fn, + fd_t *fd, + size_t size, + off_t off, + int32_t flag); + +call_stub_t * +fop_getdents_cbk_stub (call_frame_t *frame, + fop_getdents_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + dir_entry_t *entries, + int32_t count); + +call_stub_t * +fop_setdents_stub (call_frame_t *frame, + fop_setdents_t fn, + fd_t *fd, + int32_t flags, + dir_entry_t *entries, + int32_t count); + +call_stub_t * +fop_setdents_cbk_stub (call_frame_t *frame, + fop_setdents_cbk_t fn, + int32_t op_ret, + int32_t op_errno); + +call_stub_t * +fop_fsyncdir_stub (call_frame_t *frame, + fop_fsyncdir_t fn, + fd_t *fd, + int32_t datasync); + +call_stub_t * +fop_fsyncdir_cbk_stub (call_frame_t *frame, + fop_fsyncdir_cbk_t fn, + int32_t op_ret, + int32_t op_errno); + +call_stub_t * +fop_statfs_stub (call_frame_t *frame, + fop_statfs_t fn, + loc_t *loc); + +call_stub_t * +fop_statfs_cbk_stub (call_frame_t *frame, + fop_statfs_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct statvfs *buf); + +call_stub_t * +fop_setxattr_stub (call_frame_t *frame, + fop_setxattr_t fn, + loc_t *loc, + dict_t *dict, + int32_t flags); + +call_stub_t * +fop_setxattr_cbk_stub (call_frame_t *frame, + fop_setxattr_cbk_t fn, + int32_t op_ret, + int32_t op_errno); + +call_stub_t * +fop_getxattr_stub (call_frame_t *frame, + fop_getxattr_t fn, + loc_t *loc, + const char *name); + +call_stub_t * +fop_getxattr_cbk_stub (call_frame_t *frame, + fop_getxattr_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + dict_t *value); + +call_stub_t * +fop_removexattr_stub (call_frame_t *frame, + fop_removexattr_t fn, + loc_t *loc, + const char *name); + +call_stub_t * +fop_removexattr_cbk_stub (call_frame_t *frame, + fop_removexattr_cbk_t fn, + int32_t op_ret, + int32_t op_errno); +call_stub_t * +fop_lk_stub (call_frame_t *frame, + fop_lk_t fn, + fd_t *fd, + int32_t cmd, + struct flock *lock); + +call_stub_t * +fop_lk_cbk_stub (call_frame_t *frame, + fop_lk_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + struct flock *lock); + +call_stub_t * +fop_inodelk_stub (call_frame_t *frame, fop_inodelk_t fn, + loc_t *loc, int32_t cmd, struct flock *lock); + +call_stub_t * +fop_finodelk_stub (call_frame_t *frame, fop_finodelk_t fn, + fd_t *fd, int32_t cmd, struct flock *lock); + +call_stub_t * +fop_entrylk_stub (call_frame_t *frame, fop_entrylk_t fn, + loc_t *loc, const char *basename, + entrylk_cmd cmd, entrylk_type type); + +call_stub_t * +fop_fentrylk_stub (call_frame_t *frame, fop_fentrylk_t fn, + fd_t *fd, const char *basename, + entrylk_cmd cmd, entrylk_type type); + +call_stub_t * +fop_inodelk_cbk_stub (call_frame_t *frame, fop_inodelk_cbk_t fn, + int32_t op_ret, int32_t op_errno); + +call_stub_t * +fop_finodelk_cbk_stub (call_frame_t *frame, fop_inodelk_cbk_t fn, + int32_t op_ret, int32_t op_errno); + +call_stub_t * +fop_entrylk_cbk_stub (call_frame_t *frame, fop_entrylk_cbk_t fn, + int32_t op_ret, int32_t op_errno); + +call_stub_t * +fop_fentrylk_cbk_stub (call_frame_t *frame, fop_entrylk_cbk_t fn, + int32_t op_ret, int32_t op_errno); + +call_stub_t * +fop_readdir_stub (call_frame_t *frame, + fop_readdir_t fn, + fd_t *fd, + size_t size, + off_t off); + +call_stub_t * +fop_readdir_cbk_stub (call_frame_t *frame, + fop_readdir_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + gf_dirent_t *entries); + +call_stub_t * +fop_checksum_stub (call_frame_t *frame, + fop_checksum_t fn, + loc_t *loc, + int32_t flags); + +call_stub_t * +fop_checksum_cbk_stub (call_frame_t *frame, + fop_checksum_cbk_t fn, + int32_t op_ret, + int32_t op_errno, + uint8_t *file_checksum, + uint8_t *dir_checksum); + +call_stub_t * +fop_xattrop_stub (call_frame_t *frame, + fop_xattrop_t fn, + loc_t *loc, + gf_xattrop_flags_t optype, + dict_t *xattr); + +call_stub_t * +fop_xattrop_stub_cbk_stub (call_frame_t *frame, + fop_xattrop_cbk_t fn, + int32_t op_ret, + int32_t op_errno); + +call_stub_t * +fop_fxattrop_stub (call_frame_t *frame, + fop_fxattrop_t fn, + fd_t *fd, + gf_xattrop_flags_t optype, + dict_t *xattr); + +call_stub_t * +fop_fxattrop_stub_cbk_stub (call_frame_t *frame, + fop_xattrop_cbk_t fn, + int32_t op_ret, + int32_t op_errno); + +void call_resume (call_stub_t *stub); +void call_stub_destroy (call_stub_t *stub); +#endif diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c new file mode 100644 index 000000000..616c7a8ce --- /dev/null +++ b/libglusterfs/src/common-utils.c @@ -0,0 +1,1349 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_BACKTRACE +#include <execinfo.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <unistd.h> +#include <time.h> +#include <locale.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <signal.h> + +#include "logging.h" +#include "common-utils.h" +#include "revision.h" +#include "glusterfs.h" +#include "stack.h" + +typedef int32_t (*rw_op_t)(int32_t fd, char *buf, int32_t size); +typedef int32_t (*rwv_op_t)(int32_t fd, const struct iovec *buf, int32_t size); +static glusterfs_ctx_t *gf_global_ctx; + + +struct dnscache6 { + struct addrinfo *first; + struct addrinfo *next; +}; + +int32_t +gf_resolve_ip6 (const char *hostname, + uint16_t port, + int family, + void **dnscache, + struct addrinfo **addr_info) +{ + int32_t ret = 0; + struct addrinfo hints; + struct dnscache6 *cache = NULL; + char service[NI_MAXSERV], host[NI_MAXHOST]; + + if (!hostname) { + gf_log ("resolver", GF_LOG_WARNING, "hostname is NULL"); + return -1; + } + + if (!*dnscache) { + *dnscache = CALLOC (1, sizeof (struct dnscache6)); + } + + cache = *dnscache; + if (cache->first && !cache->next) { + freeaddrinfo(cache->first); + cache->first = cache->next = NULL; + gf_log ("resolver", GF_LOG_DEBUG, + "flushing DNS cache"); + } + + if (!cache->first) { + char *port_str = NULL; + gf_log ("resolver", GF_LOG_DEBUG, + "DNS cache not present, freshly probing hostname: %s", + hostname); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_ADDRCONFIG; + + asprintf (&port_str, "%d", port); + if ((ret = getaddrinfo(hostname, port_str, &hints, &cache->first)) != 0) { + gf_log ("resolver", GF_LOG_ERROR, + "getaddrinfo failed (%s)", gai_strerror (ret)); + + free (*dnscache); + *dnscache = NULL; + free (port_str); + return -1; + } + free (port_str); + + cache->next = cache->first; + } + + if (cache->next) { + ret = getnameinfo((struct sockaddr *)cache->next->ai_addr, + cache->next->ai_addrlen, + host, sizeof (host), + service, sizeof (service), + NI_NUMERICHOST); + if (ret != 0) { + gf_log ("resolver", + GF_LOG_ERROR, + "getnameinfo failed (%s)", gai_strerror (ret)); + goto err; + } + + gf_log ("resolver", GF_LOG_DEBUG, + "returning ip-%s (port-%s) for hostname: %s and port: %d", + host, service, hostname, port); + + *addr_info = cache->next; + } + + cache->next = cache->next->ai_next; + if (cache->next) { + ret = getnameinfo((struct sockaddr *)cache->next->ai_addr, + cache->next->ai_addrlen, + host, sizeof (host), + service, sizeof (service), + NI_NUMERICHOST); + if (ret != 0) { + gf_log ("resolver", + GF_LOG_ERROR, + "getnameinfo failed (%s)", gai_strerror (ret)); + goto err; + } + + gf_log ("resolver", GF_LOG_DEBUG, + "next DNS query will return: ip-%s port-%s", host, service); + } + + return 0; + +err: + freeaddrinfo (cache->first); + cache->first = cache->next = NULL; + free (cache); + *dnscache = NULL; + return -1; +} + +char *gf_fop_list[GF_FOP_MAXVALUE]; +char *gf_mop_list[GF_MOP_MAXVALUE]; +char *gf_cbk_list[GF_CBK_MAXVALUE]; + +void +gf_global_variable_init() +{ + gf_fop_list[GF_FOP_STAT] = "STAT"; /* 0 */ + gf_fop_list[GF_FOP_READLINK] = "READLINK"; /* 1 */ + gf_fop_list[GF_FOP_MKNOD] = "MKNOD"; /* 2 */ + gf_fop_list[GF_FOP_MKDIR] = "MKDIR"; + gf_fop_list[GF_FOP_UNLINK] = "UNLINK"; + gf_fop_list[GF_FOP_RMDIR] = "RMDIR"; /* 5 */ + gf_fop_list[GF_FOP_SYMLINK] = "SYMLINK"; + gf_fop_list[GF_FOP_RENAME] = "RENAME"; + gf_fop_list[GF_FOP_LINK] = "LINK"; + gf_fop_list[GF_FOP_CHMOD] = "CHMOD"; + gf_fop_list[GF_FOP_CHOWN] = "CHOWN"; /* 10 */ + gf_fop_list[GF_FOP_TRUNCATE] = "TRUNCATE"; + gf_fop_list[GF_FOP_OPEN] = "OPEN"; + gf_fop_list[GF_FOP_READ] = "READ"; + gf_fop_list[GF_FOP_WRITE] = "WRITE"; + gf_fop_list[GF_FOP_STATFS] = "STATFS"; /* 15 */ + gf_fop_list[GF_FOP_FLUSH] = "FLUSH"; + gf_fop_list[GF_FOP_FSYNC] = "FSYNC"; + gf_fop_list[GF_FOP_SETXATTR] = "SETXATTR"; + gf_fop_list[GF_FOP_GETXATTR] = "GETXATTR"; /* 20 */ + gf_fop_list[GF_FOP_REMOVEXATTR] = "REMOVEXATTR"; + gf_fop_list[GF_FOP_OPENDIR] = "OPENDIR"; + gf_fop_list[GF_FOP_GETDENTS] = "GETDENTS"; + gf_fop_list[GF_FOP_FSYNCDIR] = "FSYNCDIR"; /* 25 */ + gf_fop_list[GF_FOP_ACCESS] = "ACCESS"; + gf_fop_list[GF_FOP_CREATE] = "CREATE"; + gf_fop_list[GF_FOP_FTRUNCATE] = "FTRUNCATE"; + gf_fop_list[GF_FOP_FSTAT] = "FSTAT"; + gf_fop_list[GF_FOP_LK] = "LK"; /* 30 */ + gf_fop_list[GF_FOP_UTIMENS] = "UTIMENS"; + gf_fop_list[GF_FOP_FCHMOD] = "FCHMOD"; + gf_fop_list[GF_FOP_FCHOWN] = "FCHOWN"; + gf_fop_list[GF_FOP_LOOKUP] = "LOOKUP"; + gf_fop_list[GF_FOP_SETDENTS] = "SETDENTS"; /* 35 */ + gf_fop_list[GF_FOP_READDIR] = "READDIR"; + gf_fop_list[GF_FOP_INODELK] = "INODELK"; + gf_fop_list[GF_FOP_FINODELK] = "FINODELK"; + gf_fop_list[GF_FOP_ENTRYLK] = "ENTRYLK"; + gf_fop_list[GF_FOP_FENTRYLK] = "FENTRYLK"; /* 40 */ + gf_fop_list[GF_FOP_CHECKSUM] = "CHECKSUM"; /* 41 */ + gf_fop_list[GF_FOP_XATTROP] = "XATTROP"; + + gf_mop_list[GF_MOP_SETVOLUME] = "SETVOLUME"; /* 0 */ + gf_mop_list[GF_MOP_GETVOLUME] = "GETVOLUME"; /* 1 */ + gf_mop_list[GF_MOP_STATS] = "STATS"; + gf_mop_list[GF_MOP_SETSPEC] = "SETSPEC"; + gf_mop_list[GF_MOP_GETSPEC] = "GETSPEC"; + + gf_cbk_list[GF_CBK_FORGET] = "FORGET"; + gf_cbk_list[GF_CBK_RELEASE] = "RELEASE"; + gf_cbk_list[GF_CBK_RELEASEDIR] = "RELEASEDIR"; + /* Are there any more variables to be included? All global + variables initialization should go here */ + + return; +} + +void +set_global_ctx_ptr (glusterfs_ctx_t *ctx) +{ + gf_global_ctx = ctx; +} + +glusterfs_ctx_t * +get_global_ctx_ptr (void) +{ + return gf_global_ctx; +} + +void +gf_log_volume_file (FILE *specfp) +{ + extern FILE *gf_log_logfile; + int lcount = 0; + char data[GF_UNIT_KB]; + + fseek (specfp, 0L, SEEK_SET); + + fprintf (gf_log_logfile, "Given volfile:\n"); + fprintf (gf_log_logfile, + "+---------------------------------------" + "---------------------------------------+\n"); + while (!feof (specfp)) { + if (fgets (data, GF_UNIT_KB, specfp) == NULL) + break; + lcount++; + fprintf (gf_log_logfile, "%3d: %s", lcount, data); + } + fprintf (gf_log_logfile, + "\n+---------------------------------------" + "---------------------------------------+\n"); + fflush (gf_log_logfile); + fseek (specfp, 0L, SEEK_SET); +} + +static void +gf_dump_config_flags (int fd) +{ + + write (fd, "configuration details:\n", 22); + +/* have argp */ +#ifdef HAVE_ARGP + write (fd, "argp 1\n", 7); +#endif + +/* ifdef if found backtrace */ +#ifdef HAVE_BACKTRACE + write (fd, "backtrace 1\n", 12); +#endif + +/* Berkeley-DB version has cursor->get() */ +#ifdef HAVE_BDB_CURSOR_GET + write (fd, "bdb->cursor->get 1\n", 19); +#endif + +/* Define to 1 if you have the <db.h> header file. */ +#ifdef HAVE_DB_H + write (fd, "db.h 1\n", 7); +#endif + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#ifdef HAVE_DLFCN_H + write (fd, "dlfcn 1\n", 8); +#endif + +/* define if fdatasync exists */ +#ifdef HAVE_FDATASYNC + write (fd, "fdatasync 1\n", 12); +#endif + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#ifdef HAVE_LIBPTHREAD + write (fd, "libpthread 1\n", 13); +#endif + +/* define if llistxattr exists */ +#ifdef HAVE_LLISTXATTR + write (fd, "llistxattr 1\n", 13); +#endif + +/* define if found setfsuid setfsgid */ +#ifdef HAVE_SET_FSID + write (fd, "setfsid 1\n", 10); +#endif + +/* define if found spinlock */ +#ifdef HAVE_SPINLOCK + write (fd, "spinlock 1\n", 11); +#endif + +/* Define to 1 if you have the <sys/epoll.h> header file. */ +#ifdef HAVE_SYS_EPOLL_H + write (fd, "epoll.h 1\n", 10); +#endif + +/* Define to 1 if you have the <sys/extattr.h> header file. */ +#ifdef HAVE_SYS_EXTATTR_H + write (fd, "extattr.h 1\n", 12); +#endif + +/* Define to 1 if you have the <sys/xattr.h> header file. */ +#ifdef HAVE_SYS_XATTR_H + write (fd, "xattr.h 1\n", 10); +#endif + +/* define if found st_atim.tv_nsec */ +#ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC + write (fd, "st_atim.tv_nsec 1\n", 18); +#endif + +/* define if found st_atimespec.tv_nsec */ +#ifdef HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC + write (fd, "st_atimespec.tv_nsec 1\n",23); +#endif + +/* Define to the full name and version of this package. */ +#ifdef PACKAGE_STRING + { + char msg[128]; + sprintf (msg, "package-string: %s\n", PACKAGE_STRING); + write (fd, msg, strlen (msg)); + } +#endif + + return; +} + +/* Obtain a backtrace and print it to stdout. */ +/* TODO: It looks like backtrace_symbols allocates memory, + it may be problem because mostly memory allocation/free causes 'sigsegv' */ +void +gf_print_trace (int32_t signum) +{ + extern FILE *gf_log_logfile; + int fd = fileno (gf_log_logfile); + char msg[1024]; + + + /* Pending frames, (if any), list them in order */ + write (fd, "pending frames:\n", 16); + { + extern glusterfs_ctx_t *gf_global_ctx; + glusterfs_ctx_t *ctx = gf_global_ctx; + struct list_head *trav = ((call_pool_t *)ctx->pool)->all_frames.next; + while (trav != (&((call_pool_t *)ctx->pool)->all_frames)) { + call_frame_t *tmp = (call_frame_t *)(&((call_stack_t *)trav)->frames); + if ((tmp->root->type == GF_OP_TYPE_FOP_REQUEST) || + (tmp->root->type == GF_OP_TYPE_FOP_REPLY)) + sprintf (msg,"frame : type(%d) op(%s)\n", + tmp->root->type, + gf_fop_list[tmp->root->op]); + if ((tmp->root->type == GF_OP_TYPE_MOP_REQUEST) || + (tmp->root->type == GF_OP_TYPE_MOP_REPLY)) + sprintf (msg,"frame : type(%d) op(%s)\n", + tmp->root->type, + gf_mop_list[tmp->root->op]); + if ((tmp->root->type == GF_OP_TYPE_CBK_REQUEST) || + (tmp->root->type == GF_OP_TYPE_CBK_REPLY)) + sprintf (msg,"frame : type(%d) op(%s)\n", + tmp->root->type, + gf_cbk_list[tmp->root->op]); + + write (fd, msg, strlen (msg)); + trav = trav->next; + } + write (fd, "\n", 1); + } + + sprintf (msg, "patchset: %s\n", GLUSTERFS_REPOSITORY_REVISION); + write (fd, msg, strlen (msg)); + + sprintf (msg, "signal received: %d\n", signum); + write (fd, msg, strlen (msg)); + + gf_dump_config_flags (fd); +#if HAVE_BACKTRACE + /* Print 'backtrace' */ + { + void *array[200]; + size_t size; + + size = backtrace (array, 200); + backtrace_symbols_fd (&array[1], size-1, fd); + sprintf (msg, "---------\n"); + write (fd, msg, strlen (msg)); + } +#endif /* HAVE_BACKTRACE */ + + /* Send a signal to terminate the process */ + signal (signum, SIG_DFL); + raise (signum); +} + +void +trap (void) +{ + +} + +char * +gf_trim (char *string) +{ + register char *s, *t; + + if (string == NULL) + { + return NULL; + } + + for (s = string; isspace (*s); s++) + ; + + if (*s == 0) + return s; + + t = s + strlen (s) - 1; + while (t > s && isspace (*t)) + t--; + *++t = '\0'; + + return s; +} + +int +gf_strsplit (const char *str, const char *delim, + char ***tokens, int *token_count) +{ + char *_running = NULL; + char *running = NULL; + char *token = NULL; + char **token_list = NULL; + int count = 0; + int i = 0; + int j = 0; + + if (str == NULL || delim == NULL || tokens == NULL || token_count == NULL) + { + return -1; + } + + if ((_running = strdup (str)) == NULL) + { + return -1; + } + running = _running; + + while ((token = strsep (&running, delim)) != NULL) + { + if (token[0] != '\0') + count++; + } + free (_running); + + if ((_running = strdup (str)) == NULL) + { + return -1; + } + running = _running; + + if ((token_list = CALLOC (count, sizeof (char *))) == NULL) + { + free (_running); + return -1; + } + + while ((token = strsep (&running, delim)) != NULL) + { + if (token[0] == '\0') + continue; + + if ((token_list[i++] = strdup (token)) == NULL) + goto free_exit; + } + + free (_running); + + *tokens = token_list; + *token_count = count; + return 0; + +free_exit: + free (_running); + for (j = 0; j < i; j++) + { + free (token_list[j]); + } + free (token_list); + return -1; +} + +int +gf_volume_name_validate (const char *volume_name) +{ + const char *vname = NULL; + + if (volume_name == NULL) + { + return -1; + } + + if (!isalpha (volume_name[0])) + { + return 1; + } + + for (vname = &volume_name[1]; *vname != '\0'; vname++) + { + if (!(isalnum (*vname) || *vname == '_')) + return 1; + } + + return 0; +} + + +int +gf_string2time (const char *str, uint32_t *n) +{ + unsigned long value = 0; + char *tail = NULL; + int old_errno = 0; + const char *s = NULL; + + if (str == NULL || n == NULL) + { + errno = EINVAL; + return -1; + } + + for (s = str; *s != '\0'; s++) + { + if (isspace (*s)) + { + continue; + } + if (*s == '-') + { + return -1; + } + break; + } + + old_errno = errno; + errno = 0; + value = strtol (str, &tail, 0); + + if (errno == ERANGE || errno == EINVAL) + { + return -1; + } + + if (errno == 0) + { + errno = old_errno; + } + + if (!((tail[0] == '\0') || + ((tail[0] == 's') && (tail[1] == '\0')) || + ((tail[0] == 's') && (tail[1] == 'e') && (tail[2] == 'c') && (tail[3] == '\0')))) + { + return -1; + } + + *n = value; + + return 0; +} + + +int +gf_string2percent (const char *str, uint32_t *n) +{ + unsigned long value = 0; + char *tail = NULL; + int old_errno = 0; + const char *s = NULL; + + if (str == NULL || n == NULL) + { + errno = EINVAL; + return -1; + } + + for (s = str; *s != '\0'; s++) + { + if (isspace (*s)) + { + continue; + } + if (*s == '-') + { + return -1; + } + break; + } + + old_errno = errno; + errno = 0; + value = strtol (str, &tail, 0); + + if (errno == ERANGE || errno == EINVAL) + { + return -1; + } + + if (errno == 0) + { + errno = old_errno; + } + + if (!((tail[0] == '\0') || + ((tail[0] == '%') && (tail[1] == '\0')))) + { + return -1; + } + + *n = value; + + return 0; +} + + +static int +_gf_string2long (const char *str, long *n, int base) +{ + long value = 0; + char *tail = NULL; + int old_errno = 0; + + if (str == NULL || n == NULL) + { + errno = EINVAL; + return -1; + } + + old_errno = errno; + errno = 0; + value = strtol (str, &tail, base); + + if (errno == ERANGE || errno == EINVAL) + { + return -1; + } + + if (errno == 0) + { + errno = old_errno; + } + + if (tail[0] != '\0') + { + /* bala: invalid integer format */ + return -1; + } + + *n = value; + + return 0; +} + +static int +_gf_string2ulong (const char *str, unsigned long *n, int base) +{ + unsigned long value = 0; + char *tail = NULL; + int old_errno = 0; + const char *s = NULL; + + if (str == NULL || n == NULL) + { + errno = EINVAL; + return -1; + } + + for (s = str; *s != '\0'; s++) + { + if (isspace (*s)) + { + continue; + } + if (*s == '-') + { + /* bala: we do not support suffixed (-) sign and + invalid integer format */ + return -1; + } + break; + } + + old_errno = errno; + errno = 0; + value = strtoul (str, &tail, base); + + if (errno == ERANGE || errno == EINVAL) + { + return -1; + } + + if (errno == 0) + { + errno = old_errno; + } + + if (tail[0] != '\0') + { + /* bala: invalid integer format */ + return -1; + } + + *n = value; + + return 0; +} + +static int +_gf_string2uint (const char *str, unsigned int *n, int base) +{ + unsigned long value = 0; + char *tail = NULL; + int old_errno = 0; + const char *s = NULL; + + if (str == NULL || n == NULL) + { + errno = EINVAL; + return -1; + } + + for (s = str; *s != '\0'; s++) + { + if (isspace (*s)) + { + continue; + } + if (*s == '-') + { + /* bala: we do not support suffixed (-) sign and + invalid integer format */ + return -1; + } + break; + } + + old_errno = errno; + errno = 0; + value = strtoul (str, &tail, base); + + if (errno == ERANGE || errno == EINVAL) + { + return -1; + } + + if (errno == 0) + { + errno = old_errno; + } + + if (tail[0] != '\0') + { + /* bala: invalid integer format */ + return -1; + } + + *n = (unsigned int)value; + + return 0; +} + +static int +_gf_string2longlong (const char *str, long long *n, int base) +{ + long long value = 0; + char *tail = NULL; + int old_errno = 0; + + if (str == NULL || n == NULL) + { + errno = EINVAL; + return -1; + } + + old_errno = errno; + errno = 0; + value = strtoll (str, &tail, base); + + if (errno == ERANGE || errno == EINVAL) + { + return -1; + } + + if (errno == 0) + { + errno = old_errno; + } + + if (tail[0] != '\0') + { + /* bala: invalid integer format */ + return -1; + } + + *n = value; + + return 0; +} + +static int +_gf_string2ulonglong (const char *str, unsigned long long *n, int base) +{ + unsigned long long value = 0; + char *tail = NULL; + int old_errno = 0; + const char *s = NULL; + + if (str == NULL || n == NULL) + { + errno = EINVAL; + return -1; + } + + for (s = str; *s != '\0'; s++) + { + if (isspace (*s)) + { + continue; + } + if (*s == '-') + { + /* bala: we do not support suffixed (-) sign and + invalid integer format */ + return -1; + } + break; + } + + old_errno = errno; + errno = 0; + value = strtoull (str, &tail, base); + + if (errno == ERANGE || errno == EINVAL) + { + return -1; + } + + if (errno == 0) + { + errno = old_errno; + } + + if (tail[0] != '\0') + { + /* bala: invalid integer format */ + return -1; + } + + *n = value; + + return 0; +} + +int +gf_string2long (const char *str, long *n) +{ + return _gf_string2long (str, n, 0); +} + +int +gf_string2ulong (const char *str, unsigned long *n) +{ + return _gf_string2ulong (str, n, 0); +} + +int +gf_string2int (const char *str, int *n) +{ + return _gf_string2long (str, (long *) n, 0); +} + +int +gf_string2uint (const char *str, unsigned int *n) +{ + return _gf_string2uint (str, n, 0); +} + +int +gf_string2longlong (const char *str, long long *n) +{ + return _gf_string2longlong (str, n, 0); +} + +int +gf_string2ulonglong (const char *str, unsigned long long *n) +{ + return _gf_string2ulonglong (str, n, 0); +} + +int +gf_string2int8 (const char *str, int8_t *n) +{ + long l = 0L; + int rv = 0; + + rv = _gf_string2long (str, &l, 0); + if (rv != 0) + return rv; + + if (l >= INT8_MIN && l <= INT8_MAX) + { + *n = (int8_t) l; + return 0; + } + + errno = ERANGE; + return -1; +} + +int +gf_string2int16 (const char *str, int16_t *n) +{ + long l = 0L; + int rv = 0; + + rv = _gf_string2long (str, &l, 0); + if (rv != 0) + return rv; + + if (l >= INT16_MIN && l <= INT16_MAX) + { + *n = (int16_t) l; + return 0; + } + + errno = ERANGE; + return -1; +} + +int +gf_string2int32 (const char *str, int32_t *n) +{ + long l = 0L; + int rv = 0; + + rv = _gf_string2long (str, &l, 0); + if (rv != 0) + return rv; + + if (l >= INT32_MIN && l <= INT32_MAX) + { + *n = (int32_t) l; + return 0; + } + + errno = ERANGE; + return -1; +} + +int +gf_string2int64 (const char *str, int64_t *n) +{ + long long l = 0LL; + int rv = 0; + + rv = _gf_string2longlong (str, &l, 0); + if (rv != 0) + return rv; + + if (l >= INT64_MIN && l <= INT64_MAX) + { + *n = (int64_t) l; + return 0; + } + + errno = ERANGE; + return -1; +} + +int +gf_string2uint8 (const char *str, uint8_t *n) +{ + unsigned long l = 0L; + int rv = 0; + + rv = _gf_string2ulong (str, &l, 0); + if (rv != 0) + return rv; + + if (l >= 0 && l <= UINT8_MAX) + { + *n = (uint8_t) l; + return 0; + } + + errno = ERANGE; + return -1; +} + +int +gf_string2uint16 (const char *str, uint16_t *n) +{ + unsigned long l = 0L; + int rv = 0; + + rv = _gf_string2ulong (str, &l, 0); + if (rv != 0) + return rv; + + if (l >= 0 && l <= UINT16_MAX) + { + *n = (uint16_t) l; + return 0; + } + + errno = ERANGE; + return -1; +} + +int +gf_string2uint32 (const char *str, uint32_t *n) +{ + unsigned long l = 0L; + int rv = 0; + + rv = _gf_string2ulong (str, &l, 0); + if (rv != 0) + return rv; + + if (l >= 0 && l <= UINT32_MAX) + { + *n = (uint32_t) l; + return 0; + } + + errno = ERANGE; + return -1; +} + +int +gf_string2uint64 (const char *str, uint64_t *n) +{ + unsigned long long l = 0ULL; + int rv = 0; + + rv = _gf_string2ulonglong (str, &l, 0); + if (rv != 0) + return rv; + + if (l >= 0 && l <= UINT64_MAX) + { + *n = (uint64_t) l; + return 0; + } + + errno = ERANGE; + return -1; +} + +int +gf_string2ulong_base10 (const char *str, unsigned long *n) +{ + return _gf_string2ulong (str, n, 10); +} + +int +gf_string2uint_base10 (const char *str, unsigned int *n) +{ + return _gf_string2uint (str, n, 10); +} + +int +gf_string2uint8_base10 (const char *str, uint8_t *n) +{ + unsigned long l = 0L; + int rv = 0; + + rv = _gf_string2ulong (str, &l, 10); + if (rv != 0) + return rv; + + if (l >= 0 && l <= UINT8_MAX) + { + *n = (uint8_t) l; + return 0; + } + + errno = ERANGE; + return -1; +} + +int +gf_string2uint16_base10 (const char *str, uint16_t *n) +{ + unsigned long l = 0L; + int rv = 0; + + rv = _gf_string2ulong (str, &l, 10); + if (rv != 0) + return rv; + + if (l >= 0 && l <= UINT16_MAX) + { + *n = (uint16_t) l; + return 0; + } + + errno = ERANGE; + return -1; +} + +int +gf_string2uint32_base10 (const char *str, uint32_t *n) +{ + unsigned long l = 0L; + int rv = 0; + + rv = _gf_string2ulong (str, &l, 10); + if (rv != 0) + return rv; + + if (l >= 0 && l <= UINT32_MAX) + { + *n = (uint32_t) l; + return 0; + } + + errno = ERANGE; + return -1; +} + +int +gf_string2uint64_base10 (const char *str, uint64_t *n) +{ + unsigned long long l = 0ULL; + int rv = 0; + + rv = _gf_string2ulonglong (str, &l, 10); + if (rv != 0) + return rv; + + if (l >= 0 && l <= UINT64_MAX) + { + *n = (uint64_t) l; + return 0; + } + + errno = ERANGE; + return -1; +} + +int +gf_string2bytesize (const char *str, uint64_t *n) +{ + uint64_t value = 0ULL; + char *tail = NULL; + int old_errno = 0; + const char *s = NULL; + + if (str == NULL || n == NULL) + { + errno = EINVAL; + return -1; + } + + for (s = str; *s != '\0'; s++) + { + if (isspace (*s)) + { + continue; + } + if (*s == '-') + { + /* bala: we do not support suffixed (-) sign and + invalid integer format */ + return -1; + } + break; + } + + old_errno = errno; + errno = 0; + value = strtoull (str, &tail, 10); + + if (errno == ERANGE || errno == EINVAL) + { + return -1; + } + + if (errno == 0) + { + errno = old_errno; + } + + if (tail[0] != '\0') + { + if (strcasecmp (tail, GF_UNIT_KB_STRING) == 0) + { + value *= GF_UNIT_KB; + } + else if (strcasecmp (tail, GF_UNIT_MB_STRING) == 0) + { + value *= GF_UNIT_MB; + } + else if (strcasecmp (tail, GF_UNIT_GB_STRING) == 0) + { + value *= GF_UNIT_GB; + } + else if (strcasecmp (tail, GF_UNIT_TB_STRING) == 0) + { + value *= GF_UNIT_TB; + } + else if (strcasecmp (tail, GF_UNIT_PB_STRING) == 0) + { + value *= GF_UNIT_PB; + } + else + { + /* bala: invalid integer format */ + return -1; + } + } + + *n = value; + + return 0; +} + +int64_t +gf_str_to_long_long (const char *number) +{ + int64_t unit = 1; + int64_t ret = 0; + char *endptr = NULL ; + if (!number) + return 0; + + ret = strtoll (number, &endptr, 0); + + if (endptr) { + switch (*endptr) { + case 'G': + case 'g': + if ((* (endptr + 1) == 'B') ||(* (endptr + 1) == 'b')) + unit = 1024 * 1024 * 1024; + break; + case 'M': + case 'm': + if ((* (endptr + 1) == 'B') ||(* (endptr + 1) == 'b')) + unit = 1024 * 1024; + break; + case 'K': + case 'k': + if ((* (endptr + 1) == 'B') ||(* (endptr + 1) == 'b')) + unit = 1024; + break; + case '%': + unit = 1; + break; + default: + unit = 1; + break; + } + } + return ret * unit; +} + +int +gf_string2boolean (const char *str, gf_boolean_t *b) +{ + if (str == NULL) { + return -1; + } + + if ((strcasecmp (str, "1") == 0) || + (strcasecmp (str, "on") == 0) || + (strcasecmp (str, "yes") == 0) || + (strcasecmp (str, "true") == 0) || + (strcasecmp (str, "enable") == 0)) { + *b = _gf_true; + return 0; + } + + if ((strcasecmp (str, "0") == 0) || + (strcasecmp (str, "off") == 0) || + (strcasecmp (str, "no") == 0) || + (strcasecmp (str, "false") == 0) || + (strcasecmp (str, "disable") == 0)) { + *b = _gf_false; + return 0; + } + + return -1; +} + + +int +gf_lockfd (int fd) +{ + struct flock fl; + + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + + return fcntl (fd, F_SETLK, &fl); +} + + +int +gf_unlockfd (int fd) +{ + struct flock fl; + + fl.l_type = F_UNLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + + return fcntl (fd, F_SETLK, &fl); +} + diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h new file mode 100644 index 000000000..2016b51eb --- /dev/null +++ b/libglusterfs/src/common-utils.h @@ -0,0 +1,313 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _COMMON_UTILS_H +#define _COMMON_UTILS_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <stdint.h> +#include <sys/uio.h> +#include <netdb.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <pthread.h> +#ifndef GF_BSD_HOST_OS +#include <alloca.h> +#endif + +void trap (void); + +#define GF_UNIVERSAL_ANSWER 42 /* :O */ + +/* To solve type punned error */ +#define VOID(ptr) ((void **) ((void *) ptr)) + +#include "logging.h" +#include "glusterfs.h" +#include "locking.h" +#include "mem-pool.h" + + +#define min(a,b) ((a)<(b)?(a):(b)) +#define max(a,b) ((a)>(b)?(a):(b)) +#define roof(a,b) ((((a)+(b)-1)/((b)?(b):1))*(b)) +#define floor(a,b) (((a)/((b)?(b):1))*(b)) + + +#define GF_UNIT_KB 1024ULL +#define GF_UNIT_MB 1048576ULL +#define GF_UNIT_GB 1073741824ULL +#define GF_UNIT_TB 1099511627776ULL +#define GF_UNIT_PB 1125899906842624ULL + +#define GF_UNIT_KB_STRING "KB" +#define GF_UNIT_MB_STRING "MB" +#define GF_UNIT_GB_STRING "GB" +#define GF_UNIT_TB_STRING "TB" +#define GF_UNIT_PB_STRING "PB" + + +#define ERR_ABORT(ptr) \ + if (ptr == NULL) { \ + abort (); \ + } + +enum _gf_boolean +{ + _gf_false = 0, + _gf_true = 1 +}; + +typedef enum _gf_boolean gf_boolean_t; + +void gf_global_variable_init(void); +void set_global_ctx_ptr (glusterfs_ctx_t *ctx); +glusterfs_ctx_t *get_global_ctx_ptr (void); + +in_addr_t gf_resolve_ip (const char *hostname, void **dnscache); + +void gf_log_volume_file (FILE *specfp); +void gf_print_trace (int32_t signal); + +extern char *gf_fop_list[GF_FOP_MAXVALUE]; +extern char *gf_mop_list[GF_MOP_MAXVALUE]; +extern char *gf_cbk_list[GF_CBK_MAXVALUE]; + +#define VECTORSIZE(count) (count * (sizeof (struct iovec))) + +#define STRLEN_0(str) (strlen(str) + 1) +#define VALIDATE_OR_GOTO(arg,label) do { \ + if (!arg) { \ + errno = EINVAL; \ + gf_log ((this ? this->name : "(Govinda! Govinda!)"), \ + GF_LOG_ERROR, \ + "invalid argument: " #arg); \ + goto label; \ + } \ + } while (0); + +#define GF_VALIDATE_OR_GOTO(name,arg,label) do { \ + if (!arg) { \ + errno = EINVAL; \ + gf_log (name, GF_LOG_ERROR, \ + "invalid argument: " #arg); \ + goto label; \ + } \ + } while (0); + + +#define GF_FILE_CONTENT_REQUESTED(_xattr_req,_content_limit) \ + (dict_get_uint64 (_xattr_req, "glusterfs.content", _content_limit) == 0) + +static inline void +iov_free (struct iovec *vector, int count) +{ + int i; + + for (i = 0; i < count; i++) + FREE (vector[i].iov_base); + + FREE (vector); +} + + +static inline int +iov_length (const struct iovec *vector, int count) +{ + int i = 0; + size_t size = 0; + + for (i = 0; i < count; i++) + size += vector[i].iov_len; + + return size; +} + + +static inline struct iovec * +iov_dup (struct iovec *vector, int count) +{ + int bytecount = 0; + int i; + struct iovec *newvec = NULL; + + bytecount = (count * sizeof (struct iovec)); + newvec = MALLOC (bytecount); + if (!newvec) + return NULL; + + for (i = 0; i < count; i++) { + newvec[i].iov_len = vector[i].iov_len; + newvec[i].iov_base = vector[i].iov_base; + } + + return newvec; +} + + +static inline int +iov_subset (struct iovec *orig, int orig_count, + off_t src_offset, off_t dst_offset, + struct iovec *new) +{ + int new_count = 0; + int i; + off_t offset = 0; + size_t start_offset = 0; + size_t end_offset = 0; + + + for (i = 0; i < orig_count; i++) { + if ((offset + orig[i].iov_len < src_offset) + || (offset > dst_offset)) { + goto not_subset; + } + + if (!new) { + goto count_only; + } + + start_offset = 0; + end_offset = orig[i].iov_len; + + if (src_offset >= offset) { + start_offset = (src_offset - offset); + } + + if (dst_offset <= (offset + orig[i].iov_len)) { + end_offset = (dst_offset - offset); + } + + new[new_count].iov_base = orig[i].iov_base + start_offset; + new[new_count].iov_len = end_offset - start_offset; + + count_only: + new_count++; + + not_subset: + offset += orig[i].iov_len; + } + + return new_count; +} + + +static inline void +iov_unload (char *buf, const struct iovec *vector, int count) +{ + int i; + int copied = 0; + + for (i = 0; i < count; i++) { + memcpy (buf + copied, vector[i].iov_base, vector[i].iov_len); + copied += vector[i].iov_len; + } +} + + +static inline int +mem_0filled (const char *buf, size_t size) +{ + int i = 0; + int ret = 0; + + for (i = 0; i < size; i++) { + ret = buf[i]; + if (ret) + break; + } + + return ret; +} + + +static inline int +iov_0filled (struct iovec *vector, int count) +{ + int i = 0; + int ret = 0; + + for (i = 0; i < count; i++) { + ret = mem_0filled (vector[i].iov_base, vector[i].iov_len); + if (ret) + break; + } + + return ret; +} + + +static inline void * +memdup (const void *ptr, size_t size) +{ + void *newptr = NULL; + + newptr = MALLOC (size); + if (!newptr) + return NULL; + + memcpy (newptr, ptr, size); + return newptr; +} + + +char *gf_trim (char *string); +int gf_strsplit (const char *str, const char *delim, + char ***tokens, int *token_count); +int gf_volume_name_validate (const char *volume_name); + +int gf_string2long (const char *str, long *n); +int gf_string2ulong (const char *str, unsigned long *n); +int gf_string2int (const char *str, int *n); +int gf_string2uint (const char *str, unsigned int *n); +int gf_string2longlong (const char *str, long long *n); +int gf_string2ulonglong (const char *str, unsigned long long *n); + +int gf_string2int8 (const char *str, int8_t *n); +int gf_string2int16 (const char *str, int16_t *n); +int gf_string2int32 (const char *str, int32_t *n); +int gf_string2int64 (const char *str, int64_t *n); +int gf_string2uint8 (const char *str, uint8_t *n); +int gf_string2uint16 (const char *str, uint16_t *n); +int gf_string2uint32 (const char *str, uint32_t *n); +int gf_string2uint64 (const char *str, uint64_t *n); + +int gf_string2ulong_base10 (const char *str, unsigned long *n); +int gf_string2uint_base10 (const char *str, unsigned int *n); +int gf_string2uint8_base10 (const char *str, uint8_t *n); +int gf_string2uint16_base10 (const char *str, uint16_t *n); +int gf_string2uint32_base10 (const char *str, uint32_t *n); +int gf_string2uint64_base10 (const char *str, uint64_t *n); + +int gf_string2bytesize (const char *str, uint64_t *n); + +int gf_string2boolean (const char *str, gf_boolean_t *b); +int gf_string2percent (const char *str, uint32_t *n); +int gf_string2time (const char *str, uint32_t *n); + +int gf_lockfd (int fd); +int gf_unlockfd (int fd); + +#endif /* _COMMON_UTILS_H */ + diff --git a/libglusterfs/src/compat-errno.c b/libglusterfs/src/compat-errno.c new file mode 100644 index 000000000..a4a6c7106 --- /dev/null +++ b/libglusterfs/src/compat-errno.c @@ -0,0 +1,938 @@ +/* + Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <stdint.h> + +#include "compat-errno.h" + + +static int32_t gf_error_to_errno_array[1024]; +static int32_t gf_errno_to_error_array[1024]; + +static int32_t gf_compat_errno_init_done; + +#ifdef GF_SOLARIS_HOST_OS +static void +init_compat_errno_arrays () +{ +/* ENOMSG 35 / * No message of desired type */ + gf_error_to_errno_array[GF_ERROR_CODE_NOMSG] = ENOMSG; + gf_errno_to_error_array[ENOMSG] = GF_ERROR_CODE_NOMSG; + +/* EIDRM 36 / * Identifier removed */ + gf_error_to_errno_array[GF_ERROR_CODE_IDRM] = EIDRM; + gf_errno_to_error_array[EIDRM] = GF_ERROR_CODE_IDRM; + +/* ECHRNG 37 / * Channel number out of range */ + gf_error_to_errno_array[GF_ERROR_CODE_CHRNG] = ECHRNG; + gf_errno_to_error_array[ECHRNG] = GF_ERROR_CODE_CHRNG; + +/* EL2NSYNC 38 / * Level 2 not synchronized */ + gf_error_to_errno_array[GF_ERROR_CODE_L2NSYNC] = EL2NSYNC; + gf_errno_to_error_array[EL2NSYNC] = GF_ERROR_CODE_L2NSYNC; + +/* EL3HLT 39 / * Level 3 halted */ + gf_error_to_errno_array[GF_ERROR_CODE_L3HLT] = EL3HLT; + gf_errno_to_error_array[EL3HLT] = GF_ERROR_CODE_L3HLT; + +/* EL3RST 40 / * Level 3 reset */ + gf_error_to_errno_array[GF_ERROR_CODE_L3RST] = EL3RST; + gf_errno_to_error_array[EL3RST] = GF_ERROR_CODE_L3RST; + +/* ELNRNG 41 / * Link number out of range */ + gf_error_to_errno_array[GF_ERROR_CODE_LNRNG] = ELNRNG; + gf_errno_to_error_array[ELNRNG] = GF_ERROR_CODE_LNRNG; + +/* EUNATCH 42 / * Protocol driver not attached */ + gf_error_to_errno_array[GF_ERROR_CODE_UNATCH] = EUNATCH; + gf_errno_to_error_array[EUNATCH] = GF_ERROR_CODE_UNATCH; + +/* ENOCSI 43 / * No CSI structure available */ + gf_error_to_errno_array[GF_ERROR_CODE_NOCSI] = ENOCSI; + gf_errno_to_error_array[ENOCSI] = GF_ERROR_CODE_NOCSI; + +/* EL2HLT 44 / * Level 2 halted */ + gf_error_to_errno_array[GF_ERROR_CODE_L2HLT] = EL2HLT; + gf_errno_to_error_array[EL2HLT] = GF_ERROR_CODE_L2HLT; + +/* EDEADLK 45 / * Deadlock condition. */ + gf_error_to_errno_array[GF_ERROR_CODE_DEADLK] = EDEADLK; + gf_errno_to_error_array[EDEADLK] = GF_ERROR_CODE_DEADLK; + +/* ENOLCK 46 / * No record locks available. */ + gf_error_to_errno_array[GF_ERROR_CODE_NOLCK] = ENOLCK; + gf_errno_to_error_array[ENOLCK] = GF_ERROR_CODE_NOLCK; + +/* ECANCELED 47 / * Operation canceled */ + gf_error_to_errno_array[GF_ERROR_CODE_CANCELED] = ECANCELED; + gf_errno_to_error_array[ECANCELED] = GF_ERROR_CODE_CANCELED; + +/* ENOTSUP 48 / * Operation not supported */ + gf_error_to_errno_array[GF_ERROR_CODE_NOTSUPP] = ENOTSUP; + gf_errno_to_error_array[ENOTSUP] = GF_ERROR_CODE_NOTSUPP; + +/* Filesystem Quotas */ +/* EDQUOT 49 / * Disc quota exceeded */ + gf_error_to_errno_array[GF_ERROR_CODE_DQUOT] = EDQUOT; + gf_errno_to_error_array[EDQUOT] = GF_ERROR_CODE_DQUOT; + +/* Convergent Error Returns */ +/* EBADE 50 / * invalid exchange */ + gf_error_to_errno_array[GF_ERROR_CODE_BADE] = EBADE; + gf_errno_to_error_array[EBADE] = GF_ERROR_CODE_BADE; +/* EBADR 51 / * invalid request descriptor */ + gf_error_to_errno_array[GF_ERROR_CODE_BADR] = EBADR; + gf_errno_to_error_array[EBADR] = GF_ERROR_CODE_BADR; +/* EXFULL 52 / * exchange full */ + gf_error_to_errno_array[GF_ERROR_CODE_XFULL] = EXFULL; + gf_errno_to_error_array[EXFULL] = GF_ERROR_CODE_XFULL; +/* ENOANO 53 / * no anode */ + gf_error_to_errno_array[GF_ERROR_CODE_NOANO] = ENOANO; + gf_errno_to_error_array[ENOANO] = GF_ERROR_CODE_NOANO; +/* EBADRQC 54 / * invalid request code */ + gf_error_to_errno_array[GF_ERROR_CODE_BADRQC] = EBADRQC; + gf_errno_to_error_array[EBADRQC] = GF_ERROR_CODE_BADRQC; +/* EBADSLT 55 / * invalid slot */ + gf_error_to_errno_array[GF_ERROR_CODE_BADSLT] = EBADSLT; + gf_errno_to_error_array[EBADSLT] = GF_ERROR_CODE_BADSLT; +/* EDEADLOCK 56 / * file locking deadlock error */ +/* This is same as EDEADLK on linux */ + gf_error_to_errno_array[GF_ERROR_CODE_DEADLK] = EDEADLOCK; + gf_errno_to_error_array[EDEADLOCK] = GF_ERROR_CODE_DEADLK; + +/* EBFONT 57 / * bad font file fmt */ + gf_error_to_errno_array[GF_ERROR_CODE_BFONT] = EBFONT; + gf_errno_to_error_array[EBFONT] = GF_ERROR_CODE_BFONT; + +/* Interprocess Robust Locks */ +/* EOWNERDEAD 58 / * process died with the lock */ + gf_error_to_errno_array[GF_ERROR_CODE_OWNERDEAD] = EOWNERDEAD; + gf_errno_to_error_array[EOWNERDEAD] = GF_ERROR_CODE_OWNERDEAD; +/* ENOTRECOVERABLE 59 / * lock is not recoverable */ + gf_error_to_errno_array[GF_ERROR_CODE_NOTRECOVERABLE] = ENOTRECOVERABLE; + gf_errno_to_error_array[ENOTRECOVERABLE] = GF_ERROR_CODE_NOTRECOVERABLE; + +/* stream problems */ +/* ENOSTR 60 / * Device not a stream */ + gf_error_to_errno_array[GF_ERROR_CODE_NOSTR] = ENOSTR; + gf_errno_to_error_array[ENOSTR] = GF_ERROR_CODE_NOSTR; +/* ENODATA 61 / * no data (for no delay io) */ + gf_error_to_errno_array[GF_ERROR_CODE_NODATA] = ENODATA; + gf_errno_to_error_array[ENODATA] = GF_ERROR_CODE_NODATA; +/* ETIME 62 / * timer expired */ + gf_error_to_errno_array[GF_ERROR_CODE_TIME] = ETIME; + gf_errno_to_error_array[ETIME] = GF_ERROR_CODE_TIME; +/* ENOSR 63 / * out of streams resources */ + gf_error_to_errno_array[GF_ERROR_CODE_NOSR] = ENOSR; + gf_errno_to_error_array[ENOSR] = GF_ERROR_CODE_NOSR; + +/* ENONET 64 / * Machine is not on the network */ + gf_error_to_errno_array[GF_ERROR_CODE_NONET] = ENONET; + gf_errno_to_error_array[ENONET] = GF_ERROR_CODE_NONET; +/* ENOPKG 65 / * Package not installed */ + gf_error_to_errno_array[GF_ERROR_CODE_NOPKG] = ENOPKG; + gf_errno_to_error_array[ENOPKG] = GF_ERROR_CODE_NOPKG; +/* EREMOTE 66 / * The object is remote */ + gf_error_to_errno_array[GF_ERROR_CODE_REMOTE] = EREMOTE; + gf_errno_to_error_array[EREMOTE] = GF_ERROR_CODE_REMOTE; +/* ENOLINK 67 / * the link has been severed */ + gf_error_to_errno_array[GF_ERROR_CODE_NOLINK] = ENOLINK; + gf_errno_to_error_array[ENOLINK] = GF_ERROR_CODE_NOLINK; +/* EADV 68 / * advertise error */ + gf_error_to_errno_array[GF_ERROR_CODE_ADV] = EADV; + gf_errno_to_error_array[EADV] = GF_ERROR_CODE_ADV; +/* ESRMNT 69 / * srmount error */ + gf_error_to_errno_array[GF_ERROR_CODE_SRMNT] = ESRMNT; + gf_errno_to_error_array[ESRMNT] = GF_ERROR_CODE_SRMNT; + +/* ECOMM 70 / * Communication error on send */ + gf_error_to_errno_array[GF_ERROR_CODE_COMM] = ECOMM; + gf_errno_to_error_array[ECOMM] = GF_ERROR_CODE_COMM; +/* EPROTO 71 / * Protocol error */ + gf_error_to_errno_array[GF_ERROR_CODE_PROTO] = EPROTO; + gf_errno_to_error_array[EPROTO] = GF_ERROR_CODE_PROTO; + +/* Interprocess Robust Locks */ +/* ELOCKUNMAPPED 72 / * locked lock was unmapped */ + gf_error_to_errno_array[GF_ERROR_CODE_LOCKUNMAPPED] = ELOCKUNMAPPED; + gf_errno_to_error_array[ELOCKUNMAPPED] = GF_ERROR_CODE_LOCKUNMAPPED; + +/* ENOTACTIVE 73 / * Facility is not active */ + gf_error_to_errno_array[GF_ERROR_CODE_NOTACTIVE] = ENOTACTIVE; + gf_errno_to_error_array[ENOTACTIVE] = GF_ERROR_CODE_NOTACTIVE; +/* EMULTIHOP 74 / * multihop attempted */ + gf_error_to_errno_array[GF_ERROR_CODE_MULTIHOP] = EMULTIHOP; + gf_errno_to_error_array[EMULTIHOP] = GF_ERROR_CODE_MULTIHOP; +/* EBADMSG 77 / * trying to read unreadable message */ + gf_error_to_errno_array[GF_ERROR_CODE_BADMSG] = EBADMSG; + gf_errno_to_error_array[EBADMSG] = GF_ERROR_CODE_BADMSG; +/* ENAMETOOLONG 78 / * path name is too long */ + gf_error_to_errno_array[GF_ERROR_CODE_NAMETOOLONG] = ENAMETOOLONG; + gf_errno_to_error_array[ENAMETOOLONG] = GF_ERROR_CODE_NAMETOOLONG; +/* EOVERFLOW 79 / * value too large to be stored in data type */ + gf_error_to_errno_array[GF_ERROR_CODE_OVERFLOW] = EOVERFLOW; + gf_errno_to_error_array[EOVERFLOW] = GF_ERROR_CODE_OVERFLOW; +/* ENOTUNIQ 80 / * given log. name not unique */ + gf_error_to_errno_array[GF_ERROR_CODE_NOTUNIQ] = ENOTUNIQ; + gf_errno_to_error_array[ENOTUNIQ] = GF_ERROR_CODE_NOTUNIQ; +/* EBADFD 81 / * f.d. invalid for this operation */ + gf_error_to_errno_array[GF_ERROR_CODE_BADFD] = EBADFD; + gf_errno_to_error_array[EBADFD] = GF_ERROR_CODE_BADFD; +/* EREMCHG 82 / * Remote address changed */ + gf_error_to_errno_array[GF_ERROR_CODE_REMCHG] = EREMCHG; + gf_errno_to_error_array[EREMCHG] = GF_ERROR_CODE_REMCHG; + +/* shared library problems */ +/* ELIBACC 83 / * Can't access a needed shared lib. */ + gf_error_to_errno_array[GF_ERROR_CODE_LIBACC] = ELIBACC; + gf_errno_to_error_array[ELIBACC] = GF_ERROR_CODE_LIBACC; +/* ELIBBAD 84 / * Accessing a corrupted shared lib. */ + gf_error_to_errno_array[GF_ERROR_CODE_LIBBAD] = ELIBBAD; + gf_errno_to_error_array[ELIBBAD] = GF_ERROR_CODE_LIBBAD; +/* ELIBSCN 85 / * .lib section in a.out corrupted. */ + gf_error_to_errno_array[GF_ERROR_CODE_LIBSCN] = ELIBSCN; + gf_errno_to_error_array[ELIBSCN] = GF_ERROR_CODE_LIBSCN; +/* ELIBMAX 86 / * Attempting to link in too many libs. */ + gf_error_to_errno_array[GF_ERROR_CODE_LIBMAX] = ELIBMAX; + gf_errno_to_error_array[ELIBMAX] = GF_ERROR_CODE_LIBMAX; +/* ELIBEXEC 87 / * Attempting to exec a shared library. */ + gf_error_to_errno_array[GF_ERROR_CODE_LIBEXEC] = ELIBEXEC; + gf_errno_to_error_array[ELIBEXEC] = GF_ERROR_CODE_LIBEXEC; +/* EILSEQ 88 / * Illegal byte sequence. */ + gf_error_to_errno_array[GF_ERROR_CODE_ILSEQ] = EILSEQ; + gf_errno_to_error_array[EILSEQ] = GF_ERROR_CODE_ILSEQ; +/* ENOSYS 89 / * Unsupported file system operation */ + gf_error_to_errno_array[GF_ERROR_CODE_NOSYS] = ENOSYS; + gf_errno_to_error_array[ENOSYS] = GF_ERROR_CODE_NOSYS; +/* ELOOP 90 / * Symbolic link loop */ + gf_error_to_errno_array[GF_ERROR_CODE_LOOP] = ELOOP; + gf_errno_to_error_array[ELOOP] = GF_ERROR_CODE_LOOP; +/* ERESTART 91 / * Restartable system call */ + gf_error_to_errno_array[GF_ERROR_CODE_RESTART] = ERESTART; + gf_errno_to_error_array[ERESTART] = GF_ERROR_CODE_RESTART; +/* ESTRPIPE 92 / * if pipe/FIFO, don't sleep in stream head */ + gf_error_to_errno_array[GF_ERROR_CODE_STRPIPE] = ESTRPIPE; + gf_errno_to_error_array[ESTRPIPE] = GF_ERROR_CODE_STRPIPE; +/* ENOTEMPTY 93 / * directory not empty */ + gf_error_to_errno_array[GF_ERROR_CODE_NOTEMPTY] = ENOTEMPTY; + gf_errno_to_error_array[ENOTEMPTY] = GF_ERROR_CODE_NOTEMPTY; +/* EUSERS 94 / * Too many users (for UFS) */ + gf_error_to_errno_array[GF_ERROR_CODE_USERS] = EUSERS; + gf_errno_to_error_array[EUSERS] = GF_ERROR_CODE_USERS; + +/* BSD Networking Software */ + /* argument errors */ +/* ENOTSOCK 95 / * Socket operation on non-socket */ + gf_error_to_errno_array[GF_ERROR_CODE_NOTSOCK] = ENOTSOCK; + gf_errno_to_error_array[ENOTSOCK] = GF_ERROR_CODE_NOTSOCK; +/* EDESTADDRREQ 96 / * Destination address required */ + gf_error_to_errno_array[GF_ERROR_CODE_DESTADDRREQ] = EDESTADDRREQ; + gf_errno_to_error_array[EDESTADDRREQ] = GF_ERROR_CODE_DESTADDRREQ; +/* EMSGSIZE 97 / * Message too long */ + gf_error_to_errno_array[GF_ERROR_CODE_MSGSIZE] = EMSGSIZE; + gf_errno_to_error_array[EMSGSIZE] = GF_ERROR_CODE_MSGSIZE; +/* EPROTOTYPE 98 / * Protocol wrong type for socket */ + gf_error_to_errno_array[GF_ERROR_CODE_PROTOTYPE] = EPROTOTYPE; + gf_errno_to_error_array[EPROTOTYPE] = GF_ERROR_CODE_PROTOTYPE; +/* ENOPROTOOPT 99 / * Protocol not available */ + gf_error_to_errno_array[GF_ERROR_CODE_NOPROTOOPT] = ENOPROTOOPT; + gf_errno_to_error_array[ENOPROTOOPT] = GF_ERROR_CODE_NOPROTOOPT; +/* EPROTONOSUPPORT 120 / * Protocol not supported */ + gf_error_to_errno_array[GF_ERROR_CODE_PROTONOSUPPORT] = EPROTONOSUPPORT; + gf_errno_to_error_array[EPROTONOSUPPORT] = GF_ERROR_CODE_PROTONOSUPPORT; +/* ESOCKTNOSUPPORT 121 / * Socket type not supported */ + gf_error_to_errno_array[GF_ERROR_CODE_SOCKTNOSUPPORT] = ESOCKTNOSUPPORT; + gf_errno_to_error_array[ESOCKTNOSUPPORT] = GF_ERROR_CODE_SOCKTNOSUPPORT; + +/* EOPNOTSUPP 122 / * Operation not supported on socket */ + gf_error_to_errno_array[GF_ERROR_CODE_OPNOTSUPP] = EOPNOTSUPP; + gf_errno_to_error_array[EOPNOTSUPP] = GF_ERROR_CODE_OPNOTSUPP; +/* EPFNOSUPPORT 123 / * Protocol family not supported */ + gf_error_to_errno_array[GF_ERROR_CODE_PFNOSUPPORT] = EPFNOSUPPORT; + gf_errno_to_error_array[EPFNOSUPPORT] = GF_ERROR_CODE_PFNOSUPPORT; +/* EAFNOSUPPORT 124 / * Address family not supported by */ + /* protocol family */ + gf_error_to_errno_array[GF_ERROR_CODE_AFNOSUPPORT] = EAFNOSUPPORT; + gf_errno_to_error_array[EAFNOSUPPORT] = GF_ERROR_CODE_AFNOSUPPORT; +/* EADDRINUSE 125 / * Address already in use */ + gf_error_to_errno_array[GF_ERROR_CODE_ADDRINUSE] = EADDRINUSE; + gf_errno_to_error_array[EADDRINUSE] = GF_ERROR_CODE_ADDRINUSE; +/* EADDRNOTAVAIL 126 / * Can't assign requested address */ + /* operational errors */ + gf_error_to_errno_array[GF_ERROR_CODE_ADDRNOTAVAIL] = EADDRNOTAVAIL; + gf_errno_to_error_array[EADDRNOTAVAIL] = GF_ERROR_CODE_ADDRNOTAVAIL; +/* ENETDOWN 127 / * Network is down */ + gf_error_to_errno_array[GF_ERROR_CODE_NETDOWN] = ENETDOWN; + gf_errno_to_error_array[ENETDOWN] = GF_ERROR_CODE_NETDOWN; +/* ENETUNREACH 128 / * Network is unreachable */ + gf_error_to_errno_array[GF_ERROR_CODE_NETUNREACH] = ENETUNREACH; + gf_errno_to_error_array[ENETUNREACH] = GF_ERROR_CODE_NETUNREACH; +/* ENETRESET 129 / * Network dropped connection because */ + /* of reset */ + gf_error_to_errno_array[GF_ERROR_CODE_NETRESET] = ENETRESET; + gf_errno_to_error_array[ENETRESET] = GF_ERROR_CODE_NETRESET; +/* ECONNABORTED 130 / * Software caused connection abort */ + gf_error_to_errno_array[GF_ERROR_CODE_CONNABORTED] = ECONNABORTED; + gf_errno_to_error_array[ECONNABORTED] = GF_ERROR_CODE_CONNABORTED; +/* ECONNRESET 131 / * Connection reset by peer */ + gf_error_to_errno_array[GF_ERROR_CODE_CONNRESET] = ECONNRESET; + gf_errno_to_error_array[ECONNRESET] = GF_ERROR_CODE_CONNRESET; +/* ENOBUFS 132 / * No buffer space available */ + gf_error_to_errno_array[GF_ERROR_CODE_NOBUFS] = ENOBUFS; + gf_errno_to_error_array[ENOBUFS] = GF_ERROR_CODE_NOBUFS; +/* EISCONN 133 / * Socket is already connected */ + gf_error_to_errno_array[GF_ERROR_CODE_ISCONN] = EISCONN; + gf_errno_to_error_array[EISCONN] = GF_ERROR_CODE_ISCONN; +/* ENOTCONN 134 / * Socket is not connected */ + gf_error_to_errno_array[GF_ERROR_CODE_NOTCONN] = ENOTCONN; + gf_errno_to_error_array[ENOTCONN] = GF_ERROR_CODE_NOTCONN; +/* XENIX has 135 - 142 */ +/* ESHUTDOWN 143 / * Can't send after socket shutdown */ + gf_error_to_errno_array[GF_ERROR_CODE_SHUTDOWN] = ESHUTDOWN; + gf_errno_to_error_array[ESHUTDOWN] = GF_ERROR_CODE_SHUTDOWN; +/* ETOOMANYREFS 144 / * Too many references: can't splice */ + gf_error_to_errno_array[GF_ERROR_CODE_TOOMANYREFS] = ETOOMANYREFS; + gf_errno_to_error_array[ETOOMANYREFS] = GF_ERROR_CODE_TOOMANYREFS; +/* ETIMEDOUT 145 / * Connection timed out */ + gf_error_to_errno_array[GF_ERROR_CODE_TIMEDOUT] = ETIMEDOUT; + gf_errno_to_error_array[ETIMEDOUT] = GF_ERROR_CODE_TIMEDOUT; + +/* ECONNREFUSED 146 / * Connection refused */ + gf_error_to_errno_array[GF_ERROR_CODE_CONNREFUSED] = ECONNREFUSED; + gf_errno_to_error_array[ECONNREFUSED] = GF_ERROR_CODE_CONNREFUSED; +/* EHOSTDOWN 147 / * Host is down */ + gf_error_to_errno_array[GF_ERROR_CODE_HOSTDOWN] = EHOSTDOWN; + gf_errno_to_error_array[EHOSTDOWN] = GF_ERROR_CODE_HOSTDOWN; +/* EHOSTUNREACH 148 / * No route to host */ + gf_error_to_errno_array[GF_ERROR_CODE_HOSTUNREACH] = EHOSTUNREACH; + gf_errno_to_error_array[EHOSTUNREACH] = GF_ERROR_CODE_HOSTUNREACH; +/* EALREADY 149 / * operation already in progress */ + gf_error_to_errno_array[GF_ERROR_CODE_ALREADY] = EALREADY; + gf_errno_to_error_array[EALREADY] = GF_ERROR_CODE_ALREADY; +/* EINPROGRESS 150 / * operation now in progress */ + gf_error_to_errno_array[GF_ERROR_CODE_INPROGRESS] = EINPROGRESS; + gf_errno_to_error_array[EINPROGRESS] = GF_ERROR_CODE_INPROGRESS; + +/* SUN Network File System */ +/* ESTALE 151 / * Stale NFS file handle */ + gf_error_to_errno_array[GF_ERROR_CODE_STALE] = ESTALE; + gf_errno_to_error_array[ESTALE] = GF_ERROR_CODE_STALE; + + return ; +} +#endif /* GF_SOLARIS_HOST_OS */ + +#ifdef GF_DARWIN_HOST_OS +static void +init_compat_errno_arrays () +{ + /* EDEADLK 11 / * Resource deadlock would occur */ + gf_error_to_errno_array[GF_ERROR_CODE_DEADLK] = EDEADLK; + gf_errno_to_error_array[EDEADLK] = GF_ERROR_CODE_DEADLK; + + /* EAGAIN 35 / * Try Again */ + gf_error_to_errno_array[GF_ERROR_CODE_AGAIN] = EAGAIN; + gf_errno_to_error_array[EAGAIN] = GF_ERROR_CODE_AGAIN; + + /* EINPROGRESS 36 / * Operation now in progress */ + gf_error_to_errno_array[GF_ERROR_CODE_INPROGRESS] = EINPROGRESS; + gf_errno_to_error_array[EINPROGRESS] = GF_ERROR_CODE_INPROGRESS; + + /* EALREADY 37 / * Operation already in progress */ + gf_error_to_errno_array[GF_ERROR_CODE_ALREADY] = EALREADY; + gf_errno_to_error_array[EALREADY] = GF_ERROR_CODE_ALREADY; + + /* ENOTSOCK 38 / * Socket operation on non-socket */ + gf_error_to_errno_array[GF_ERROR_CODE_NOTSOCK] = ENOTSOCK; + gf_errno_to_error_array[ENOTSOCK] = GF_ERROR_CODE_NOTSOCK; + + /* EDESTADDRREQ 39 / * Destination address required */ + gf_error_to_errno_array[GF_ERROR_CODE_DESTADDRREQ] = EDESTADDRREQ; + gf_errno_to_error_array[EDESTADDRREQ] = GF_ERROR_CODE_DESTADDRREQ; + + /* EMSGSIZE 40 / * Message too long */ + gf_error_to_errno_array[GF_ERROR_CODE_MSGSIZE] = EMSGSIZE; + gf_errno_to_error_array[EMSGSIZE] = GF_ERROR_CODE_MSGSIZE; + + /* EPROTOTYPE 41 / * Protocol wrong type for socket */ + gf_error_to_errno_array[GF_ERROR_CODE_PROTOTYPE] = EPROTOTYPE; + gf_errno_to_error_array[EPROTOTYPE] = GF_ERROR_CODE_PROTOTYPE; + + /* ENOPROTOOPT 42 / * Protocol not available */ + gf_error_to_errno_array[GF_ERROR_CODE_NOPROTOOPT] = ENOPROTOOPT; + gf_errno_to_error_array[ENOPROTOOPT] = GF_ERROR_CODE_NOPROTOOPT; + + /* EPROTONOSUPPORT 43 / * Protocol not supported */ + gf_error_to_errno_array[GF_ERROR_CODE_PROTONOSUPPORT] = EPROTONOSUPPORT; + gf_errno_to_error_array[EPROTONOSUPPORT] = GF_ERROR_CODE_PROTONOSUPPORT; + + /* ESOCKTNOSUPPORT 44 / * Socket type not supported */ + gf_error_to_errno_array[GF_ERROR_CODE_SOCKTNOSUPPORT] = ESOCKTNOSUPPORT; + gf_errno_to_error_array[ESOCKTNOSUPPORT] = GF_ERROR_CODE_SOCKTNOSUPPORT; + + /* EOPNOTSUPP 45 / * Operation not supported */ + gf_error_to_errno_array[GF_ERROR_CODE_OPNOTSUPP] = EOPNOTSUPP; + gf_errno_to_error_array[EOPNOTSUPP] = GF_ERROR_CODE_OPNOTSUPP; + + /* EPFNOSUPPORT 46 / * Protocol family not supported */ + gf_error_to_errno_array[GF_ERROR_CODE_PFNOSUPPORT] = EPFNOSUPPORT; + gf_errno_to_error_array[EPFNOSUPPORT] = GF_ERROR_CODE_PFNOSUPPORT; + + /* EAFNOSUPPORT 47 / * Address family not supported by protocol family */ + gf_error_to_errno_array[GF_ERROR_CODE_AFNOSUPPORT] = EAFNOSUPPORT; + gf_errno_to_error_array[EAFNOSUPPORT] = GF_ERROR_CODE_AFNOSUPPORT; + + /* EADDRINUSE 48 / * Address already in use */ + gf_error_to_errno_array[GF_ERROR_CODE_ADDRINUSE] = EADDRINUSE; + gf_errno_to_error_array[EADDRINUSE] = GF_ERROR_CODE_ADDRINUSE; + + /* EADDRNOTAVAIL 49 / * Can't assign requested address */ + gf_error_to_errno_array[GF_ERROR_CODE_ADDRNOTAVAIL] = EADDRNOTAVAIL; + gf_errno_to_error_array[EADDRNOTAVAIL] = GF_ERROR_CODE_ADDRNOTAVAIL; + + /* ENETDOWN 50 / * Network is down */ + gf_error_to_errno_array[GF_ERROR_CODE_NETDOWN] = ENETDOWN; + gf_errno_to_error_array[ENETDOWN] = GF_ERROR_CODE_NETDOWN; + + /* ENETUNREACH 51 / * Network is unreachable */ + gf_error_to_errno_array[GF_ERROR_CODE_NETUNREACH] = ENETUNREACH; + gf_errno_to_error_array[ENETUNREACH] = GF_ERROR_CODE_NETUNREACH; + + /* ENETRESET 52 / * Network dropped connection on reset */ + gf_error_to_errno_array[GF_ERROR_CODE_NETRESET] = ENETRESET; + gf_errno_to_error_array[ENETRESET] = GF_ERROR_CODE_NETRESET; + + /* ECONNABORTED 53 / * Software caused connection abort */ + gf_error_to_errno_array[GF_ERROR_CODE_CONNABORTED] = ECONNABORTED; + gf_errno_to_error_array[ECONNABORTED] = GF_ERROR_CODE_CONNABORTED; + + /* ECONNRESET 54 / * Connection reset by peer */ + gf_error_to_errno_array[GF_ERROR_CODE_CONNRESET] = ECONNRESET; + gf_errno_to_error_array[ECONNRESET] = GF_ERROR_CODE_CONNRESET; + + /* ENOBUFS 55 / * No buffer space available */ + gf_error_to_errno_array[GF_ERROR_CODE_NOBUFS] = ENOBUFS; + gf_errno_to_error_array[ENOBUFS] = GF_ERROR_CODE_NOBUFS; + + /* EISCONN 56 / * Socket is already connected */ + gf_error_to_errno_array[GF_ERROR_CODE_ISCONN] = EISCONN; + gf_errno_to_error_array[EISCONN] = GF_ERROR_CODE_ISCONN; + + /* ENOTCONN 57 / * Socket is not connected */ + gf_error_to_errno_array[GF_ERROR_CODE_NOTCONN] = ENOTCONN; + gf_errno_to_error_array[ENOTCONN] = GF_ERROR_CODE_NOTCONN; + + /* ESHUTDOWN 58 / * Can't send after socket shutdown */ + gf_error_to_errno_array[GF_ERROR_CODE_SHUTDOWN] = ESHUTDOWN; + gf_errno_to_error_array[ESHUTDOWN] = GF_ERROR_CODE_SHUTDOWN; + + /* ETOOMANYREFS 59 / * Too many references: can't splice */ + gf_error_to_errno_array[GF_ERROR_CODE_TOOMANYREFS] = ETOOMANYREFS; + gf_errno_to_error_array[ETOOMANYREFS] = GF_ERROR_CODE_TOOMANYREFS; + + /* ETIMEDOUT 60 / * Operation timed out */ + gf_error_to_errno_array[GF_ERROR_CODE_TIMEDOUT] = ETIMEDOUT; + gf_errno_to_error_array[ETIMEDOUT] = GF_ERROR_CODE_TIMEDOUT; + + /* ECONNREFUSED 61 / * Connection refused */ + gf_error_to_errno_array[GF_ERROR_CODE_CONNREFUSED] = ECONNREFUSED; + gf_errno_to_error_array[ECONNREFUSED] = GF_ERROR_CODE_CONNREFUSED; + + /* ELOOP 62 / * Too many levels of symbolic links */ + gf_error_to_errno_array[GF_ERROR_CODE_LOOP] = ELOOP; + gf_errno_to_error_array[ELOOP] = GF_ERROR_CODE_LOOP; + + /* ENAMETOOLONG 63 / * File name too long */ + gf_error_to_errno_array[GF_ERROR_CODE_NAMETOOLONG] = ENAMETOOLONG; + gf_errno_to_error_array[ENAMETOOLONG] = GF_ERROR_CODE_NAMETOOLONG; + + /* EHOSTDOWN 64 / * Host is down */ + gf_error_to_errno_array[GF_ERROR_CODE_HOSTDOWN] = EHOSTDOWN; + gf_errno_to_error_array[EHOSTDOWN] = GF_ERROR_CODE_HOSTDOWN; + + /* EHOSTUNREACH 65 / * No route to host */ + gf_error_to_errno_array[GF_ERROR_CODE_HOSTUNREACH] = EHOSTUNREACH; + gf_errno_to_error_array[EHOSTUNREACH] = GF_ERROR_CODE_HOSTUNREACH; + + /* ENOTEMPTY 66 / * Directory not empty */ + gf_error_to_errno_array[GF_ERROR_CODE_NOTEMPTY] = ENOTEMPTY; + gf_errno_to_error_array[ENOTEMPTY] = GF_ERROR_CODE_NOTEMPTY; + + /* EPROCLIM 67 / * Too many processes */ + gf_error_to_errno_array[GF_ERROR_CODE_PROCLIM] = EPROCLIM; + gf_errno_to_error_array[EPROCLIM] = GF_ERROR_CODE_PROCLIM; + + /* EUSERS 68 / * Too many users */ + gf_error_to_errno_array[GF_ERROR_CODE_USERS] = EUSERS; + gf_errno_to_error_array[EUSERS] = GF_ERROR_CODE_USERS; + + /* EDQUOT 69 / * Disc quota exceeded */ + gf_error_to_errno_array[GF_ERROR_CODE_DQUOT] = EDQUOT; + gf_errno_to_error_array[EDQUOT] = GF_ERROR_CODE_DQUOT; + + /* ESTALE 70 / * Stale NFS file handle */ + gf_error_to_errno_array[GF_ERROR_CODE_STALE] = ESTALE; + gf_errno_to_error_array[ESTALE] = GF_ERROR_CODE_STALE; + + /* EREMOTE 71 / * Too many levels of remote in path */ + gf_error_to_errno_array[GF_ERROR_CODE_REMOTE] = EREMOTE; + gf_errno_to_error_array[EREMOTE] = GF_ERROR_CODE_REMOTE; + + /* EBADRPC 72 / * RPC struct is bad */ + gf_error_to_errno_array[GF_ERROR_CODE_BADRPC] = EBADRPC; + gf_errno_to_error_array[EBADRPC] = GF_ERROR_CODE_BADRPC; + + /* ERPCMISMATCH 73 / * RPC version wrong */ + gf_error_to_errno_array[GF_ERROR_CODE_RPCMISMATCH] = ERPCMISMATCH; + gf_errno_to_error_array[ERPCMISMATCH] = GF_ERROR_CODE_RPCMISMATCH; + + /* EPROGUNAVAIL 74 / * RPC prog. not avail */ + gf_error_to_errno_array[GF_ERROR_CODE_PROGUNAVAIL] = EPROGUNAVAIL; + gf_errno_to_error_array[EPROGUNAVAIL] = GF_ERROR_CODE_PROGUNAVAIL; + + /* EPROGMISMATCH 75 / * Program version wrong */ + gf_error_to_errno_array[GF_ERROR_CODE_PROGMISMATCH] = EPROGMISMATCH; + gf_errno_to_error_array[EPROGMISMATCH] = GF_ERROR_CODE_PROGMISMATCH; + + /* EPROCUNAVAIL 76 / * Bad procedure for program */ + gf_error_to_errno_array[GF_ERROR_CODE_PROCUNAVAIL] = EPROCUNAVAIL; + gf_errno_to_error_array[EPROCUNAVAIL] = GF_ERROR_CODE_PROCUNAVAIL; + + /* ENOLCK 77 / * No locks available */ + gf_error_to_errno_array[GF_ERROR_CODE_NOLCK] = ENOLCK; + gf_errno_to_error_array[ENOLCK] = GF_ERROR_CODE_NOLCK; + + /* ENOSYS 78 / * Function not implemented */ + gf_error_to_errno_array[GF_ERROR_CODE_NOSYS] = ENOSYS; + gf_errno_to_error_array[ENOSYS] = GF_ERROR_CODE_NOSYS; + + /* EFTYPE 79 / * Inappropriate file type or format */ + gf_error_to_errno_array[GF_ERROR_CODE_FTYPE] = EFTYPE; + gf_errno_to_error_array[EFTYPE] = GF_ERROR_CODE_FTYPE; + + /* EAUTH 80 / * Authentication error */ + gf_error_to_errno_array[GF_ERROR_CODE_AUTH] = EAUTH; + gf_errno_to_error_array[EAUTH] = GF_ERROR_CODE_AUTH; + + /* ENEEDAUTH 81 / * Need authenticator */ + gf_error_to_errno_array[GF_ERROR_CODE_NEEDAUTH] = ENEEDAUTH; + gf_errno_to_error_array[ENEEDAUTH] = GF_ERROR_CODE_NEEDAUTH; +/* Intelligent device errors */ +/* EPWROFF 82 / * Device power is off */ + gf_error_to_errno_array[GF_ERROR_CODE_PWROFF] = EPWROFF; + gf_errno_to_error_array[EPWROFF] = GF_ERROR_CODE_PWROFF; +/* EDEVERR 83 / * Device error, e.g. paper out */ + gf_error_to_errno_array[GF_ERROR_CODE_DEVERR] = EDEVERR; + gf_errno_to_error_array[EDEVERR] = GF_ERROR_CODE_DEVERR; + + /* EOVERFLOW 84 / * Value too large to be stored in data type */ + gf_error_to_errno_array[GF_ERROR_CODE_OVERFLOW] = EOVERFLOW; + gf_errno_to_error_array[EOVERFLOW] = GF_ERROR_CODE_OVERFLOW; + +/* Program loading errors */ +/* EBADEXEC 85 / * Bad executable */ + gf_error_to_errno_array[GF_ERROR_CODE_BADEXEC] = EBADEXEC; + gf_errno_to_error_array[EBADEXEC] = GF_ERROR_CODE_BADEXEC; + +/* EBADARCH 86 / * Bad CPU type in executable */ + gf_error_to_errno_array[GF_ERROR_CODE_BADARCH] = EBADARCH; + gf_errno_to_error_array[EBADARCH] = GF_ERROR_CODE_BADARCH; + +/* ESHLIBVERS 87 / * Shared library version mismatch */ + gf_error_to_errno_array[GF_ERROR_CODE_SHLIBVERS] = ESHLIBVERS; + gf_errno_to_error_array[ESHLIBVERS] = GF_ERROR_CODE_SHLIBVERS; + +/* EBADMACHO 88 / * Malformed Macho file */ + gf_error_to_errno_array[GF_ERROR_CODE_BADMACHO] = EBADMACHO; + gf_errno_to_error_array[EBADMACHO] = GF_ERROR_CODE_BADMACHO; + +#if 0 + /* EDOOFUS 88 / * Programming error */ + gf_error_to_errno_array[GF_ERROR_CODE_DOOFUS] = EDOOFUS; + gf_errno_to_error_array[EDOOFUS] = GF_ERROR_CODE_DOOFUS; +#endif + + /* ECANCELED 89 / * Operation canceled */ + gf_error_to_errno_array[GF_ERROR_CODE_CANCELED] = ECANCELED; + gf_errno_to_error_array[ECANCELED] = GF_ERROR_CODE_CANCELED; + + /* EIDRM 90 / * Identifier removed */ + gf_error_to_errno_array[GF_ERROR_CODE_IDRM] = EIDRM; + gf_errno_to_error_array[EIDRM] = GF_ERROR_CODE_IDRM; + /* ENOMSG 91 / * No message of desired type */ + gf_error_to_errno_array[GF_ERROR_CODE_NOMSG] = ENOMSG; + gf_errno_to_error_array[ENOMSG] = GF_ERROR_CODE_NOMSG; + + /* EILSEQ 92 / * Illegal byte sequence */ + gf_error_to_errno_array[GF_ERROR_CODE_ILSEQ] = EILSEQ; + gf_errno_to_error_array[EILSEQ] = GF_ERROR_CODE_ILSEQ; + + /* ENOATTR 93 / * Attribute not found */ + gf_error_to_errno_array[GF_ERROR_CODE_NOATTR] = ENOATTR; + gf_errno_to_error_array[ENOATTR] = GF_ERROR_CODE_NOATTR; + + /* EBADMSG 94 / * Bad message */ + gf_error_to_errno_array[GF_ERROR_CODE_BADMSG] = EBADMSG; + gf_errno_to_error_array[EBADMSG] = GF_ERROR_CODE_BADMSG; + + /* EMULTIHOP 95 / * Reserved */ + gf_error_to_errno_array[GF_ERROR_CODE_MULTIHOP] = EMULTIHOP; + gf_errno_to_error_array[EMULTIHOP] = GF_ERROR_CODE_MULTIHOP; + + /* ENODATA 96 / * No message available on STREAM */ + gf_error_to_errno_array[GF_ERROR_CODE_NEEDAUTH] = ENEEDAUTH; + gf_errno_to_error_array[ENEEDAUTH] = GF_ERROR_CODE_NEEDAUTH; + + /* ENOLINK 97 / * Reserved */ + gf_error_to_errno_array[GF_ERROR_CODE_NOLINK] = ENOLINK; + gf_errno_to_error_array[ENOLINK] = GF_ERROR_CODE_NOLINK; + + /* ENOSR 98 / * No STREAM resources */ + gf_error_to_errno_array[GF_ERROR_CODE_NOSR] = ENOSR; + gf_errno_to_error_array[ENOSR] = GF_ERROR_CODE_NOSR; + + /* ENOSTR 99 / * Not a STREAM */ + gf_error_to_errno_array[GF_ERROR_CODE_NOSTR] = ENOSTR; + gf_errno_to_error_array[ENOSTR] = GF_ERROR_CODE_NOSTR; + +/* EPROTO 100 / * Protocol error */ + gf_error_to_errno_array[GF_ERROR_CODE_PROTO] = EPROTO; + gf_errno_to_error_array[EPROTO] = GF_ERROR_CODE_PROTO; +/* ETIME 101 / * STREAM ioctl timeout */ + gf_error_to_errno_array[GF_ERROR_CODE_TIME] = ETIME; + gf_errno_to_error_array[ETIME] = GF_ERROR_CODE_TIME; + +/* This value is only discrete when compiling __DARWIN_UNIX03, or KERNEL */ +/* EOPNOTSUPP 102 / * Operation not supported on socket */ + gf_error_to_errno_array[GF_ERROR_CODE_OPNOTSUPP] = EOPNOTSUPP; + gf_errno_to_error_array[EOPNOTSUPP] = GF_ERROR_CODE_OPNOTSUPP; + +/* ENOPOLICY 103 / * No such policy registered */ + gf_error_to_errno_array[GF_ERROR_CODE_NOPOLICY] = ENOPOLICY; + gf_errno_to_error_array[ENOPOLICY] = GF_ERROR_CODE_NOPOLICY; + + return ; +} +#endif /* GF_DARWIN_HOST_OS */ + +#ifdef GF_BSD_HOST_OS +static void +init_compat_errno_arrays () +{ + /* Quite a bit of things changed in FreeBSD - current */ + + /* EAGAIN 35 / * Try Again */ + gf_error_to_errno_array[GF_ERROR_CODE_AGAIN] = EAGAIN; + gf_errno_to_error_array[EAGAIN] = GF_ERROR_CODE_AGAIN; + + /* EDEADLK 11 / * Resource deadlock would occur */ + gf_error_to_errno_array[GF_ERROR_CODE_DEADLK] = EDEADLK; + gf_errno_to_error_array[EDEADLK] = GF_ERROR_CODE_DEADLK; + + /* EINPROGRESS 36 / * Operation now in progress */ + gf_error_to_errno_array[GF_ERROR_CODE_INPROGRESS] = EINPROGRESS; + gf_errno_to_error_array[EINPROGRESS] = GF_ERROR_CODE_INPROGRESS; + + /* EALREADY 37 / * Operation already in progress */ + gf_error_to_errno_array[GF_ERROR_CODE_ALREADY] = EALREADY; + gf_errno_to_error_array[EALREADY] = GF_ERROR_CODE_ALREADY; + + /* ENOTSOCK 38 / * Socket operation on non-socket */ + gf_error_to_errno_array[GF_ERROR_CODE_NOTSOCK] = ENOTSOCK; + gf_errno_to_error_array[ENOTSOCK] = GF_ERROR_CODE_NOTSOCK; + + /* EDESTADDRREQ 39 / * Destination address required */ + gf_error_to_errno_array[GF_ERROR_CODE_DESTADDRREQ] = EDESTADDRREQ; + gf_errno_to_error_array[EDESTADDRREQ] = GF_ERROR_CODE_DESTADDRREQ; + + /* EMSGSIZE 40 / * Message too long */ + gf_error_to_errno_array[GF_ERROR_CODE_MSGSIZE] = EMSGSIZE; + gf_errno_to_error_array[EMSGSIZE] = GF_ERROR_CODE_MSGSIZE; + + /* EPROTOTYPE 41 / * Protocol wrong type for socket */ + gf_error_to_errno_array[GF_ERROR_CODE_PROTOTYPE] = EPROTOTYPE; + gf_errno_to_error_array[EPROTOTYPE] = GF_ERROR_CODE_PROTOTYPE; + + /* ENOPROTOOPT 42 / * Protocol not available */ + gf_error_to_errno_array[GF_ERROR_CODE_NOPROTOOPT] = ENOPROTOOPT; + gf_errno_to_error_array[ENOPROTOOPT] = GF_ERROR_CODE_NOPROTOOPT; + + /* EPROTONOSUPPORT 43 / * Protocol not supported */ + gf_error_to_errno_array[GF_ERROR_CODE_PROTONOSUPPORT] = EPROTONOSUPPORT; + gf_errno_to_error_array[EPROTONOSUPPORT] = GF_ERROR_CODE_PROTONOSUPPORT; + + /* ESOCKTNOSUPPORT 44 / * Socket type not supported */ + gf_error_to_errno_array[GF_ERROR_CODE_SOCKTNOSUPPORT] = ESOCKTNOSUPPORT; + gf_errno_to_error_array[ESOCKTNOSUPPORT] = GF_ERROR_CODE_SOCKTNOSUPPORT; + + /* EOPNOTSUPP 45 / * Operation not supported */ + gf_error_to_errno_array[GF_ERROR_CODE_OPNOTSUPP] = EOPNOTSUPP; + gf_errno_to_error_array[EOPNOTSUPP] = GF_ERROR_CODE_OPNOTSUPP; + + /* EPFNOSUPPORT 46 / * Protocol family not supported */ + gf_error_to_errno_array[GF_ERROR_CODE_PFNOSUPPORT] = EPFNOSUPPORT; + gf_errno_to_error_array[EPFNOSUPPORT] = GF_ERROR_CODE_PFNOSUPPORT; + + /* EAFNOSUPPORT 47 / * Address family not supported by protocol family */ + gf_error_to_errno_array[GF_ERROR_CODE_AFNOSUPPORT] = EAFNOSUPPORT; + gf_errno_to_error_array[EAFNOSUPPORT] = GF_ERROR_CODE_AFNOSUPPORT; + + /* EADDRINUSE 48 / * Address already in use */ + gf_error_to_errno_array[GF_ERROR_CODE_ADDRINUSE] = EADDRINUSE; + gf_errno_to_error_array[EADDRINUSE] = GF_ERROR_CODE_ADDRINUSE; + + /* EADDRNOTAVAIL 49 / * Can't assign requested address */ + gf_error_to_errno_array[GF_ERROR_CODE_ADDRNOTAVAIL] = EADDRNOTAVAIL; + gf_errno_to_error_array[EADDRNOTAVAIL] = GF_ERROR_CODE_ADDRNOTAVAIL; + + /* ENETDOWN 50 / * Network is down */ + gf_error_to_errno_array[GF_ERROR_CODE_NETDOWN] = ENETDOWN; + gf_errno_to_error_array[ENETDOWN] = GF_ERROR_CODE_NETDOWN; + + /* ENETUNREACH 51 / * Network is unreachable */ + gf_error_to_errno_array[GF_ERROR_CODE_NETUNREACH] = ENETUNREACH; + gf_errno_to_error_array[ENETUNREACH] = GF_ERROR_CODE_NETUNREACH; + + /* ENETRESET 52 / * Network dropped connection on reset */ + gf_error_to_errno_array[GF_ERROR_CODE_NETRESET] = ENETRESET; + gf_errno_to_error_array[ENETRESET] = GF_ERROR_CODE_NETRESET; + + /* ECONNABORTED 53 / * Software caused connection abort */ + gf_error_to_errno_array[GF_ERROR_CODE_CONNABORTED] = ECONNABORTED; + gf_errno_to_error_array[ECONNABORTED] = GF_ERROR_CODE_CONNABORTED; + + /* ECONNRESET 54 / * Connection reset by peer */ + gf_error_to_errno_array[GF_ERROR_CODE_CONNRESET] = ECONNRESET; + gf_errno_to_error_array[ECONNRESET] = GF_ERROR_CODE_CONNRESET; + + /* ENOBUFS 55 / * No buffer space available */ + gf_error_to_errno_array[GF_ERROR_CODE_NOBUFS] = ENOBUFS; + gf_errno_to_error_array[ENOBUFS] = GF_ERROR_CODE_NOBUFS; + + /* EISCONN 56 / * Socket is already connected */ + gf_error_to_errno_array[GF_ERROR_CODE_ISCONN] = EISCONN; + gf_errno_to_error_array[EISCONN] = GF_ERROR_CODE_ISCONN; + + /* ENOTCONN 57 / * Socket is not connected */ + gf_error_to_errno_array[GF_ERROR_CODE_NOTCONN] = ENOTCONN; + gf_errno_to_error_array[ENOTCONN] = GF_ERROR_CODE_NOTCONN; + + /* ESHUTDOWN 58 / * Can't send after socket shutdown */ + gf_error_to_errno_array[GF_ERROR_CODE_SHUTDOWN] = ESHUTDOWN; + gf_errno_to_error_array[ESHUTDOWN] = GF_ERROR_CODE_SHUTDOWN; + + /* ETOOMANYREFS 59 / * Too many references: can't splice */ + gf_error_to_errno_array[GF_ERROR_CODE_TOOMANYREFS] = ETOOMANYREFS; + gf_errno_to_error_array[ETOOMANYREFS] = GF_ERROR_CODE_TOOMANYREFS; + + /* ETIMEDOUT 60 / * Operation timed out */ + gf_error_to_errno_array[GF_ERROR_CODE_TIMEDOUT] = ETIMEDOUT; + gf_errno_to_error_array[ETIMEDOUT] = GF_ERROR_CODE_TIMEDOUT; + + /* ECONNREFUSED 61 / * Connection refused */ + gf_error_to_errno_array[GF_ERROR_CODE_CONNREFUSED] = ECONNREFUSED; + gf_errno_to_error_array[ECONNREFUSED] = GF_ERROR_CODE_CONNREFUSED; + + /* ELOOP 62 / * Too many levels of symbolic links */ + gf_error_to_errno_array[GF_ERROR_CODE_LOOP] = ELOOP; + gf_errno_to_error_array[ELOOP] = GF_ERROR_CODE_LOOP; + + /* ENAMETOOLONG 63 / * File name too long */ + gf_error_to_errno_array[GF_ERROR_CODE_NAMETOOLONG] = ENAMETOOLONG; + gf_errno_to_error_array[ENAMETOOLONG] = GF_ERROR_CODE_NAMETOOLONG; + + /* EHOSTDOWN 64 / * Host is down */ + gf_error_to_errno_array[GF_ERROR_CODE_HOSTDOWN] = EHOSTDOWN; + gf_errno_to_error_array[EHOSTDOWN] = GF_ERROR_CODE_HOSTDOWN; + + /* EHOSTUNREACH 65 / * No route to host */ + gf_error_to_errno_array[GF_ERROR_CODE_HOSTUNREACH] = EHOSTUNREACH; + gf_errno_to_error_array[EHOSTUNREACH] = GF_ERROR_CODE_HOSTUNREACH; + + /* ENOTEMPTY 66 / * Directory not empty */ + gf_error_to_errno_array[GF_ERROR_CODE_NOTEMPTY] = ENOTEMPTY; + gf_errno_to_error_array[ENOTEMPTY] = GF_ERROR_CODE_NOTEMPTY; + + /* EPROCLIM 67 / * Too many processes */ + gf_error_to_errno_array[GF_ERROR_CODE_PROCLIM] = EPROCLIM; + gf_errno_to_error_array[EPROCLIM] = GF_ERROR_CODE_PROCLIM; + + /* EUSERS 68 / * Too many users */ + gf_error_to_errno_array[GF_ERROR_CODE_USERS] = EUSERS; + gf_errno_to_error_array[EUSERS] = GF_ERROR_CODE_USERS; + + /* EDQUOT 69 / * Disc quota exceeded */ + gf_error_to_errno_array[GF_ERROR_CODE_DQUOT] = EDQUOT; + gf_errno_to_error_array[EDQUOT] = GF_ERROR_CODE_DQUOT; + + /* ESTALE 70 / * Stale NFS file handle */ + gf_error_to_errno_array[GF_ERROR_CODE_STALE] = ESTALE; + gf_errno_to_error_array[ESTALE] = GF_ERROR_CODE_STALE; + + /* EREMOTE 71 / * Too many levels of remote in path */ + gf_error_to_errno_array[GF_ERROR_CODE_REMOTE] = EREMOTE; + gf_errno_to_error_array[EREMOTE] = GF_ERROR_CODE_REMOTE; + + /* EBADRPC 72 / * RPC struct is bad */ + gf_error_to_errno_array[GF_ERROR_CODE_BADRPC] = EBADRPC; + gf_errno_to_error_array[EBADRPC] = GF_ERROR_CODE_BADRPC; + + /* ERPCMISMATCH 73 / * RPC version wrong */ + gf_error_to_errno_array[GF_ERROR_CODE_RPCMISMATCH] = ERPCMISMATCH; + gf_errno_to_error_array[ERPCMISMATCH] = GF_ERROR_CODE_RPCMISMATCH; + + /* EPROGUNAVAIL 74 / * RPC prog. not avail */ + gf_error_to_errno_array[GF_ERROR_CODE_PROGUNAVAIL] = EPROGUNAVAIL; + gf_errno_to_error_array[EPROGUNAVAIL] = GF_ERROR_CODE_PROGUNAVAIL; + + /* EPROGMISMATCH 75 / * Program version wrong */ + gf_error_to_errno_array[GF_ERROR_CODE_PROGMISMATCH] = EPROGMISMATCH; + gf_errno_to_error_array[EPROGMISMATCH] = GF_ERROR_CODE_PROGMISMATCH; + + /* EPROCUNAVAIL 76 / * Bad procedure for program */ + gf_error_to_errno_array[GF_ERROR_CODE_PROCUNAVAIL] = EPROCUNAVAIL; + gf_errno_to_error_array[EPROCUNAVAIL] = GF_ERROR_CODE_PROCUNAVAIL; + + /* ENOLCK 77 / * No locks available */ + gf_error_to_errno_array[GF_ERROR_CODE_NOLCK] = ENOLCK; + gf_errno_to_error_array[ENOLCK] = GF_ERROR_CODE_NOLCK; + + /* ENOSYS 78 / * Function not implemented */ + gf_error_to_errno_array[GF_ERROR_CODE_NOSYS] = ENOSYS; + gf_errno_to_error_array[ENOSYS] = GF_ERROR_CODE_NOSYS; + + /* EFTYPE 79 / * Inappropriate file type or format */ + gf_error_to_errno_array[GF_ERROR_CODE_FTYPE] = EFTYPE; + gf_errno_to_error_array[EFTYPE] = GF_ERROR_CODE_FTYPE; + + /* EAUTH 80 / * Authentication error */ + gf_error_to_errno_array[GF_ERROR_CODE_AUTH] = EAUTH; + gf_errno_to_error_array[EAUTH] = GF_ERROR_CODE_AUTH; + + /* ENEEDAUTH 81 / * Need authenticator */ + gf_error_to_errno_array[GF_ERROR_CODE_NEEDAUTH] = ENEEDAUTH; + gf_errno_to_error_array[ENEEDAUTH] = GF_ERROR_CODE_NEEDAUTH; + + /* EIDRM 82 / * Identifier removed */ + gf_error_to_errno_array[GF_ERROR_CODE_IDRM] = EIDRM; + gf_errno_to_error_array[EIDRM] = GF_ERROR_CODE_IDRM; + + /* ENOMSG 83 / * No message of desired type */ + gf_error_to_errno_array[GF_ERROR_CODE_NOMSG] = ENOMSG; + gf_errno_to_error_array[ENOMSG] = GF_ERROR_CODE_NOMSG; + + /* EOVERFLOW 84 / * Value too large to be stored in data type */ + gf_error_to_errno_array[GF_ERROR_CODE_OVERFLOW] = EOVERFLOW; + gf_errno_to_error_array[EOVERFLOW] = GF_ERROR_CODE_OVERFLOW; + + /* ECANCELED 85 / * Operation canceled */ + gf_error_to_errno_array[GF_ERROR_CODE_CANCELED] = ECANCELED; + gf_errno_to_error_array[ECANCELED] = GF_ERROR_CODE_CANCELED; + + /* EILSEQ 86 / * Illegal byte sequence */ + gf_error_to_errno_array[GF_ERROR_CODE_ILSEQ] = EILSEQ; + gf_errno_to_error_array[EILSEQ] = GF_ERROR_CODE_ILSEQ; + + /* ENOATTR 87 / * Attribute not found */ + gf_error_to_errno_array[GF_ERROR_CODE_NOATTR] = ENOATTR; + gf_errno_to_error_array[ENOATTR] = GF_ERROR_CODE_NOATTR; + + /* EDOOFUS 88 / * Programming error */ + gf_error_to_errno_array[GF_ERROR_CODE_DOOFUS] = EDOOFUS; + gf_errno_to_error_array[EDOOFUS] = GF_ERROR_CODE_DOOFUS; + + /* EBADMSG 89 / * Bad message */ + gf_error_to_errno_array[GF_ERROR_CODE_BADMSG] = EBADMSG; + gf_errno_to_error_array[EBADMSG] = GF_ERROR_CODE_BADMSG; + + /* EMULTIHOP 90 / * Multihop attempted */ + gf_error_to_errno_array[GF_ERROR_CODE_MULTIHOP] = EMULTIHOP; + gf_errno_to_error_array[EMULTIHOP] = GF_ERROR_CODE_MULTIHOP; + + /* ENOLINK 91 / * Link has been severed */ + gf_error_to_errno_array[GF_ERROR_CODE_NOLINK] = ENOLINK; + gf_errno_to_error_array[ENOLINK] = GF_ERROR_CODE_NOLINK; + + /* EPROTO 92 / * Protocol error */ + gf_error_to_errno_array[GF_ERROR_CODE_PROTO] = EPROTO; + gf_errno_to_error_array[EPROTO] = GF_ERROR_CODE_PROTO; + + + return ; +} +#endif /* GF_BSD_HOST_OS */ + +#ifdef GF_LINUX_HOST_OS +static void +init_compat_errno_arrays () +{ + /* Things are fine. Everything should work seemlessly on GNU/Linux machines */ + return ; +} +#endif /* GF_LINUX_HOST_OS */ + + +static void +init_errno_arrays () +{ + int i; + for (i=0; i < GF_ERROR_CODE_UNKNOWN; i++) { + gf_errno_to_error_array[i] = i; + gf_error_to_errno_array[i] = i; + } + /* Now change the order if it needs to be. */ + init_compat_errno_arrays(); + + return; +} + +int32_t +gf_errno_to_error (int32_t op_errno) +{ + if (!gf_compat_errno_init_done) { + init_errno_arrays (); + gf_compat_errno_init_done = 1; + } + + if ((op_errno > GF_ERROR_CODE_SUCCESS) && (op_errno < GF_ERROR_CODE_UNKNOWN)) + return gf_errno_to_error_array[op_errno]; + + return op_errno; +} + + +int32_t +gf_error_to_errno (int32_t error) +{ + if (!gf_compat_errno_init_done) { + init_errno_arrays (); + gf_compat_errno_init_done = 1; + } + + if ((error > GF_ERROR_CODE_SUCCESS) && (error < GF_ERROR_CODE_UNKNOWN)) + return gf_error_to_errno_array[error]; + + return error; +} + diff --git a/libglusterfs/src/compat-errno.h b/libglusterfs/src/compat-errno.h new file mode 100644 index 000000000..918df45eb --- /dev/null +++ b/libglusterfs/src/compat-errno.h @@ -0,0 +1,240 @@ +/* + Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef __COMPAT_ERRNO_H__ +#define __COMPAT_ERRNO_H__ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <errno.h> + +#define GF_ERROR_CODE_SUCCESS 0 +#define GF_ERROR_CODE_UNKNOWN 1024 +#define GF_ERRNO_UNKNOWN 1024 + +#define GF_ERROR_CODE_PERM 1 /* Operation not permitted */ +#define GF_ERROR_CODE_NOENT 2 /* No such file or directory */ +#define GF_ERROR_CODE_SRCH 3 /* No such process */ +#define GF_ERROR_CODE_INTR 4 /* Interrupted system call */ +#define GF_ERROR_CODE_IO 5 /* I/O error */ +#define GF_ERROR_CODE_NXIO 6 /* No such device or address */ +#define GF_ERROR_CODE_2BIG 7 /* Argument list too long */ +#define GF_ERROR_CODE_NOEXEC 8 /* Exec format error */ +#define GF_ERROR_CODE_BADF 9 /* Bad file number */ +#define GF_ERROR_CODE_CHILD 10 /* No child processes */ +#define GF_ERROR_CODE_AGAIN 11 /* Try again */ +#define GF_ERROR_CODE_NOMEM 12 /* Out of memory */ +#define GF_ERROR_CODE_ACCES 13 /* Permission denied */ +#define GF_ERROR_CODE_FAULT 14 /* Bad address */ +#define GF_ERROR_CODE_NOTBLK 15 /* Block device required */ +#define GF_ERROR_CODE_BUSY 16 /* Device or resource busy */ +#define GF_ERROR_CODE_EXIST 17 /* File exists */ +#define GF_ERROR_CODE_XDEV 18 /* Cross-device link */ +#define GF_ERROR_CODE_NODEV 19 /* No such device */ +#define GF_ERROR_CODE_NOTDIR 20 /* Not a directory */ +#define GF_ERROR_CODE_ISDIR 21 /* Is a directory */ +#define GF_ERROR_CODE_INVAL 22 /* Invalid argument */ +#define GF_ERROR_CODE_NFILE 23 /* File table overflow */ +#define GF_ERROR_CODE_MFILE 24 /* Too many open files */ +#define GF_ERROR_CODE_NOTTY 25 /* Not a typewriter */ +#define GF_ERROR_CODE_TXTBSY 26 /* Text file busy */ +#define GF_ERROR_CODE_FBIG 27 /* File too large */ +#define GF_ERROR_CODE_NOSPC 28 /* No space left on device */ +#define GF_ERROR_CODE_SPIPE 29 /* Illegal seek */ +#define GF_ERROR_CODE_ROFS 30 /* Read-only file system */ +#define GF_ERROR_CODE_MLINK 31 /* Too many links */ +#define GF_ERROR_CODE_PIPE 32 /* Broken pipe */ +#define GF_ERROR_CODE_DOM 33 /* Math argument out of domain of func */ +#define GF_ERROR_CODE_RANGE 34 /* Math result not representable */ +#define GF_ERROR_CODE_DEADLK 35 /* Resource deadlock would occur */ +#define GF_ERROR_CODE_NAMETOOLONG 36 /* File name too long */ +#define GF_ERROR_CODE_NOLCK 37 /* No record locks available */ +#define GF_ERROR_CODE_NOSYS 38 /* Function not implemented */ +#define GF_ERROR_CODE_NOTEMPTY 39 /* Directory not empty */ +#define GF_ERROR_CODE_LOOP 40 /* Too many symbolic links encountered */ + +#define GF_ERROR_CODE_NOMSG 42 /* No message of desired type */ +#define GF_ERROR_CODE_IDRM 43 /* Identifier removed */ +#define GF_ERROR_CODE_CHRNG 44 /* Channel number out of range */ +#define GF_ERROR_CODE_L2NSYNC 45 /* Level 2 not synchronized */ +#define GF_ERROR_CODE_L3HLT 46 /* Level 3 halted */ +#define GF_ERROR_CODE_L3RST 47 /* Level 3 reset */ +#define GF_ERROR_CODE_LNRNG 48 /* Link number out of range */ +#define GF_ERROR_CODE_UNATCH 49 /* Protocol driver not attached */ +#define GF_ERROR_CODE_NOCSI 50 /* No CSI structure available */ +#define GF_ERROR_CODE_L2HLT 51 /* Level 2 halted */ +#define GF_ERROR_CODE_BADE 52 /* Invalid exchange */ +#define GF_ERROR_CODE_BADR 53 /* Invalid request descriptor */ +#define GF_ERROR_CODE_XFULL 54 /* Exchange full */ +#define GF_ERROR_CODE_NOANO 55 /* No anode */ +#define GF_ERROR_CODE_BADRQC 56 /* Invalid request code */ +#define GF_ERROR_CODE_BADSLT 57 /* Invalid slot */ +#define GF_ERROR_CODE_BFONT 59 /* Bad font file format */ +#define GF_ERROR_CODE_NOSTR 60 /* Device not a stream */ +#define GF_ERROR_CODE_NODATA 61 /* No data available */ +#define GF_ERROR_CODE_TIME 62 /* Timer expired */ +#define GF_ERROR_CODE_NOSR 63 /* Out of streams resources */ +#define GF_ERROR_CODE_NONET 64 /* Machine is not on the network */ +#define GF_ERROR_CODE_NOPKG 65 /* Package not installed */ +#define GF_ERROR_CODE_REMOTE 66 /* Object is remote */ +#define GF_ERROR_CODE_NOLINK 67 /* Link has been severed */ +#define GF_ERROR_CODE_ADV 68 /* Advertise error */ +#define GF_ERROR_CODE_SRMNT 69 /* Srmount error */ +#define GF_ERROR_CODE_COMM 70 /* Communication error on send */ +#define GF_ERROR_CODE_PROTO 71 /* Protocol error */ +#define GF_ERROR_CODE_MULTIHOP 72 /* Multihop attempted */ +#define GF_ERROR_CODE_DOTDOT 73 /* RFS specific error */ +#define GF_ERROR_CODE_BADMSG 74 /* Not a data message */ +#define GF_ERROR_CODE_OVERFLOW 75 /* Value too large for defined data type */ +#define GF_ERROR_CODE_NOTUNIQ 76 /* Name not unique on network */ +#define GF_ERROR_CODE_BADFD 77 /* File descriptor in bad state */ +#define GF_ERROR_CODE_REMCHG 78 /* Remote address changed */ +#define GF_ERROR_CODE_LIBACC 79 /* Can not access a needed shared library */ +#define GF_ERROR_CODE_LIBBAD 80 /* Accessing a corrupted shared library */ +#define GF_ERROR_CODE_LIBSCN 81 /* .lib section in a.out corrupted */ +#define GF_ERROR_CODE_LIBMAX 82 /* Attempting to link in too many shared libraries */ +#define GF_ERROR_CODE_LIBEXEC 83 /* Cannot exec a shared library directly */ +#define GF_ERROR_CODE_ILSEQ 84 /* Illegal byte sequence */ +#define GF_ERROR_CODE_RESTART 85 /* Interrupted system call should be restarted */ +#define GF_ERROR_CODE_STRPIPE 86 /* Streams pipe error */ +#define GF_ERROR_CODE_USERS 87 /* Too many users */ +#define GF_ERROR_CODE_NOTSOCK 88 /* Socket operation on non-socket */ +#define GF_ERROR_CODE_DESTADDRREQ 89 /* Destination address required */ +#define GF_ERROR_CODE_MSGSIZE 90 /* Message too long */ +#define GF_ERROR_CODE_PROTOTYPE 91 /* Protocol wrong type for socket */ +#define GF_ERROR_CODE_NOPROTOOPT 92 /* Protocol not available */ +#define GF_ERROR_CODE_PROTONOSUPPORT 93 /* Protocol not supported */ +#define GF_ERROR_CODE_SOCKTNOSUPPORT 94 /* Socket type not supported */ +#define GF_ERROR_CODE_OPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define GF_ERROR_CODE_PFNOSUPPORT 96 /* Protocol family not supported */ +#define GF_ERROR_CODE_AFNOSUPPORT 97 /* Address family not supported by protocol */ +#define GF_ERROR_CODE_ADDRINUSE 98 /* Address already in use */ +#define GF_ERROR_CODE_ADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define GF_ERROR_CODE_NETDOWN 100 /* Network is down */ +#define GF_ERROR_CODE_NETUNREACH 101 /* Network is unreachable */ +#define GF_ERROR_CODE_NETRESET 102 /* Network dropped connection because of reset */ +#define GF_ERROR_CODE_CONNABORTED 103 /* Software caused connection abort */ +#define GF_ERROR_CODE_CONNRESET 104 /* Connection reset by peer */ +#define GF_ERROR_CODE_NOBUFS 105 /* No buffer space available */ +#define GF_ERROR_CODE_ISCONN 106 /* Transport endpoint is already connected */ +#define GF_ERROR_CODE_NOTCONN 107 /* Transport endpoint is not connected */ +#define GF_ERROR_CODE_SHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define GF_ERROR_CODE_TOOMANYREFS 109 /* Too many references: cannot splice */ +#define GF_ERROR_CODE_TIMEDOUT 110 /* Connection timed out */ +#define GF_ERROR_CODE_CONNREFUSED 111 /* Connection refused */ +#define GF_ERROR_CODE_HOSTDOWN 112 /* Host is down */ +#define GF_ERROR_CODE_HOSTUNREACH 113 /* No route to host */ +#define GF_ERROR_CODE_ALREADY 114 /* Operation already in progress */ +#define GF_ERROR_CODE_INPROGRESS 115 /* Operation now in progress */ +#define GF_ERROR_CODE_ALREADY 114 /* Operation already in progress */ +#define GF_ERROR_CODE_INPROGRESS 115 /* Operation now in progress */ +#define GF_ERROR_CODE_STALE 116 /* Stale NFS file handle */ +#define GF_ERROR_CODE_UCLEAN 117 /* Structure needs cleaning */ +#define GF_ERROR_CODE_NOTNAM 118 /* Not a XENIX named type file */ +#define GF_ERROR_CODE_NAVAIL 119 /* No XENIX semaphores available */ +#define GF_ERROR_CODE_ISNAM 120 /* Is a named type file */ +#define GF_ERROR_CODE_REMOTEIO 121 /* Remote I/O error */ +#define GF_ERROR_CODE_DQUOT 122 /* Quota exceeded */ +#define GF_ERROR_CODE_NOMEDIUM 123 /* No medium found */ +#define GF_ERROR_CODE_MEDIUMTYPE 124 /* Wrong medium type */ +#define GF_ERROR_CODE_CANCELED 125 /* Operation Canceled */ +#define GF_ERROR_CODE_NOKEY 126 /* Required key not available */ +#define GF_ERROR_CODE_KEYEXPIRED 127 /* Key has expired */ +#define GF_ERROR_CODE_KEYREVOKED 128 /* Key has been revoked */ +#define GF_ERROR_CODE_KEYREJECTED 129 /* Key was rejected by service */ + +/* for robust mutexes */ +#define GF_ERROR_CODE_OWNERDEAD 130 /* Owner died */ +#define GF_ERROR_CODE_NOTRECOVERABLE 131 /* State not recoverable */ + + + +/* Should never be seen by user programs */ +#define GF_ERROR_CODE_RESTARTSYS 512 +#define GF_ERROR_CODE_RESTARTNOINTR 513 +#define GF_ERROR_CODE_RESTARTNOHAND 514 /* restart if no handler.. */ +#define GF_ERROR_CODE_NOIOCTLCMD 515 /* No ioctl command */ +#define GF_ERROR_CODE_RESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */ + +/* Defined for the NFSv3 protocol */ +#define GF_ERROR_CODE_BADHANDLE 521 /* Illegal NFS file handle */ +#define GF_ERROR_CODE_NOTSYNC 522 /* Update synchronization mismatch */ +#define GF_ERROR_CODE_BADCOOKIE 523 /* Cookie is stale */ +#define GF_ERROR_CODE_NOTSUPP 524 /* Operation is not supported */ +#define GF_ERROR_CODE_TOOSMALL 525 /* Buffer or request is too small */ +#define GF_ERROR_CODE_SERVERFAULT 526 /* An untranslatable error occurred */ +#define GF_ERROR_CODE_BADTYPE 527 /* Type not supported by server */ +#define GF_ERROR_CODE_JUKEBOX 528 /* Request initiated, but will not complete before timeout */ +#define GF_ERROR_CODE_IOCBQUEUED 529 /* iocb queued, will get completion event */ +#define GF_ERROR_CODE_IOCBRETRY 530 /* iocb queued, will trigger a retry */ + +/* Darwin OS X */ +#define GF_ERROR_CODE_NOPOLICY 701 +#define GF_ERROR_CODE_BADMACHO 702 +#define GF_ERROR_CODE_PWROFF 703 +#define GF_ERROR_CODE_DEVERR 704 +#define GF_ERROR_CODE_BADARCH 705 +#define GF_ERROR_CODE_BADEXEC 706 +#define GF_ERROR_CODE_SHLIBVERS 707 + + + +/* Solaris */ +/* ENOTACTIVE 73 / * Facility is not active */ +#define GF_ERROR_CODE_NOTACTIVE 801 +/* ELOCKUNMAPPED 72 / * locked lock was unmapped */ +#define GF_ERROR_CODE_LOCKUNMAPPED 802 + +/* BSD system */ +#define GF_ERROR_CODE_PROCLIM 901 /* Too many processes */ +#define GF_ERROR_CODE_BADRPC 902 /* RPC struct is bad */ +#define GF_ERROR_CODE_RPCMISMATCH 903 /* RPC version wrong */ +#define GF_ERROR_CODE_PROGUNAVAIL 904 /* RPC prog. not avail */ +#define GF_ERROR_CODE_PROGMISMATCH 905 /* Program version wrong */ +#define GF_ERROR_CODE_PROCUNAVAIL 905 /* Bad procedure for program */ +#define GF_ERROR_CODE_FTYPE 906 /* Inappropriate file type or format */ +#define GF_ERROR_CODE_AUTH 907 /* Authentication error */ +#define GF_ERROR_CODE_NEEDAUTH 908 /* Need authenticator */ +#define GF_ERROR_CODE_DOOFUS 909 /* Programming error */ + +#define GF_ERROR_CODE_NOATTR GF_ERROR_CODE_NODATA /* Attribute not found */ + +/* Either one of enodata or enoattr will be there in system */ +#ifndef ENOATTR +#define ENOATTR ENODATA +#endif /* ENOATTR */ + +#ifndef ENODATA +#define ENODATA ENOATTR +#endif /* ENODATA */ + +#ifndef EBADFD +#define EBADFD EBADRPC +#endif /* EBADFD */ + +/* These functions are defined for all the OS flags, but content will + * be different for each OS flag. + */ +int32_t gf_errno_to_error (int32_t op_errno); +int32_t gf_error_to_errno (int32_t error); + +#endif /* __COMPAT_ERRNO_H__ */ diff --git a/libglusterfs/src/compat.c b/libglusterfs/src/compat.c new file mode 100644 index 000000000..71aeb32c7 --- /dev/null +++ b/libglusterfs/src/compat.c @@ -0,0 +1,383 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> +#include <getopt.h> +#include <sys/types.h> +#include <dirent.h> + +#ifdef GF_SOLARIS_HOST_OS +#include "logging.h" +#endif /* GF_SOLARIS_HOST_OS */ + +#include "compat.h" +#include "common-utils.h" + +#ifdef GF_DARWIN_HOST_OS + +#define GF_FINDER_INFO_XATTR "com.apple.FinderInfo" +#define GF_RESOURCE_FORK_XATTR "com.apple.ResourceFork" +#define GF_FINDER_INFO_SIZE 32 + +static const char gf_finder_info_content[GF_FINDER_INFO_SIZE] = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, +}; + + +int32_t +gf_darwin_compat_listxattr (int len, dict_t *dict, int size) +{ + data_t *data = NULL; + if (len == -1) + len = 0; + + data = dict_get (dict, GF_FINDER_INFO_XATTR); + if (!data) { + dict_set (dict, GF_FINDER_INFO_XATTR, + bin_to_data ((void *)gf_finder_info_content, + GF_FINDER_INFO_SIZE)); + len += strlen (GF_FINDER_INFO_XATTR); + } + + data = dict_get (dict, GF_RESOURCE_FORK_XATTR); + if (!data) { + dict_set (dict, GF_RESOURCE_FORK_XATTR, str_to_data ("")); + len += strlen (GF_RESOURCE_FORK_XATTR); + } + + return len; +} + +int32_t +gf_darwin_compat_getxattr (const char *key, dict_t *dict) +{ + data_t *data = NULL; + + if (strcmp(key, GF_FINDER_INFO_XATTR) == 0) { + data = dict_get (dict, GF_FINDER_INFO_XATTR); + if (!data) { + dict_set (dict, GF_FINDER_INFO_XATTR, + bin_to_data ((void *)gf_finder_info_content, + GF_FINDER_INFO_SIZE)); + return GF_FINDER_INFO_SIZE; + } + return 0; + } + + if (strcmp(key, GF_RESOURCE_FORK_XATTR) == 0) { + data = dict_get (dict, GF_RESOURCE_FORK_XATTR); + if (!data) { + /* Always null */ + dict_set (dict, GF_RESOURCE_FORK_XATTR, + str_to_data ("")); + return 0; + } + return 0; + } + return -1; +} + + +int32_t +gf_darwin_compat_setxattr (dict_t *dict) +{ + data_t *data = NULL; + + data = dict_get (dict, GF_FINDER_INFO_XATTR); + if (data) + return 0; + data = dict_get (dict, GF_RESOURCE_FORK_XATTR); + if (data) + return 0; + + return -1; +} + +#endif /* DARWIN */ + + +#ifdef GF_SOLARIS_HOST_OS + +int +solaris_fsetxattr(int fd, + const char* key, + const char *value, + size_t size, + int flags) +{ + int attrfd = -1; + int ret = 0; + + attrfd = openat (fd, key, flags|O_CREAT|O_WRONLY|O_XATTR, 0777); + if (attrfd >= 0) { + ftruncate (attrfd, 0); + ret = write (attrfd, value, size); + close (attrfd); + } else { + if (errno != ENOENT) + gf_log ("libglusterfs", GF_LOG_ERROR, + "Couldn't set extended attribute for %d (%d)", + fd, errno); + return -1; + } + + return 0; +} + + +int +solaris_fgetxattr(int fd, + const char* key, + char *value, + size_t size) +{ + int attrfd = -1; + int ret = 0; + + attrfd = openat (fd, key, O_RDONLY|O_XATTR); + if (attrfd >= 0) { + if (size == 0) { + struct stat buf; + fstat (attrfd, &buf); + ret = buf.st_size; + } else { + ret = read (attrfd, value, size); + } + close (attrfd); + } else { + if (errno == ENOENT) + errno = ENODATA; + if (errno != ENOENT) + gf_log ("libglusterfs", GF_LOG_DEBUG, + "Couldn't read extended attribute for the file %d (%d)", + fd, errno); + return -1; + } + + return ret; +} + + +int +solaris_setxattr(const char *path, + const char* key, + const char *value, + size_t size, + int flags) +{ + int attrfd = -1; + int ret = 0; + + attrfd = attropen (path, key, flags|O_CREAT|O_WRONLY, 0777); + if (attrfd >= 0) { + ftruncate (attrfd, 0); + ret = write (attrfd, value, size); + close (attrfd); + } else { + if (errno != ENOENT) + gf_log ("libglusterfs", GF_LOG_ERROR, + "Couldn't set extended attribute for %s (%d)", + path, errno); + return -1; + } + + return 0; +} + + +int +solaris_listxattr(const char *path, + char *list, + size_t size) +{ + int attrdirfd = -1; + ssize_t len = 0; + DIR *dirptr = NULL; + struct dirent *dent = NULL; + int newfd = -1; + + attrdirfd = attropen (path, ".", O_RDONLY, 0); + if (attrdirfd >= 0) { + newfd = dup(attrdirfd); + dirptr = fdopendir(newfd); + if (dirptr) { + while ((dent = readdir(dirptr))) { + size_t listlen = strlen(dent->d_name); + if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) { + /* we don't want "." and ".." here */ + continue; + } + if (size == 0) { + /* return the current size of the list of extended attribute names*/ + len += listlen + 1; + } else { + /* check size and copy entrie + nul into list. */ + if ((len + listlen + 1) > size) { + errno = ERANGE; + len = -1; + break; + } else { + strncpy(list + len, dent->d_name, listlen); + len += listlen; + list[len] = '\0'; + ++len; + } + } + } + + if (closedir(dirptr) == -1) { + close (attrdirfd); + return -1; + } + } else { + close (attrdirfd); + return -1; + } + close (attrdirfd); + } + return len; +} + +int +solaris_removexattr(const char *path, + const char* key) +{ + int ret = -1; + int attrfd = attropen (path, ".", O_RDONLY, 0); + if (attrfd >= 0) { + ret = unlinkat (attrfd, key, 0); + close (attrfd); + } else { + if (errno == ENOENT) + errno = ENODATA; + return -1; + } + + return ret; +} + +int +solaris_getxattr(const char *path, + const char* key, + char *value, + size_t size) +{ + int attrfd = -1; + int ret = 0; + + attrfd = attropen (path, key, O_RDONLY, 0); + if (attrfd >= 0) { + if (size == 0) { + struct stat buf; + fstat (attrfd, &buf); + ret = buf.st_size; + } else { + ret = read (attrfd, value, size); + } + close (attrfd); + } else { + if (errno == ENOENT) + errno = ENODATA; + if (errno != ENOENT) + gf_log ("libglusterfs", GF_LOG_DEBUG, + "Couldn't read extended attribute for the file %s (%d)", + path, errno); + return -1; + } + return ret; +} + + +int +asprintf(char **string_ptr, const char *format, ...) +{ + va_list arg; + char *str; + int size; + int rv; + + if (!string_ptr || !format) + return -1; + + va_start(arg, format); + size = vsnprintf(NULL, 0, format, arg); + size++; + va_start(arg, format); + str = MALLOC(size); + if (str == NULL) { + va_end(arg); + /* + * Strictly speaking, GNU asprintf doesn't do this, + * but the caller isn't checking the return value. + */ + gf_log ("libglusterfs", GF_LOG_CRITICAL, "failed to allocate memory"); + return -1; + } + rv = vsnprintf(str, size, format, arg); + va_end(arg); + + *string_ptr = str; + return (rv); +} + +char* strsep(char** str, const char* delims) +{ + char* token; + + if (*str==NULL) { + /* No more tokens */ + return NULL; + } + + token=*str; + while (**str!='\0') { + if (strchr(delims,**str)!=NULL) { + **str='\0'; + (*str)++; + return token; + } + (*str)++; + } + /* There is no other token */ + *str=NULL; + return token; +} + +#endif /* GF_SOLARIS_HOST_OS */ + +#ifndef HAVE_STRNLEN +size_t +strnlen(const char *string, size_t maxlen) +{ + int len = 0; + while ((len < maxlen) && string[len]) + len++; + return len; +} +#endif /* STRNLEN */ diff --git a/libglusterfs/src/compat.h b/libglusterfs/src/compat.h new file mode 100644 index 000000000..1e8ccaab1 --- /dev/null +++ b/libglusterfs/src/compat.h @@ -0,0 +1,356 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef __COMPAT_H__ +#define __COMPAT_H__ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <stdint.h> +#include "dict.h" + +#ifndef LLONG_MAX +#define LLONG_MAX LONG_LONG_MAX /* compat with old gcc */ +#endif /* LLONG_MAX */ + + +#ifdef GF_LINUX_HOST_OS + +#define UNIX_PATH_MAX 108 + +#include <sys/un.h> +#include <linux/limits.h> +#include <sys/xattr.h> +#include <endian.h> + + +#ifndef HAVE_LLISTXATTR + +/* This part is valid only incase of old glibc which doesn't support + * 'llistxattr()' system calls. + */ + +#define lremovexattr(path,key) removexattr(path,key) +#define llistxattr(path,key,size) listxattr(path,key,size) +#define lgetxattr(path, key, value, size) getxattr(path,key,value,size) +#define lsetxattr(path,key,value,size,flags) setxattr(path,key,value,size,flags) + +#endif /* HAVE_LLISTXATTR */ +#endif /* GF_LINUX_HOST_OS */ + +#ifdef GF_BSD_HOST_OS +/* In case of FreeBSD */ + +#define UNIX_PATH_MAX 104 +#include <sys/types.h> + +#include <sys/un.h> +#include <sys/endian.h> +#include <sys/extattr.h> +#include <limits.h> + +#include <libgen.h> + +enum { + ATTR_CREATE = 1, +#define XATTR_CREATE ATTR_CREATE + ATTR_REPLACE = 2 +#define XATTR_REPLACE ATTR_REPLACE +}; + + +#ifndef sighandler_t +#define sighandler_t sig_t +#endif + +#ifndef ino64_t +#define ino64_t ino_t +#endif + +#ifndef EUCLEAN +#define EUCLEAN 0 +#endif + +#include <netinet/in.h> +#ifndef s6_addr16 +#define s6_addr16 __u6_addr.__u6_addr16 +#endif +#ifndef s6_addr32 +#define s6_addr32 __u6_addr.__u6_addr32 +#endif + +/* Posix dictates NAME_MAX to be used */ +# ifndef NAME_MAX +# ifdef MAXNAMLEN +# define NAME_MAX MAXNAMLEN +# else +# define NAME_MAX 255 +# endif +# endif + +#define lremovexattr(path,key) extattr_delete_link(path, EXTATTR_NAMESPACE_USER, key) +#define llistxattr(path,key,size) extattr_list_link(path, EXTATTR_NAMESPACE_USER, key, size) +#define lgetxattr(path, key, value, size) extattr_get_link(path, EXTATTR_NAMESPACE_USER, key, value, size) +#define lsetxattr(path,key,value,size,flags) extattr_set_link(path, EXTATTR_NAMESPACE_USER, key, value, size) +#define fgetxattr(fd,key,value,size) extattr_get_fd(fd, EXTATTR_NAMESPACE_USER, key, value, size) +#define fsetxattr(fd,key,value,size,flag) extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, key, value, size) + + +#define F_GETLK64 F_GETLK +#define F_SETLK64 F_SETLK +#define F_SETLKW64 F_SETLKW + +#endif /* GF_BSD_HOST_OS */ + +#ifdef GF_DARWIN_HOST_OS + +#define UNIX_PATH_MAX 104 +#include <sys/types.h> + +#include <sys/un.h> +#include <machine/endian.h> +#include <sys/xattr.h> +#include <limits.h> + +#include <libgen.h> + + +#if __DARWIN_64_BIT_INO_T == 0 +# error '64 bit ino_t is must for GlusterFS to work, Compile with "CFLAGS=-D__DARWIN_64_BIT_INO_T"' +#endif /* __DARWIN_64_BIT_INO_T */ + + +#if __DARWIN_64_BIT_INO_T == 0 +# error '64 bit ino_t is must for GlusterFS to work, Compile with "CFLAGS=-D__DARWIN_64_BIT_INO_T"' +#endif /* __DARWIN_64_BIT_INO_T */ + +#ifndef sighandler_t +#define sighandler_t sig_t +#endif + +#ifndef EUCLEAN +#define EUCLEAN 0 +#endif + +#include <netinet/in.h> +#ifndef s6_addr16 +#define s6_addr16 __u6_addr.__u6_addr16 +#endif +#ifndef s6_addr32 +#define s6_addr32 __u6_addr.__u6_addr32 +#endif + +/* Posix dictates NAME_MAX to be used */ +# ifndef NAME_MAX +# ifdef MAXNAMLEN +# define NAME_MAX MAXNAMLEN +# else +# define NAME_MAX 255 +# endif +# endif + +#define llistxattr(path,key,size) listxattr(path,key,size,XATTR_NOFOLLOW) +#define lgetxattr(path,key,value,size) getxattr(path,key,value,size,0,XATTR_NOFOLLOW) +#define lsetxattr(path,key,value,size,flags) setxattr(path,key,value,size,0,flags|XATTR_NOFOLLOW) +#define lremovexattr(path,key) removexattr(path,key,XATTR_NOFOLLOW) +#define fgetxattr(path,key,value,size) fgetxattr(path,key,value,size,0,0) +#define fsetxattr(path,key,value,size,flag) fsetxattr(path,key,value,size,0,flag) + +#define F_GETLK64 F_GETLK +#define F_SETLK64 F_SETLK +#define F_SETLKW64 F_SETLKW + +int32_t gf_darwin_compat_listxattr (int len, dict_t *dict, int size); +int32_t gf_darwin_compat_getxattr (const char *key, dict_t *dict); +int32_t gf_darwin_compat_setxattr (dict_t *dict); + +#endif /* GF_DARWIN_HOST_OS */ + +#ifdef GF_SOLARIS_HOST_OS + +#define UNIX_PATH_MAX 108 +#define EUCLEAN 117 + +#include <sys/un.h> +#include <limits.h> +#include <sys/stat.h> +#include <unistd.h> +#include <sys/fcntl.h> +#include <libgen.h> +#include <sys/mkdev.h> + +#ifndef lchmod +#define lchmod chmod +#endif + +enum { + ATTR_CREATE = 1, +#define XATTR_CREATE ATTR_CREATE + ATTR_REPLACE = 2 +#define XATTR_REPLACE ATTR_REPLACE +}; + +/* This patch is not present in Solaris 10 and before */ +#ifndef dirfd +#define dirfd(dirp) ((dirp)->dd_fd) +#endif + +/* Posix dictates NAME_MAX to be used */ +# ifndef NAME_MAX +# ifdef MAXNAMLEN +# define NAME_MAX MAXNAMLEN +# else +# define NAME_MAX 255 +# endif +# endif + +#include <netinet/in.h> +#ifndef s6_addr16 +#define S6_ADDR16(x) ((uint16_t*) ((char*)&(x).s6_addr)) +#endif +#ifndef s6_addr32 +#define s6_addr32 _S6_un._S6_u32 +#endif + +#define lremovexattr(path,key) solaris_removexattr(path,key) +#define llistxattr(path,key,size) solaris_listxattr(path,key,size) +#define lgetxattr(path,key,value,size) solaris_getxattr(path,key,value,size) +#define lsetxattr(path,key,value,size,flags) solaris_setxattr(path,key,value,size,flags) +#define fgetxattr(fd,key,value,size) solaris_fgetxattr(fd,key,value,size) +#define fsetxattr(fd,key,value,size,flags) solaris_fsetxattr(fd,key,value,size,flags) +#define lutimes(filename,times) utimes(filename,times) + +int asprintf(char **string_ptr, const char *format, ...); +char* strsep(char** str, const char* delims); +int solaris_listxattr(const char *path, char *list, size_t size); +int solaris_removexattr(const char *path, const char* key); +int solaris_getxattr(const char *path, const char* key, + char *value, size_t size); +int solaris_setxattr(const char *path, const char* key, const char *value, + size_t size, int flags); +int solaris_fgetxattr(int fd, const char* key, + char *value, size_t size); +int solaris_fsetxattr(int fd, const char* key, const char *value, + size_t size, int flags); + +#endif /* GF_SOLARIS_HOST_OS */ + +#ifndef HAVE_ARGP +#include "argp.h" +#else +#include <argp.h> +#endif /* HAVE_ARGP */ + +#ifndef HAVE_STRNLEN +size_t strnlen(const char *string, size_t maxlen); +#endif /* STRNLEN */ + +#ifndef strdupa +#define strdupa(s) \ + (__extension__ \ + ({ \ + __const char *__old = (s); \ + size_t __len = strlen (__old) + 1; \ + char *__new = (char *) __builtin_alloca (__len); \ + (char *) memcpy (__new, __old, __len); \ + })) +#endif + +#define ALIGN(x) (((x) + sizeof (uint64_t) - 1) & ~(sizeof (uint64_t) - 1)) + +#include <sys/types.h> +#include <dirent.h> + +static inline int32_t +dirent_size (struct dirent *entry) +{ +#ifdef GF_BSD_HOST_OS + return ALIGN (24 /* FIX MEEEE!!! */ + entry->d_namlen); +#endif +#ifdef GF_DARWIN_HOST_OS + return ALIGN (24 /* FIX MEEEE!!! */ + entry->d_namlen); +#endif +#ifdef GF_LINUX_HOST_OS + return ALIGN (24 /* FIX MEEEE!!! */ + entry->d_reclen); +#endif +#ifdef GF_SOLARIS_HOST_OS + return ALIGN (24 /* FIX MEEEE!!! */ + entry->d_reclen); +#endif +} + + +static inline int32_t +gf_compat_getxattr (const char *key, dict_t *dict) +{ +#ifdef GF_DARWIN_HOST_OS + return gf_darwin_compat_getxattr (key, dict); +#endif + return -1; +} + + +static inline int32_t +gf_compat_setxattr (dict_t *dict) +{ +#ifdef GF_DARWIN_HOST_OS + return gf_darwin_compat_setxattr (dict); +#endif + return -1; +} + + +static inline int32_t +gf_compat_listxattr (int len, dict_t *dict, int size) +{ +#ifdef GF_DARWIN_HOST_OS + return gf_darwin_compat_listxattr (len, dict, size); +#endif + return len; +} + + +#ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC +/* Linux, Solaris, Cygwin */ +#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atim.tv_nsec) +#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctim.tv_nsec) +#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtim.tv_nsec) +#define ST_ATIM_NSEC_SET(stbuf, val) ((stbuf)->st_atim.tv_nsec = (val)) +#define ST_MTIM_NSEC_SET(stbuf, val) ((stbuf)->st_mtim.tv_nsec = (val)) +#define ST_CTIM_NSEC_SET(stbuf, val) ((stbuf)->st_ctim.tv_nsec = (val)) +#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC) +/* FreeBSD, NetBSD */ +#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atimespec.tv_nsec) +#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctimespec.tv_nsec) +#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtimespec.tv_nsec) +#define ST_ATIM_NSEC_SET(stbuf, val) ((stbuf)->st_atimespec.tv_nsec = (val)) +#define ST_MTIM_NSEC_SET(stbuf, val) ((stbuf)->st_mtimespec.tv_nsec = (val)) +#define ST_CTIM_NSEC_SET(stbuf, val) ((stbuf)->st_ctimespec.tv_nsec = (val)) +#else +#define ST_ATIM_NSEC(stbuf) (0) +#define ST_CTIM_NSEC(stbuf) (0) +#define ST_MTIM_NSEC(stbuf) (0) +#define ST_ATIM_NSEC_SET(stbuf, val) do { } while (0); +#define ST_MTIM_NSEC_SET(stbuf, val) do { } while (0); +#define ST_CTIM_NSEC_SET(stbuf, val) do { } while (0); +#endif + +#endif /* __COMPAT_H__ */ diff --git a/libglusterfs/src/defaults.c b/libglusterfs/src/defaults.c new file mode 100644 index 000000000..575e3d86e --- /dev/null +++ b/libglusterfs/src/defaults.c @@ -0,0 +1,1388 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +/* libglusterfs/src/defaults.c: + This file contains functions, which are used to fill the 'fops' and 'mops' + structures in the xlator structures, if they are not written. Here, all the + function calls are plainly forwared to the first child of the xlator, and + all the *_cbk function does plain STACK_UNWIND of the frame, and returns. + + All the functions are plain enough to understand. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "xlator.h" + +static int32_t +default_lookup_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf, + dict_t *dict) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + inode, + buf, + dict); + return 0; +} + +int32_t +default_lookup (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + dict_t *xattr_req) +{ + STACK_WIND (frame, + default_lookup_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lookup, + loc, + xattr_req); + return 0; +} + + +int32_t +default_forget (xlator_t *this, + inode_t *inode) +{ + return 0; +} + +static int32_t +default_stat_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + buf); + return 0; +} + +int32_t +default_stat (call_frame_t *frame, + xlator_t *this, + loc_t *loc) +{ + STACK_WIND (frame, + default_stat_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->stat, + loc); + return 0; +} + +static int32_t +default_chmod_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + buf); + return 0; +} + +int32_t +default_chmod (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + mode_t mode) +{ + STACK_WIND (frame, + default_chmod_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->chmod, + loc, + mode); + return 0; +} + + +static int32_t +default_fchmod_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + buf); + return 0; +} + +int32_t +default_fchmod (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + mode_t mode) +{ + STACK_WIND (frame, + default_fchmod_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fchmod, + fd, + mode); + return 0; +} + +static int32_t +default_chown_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + buf); + return 0; +} + +int32_t +default_chown (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + uid_t uid, + gid_t gid) +{ + STACK_WIND (frame, + default_chown_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->chown, + loc, + uid, + gid); + return 0; +} + +static int32_t +default_fchown_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + buf); + return 0; +} + +int32_t +default_fchown (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + uid_t uid, + gid_t gid) +{ + STACK_WIND (frame, + default_fchown_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fchown, + fd, + uid, + gid); + return 0; +} + +static int32_t +default_truncate_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + buf); + return 0; +} + +int32_t +default_truncate (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + off_t offset) +{ + STACK_WIND (frame, + default_truncate_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->truncate, + loc, + offset); + return 0; +} + +static int32_t +default_ftruncate_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + buf); + return 0; +} + +int32_t +default_ftruncate (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + off_t offset) +{ + STACK_WIND (frame, + default_ftruncate_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->ftruncate, + fd, + offset); + return 0; +} + +int32_t +default_utimens_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + buf); + return 0; +} + + +int32_t +default_utimens (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + struct timespec tv[2]) +{ + STACK_WIND (frame, + default_utimens_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->utimens, + loc, + tv); + return 0; +} + +static int32_t +default_access_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno) +{ + STACK_UNWIND (frame, + op_ret, + op_errno); + return 0; +} + +int32_t +default_access (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + int32_t mask) +{ + STACK_WIND (frame, + default_access_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->access, + loc, + mask); + return 0; +} + + +static int32_t +default_readlink_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + const char *path) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + path); + return 0; +} + +int32_t +default_readlink (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + size_t size) +{ + STACK_WIND (frame, + default_readlink_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readlink, + loc, + size); + return 0; +} + + +static int32_t +default_mknod_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + inode, + buf); + return 0; +} + +int32_t +default_mknod (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + mode_t mode, + dev_t rdev) +{ + STACK_WIND (frame, + default_mknod_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->mknod, + loc, mode, rdev); + return 0; +} + +static int32_t +default_mkdir_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + inode, + buf); + return 0; +} + +int32_t +default_mkdir (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + mode_t mode) +{ + STACK_WIND (frame, + default_mkdir_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->mkdir, + loc, mode); + return 0; +} + +static int32_t +default_unlink_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno) +{ + STACK_UNWIND (frame, op_ret, op_errno); + return 0; +} + +int32_t +default_unlink (call_frame_t *frame, + xlator_t *this, + loc_t *loc) +{ + STACK_WIND (frame, + default_unlink_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->unlink, + loc); + return 0; +} + +static int32_t +default_rmdir_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno) +{ + STACK_UNWIND (frame, + op_ret, + op_errno); + return 0; +} + +int32_t +default_rmdir (call_frame_t *frame, + xlator_t *this, + loc_t *loc) +{ + STACK_WIND (frame, + default_rmdir_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->rmdir, + loc); + return 0; +} + + +static int32_t +default_symlink_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf) +{ + STACK_UNWIND (frame, op_ret, op_errno, inode, buf); + return 0; +} + +int32_t +default_symlink (call_frame_t *frame, + xlator_t *this, + const char *linkpath, + loc_t *loc) +{ + STACK_WIND (frame, + default_symlink_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->symlink, + linkpath, loc); + return 0; +} + + +static int32_t +default_rename_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + STACK_UNWIND (frame, op_ret, op_errno, buf); + return 0; +} + +int32_t +default_rename (call_frame_t *frame, + xlator_t *this, + loc_t *oldloc, + loc_t *newloc) +{ + STACK_WIND (frame, + default_rename_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->rename, + oldloc, newloc); + return 0; +} + + +static int32_t +default_link_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf) +{ + STACK_UNWIND (frame, op_ret, op_errno, inode, buf); + return 0; +} + +int32_t +default_link (call_frame_t *frame, + xlator_t *this, + loc_t *oldloc, + loc_t *newloc) +{ + STACK_WIND (frame, + default_link_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->link, + oldloc, newloc); + return 0; +} + + +static int32_t +default_create_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + fd_t *fd, + inode_t *inode, + struct stat *buf) +{ + STACK_UNWIND (frame, op_ret, op_errno, fd, inode, buf); + return 0; +} + +int32_t +default_create (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + int32_t flags, + mode_t mode, fd_t *fd) +{ + STACK_WIND (frame, default_create_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->create, + loc, flags, mode, fd); + return 0; +} + +static int32_t +default_open_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + fd_t *fd) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + fd); + return 0; +} + +int32_t +default_open (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + int32_t flags, fd_t *fd) +{ + STACK_WIND (frame, + default_open_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, + loc, flags, fd); + return 0; +} + +static int32_t +default_readv_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct iovec *vector, + int32_t count, + struct stat *stbuf) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + vector, + count, + stbuf); + return 0; +} + +int32_t +default_readv (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + size_t size, + off_t offset) +{ + STACK_WIND (frame, + default_readv_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readv, + fd, + size, + offset); + return 0; +} + + +static int32_t +default_writev_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *stbuf) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + stbuf); + return 0; +} + +int32_t +default_writev (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + struct iovec *vector, + int32_t count, + off_t off) +{ + STACK_WIND (frame, + default_writev_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->writev, + fd, + vector, + count, + off); + return 0; +} + +static int32_t +default_flush_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno) +{ + STACK_UNWIND (frame, + op_ret, + op_errno); + return 0; +} + +int32_t +default_flush (call_frame_t *frame, + xlator_t *this, + fd_t *fd) +{ + STACK_WIND (frame, + default_flush_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->flush, + fd); + return 0; +} + + +static int32_t +default_fsync_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno) +{ + STACK_UNWIND (frame, + op_ret, + op_errno); + return 0; +} + +int32_t +default_fsync (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t flags) +{ + STACK_WIND (frame, + default_fsync_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsync, + fd, + flags); + return 0; +} + +static int32_t +default_fstat_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + buf); + return 0; +} + +int32_t +default_fstat (call_frame_t *frame, + xlator_t *this, + fd_t *fd) +{ + STACK_WIND (frame, + default_fstat_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fstat, + fd); + return 0; +} + +static int32_t +default_opendir_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + fd_t *fd) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + fd); + return 0; +} + +int32_t +default_opendir (call_frame_t *frame, + xlator_t *this, + loc_t *loc, fd_t *fd) +{ + STACK_WIND (frame, + default_opendir_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->opendir, + loc, fd); + return 0; +} + + +static int32_t +default_getdents_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + dir_entry_t *entries, + int32_t count) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + entries, + count); + return 0; +} + +int32_t +default_getdents (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + size_t size, + off_t offset, + int32_t flag) +{ + STACK_WIND (frame, + default_getdents_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getdents, + fd, + size, + offset, + flag); + return 0; +} + + +static int32_t +default_setdents_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno) +{ + STACK_UNWIND (frame, + op_ret, + op_errno); + return 0; +} + +int32_t +default_setdents (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t flags, + dir_entry_t *entries, + int32_t count) +{ + STACK_WIND (frame, + default_setdents_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->setdents, + fd, + flags, + entries, + count); + return 0; +} + + +static int32_t +default_fsyncdir_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno) +{ + STACK_UNWIND (frame, + op_ret, + op_errno); + return 0; +} + +int32_t +default_fsyncdir (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t flags) +{ + STACK_WIND (frame, + default_fsyncdir_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsyncdir, + fd, + flags); + return 0; +} + + +static int32_t +default_statfs_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct statvfs *buf) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + buf); + return 0; +} + +int32_t +default_statfs (call_frame_t *frame, + xlator_t *this, + loc_t *loc) +{ + STACK_WIND (frame, + default_statfs_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->statfs, + loc); + return 0; +} + + +static int32_t +default_setxattr_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno) +{ + STACK_UNWIND (frame, + op_ret, + op_errno); + return 0; +} + +int32_t +default_setxattr (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + dict_t *dict, + int32_t flags) +{ + STACK_WIND (frame, + default_setxattr_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->setxattr, + loc, + dict, + flags); + return 0; +} + +static int32_t +default_getxattr_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + dict_t *dict) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + dict); + return 0; +} + +int32_t +default_getxattr (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + const char *name) +{ + STACK_WIND (frame, + default_getxattr_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getxattr, + loc, + name); + return 0; +} + +int32_t +default_xattrop_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + dict_t *dict) +{ + STACK_UNWIND (frame, op_ret, op_errno, dict); + return 0; +} + +int32_t +default_xattrop (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + gf_xattrop_flags_t flags, + dict_t *dict) +{ + STACK_WIND (frame, + default_xattrop_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->xattrop, + loc, + flags, + dict); + return 0; +} + +int32_t +default_fxattrop_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + dict_t *dict) +{ + STACK_UNWIND (frame, op_ret, op_errno, dict); + return 0; +} + +int32_t +default_fxattrop (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + gf_xattrop_flags_t flags, + dict_t *dict) +{ + STACK_WIND (frame, + default_fxattrop_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fxattrop, + fd, + flags, + dict); + return 0; +} + + +static int32_t +default_removexattr_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno) +{ + STACK_UNWIND (frame, + op_ret, + op_errno); + return 0; +} + +int32_t +default_removexattr (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + const char *name) +{ + STACK_WIND (frame, + default_removexattr_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->removexattr, + loc, + name); + return 0; +} + +static int32_t +default_lk_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct flock *lock) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + lock); + return 0; +} + +int32_t +default_lk (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t cmd, + struct flock *lock) +{ + STACK_WIND (frame, + default_lk_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lk, + fd, + cmd, + lock); + return 0; +} + + +static int32_t +default_inodelk_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, int32_t op_errno) + +{ + STACK_UNWIND (frame, op_ret, op_errno); + return 0; +} + + +int32_t +default_inodelk (call_frame_t *frame, xlator_t *this, + loc_t *loc, int32_t cmd, struct flock *lock) +{ + STACK_WIND (frame, + default_inodelk_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->inodelk, + loc, cmd, lock); + return 0; +} + + +static int32_t +default_finodelk_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, int32_t op_errno) + +{ + STACK_UNWIND (frame, op_ret, op_errno); + return 0; +} + + +int32_t +default_finodelk (call_frame_t *frame, xlator_t *this, + fd_t *fd, int32_t cmd, struct flock *lock) +{ + STACK_WIND (frame, + default_finodelk_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->finodelk, + fd, cmd, lock); + return 0; +} + + +static int32_t +default_entrylk_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, int32_t op_errno) + +{ + STACK_UNWIND (frame, op_ret, op_errno); + return 0; +} + +int32_t +default_entrylk (call_frame_t *frame, xlator_t *this, + loc_t *loc, const char *basename, + entrylk_cmd cmd, entrylk_type type) +{ + STACK_WIND (frame, default_entrylk_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->entrylk, + loc, basename, cmd, type); + return 0; +} + +static int32_t +default_fentrylk_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, int32_t op_errno) + +{ + STACK_UNWIND (frame, op_ret, op_errno); + return 0; +} + +int32_t +default_fentrylk (call_frame_t *frame, xlator_t *this, + fd_t *fd, const char *basename, + entrylk_cmd cmd, entrylk_type type) +{ + STACK_WIND (frame, default_fentrylk_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fentrylk, + fd, basename, cmd, type); + return 0; +} + + +/* Management operations */ + +static int32_t +default_stats_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct xlator_stats *stats) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + stats); + return 0; +} + + +int32_t +default_stats (call_frame_t *frame, + xlator_t *this, + int32_t flags) +{ + STACK_WIND (frame, + default_stats_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->mops->stats, + flags); + return 0; +} + +static int32_t +default_getspec_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + char *spec_data) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + spec_data); + return 0; +} + + +int32_t +default_getspec (call_frame_t *frame, + xlator_t *this, + const char *key, + int32_t flags) +{ + STACK_WIND (frame, + default_getspec_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->mops->getspec, + key, flags); + return 0; +} + + +static int32_t +default_checksum_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + uint8_t *file_checksum, + uint8_t *dir_checksum) +{ + STACK_UNWIND (frame, + op_ret, + op_errno, + file_checksum, + dir_checksum); + return 0; +} + + +int32_t +default_checksum (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + int32_t flag) +{ + STACK_WIND (frame, + default_checksum_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->checksum, + loc, + flag); + return 0; +} + + +int32_t +default_readdir_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + gf_dirent_t *entries) +{ + STACK_UNWIND (frame, op_ret, op_errno, entries); + return 0; +} + + +int32_t +default_readdir (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + size_t size, + off_t off) +{ + STACK_WIND (frame, + default_readdir_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readdir, + fd, size, off); + return 0; +} + +/* notify */ +int32_t +default_notify (xlator_t *this, + int32_t event, + void *data, + ...) +{ + switch (event) + { + case GF_EVENT_PARENT_UP: + { + xlator_list_t *list = this->children; + + while (list) + { + list->xlator->notify (list->xlator, event, this); + list = list->next; + } + } + break; + case GF_EVENT_CHILD_DOWN: + case GF_EVENT_CHILD_UP: + default: + { + xlator_list_t *parent = this->parents; + while (parent) { + parent->xlator->notify (parent->xlator, event, this, NULL); + parent = parent->next; + } + } + } + + return 0; +} + +int32_t +default_releasedir (xlator_t *this, + fd_t *fd) +{ + return 0; +} + +int32_t +default_release (xlator_t *this, + fd_t *fd) +{ + return 0; +} + diff --git a/libglusterfs/src/defaults.h b/libglusterfs/src/defaults.h new file mode 100644 index 000000000..aa15df599 --- /dev/null +++ b/libglusterfs/src/defaults.h @@ -0,0 +1,273 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +/* libglusterfs/src/defaults.h: + This file contains definition of default fops and mops functions. +*/ + +#ifndef _DEFAULTS_H +#define _DEFAULTS_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "xlator.h" + +/* Management Operations */ + +int32_t default_stats (call_frame_t *frame, + xlator_t *this, + int32_t flags); + +int32_t default_getspec (call_frame_t *frame, + xlator_t *this, + const char *key, + int32_t flag); + +int32_t default_checksum (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + int32_t flag); + + +/* FileSystem operations */ +int32_t default_lookup (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + dict_t *xattr_req); + +int32_t default_stat (call_frame_t *frame, + xlator_t *this, + loc_t *loc); + +int32_t default_fstat (call_frame_t *frame, + xlator_t *this, + fd_t *fd); + +int32_t default_chmod (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + mode_t mode); + +int32_t default_fchmod (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + mode_t mode); + +int32_t default_chown (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + uid_t uid, + gid_t gid); + +int32_t default_fchown (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + uid_t uid, + gid_t gid); + +int32_t default_truncate (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + off_t offset); + +int32_t default_ftruncate (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + off_t offset); + +int32_t default_utimens (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + struct timespec tv[2]); + +int32_t default_access (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + int32_t mask); + +int32_t default_readlink (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + size_t size); + +int32_t default_mknod (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + mode_t mode, + dev_t rdev); + +int32_t default_mkdir (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + mode_t mode); + +int32_t default_unlink (call_frame_t *frame, + xlator_t *this, + loc_t *loc); + +int32_t default_rmdir (call_frame_t *frame, + xlator_t *this, + loc_t *loc); + +int32_t default_symlink (call_frame_t *frame, + xlator_t *this, + const char *linkpath, + loc_t *loc); + +int32_t default_rename (call_frame_t *frame, + xlator_t *this, + loc_t *oldloc, + loc_t *newloc); + +int32_t default_link (call_frame_t *frame, + xlator_t *this, + loc_t *oldloc, + loc_t *newloc); + +int32_t default_create (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + int32_t flags, + mode_t mode, fd_t *fd); + +int32_t default_open (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + int32_t flags, fd_t *fd); + +int32_t default_readv (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + size_t size, + off_t offset); + +int32_t default_writev (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + struct iovec *vector, + int32_t count, + off_t offset); + +int32_t default_flush (call_frame_t *frame, + xlator_t *this, + fd_t *fd); + +int32_t default_fsync (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t datasync); + +int32_t default_opendir (call_frame_t *frame, + xlator_t *this, + loc_t *loc, fd_t *fd); + +int32_t default_getdents (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + size_t size, + off_t offset, + int32_t flag); + +int32_t default_fsyncdir (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t datasync); + +int32_t default_statfs (call_frame_t *frame, + xlator_t *this, + loc_t *loc); + +int32_t default_setxattr (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + dict_t *dict, + int32_t flags); + +int32_t default_getxattr (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + const char *name); + +int32_t default_removexattr (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + const char *name); + +int32_t default_lk (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t cmd, + struct flock *flock); + +int32_t default_inodelk (call_frame_t *frame, xlator_t *this, + loc_t *loc, int32_t cmd, struct flock *flock); + +int32_t default_finodelk (call_frame_t *frame, xlator_t *this, + fd_t *fd, int32_t cmd, struct flock *flock); + +int32_t default_entrylk (call_frame_t *frame, xlator_t *this, + loc_t *loc, const char *basename, + entrylk_cmd cmd, entrylk_type type); + +int32_t default_fentrylk (call_frame_t *frame, xlator_t *this, + fd_t *fd, const char *basename, + entrylk_cmd cmd, entrylk_type type); + +int32_t default_readdir (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + size_t size, off_t off); + +int32_t default_setdents (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t flags, + dir_entry_t *entries, + int32_t count); + +int32_t default_xattrop (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + gf_xattrop_flags_t flags, + dict_t *dict); + +int32_t default_fxattrop (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + gf_xattrop_flags_t flags, + dict_t *dict); + +int32_t default_notify (xlator_t *this, + int32_t event, + void *data, + ...); + +int32_t default_forget (xlator_t *this, + inode_t *inode); + +int32_t default_release (xlator_t *this, + fd_t *fd); + +int32_t default_releasedir (xlator_t *this, + fd_t *fd); + +#endif /* _DEFAULTS_H */ diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c new file mode 100644 index 000000000..eb181f191 --- /dev/null +++ b/libglusterfs/src/dict.c @@ -0,0 +1,2243 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <inttypes.h> + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "common-utils.h" +#include "dict.h" +#include "hashfn.h" +#include "logging.h" +#include "compat.h" +#include "byte-order.h" + +data_pair_t * +get_new_data_pair () +{ + data_pair_t *data_pair_ptr = NULL; + + data_pair_ptr = (data_pair_t *) CALLOC (1, sizeof (data_pair_t)); + ERR_ABORT (data_pair_ptr); + + return data_pair_ptr; +} + +data_t * +get_new_data () +{ + data_t *data = NULL; + + data = (data_t *) CALLOC (1, sizeof (data_t)); + if (!data) { + gf_log ("dict", GF_LOG_CRITICAL, + "calloc () returned NULL"); + return NULL; + } + + LOCK_INIT (&data->lock); + return data; +} + +dict_t * +get_new_dict_full (int size_hint) +{ + dict_t *dict = CALLOC (1, sizeof (dict_t)); + + if (!dict) { + gf_log ("dict", GF_LOG_CRITICAL, + "calloc () returned NULL"); + return NULL; + } + + dict->hash_size = size_hint; + dict->members = CALLOC (size_hint, sizeof (data_pair_t *)); + + if (!dict->members) { + gf_log ("dict", GF_LOG_CRITICAL, + "calloc () returned NULL"); + return NULL; + } + + LOCK_INIT (&dict->lock); + + return dict; +} + +dict_t * +get_new_dict (void) +{ + return get_new_dict_full (1); +} + +dict_t * +dict_new (void) +{ + dict_t *dict = NULL; + + dict = get_new_dict_full(1); + + if (dict) + dict_ref (dict); + + return dict; +} + + +int32_t +is_data_equal (data_t *one, + data_t *two) +{ + if (!one || !two || !one->data || !two->data) + return 1; + + if (one == two) + return 1; + + if (one->len != two->len) + return 0; + + if (one->data == two->data) + return 1; + + if (memcmp (one->data, two->data, one->len) == 0) + return 1; + + return 0; +} + +void +data_destroy (data_t *data) +{ + if (data) { + LOCK_DESTROY (&data->lock); + + if (!data->is_static) { + if (data->data) + FREE (data->data); + if (data->vec) + FREE (data->vec); + } + + data->len = 0xbabababa; + if (!data->is_const) + FREE (data); + } +} + +data_t * +data_copy (data_t *old) +{ + if (!old) { + gf_log ("dict", GF_LOG_CRITICAL, + "@old is NULL"); + return NULL; + } + + data_t *newdata = (data_t *) CALLOC (1, sizeof (*newdata)); + + if (!newdata) { + gf_log ("dict", GF_LOG_CRITICAL, + "@old is NULL"); + return NULL; + } + + if (old) { + newdata->len = old->len; + if (old->data) + newdata->data = memdup (old->data, old->len); + if (old->vec) + newdata->vec = memdup (old->vec, old->len * (sizeof (void *) + + sizeof (size_t))); + if (!old->data && !old->vec) { + gf_log ("dict", GF_LOG_CRITICAL, + "@newdata->data || @newdata->vec got NULL from CALLOC()"); + return NULL; + } + } + + return newdata; +} + +static data_pair_t * +_dict_lookup (dict_t *this, char *key) +{ + if (!this || !key) { + gf_log ("dict", GF_LOG_CRITICAL, + "@this=%p @key=%p", this, key); + return NULL; + } + + int hashval = SuperFastHash (key, strlen (key)) % this->hash_size; + data_pair_t *pair; + + for (pair = this->members[hashval]; pair != NULL; pair = pair->hash_next) { + if (pair->key && !strcmp (pair->key, key)) + return pair; + } + + return NULL; +} + + +static int32_t +_dict_set (dict_t *this, + char *key, + data_t *value) +{ + int hashval; + data_pair_t *pair; + char key_free = 0; + int tmp = 0; + + if (!key) { + asprintf (&key, "ref:%p", value); + key_free = 1; + } + + tmp = SuperFastHash (key, strlen (key)); + hashval = (tmp % this->hash_size); + pair = _dict_lookup (this, key); + + if (pair) { + data_t *unref_data = pair->value; + pair->value = data_ref (value); + data_unref (unref_data); + if (key_free) + FREE (key); + /* Indicates duplicate key */ + return 0; + } + pair = (data_pair_t *) CALLOC (1, sizeof (*pair)); + if (!pair) { + gf_log ("dict", GF_LOG_CRITICAL, + "@pair - NULL returned by CALLOC"); + return -1; + } + + pair->key = (char *) CALLOC (1, strlen (key) + 1); + if (!pair->key) { + gf_log ("dict", GF_LOG_CRITICAL, + "@pair->key - NULL returned by CALLOC"); + return -1; + } + + strcpy (pair->key, key); + pair->value = data_ref (value); + + pair->hash_next = this->members[hashval]; + this->members[hashval] = pair; + + pair->next = this->members_list; + pair->prev = NULL; + if (this->members_list) + this->members_list->prev = pair; + this->members_list = pair; + this->count++; + + if (key_free) + FREE (key); + return 0; +} + +int32_t +dict_set (dict_t *this, + char *key, + data_t *value) +{ + int32_t ret; + + if (!this || !value) { + gf_log ("dict", GF_LOG_CRITICAL, + "@this=%p @value=%p", this, value); + return -1; + } + + LOCK (&this->lock); + + ret = _dict_set (this, key, value); + + UNLOCK (&this->lock); + + return ret; +} + + +data_t * +dict_get (dict_t *this, + char *key) +{ + data_pair_t *pair; + + if (!this || !key) { + gf_log ("dict", GF_LOG_DEBUG, + "@this=%p @key=%p", this, key); + return NULL; + } + + LOCK (&this->lock); + + pair = _dict_lookup (this, key); + + UNLOCK (&this->lock); + + if (pair) + return pair->value; + + return NULL; +} + +void +dict_del (dict_t *this, + char *key) +{ + if (!this || !key) { + gf_log ("dict", GF_LOG_DEBUG, + "@this=%p @key=%p", this, key); + return; + } + + LOCK (&this->lock); + + int hashval = SuperFastHash (key, strlen (key)) % this->hash_size; + data_pair_t *pair = this->members[hashval]; + data_pair_t *prev = NULL; + + while (pair) { + if (strcmp (pair->key, key) == 0) { + if (prev) + prev->hash_next = pair->hash_next; + else + this->members[hashval] = pair->hash_next; + + data_unref (pair->value); + + if (pair->prev) + pair->prev->next = pair->next; + else + this->members_list = pair->next; + + if (pair->next) + pair->next->prev = pair->prev; + + FREE (pair->key); + FREE (pair); + this->count--; + break; + } + + prev = pair; + pair = pair->hash_next; + } + + UNLOCK (&this->lock); + + return; +} + +void +dict_destroy (dict_t *this) +{ + if (!this) { + gf_log ("dict", GF_LOG_DEBUG, + "@this=%p", this); + return; + } + + data_pair_t *pair = this->members_list; + data_pair_t *prev = this->members_list; + + LOCK_DESTROY (&this->lock); + + while (prev) { + pair = pair->next; + data_unref (prev->value); + FREE (prev->key); + FREE (prev); + prev = pair; + } + + FREE (this->members); + + if (this->extra_free) + FREE (this->extra_free); + + if (!this->is_static) + FREE (this); + + return; +} + +void +dict_unref (dict_t *this) +{ + int32_t ref; + + if (!this) { + gf_log ("dict", GF_LOG_DEBUG, + "@this=%p", this); + return; + } + + LOCK (&this->lock); + + this->refcount--; + ref = this->refcount; + + UNLOCK (&this->lock); + + if (!ref) + dict_destroy (this); +} + +dict_t * +dict_ref (dict_t *this) +{ + if (!this) { + gf_log ("dict", GF_LOG_DEBUG, + "@this=%p", this); + return NULL; + } + + LOCK (&this->lock); + + this->refcount++; + + UNLOCK (&this->lock); + + return this; +} + +void +data_unref (data_t *this) +{ + int32_t ref; + + if (!this) { + gf_log ("dict", GF_LOG_DEBUG, + "@this=%p", this); + return; + } + + LOCK (&this->lock); + + this->refcount--; + ref = this->refcount; + + UNLOCK (&this->lock); + + if (!ref) + data_destroy (this); +} + +data_t * +data_ref (data_t *this) +{ + if (!this) { + gf_log ("dict", GF_LOG_DEBUG, + "@this=%p", this); + return NULL; + } + + LOCK (&this->lock); + + this->refcount++; + + UNLOCK (&this->lock); + + return this; +} + +/* + Serialization format: + ---- + Count:8 + Key_len:8:Value_len:8 + Key + Value + . + . + . +*/ + +int32_t +dict_serialized_length_old (dict_t *this) +{ + + if (!this) { + gf_log ("dict", GF_LOG_DEBUG, + "@this=%p", this); + return -1; + } + + int32_t len = 9; /* count + \n */ + int32_t count = this->count; + data_pair_t *pair = this->members_list; + + while (count) { + len += 18; + len += strlen (pair->key) + 1; + if (pair->value->vec) { + int i; + for (i=0; i<pair->value->len; i++) { + len += pair->value->vec[i].iov_len; + } + } else { + len += pair->value->len; + } + pair = pair->next; + count--; + } + + return len; +} + +int32_t +dict_serialize_old (dict_t *this, char *buf) +{ + if (!this || !buf) { + gf_log ("dict", GF_LOG_DEBUG, + "@this=%p @buf=%p", this, buf); + return -1; + } + + data_pair_t *pair = this->members_list; + int32_t count = this->count; + uint64_t dcount = this->count; + + // FIXME: magic numbers + + sprintf (buf, "%08"PRIx64"\n", dcount); + buf += 9; + while (count) { + uint64_t keylen = strlen (pair->key) + 1; + uint64_t vallen = pair->value->len; + + sprintf (buf, "%08"PRIx64":%08"PRIx64"\n", keylen, vallen); + buf += 18; + memcpy (buf, pair->key, keylen); + buf += keylen; + memcpy (buf, pair->value->data, pair->value->len); + buf += pair->value->len; + pair = pair->next; + count--; + } + return (0); +} + + +dict_t * +dict_unserialize_old (char *buf, int32_t size, dict_t **fill) +{ + int32_t ret = 0; + int32_t cnt = 0; + + if (!buf || fill == NULL || !*fill) { + gf_log ("dict", GF_LOG_ERROR, + "@buf=%p @fill=%p @*fill=%p", buf, fill, *fill); + return NULL; + } + + uint64_t count; + ret = sscanf (buf, "%"SCNx64"\n", &count); + (*fill)->count = 0; + + if (!ret){ + gf_log ("dict", + GF_LOG_ERROR, + "sscanf on buf failed"); + goto err; + } + buf += 9; + + if (count == 0) { + gf_log ("dict", + GF_LOG_ERROR, + "count == 0"); + goto err; + } + + for (cnt = 0; cnt < count; cnt++) { + data_t *value = NULL; + char *key = NULL; + uint64_t key_len, value_len; + + ret = sscanf (buf, "%"SCNx64":%"SCNx64"\n", &key_len, &value_len); + if (ret != 2) { + gf_log ("dict", + GF_LOG_ERROR, + "sscanf for key_len and value_len failed"); + goto err; + } + buf += 18; + + key = buf; + buf += key_len; + + value = get_new_data (); + value->len = value_len; + value->data = buf; + value->is_static = 1; + buf += value_len; + + dict_set (*fill, key, value); + } + + goto ret; + +err: + FREE (*fill); + *fill = NULL; + +ret: + return *fill; +} + + +int32_t +dict_iovec_len (dict_t *this) +{ + if (!this) { + gf_log ("dict", GF_LOG_CRITICAL, + "@this=%p", this); + return -1; + } + + int32_t len = 0; + data_pair_t *pair = this->members_list; + + len++; /* initial header */ + while (pair) { + len++; /* pair header */ + len++; /* key */ + + if (pair->value->vec) + len += pair->value->len; + else + len++; + pair = pair->next; + } + + return len; +} + +int32_t +dict_to_iovec (dict_t *this, + struct iovec *vec, + int32_t count) +{ + if (!this || !vec) { + gf_log ("dict", GF_LOG_CRITICAL, + "@this=%p @vec=%p", this, vec); + return -1; + } + + int32_t i = 0; + data_pair_t *pair = this->members_list; + + vec[0].iov_len = 9; + if (vec[0].iov_base) + sprintf (vec[0].iov_base, + "%08"PRIx64"\n", + (int64_t)this->count); + i++; + + while (pair) { + int64_t keylen = strlen (pair->key) + 1; + int64_t vallen = 0; + + if (pair->value->vec) { + int i; + + for (i=0; i<pair->value->len; i++) { + vallen += pair->value->vec[i].iov_len; + } + } else { + vallen = pair->value->len; + } + + vec[i].iov_len = 18; + if (vec[i].iov_base) + sprintf (vec[i].iov_base, + "%08"PRIx64":%08"PRIx64"\n", + keylen, + vallen); + i++; + + vec[i].iov_len = keylen; + vec[i].iov_base = pair->key; + i++; + + if (pair->value->vec) { + int k; + + for (k=0; k<pair->value->len; k++) { + vec[i].iov_len = pair->value->vec[k].iov_len; + vec[i].iov_base = pair->value->vec[k].iov_base; + i++; + } + } else { + vec[i].iov_len = pair->value->len; + vec[i].iov_base = pair->value->data; + i++; + } + + pair = pair->next; + } + + return 0; +} + +data_t * +int_to_data (int64_t value) +{ + data_t *data = get_new_data (); + + if (!data) { + gf_log ("dict", GF_LOG_CRITICAL, + "@data - NULL returned by CALLOC"); + return NULL; + } + + asprintf (&data->data, "%"PRId64, value); + data->len = strlen (data->data) + 1; + + return data; +} + +data_t * +data_from_int64 (int64_t value) +{ + data_t *data = get_new_data (); + + if (!data) { + gf_log ("dict", GF_LOG_CRITICAL, + "@data - NULL returned by CALLOC"); + return NULL; + } + asprintf (&data->data, "%"PRId64, value); + data->len = strlen (data->data) + 1; + + return data; +} + +data_t * +data_from_int32 (int32_t value) +{ + data_t *data = get_new_data (); + + if (!data) { + gf_log ("dict", GF_LOG_CRITICAL, + "@data - NULL returned by CALLOC"); + return NULL; + } + asprintf (&data->data, "%"PRId32, value); + data->len = strlen (data->data) + 1; + + return data; +} + +data_t * +data_from_int16 (int16_t value) +{ + + data_t *data = get_new_data (); + + if (!data) { + gf_log ("dict", GF_LOG_CRITICAL, + "@data - NULL returned by CALLOC"); + return NULL; + } + asprintf (&data->data, "%"PRId16, value); + data->len = strlen (data->data) + 1; + + return data; +} + +data_t * +data_from_int8 (int8_t value) +{ + + data_t *data = get_new_data (); + + if (!data) { + gf_log ("dict", GF_LOG_CRITICAL, + "@data - NULL returned by CALLOC"); + return NULL; + } + asprintf (&data->data, "%d", value); + data->len = strlen (data->data) + 1; + + return data; +} + +data_t * +data_from_uint64 (uint64_t value) +{ + data_t *data = get_new_data (); + + if (!data) { + gf_log ("dict", GF_LOG_CRITICAL, + "@data - NULL returned by CALLOC"); + return NULL; + } + asprintf (&data->data, "%"PRIu64, value); + data->len = strlen (data->data) + 1; + + return data; +} + + +data_t * +data_from_uint32 (uint32_t value) +{ + data_t *data = get_new_data (); + + if (!data) { + gf_log ("dict", GF_LOG_CRITICAL, + "@data - NULL returned by CALLOC"); + return NULL; + } + asprintf (&data->data, "%"PRIu32, value); + data->len = strlen (data->data) + 1; + + return data; +} + + +data_t * +data_from_uint16 (uint16_t value) +{ + data_t *data = get_new_data (); + + if (!data) { + gf_log ("dict", GF_LOG_CRITICAL, + "@data - NULL returned by CALLOC"); + return NULL; + } + asprintf (&data->data, "%"PRIu16, value); + data->len = strlen (data->data) + 1; + + return data; +} + + +data_t * +data_from_ptr (void *value) +{ + if (!value) { + gf_log ("dict", GF_LOG_CRITICAL, + "@value=%p", value); + return NULL; + } + + data_t *data = get_new_data (); + + if (!data) { + gf_log ("dict", GF_LOG_CRITICAL, + "@data - NULL returned by CALLOC"); + return NULL; + } + + data->data = value; + return data; +} + +data_t * +data_from_static_ptr (void *value) +{ +/* + this is valid to set 0 as value.. + + if (!value) { + gf_log ("dict", GF_LOG_CRITICAL, + "@value=%p", value); + return NULL; + } +*/ + data_t *data = get_new_data (); + + if (!data) { + gf_log ("dict", GF_LOG_CRITICAL, + "@data - NULL returned by CALLOC"); + return NULL; + } + + data->is_static = 1; + data->data = value; + + return data; +} + +data_t * +str_to_data (char *value) +{ + if (!value) { + gf_log ("dict", GF_LOG_CRITICAL, + "@value=%p", value); + return NULL; + } + data_t *data = get_new_data (); + + if (!data) { + gf_log ("dict", GF_LOG_CRITICAL, + "@data - NULL returned by CALLOC"); + return NULL; + } + data->len = strlen (value) + 1; + + data->data = value; + data->is_static = 1; + + return data; +} + +data_t * +data_from_dynstr (char *value) +{ + if (!value) { + gf_log ("dict", GF_LOG_CRITICAL, + "@value=%p", value); + return NULL; + } + + data_t *data = get_new_data (); + + data->len = strlen (value) + 1; + data->data = value; + + return data; +} + +data_t * +data_from_dynptr (void *value, int32_t len) +{ + data_t *data = get_new_data (); + + data->len = len; + data->data = value; + + return data; +} + +data_t * +bin_to_data (void *value, int32_t len) +{ + if (!value) { + gf_log ("dict", GF_LOG_CRITICAL, + "@value=%p", value); + return NULL; + } + + data_t *data = get_new_data (); + + data->is_static = 1; + data->len = len; + data->data = value; + + return data; +} + +int64_t +data_to_int64 (data_t *data) +{ + if (!data) + return -1; + + char *str = alloca (data->len + 1); + ERR_ABORT (str); + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + return (int64_t) strtoull (str, NULL, 0); +} + +int32_t +data_to_int32 (data_t *data) +{ + if (!data) + return -1; + + char *str = alloca (data->len + 1); + ERR_ABORT (str); + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + return strtoul (str, NULL, 0); +} + +int16_t +data_to_int16 (data_t *data) +{ + if (!data) + return -1; + + char *str = alloca (data->len + 1); + ERR_ABORT (str); + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + return strtol (str, NULL, 0); +} + + +int8_t +data_to_int8 (data_t *data) +{ + if (!data) + return -1; + + char *str = alloca (data->len + 1); + ERR_ABORT (str); + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + return (int8_t)strtol (str, NULL, 0); +} + + +uint64_t +data_to_uint64 (data_t *data) +{ + if (!data) + return -1; + char *str = alloca (data->len + 1); + ERR_ABORT (str); + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + return strtoll (str, NULL, 0); +} + +uint32_t +data_to_uint32 (data_t *data) +{ + if (!data) + return -1; + + char *str = alloca (data->len + 1); + ERR_ABORT (str); + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + return strtol (str, NULL, 0); +} + +uint16_t +data_to_uint16 (data_t *data) +{ + if (!data) + return -1; + + char *str = alloca (data->len + 1); + ERR_ABORT (str); + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + return strtol (str, NULL, 0); +} + +char * +data_to_str (data_t *data) +{ + if (!data) { + gf_log ("dict", GF_LOG_CRITICAL, + "@data=%p", data); + return NULL; + } + return data->data; +} + +void * +data_to_ptr (data_t *data) +{ + if (!data) { + return NULL; + } + return data->data; +} + +void * +data_to_bin (data_t *data) +{ + if (!data) { + gf_log ("dict", GF_LOG_CRITICAL, + "@data=%p", data); + return NULL; + } + return data->data; +} + +void +dict_foreach (dict_t *dict, + void (*fn)(dict_t *this, + char *key, + data_t *value, + void *data), + void *data) +{ + if (!data) { + gf_log ("dict", GF_LOG_CRITICAL, + "@data=%p", data); + return; + } + + data_pair_t *pairs = dict->members_list; + + while (pairs) { + fn (dict, pairs->key, pairs->value, data); + pairs = pairs->next; + } +} + + +static void +_copy (dict_t *unused, + char *key, + data_t *value, + void *newdict) +{ + dict_set ((dict_t *)newdict, key, (value)); +} + + +dict_t * +dict_copy (dict_t *dict, + dict_t *new) +{ + if (!dict) { + gf_log ("dict", GF_LOG_CRITICAL, + "@data=%p", dict); + return NULL; + } + + if (!new) + new = get_new_dict_full (dict->hash_size); + + dict_foreach (dict, _copy, new); + + return new; +} + +dict_t * +dict_copy_with_ref (dict_t *dict, + dict_t *new) +{ + dict_t *local_new = NULL; + + GF_VALIDATE_OR_GOTO("dict", dict, fail); + + if (new == NULL) { + local_new = dict_new (); + GF_VALIDATE_OR_GOTO("dict", local_new, fail); + new = local_new; + } + + dict_foreach (dict, _copy, new); +fail: + return new; +} + +/* + * !!!!!!! CLEANED UP CODE !!!!!!! + */ + +/** + * Common cleaned up interface: + * + * Return value: 0 success + * -val error, val = errno + */ + + +static int +dict_get_with_ref (dict_t *this, char *key, data_t **data) +{ + data_pair_t * pair = NULL; + int ret = -ENOENT; + + if (!this || !key || !data) { + ret = -EINVAL; + goto err; + } + + LOCK (&this->lock); + { + pair = _dict_lookup (this, key); + } + UNLOCK (&this->lock); + + if (pair) { + ret = 0; + *data = data_ref (pair->value); + } + +err: + return ret; +} + +static int +_data_to_ptr (data_t *data, void **val) +{ + int ret = 0; + + if (!data) { + ret = -EINVAL; + goto err; + } + + *val = data->data; +err: + return ret; +} + + +static int +_data_to_int8 (data_t *data, int8_t *val) +{ + int ret = 0; + char * str = NULL; + + if (!data || !val) { + ret = -EINVAL; + goto err; + } + + str = alloca (data->len + 1); + if (!str) { + ret = -ENOMEM; + goto err; + } + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + errno = 0; + *val = strtol (str, NULL, 0); + if (errno != 0) + ret = -errno; + +err: + return ret; +} + +static int +_data_to_int16 (data_t *data, int16_t *val) +{ + int ret = 0; + char * str = NULL; + + if (!data || !val) { + ret = -EINVAL; + goto err; + } + + str = alloca (data->len + 1); + if (!str) { + ret = -ENOMEM; + goto err; + } + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + errno = 0; + *val = strtol (str, NULL, 0); + if (errno != 0) + ret = -errno; + +err: + return ret; +} + +static int +_data_to_int32 (data_t *data, int32_t *val) +{ + int ret = 0; + char * str = NULL; + + if (!data || !val) { + ret = -EINVAL; + goto err; + } + + str = alloca (data->len + 1); + if (!str) { + ret = -ENOMEM; + goto err; + } + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + errno = 0; + *val = strtol (str, NULL, 0); + if (errno != 0) + ret = -errno; + +err: + return ret; +} + +static int +_data_to_int64 (data_t *data, int64_t *val) +{ + int ret = 0; + char * str = NULL; + + if (!data || !val) { + ret = -EINVAL; + goto err; + } + + str = alloca (data->len + 1); + if (!str) { + ret = -ENOMEM; + goto err; + } + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + errno = 0; + *val = strtoll (str, NULL, 0); + if (errno != 0) + ret = -errno; + +err: + return ret; +} + +static int +_data_to_uint16 (data_t *data, uint16_t *val) +{ + int ret = 0; + char * str = NULL; + + if (!data || !val) { + ret = -EINVAL; + goto err; + } + + str = alloca (data->len + 1); + if (!str) { + ret = -ENOMEM; + goto err; + } + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + errno = 0; + *val = strtoul (str, NULL, 0); + if (errno != 0) + ret = -errno; + +err: + return ret; +} + +static int +_data_to_uint32 (data_t *data, uint32_t *val) +{ + int ret = 0; + char * str = NULL; + + if (!data || !val) { + ret = -EINVAL; + goto err; + } + + str = alloca (data->len + 1); + if (!str) { + ret = -ENOMEM; + goto err; + } + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + errno = 0; + *val = strtoul (str, NULL, 0); + if (errno != 0) + ret = -errno; + +err: + return ret; +} + +static int +_data_to_uint64 (data_t *data, uint64_t *val) +{ + int ret = 0; + char * str = NULL; + + if (!data || !val) { + ret = -EINVAL; + goto err; + } + + str = alloca (data->len + 1); + if (!str) { + ret = -ENOMEM; + goto err; + } + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + errno = 0; + *val = strtoull (str, NULL, 0); + if (errno != 0) + ret = -errno; + +err: + return ret; +} + +int +dict_get_int8 (dict_t *this, char *key, int8_t *val) +{ + data_t * data = NULL; + int ret = 0; + + if (!this || !key || !val) { + ret = -EINVAL; + goto err; + } + + ret = dict_get_with_ref (this, key, &data); + if (ret != 0) { + goto err; + } + + ret = _data_to_int8 (data, val); + +err: + if (data) + data_unref (data); + return ret; +} + + +int +dict_set_int8 (dict_t *this, char *key, int8_t val) +{ + data_t * data = NULL; + int ret = 0; + + data = data_from_int8 (val); + if (!data) { + ret = -EINVAL; + goto err; + } + + ret = dict_set (this, key, data); + +err: + return ret; +} + +int +dict_get_int16 (dict_t *this, char *key, int16_t *val) +{ + data_t * data = NULL; + int ret = 0; + + if (!this || !key || !val) { + ret = -EINVAL; + goto err; + } + + ret = dict_get_with_ref (this, key, &data); + if (ret != 0) { + goto err; + } + + ret = _data_to_int16 (data, val); + +err: + if (data) + data_unref (data); + return ret; +} + + +int +dict_set_int16 (dict_t *this, char *key, int16_t val) +{ + data_t * data = NULL; + int ret = 0; + + data = data_from_int16 (val); + if (!data) { + ret = -EINVAL; + goto err; + } + + ret = dict_set (this, key, data); + +err: + return ret; +} + +int +dict_get_int32 (dict_t *this, char *key, int32_t *val) +{ + data_t * data = NULL; + int ret = 0; + + if (!this || !key || !val) { + ret = -EINVAL; + goto err; + } + + ret = dict_get_with_ref (this, key, &data); + if (ret != 0) { + goto err; + } + + ret = _data_to_int32 (data, val); + +err: + if (data) + data_unref (data); + return ret; +} + + +int +dict_set_int32 (dict_t *this, char *key, int32_t val) +{ + data_t * data = NULL; + int ret = 0; + + data = data_from_int32 (val); + if (!data) { + ret = -EINVAL; + goto err; + } + + ret = dict_set (this, key, data); + +err: + return ret; +} + +int +dict_get_int64 (dict_t *this, char *key, int64_t *val) +{ + data_t * data = NULL; + int ret = 0; + + if (!this || !key || !val) { + ret = -EINVAL; + goto err; + } + + ret = dict_get_with_ref (this, key, &data); + if (ret != 0) { + goto err; + } + + ret = _data_to_int64 (data, val); + +err: + if (data) + data_unref (data); + return ret; +} + + +int +dict_set_int64 (dict_t *this, char *key, int64_t val) +{ + data_t * data = NULL; + int ret = 0; + + data = data_from_int64 (val); + if (!data) { + ret = -EINVAL; + goto err; + } + + ret = dict_set (this, key, data); + +err: + return ret; +} + +int +dict_get_uint16 (dict_t *this, char *key, uint16_t *val) +{ + data_t * data = NULL; + int ret = 0; + + if (!this || !key || !val) { + ret = -EINVAL; + goto err; + } + + ret = dict_get_with_ref (this, key, &data); + if (ret != 0) { + goto err; + } + + ret = _data_to_uint16 (data, val); + +err: + if (data) + data_unref (data); + return ret; +} + + +int +dict_set_uint16 (dict_t *this, char *key, uint16_t val) +{ + data_t * data = NULL; + int ret = 0; + + data = data_from_uint16 (val); + if (!data) { + ret = -EINVAL; + goto err; + } + + ret = dict_set (this, key, data); + +err: + return ret; +} + +int +dict_get_uint32 (dict_t *this, char *key, uint32_t *val) +{ + data_t * data = NULL; + int ret = 0; + + if (!this || !key || !val) { + ret = -EINVAL; + goto err; + } + + ret = dict_get_with_ref (this, key, &data); + if (ret != 0) { + goto err; + } + + ret = _data_to_uint32 (data, val); + +err: + if (data) + data_unref (data); + return ret; +} + + +int +dict_set_uint32 (dict_t *this, char *key, uint32_t val) +{ + data_t * data = NULL; + int ret = 0; + + data = data_from_uint32 (val); + if (!data) { + ret = -EINVAL; + goto err; + } + + ret = dict_set (this, key, data); + +err: + return ret; +} + +int +dict_get_uint64 (dict_t *this, char *key, uint64_t *val) +{ + data_t * data = NULL; + int ret = 0; + + if (!this || !key || !val) { + ret = -EINVAL; + goto err; + } + + ret = dict_get_with_ref (this, key, &data); + if (ret != 0) { + goto err; + } + + ret = _data_to_uint64 (data, val); + +err: + if (data) + data_unref (data); + return ret; +} + + +int +dict_set_uint64 (dict_t *this, char *key, uint64_t val) +{ + data_t * data = NULL; + int ret = 0; + + data = data_from_uint64 (val); + if (!data) { + ret = -EINVAL; + goto err; + } + + ret = dict_set (this, key, data); + +err: + return ret; +} + +int +dict_set_static_ptr (dict_t *this, char *key, void *ptr) +{ + data_t * data = NULL; + int ret = 0; + + data = data_from_static_ptr (ptr); + if (!data) { + ret = -EINVAL; + goto err; + } + + ret = dict_set (this, key, data); + +err: + return ret; +} + +int +dict_set_dynptr (dict_t *this, char *key, void *ptr, size_t len) +{ + data_t * data = NULL; + int ret = 0; + + data = data_from_dynptr (ptr, len); + if (!data) { + ret = -EINVAL; + goto err; + } + + ret = dict_set (this, key, data); + +err: + return ret; +} + +int +dict_get_ptr (dict_t *this, char *key, void **ptr) +{ + data_t * data = NULL; + int ret = 0; + + if (!this || !key || !ptr) { + ret = -EINVAL; + goto err; + } + + ret = dict_get_with_ref (this, key, &data); + if (ret != 0) { + goto err; + } + + ret = _data_to_ptr (data, ptr); + if (ret != 0) { + goto err; + } + +err: + if (data) + data_unref (data); + + return ret; +} + +int +dict_set_ptr (dict_t *this, char *key, void *ptr) +{ + data_t * data = NULL; + int ret = 0; + + data = data_from_ptr (ptr); + if (!data) { + ret = -EINVAL; + goto err; + } + + ret = dict_set (this, key, data); + +err: + return ret; +} + + +int +dict_get_str (dict_t *this, char *key, char **str) +{ + data_t * data = NULL; + int ret = -EINVAL; + + if (!this || !key || !str) { + goto err; + } + + ret = dict_get_with_ref (this, key, &data); + if (ret < 0) { + goto err; + } + + if (!data || !data->data) { + goto err; + } + *str = data->data; + +err: + if (data) + data_unref (data); + + return ret; +} + +int +dict_set_str (dict_t *this, char *key, char *str) +{ + data_t * data = NULL; + int ret = 0; + + data = str_to_data (str); + if (!data) { + ret = -EINVAL; + goto err; + } + + ret = dict_set (this, key, data); + +err: + return ret; +} + +int +dict_set_dynstr (dict_t *this, char *key, char *str) +{ + data_t * data = NULL; + int ret = 0; + + data = data_from_dynstr (str); + if (!data) { + ret = -EINVAL; + goto err; + } + + ret = dict_set (this, key, data); + +err: + return ret; +} + + +int +dict_get_bin (dict_t *this, char *key, void **bin) +{ + data_t * data = NULL; + int ret = -EINVAL; + + if (!this || !key || !bin) { + goto err; + } + + ret = dict_get_with_ref (this, key, &data); + if (ret < 0) { + goto err; + } + + if (!data || !data->data) { + goto err; + } + *bin = data->data; + +err: + if (data) + data_unref (data); + + return ret; +} + + +int +dict_set_bin (dict_t *this, char *key, void *ptr, size_t size) +{ + data_t * data = NULL; + int ret = 0; + + if (!ptr || (size < 0)) { + ret = -EINVAL; + goto err; + } + + data = bin_to_data (ptr, size); + if (!data) { + ret = -EINVAL; + goto err; + } + + data->data = ptr; + data->len = size; + data->is_static = 0; + + ret = dict_set (this, key, data); + +err: + return ret; +} + + +int +dict_set_static_bin (dict_t *this, char *key, void *ptr, size_t size) +{ + data_t * data = NULL; + int ret = 0; + + if (!ptr || (size < 0)) { + ret = -EINVAL; + goto err; + } + + data = bin_to_data (ptr, size); + if (!data) { + ret = -EINVAL; + goto err; + } + + data->data = ptr; + data->len = size; + data->is_static = 1; + + ret = dict_set (this, key, data); + +err: + return ret; +} + +/** + * Serialization format: + * -------- -------- -------- ----------- ------------- + * | count | key len | val len | key \0| value + * ---------------------------------------- ------------- + * 4 4 4 <key len> <value len> + */ + +#define DICT_HDR_LEN 4 +#define DICT_DATA_HDR_KEY_LEN 4 +#define DICT_DATA_HDR_VAL_LEN 4 + +/** + * dict_serialized_length - return the length of serialized dict + * + * @this: dict to be serialized + * @return: success: len + * : failure: -errno + */ + +int +dict_serialized_length (dict_t *this) +{ + int ret = -EINVAL; + int count = 0; + int len = 0; + int i = 0; + data_pair_t * pair = NULL; + + if (!this) { + gf_log ("dict", GF_LOG_ERROR, "this is null!"); + goto out; + } + + len = DICT_HDR_LEN; + count = this->count; + + if (count < 0) { + gf_log ("dict", GF_LOG_ERROR, "count (%d) < 0!", count); + goto out; + } + + pair = this->members_list; + + while (count) { + if (!pair) { + gf_log ("dict", GF_LOG_ERROR, + "less than count data pairs found!"); + goto out; + } + + len += DICT_DATA_HDR_KEY_LEN + DICT_DATA_HDR_VAL_LEN; + + if (!pair->key) { + gf_log ("dict", GF_LOG_ERROR, "pair->key is null!"); + goto out; + } + + len += strlen (pair->key) + 1 /* for '\0' */; + + if (!pair->value) { + gf_log ("dict", GF_LOG_ERROR, + "pair->value is null!"); + goto out; + } + + if (pair->value->vec) { + for (i = 0; i < pair->value->len; i++) { + if (pair->value->vec[i].iov_len < 0) { + gf_log ("dict", GF_LOG_ERROR, + "iov_len (%"GF_PRI_SIZET") < 0!", + pair->value->vec[i].iov_len); + goto out; + } + + len += pair->value->vec[i].iov_len; + } + } else { + if (pair->value->len < 0) { + gf_log ("dict", GF_LOG_ERROR, + "value->len (%d) < 0", + pair->value->len); + goto out; + } + + len += pair->value->len; + } + + pair = pair->next; + count--; + } + + ret = len; +out: + return ret; +} + +/** + * dict_serialize - serialize a dictionary into a buffer + * + * @this: dict to serialize + * @buf: buffer to serialize into. This must be + * atleast dict_serialized_length (this) large + * + * @return: success: 0 + * failure: -errno + */ + +int +dict_serialize (dict_t *this, char *buf) +{ + int ret = -1; + data_pair_t * pair = NULL; + int32_t count = 0; + int32_t keylen = 0; + int32_t vallen = 0; + + if (!this) { + gf_log ("dict", GF_LOG_ERROR, + "this is null!"); + goto out; + } + if (!buf) { + gf_log ("dict", GF_LOG_ERROR, + "buf is null!"); + goto out; + } + + count = this->count; + if (count < 0) { + gf_log ("dict", GF_LOG_ERROR, "count (%d) < 0!", count); + goto out; + } + + *(int32_t *) buf = hton32 (count); + buf += DICT_HDR_LEN; + pair = this->members_list; + + while (count) { + if (!pair) { + gf_log ("dict", GF_LOG_ERROR, + "less than count data pairs found!"); + goto out; + } + + if (!pair->key) { + gf_log ("dict", GF_LOG_ERROR, + "pair->key is null!"); + goto out; + } + + keylen = strlen (pair->key); + *(int32_t *) buf = hton32 (keylen); + buf += DICT_DATA_HDR_KEY_LEN; + + if (!pair->value) { + gf_log ("dict", GF_LOG_ERROR, + "pair->value is null!"); + goto out; + } + + vallen = pair->value->len; + *(int32_t *) buf = hton32 (vallen); + buf += DICT_DATA_HDR_VAL_LEN; + + memcpy (buf, pair->key, keylen); + buf += keylen; + *buf++ = '\0'; + + if (!pair->value->data) { + gf_log ("dict", GF_LOG_ERROR, + "pair->value->data is null!"); + goto out; + } + memcpy (buf, pair->value->data, vallen); + buf += vallen; + + pair = pair->next; + count--; + } + + ret = 0; +out: + return ret; +} + + +/** + * dict_unserialize - unserialize a buffer into a dict + * + * @buf: buf containing serialized dict + * @size: size of the @buf + * @fill: dict to fill in + * + * @return: success: 0 + * failure: -errno + */ + +int32_t +dict_unserialize (char *orig_buf, int32_t size, dict_t **fill) +{ + char *buf = NULL; + int ret = -1; + int32_t count = 0; + int i = 0; + + data_t * value = NULL; + char * key = NULL; + int32_t keylen = 0; + int32_t vallen = 0; + + + buf = orig_buf; + + if (!buf) { + gf_log ("dict", GF_LOG_ERROR, + "buf is null!"); + goto out; + } + + if (size == 0) { + gf_log ("dict", GF_LOG_ERROR, + "size is 0!"); + goto out; + } + + if (!fill) { + gf_log ("dict", GF_LOG_ERROR, + "fill is null!"); + goto out; + } + + if (!*fill) { + gf_log ("dict", GF_LOG_ERROR, + "*fill is null!"); + goto out; + } + + if ((buf + DICT_HDR_LEN) > (orig_buf + size)) { + gf_log ("dict", GF_LOG_ERROR, + "undersized buffer passsed"); + goto out; + } + + count = ntoh32 (*(int32_t *) buf); + buf += DICT_HDR_LEN; + + if (count < 0) { + gf_log ("dict", GF_LOG_ERROR, + "count (%d) <= 0", count); + goto out; + } + + /* count will be set by the dict_set's below */ + (*fill)->count = 0; + + for (i = 0; i < count; i++) { + if ((buf + DICT_DATA_HDR_KEY_LEN) > (orig_buf + size)) { + gf_log ("dict", GF_LOG_ERROR, + "undersized buffer passsed"); + goto out; + } + keylen = ntoh32 (*(int32_t *) buf); + buf += DICT_DATA_HDR_KEY_LEN; + + if ((buf + DICT_DATA_HDR_VAL_LEN) > (orig_buf + size)) { + gf_log ("dict", GF_LOG_ERROR, + "undersized buffer passsed"); + goto out; + } + vallen = ntoh32 (*(int32_t *) buf); + buf += DICT_DATA_HDR_VAL_LEN; + + if ((buf + keylen) > (orig_buf + size)) { + gf_log ("dict", GF_LOG_ERROR, + "undersized buffer passsed"); + goto out; + } + key = buf; + buf += keylen + 1; /* for '\0' */ + + if ((buf + vallen) > (orig_buf + size)) { + gf_log ("dict", GF_LOG_ERROR, + "undersized buffer passsed"); + goto out; + } + value = get_new_data (); + value->len = vallen; + value->data = buf; + value->is_static = 1; + buf += vallen; + + dict_set (*fill, key, value); + } + + ret = 0; +out: + return ret; +} + diff --git a/libglusterfs/src/dict.h b/libglusterfs/src/dict.h new file mode 100644 index 000000000..5c299d039 --- /dev/null +++ b/libglusterfs/src/dict.h @@ -0,0 +1,179 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _DICT_H +#define _DICT_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <inttypes.h> +#include <sys/uio.h> +#include <pthread.h> + +#include "common-utils.h" + +typedef struct _data data_t; +typedef struct _dict dict_t; +typedef struct _data_pair data_pair_t; + +struct _data { + unsigned char is_static:1; + unsigned char is_const:1; + int32_t len; + struct iovec *vec; + char *data; + int32_t refcount; + gf_lock_t lock; +}; + +struct _data_pair { + struct _data_pair *hash_next; + struct _data_pair *prev; + struct _data_pair *next; + data_t *value; + char *key; +}; + +struct _dict { + unsigned char is_static:1; + int32_t hash_size; + int32_t count; + int32_t refcount; + data_pair_t **members; + data_pair_t *members_list; + char *extra_free; + gf_lock_t lock; +}; + + +int32_t is_data_equal (data_t *one, data_t *two); +void data_destroy (data_t *data); + +int32_t dict_set (dict_t *this, char *key, data_t *value); +data_t *dict_get (dict_t *this, char *key); +void dict_del (dict_t *this, char *key); + +int32_t dict_serialized_length (dict_t *dict); +int32_t dict_serialize (dict_t *dict, char *buf); +int32_t dict_unserialize (char *buf, int32_t size, dict_t **fill); + +int32_t dict_iovec_len (dict_t *dict); +int32_t dict_to_iovec (dict_t *dict, struct iovec *vec, int32_t count); + +void dict_destroy (dict_t *dict); +void dict_unref (dict_t *dict); +dict_t *dict_ref (dict_t *dict); +data_t *data_ref (data_t *data); +void data_unref (data_t *data); + +/* + TODO: provide converts for differnt byte sizes, signedness, and void * + */ +data_t *int_to_data (int64_t value); +data_t *str_to_data (char *value); +data_t *data_from_dynstr (char *value); +data_t *data_from_dynptr (void *value, int32_t len); +data_t *bin_to_data (void *value, int32_t len); +data_t *static_str_to_data (char *value); +data_t *static_bin_to_data (void *value); + +int64_t data_to_int64 (data_t *data); +int32_t data_to_int32 (data_t *data); +int16_t data_to_int16 (data_t *data); +int8_t data_to_int8 (data_t *data); + +uint64_t data_to_uint64 (data_t *data); +uint32_t data_to_uint32 (data_t *data); +uint16_t data_to_uint16 (data_t *data); + +data_t *data_from_ptr (void *value); +data_t *data_from_static_ptr (void *value); + +data_t *data_from_int64 (int64_t value); +data_t *data_from_int32 (int32_t value); +data_t *data_from_int16 (int16_t value); +data_t *data_from_int8 (int8_t value); + +data_t *data_from_uint64 (uint64_t value); +data_t *data_from_uint32 (uint32_t value); +data_t *data_from_uint16 (uint16_t value); + +char *data_to_str (data_t *data); +void *data_to_bin (data_t *data); +void *data_to_ptr (data_t *data); + +data_t *get_new_data (); +dict_t *get_new_dict_full (int size_hint); +dict_t *get_new_dict (); + +data_pair_t *get_new_data_pair (); + +void dict_foreach (dict_t *this, + void (*fn)(dict_t *this, + char *key, + data_t *value, + void *data), + void *data); + +dict_t *dict_copy (dict_t *this, + dict_t *new); + +/* CLEANED UP FUNCTIONS DECLARATIONS */ +GF_MUST_CHECK dict_t *dict_new (void); +dict_t *dict_copy_with_ref (dict_t *this, + dict_t *new); + +GF_MUST_CHECK int dict_get_int8 (dict_t *this, char *key, int8_t *val); +GF_MUST_CHECK int dict_set_int8 (dict_t *this, char *key, int8_t val); + +GF_MUST_CHECK int dict_get_int16 (dict_t *this, char *key, int16_t *val); +GF_MUST_CHECK int dict_set_int16 (dict_t *this, char *key, int16_t val); + +GF_MUST_CHECK int dict_get_int32 (dict_t *this, char *key, int32_t *val); +GF_MUST_CHECK int dict_set_int32 (dict_t *this, char *key, int32_t val); + +GF_MUST_CHECK int dict_get_int64 (dict_t *this, char *key, int64_t *val); +GF_MUST_CHECK int dict_set_int64 (dict_t *this, char *key, int64_t val); + +GF_MUST_CHECK int dict_get_uint16 (dict_t *this, char *key, uint16_t *val); +GF_MUST_CHECK int dict_set_uint16 (dict_t *this, char *key, uint16_t val); + +GF_MUST_CHECK int dict_get_uint32 (dict_t *this, char *key, uint32_t *val); +GF_MUST_CHECK int dict_set_uint32 (dict_t *this, char *key, uint32_t val); + +GF_MUST_CHECK int dict_get_uint64 (dict_t *this, char *key, uint64_t *val); +GF_MUST_CHECK int dict_set_uint64 (dict_t *this, char *key, uint64_t val); + +GF_MUST_CHECK int dict_set_static_ptr (dict_t *this, char *key, void *ptr); +GF_MUST_CHECK int dict_get_ptr (dict_t *this, char *key, void **ptr); +GF_MUST_CHECK int dict_set_ptr (dict_t *this, char *key, void *ptr); +GF_MUST_CHECK int dict_set_dynptr (dict_t *this, char *key, void *ptr, size_t size); + +GF_MUST_CHECK int dict_get_bin (dict_t *this, char *key, void **ptr); +GF_MUST_CHECK int dict_set_bin (dict_t *this, char *key, void *ptr, size_t size); +GF_MUST_CHECK int dict_set_static_bin (dict_t *this, char *key, void *ptr, size_t size); + +GF_MUST_CHECK int dict_set_str (dict_t *this, char *key, char *str); +GF_MUST_CHECK int dict_set_dynstr (dict_t *this, char *key, char *str); +GF_MUST_CHECK int dict_get_str (dict_t *this, char *key, char **str); + +#endif diff --git a/libglusterfs/src/event.c b/libglusterfs/src/event.c new file mode 100644 index 000000000..f2bbddd20 --- /dev/null +++ b/libglusterfs/src/event.c @@ -0,0 +1,978 @@ +/* + Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <sys/poll.h> +#include <pthread.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> + +#include "logging.h" +#include "event.h" +#include "mem-pool.h" + + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +static int +event_register_poll (struct event_pool *event_pool, int fd, + event_handler_t handler, + void *data, int poll_in, int poll_out); + + +static int +__flush_fd (int fd, int idx, void *data, + int poll_in, int poll_out, int poll_err) +{ + char buf[64]; + int ret = -1; + + if (!poll_in) + return ret; + + do { + ret = read (fd, buf, 64); + if (ret == -1 && errno != EAGAIN) { + gf_log ("poll", GF_LOG_ERROR, + "read on %d returned error (%s)", + fd, strerror (errno)); + } + } while (ret == 64); + + return ret; +} + + +static int +__event_getindex (struct event_pool *event_pool, int fd, int idx) +{ + int ret = -1; + int i = 0; + + if (event_pool == NULL) { + gf_log ("event", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + if (idx > -1 && idx < event_pool->used) { + if (event_pool->reg[idx].fd == fd) + ret = idx; + } + + for (i=0; ret == -1 && i<event_pool->used; i++) { + if (event_pool->reg[i].fd == fd) { + ret = i; + break; + } + } + + return ret; +} + + +static struct event_pool * +event_pool_new_poll (int count) +{ + struct event_pool *event_pool = NULL; + int ret = -1; + + event_pool = CALLOC (1, sizeof (*event_pool)); + + if (!event_pool) + return NULL; + + event_pool->count = count; + event_pool->reg = CALLOC (event_pool->count, + sizeof (*event_pool->reg)); + + if (!event_pool->reg) { + gf_log ("poll", GF_LOG_CRITICAL, + "failed to allocate event registry"); + free (event_pool); + return NULL; + } + + pthread_mutex_init (&event_pool->mutex, NULL); + + ret = pipe (event_pool->breaker); + + if (ret == -1) { + gf_log ("poll", GF_LOG_ERROR, + "pipe creation failed (%s)", strerror (errno)); + free (event_pool->reg); + free (event_pool); + return NULL; + } + + ret = fcntl (event_pool->breaker[0], F_SETFL, O_NONBLOCK); + if (ret == -1) { + gf_log ("poll", GF_LOG_ERROR, + "could not set pipe to non blocking mode (%s)", + strerror (errno)); + close (event_pool->breaker[0]); + close (event_pool->breaker[1]); + event_pool->breaker[0] = event_pool->breaker[1] = -1; + + free (event_pool->reg); + free (event_pool); + return NULL; + } + + ret = fcntl (event_pool->breaker[1], F_SETFL, O_NONBLOCK); + if (ret == -1) { + gf_log ("poll", GF_LOG_ERROR, + "could not set pipe to non blocking mode (%s)", + strerror (errno)); + + close (event_pool->breaker[0]); + close (event_pool->breaker[1]); + event_pool->breaker[0] = event_pool->breaker[1] = -1; + + free (event_pool->reg); + free (event_pool); + return NULL; + } + + ret = event_register_poll (event_pool, event_pool->breaker[0], + __flush_fd, NULL, 1, 0); + if (ret == -1) { + gf_log ("poll", GF_LOG_ERROR, + "could not register pipe fd with poll event loop"); + close (event_pool->breaker[0]); + close (event_pool->breaker[1]); + event_pool->breaker[0] = event_pool->breaker[1] = -1; + + free (event_pool->reg); + free (event_pool); + return NULL; + } + + return event_pool; +} + + +static int +event_register_poll (struct event_pool *event_pool, int fd, + event_handler_t handler, + void *data, int poll_in, int poll_out) +{ + int idx = -1; + + if (event_pool == NULL) { + gf_log ("event", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + pthread_mutex_lock (&event_pool->mutex); + { + if (event_pool->count == event_pool->used) + { + event_pool->count += 256; + + event_pool->reg = realloc (event_pool->reg, + event_pool->count * + sizeof (*event_pool->reg)); + } + + idx = event_pool->used++; + + event_pool->reg[idx].fd = fd; + event_pool->reg[idx].events = POLLPRI; + event_pool->reg[idx].handler = handler; + event_pool->reg[idx].data = data; + + switch (poll_in) { + case 1: + event_pool->reg[idx].events |= POLLIN; + break; + case 0: + event_pool->reg[idx].events &= ~POLLIN; + break; + case -1: + /* do nothing */ + break; + default: + gf_log ("poll", GF_LOG_ERROR, + "invalid poll_in value %d", poll_in); + break; + } + + switch (poll_out) { + case 1: + event_pool->reg[idx].events |= POLLOUT; + break; + case 0: + event_pool->reg[idx].events &= ~POLLOUT; + break; + case -1: + /* do nothing */ + break; + default: + gf_log ("poll", GF_LOG_ERROR, + "invalid poll_out value %d", poll_in); + break; + } + + event_pool->changed = 1; + + } + pthread_mutex_unlock (&event_pool->mutex); + + return idx; +} + + +static int +event_unregister_poll (struct event_pool *event_pool, int fd, int idx_hint) +{ + int idx = -1; + + if (event_pool == NULL) { + gf_log ("event", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + pthread_mutex_lock (&event_pool->mutex); + { + idx = __event_getindex (event_pool, fd, idx_hint); + + if (idx == -1) { + gf_log ("poll", GF_LOG_ERROR, + "index not found for fd=%d (idx_hint=%d)", + fd, idx_hint); + errno = ENOENT; + goto unlock; + } + + event_pool->reg[idx] = event_pool->reg[--event_pool->used]; + event_pool->changed = 1; + } +unlock: + pthread_mutex_unlock (&event_pool->mutex); + + return idx; +} + + +static int +event_select_on_poll (struct event_pool *event_pool, int fd, int idx_hint, + int poll_in, int poll_out) +{ + int idx = -1; + + if (event_pool == NULL) { + gf_log ("event", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + pthread_mutex_lock (&event_pool->mutex); + { + idx = __event_getindex (event_pool, fd, idx_hint); + + if (idx == -1) { + gf_log ("poll", GF_LOG_ERROR, + "index not found for fd=%d (idx_hint=%d)", + fd, idx_hint); + errno = ENOENT; + goto unlock; + } + + switch (poll_in) { + case 1: + event_pool->reg[idx].events |= POLLIN; + break; + case 0: + event_pool->reg[idx].events &= ~POLLIN; + break; + case -1: + /* do nothing */ + break; + default: + /* TODO: log error */ + break; + } + + switch (poll_out) { + case 1: + event_pool->reg[idx].events |= POLLOUT; + break; + case 0: + event_pool->reg[idx].events &= ~POLLOUT; + break; + case -1: + /* do nothing */ + break; + default: + /* TODO: log error */ + break; + } + + if (poll_in + poll_out > -2) + event_pool->changed = 1; + } +unlock: + pthread_mutex_unlock (&event_pool->mutex); + + return idx; +} + + +static int +event_dispatch_poll_handler (struct event_pool *event_pool, + struct pollfd *ufds, int i) +{ + event_handler_t handler = NULL; + void *data = NULL; + int idx = -1; + int ret = 0; + + handler = NULL; + data = NULL; + idx = -1; + + pthread_mutex_lock (&event_pool->mutex); + { + idx = __event_getindex (event_pool, ufds[i].fd, i); + + if (idx == -1) { + gf_log ("poll", GF_LOG_ERROR, + "index not found for fd=%d (idx_hint=%d)", + ufds[i].fd, i); + goto unlock; + } + + handler = event_pool->reg[idx].handler; + data = event_pool->reg[idx].data; + } +unlock: + pthread_mutex_unlock (&event_pool->mutex); + + if (handler) + ret = handler (ufds[i].fd, idx, data, + (ufds[i].revents & (POLLIN|POLLPRI)), + (ufds[i].revents & (POLLOUT)), + (ufds[i].revents & (POLLERR|POLLHUP|POLLNVAL))); + + return ret; +} + + +static int +event_dispatch_poll_resize (struct event_pool *event_pool, + struct pollfd *ufds, int size) +{ + int i = 0; + + pthread_mutex_lock (&event_pool->mutex); + { + if (event_pool->changed == 0) { + goto unlock; + } + + if (event_pool->used > event_pool->evcache_size) { + if (event_pool->evcache) + free (event_pool->evcache); + + event_pool->evcache = ufds = NULL; + + event_pool->evcache_size = event_pool->used; + + ufds = CALLOC (sizeof (struct pollfd), + event_pool->evcache_size); + event_pool->evcache = ufds; + } + + for (i = 0; i < event_pool->used; i++) { + ufds[i].fd = event_pool->reg[i].fd; + ufds[i].events = event_pool->reg[i].events; + ufds[i].revents = 0; + } + + size = i; + } +unlock: + pthread_mutex_unlock (&event_pool->mutex); + + return size; +} + + +static int +event_dispatch_poll (struct event_pool *event_pool) +{ + struct pollfd *ufds = NULL; + int size = 0; + int i = 0; + int ret = -1; + + + if (event_pool == NULL) { + gf_log ("event", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + while (1) { + size = event_dispatch_poll_resize (event_pool, ufds, size); + ufds = event_pool->evcache; + + ret = poll (ufds, size, 1); + + if (ret == 0) + /* timeout */ + continue; + + if (ret == -1 && errno == EINTR) + /* sys call */ + continue; + + for (i = 0; i < size; i++) { + if (!ufds[i].revents) + continue; + + event_dispatch_poll_handler (event_pool, ufds, i); + } + } + + return -1; +} + + +static struct event_ops event_ops_poll = { + .new = event_pool_new_poll, + .event_register = event_register_poll, + .event_select_on = event_select_on_poll, + .event_unregister = event_unregister_poll, + .event_dispatch = event_dispatch_poll +}; + + + +#ifdef HAVE_SYS_EPOLL_H +#include <sys/epoll.h> + + +static struct event_pool * +event_pool_new_epoll (int count) +{ + struct event_pool *event_pool = NULL; + int epfd = -1; + + event_pool = CALLOC (1, sizeof (*event_pool)); + + if (!event_pool) + return NULL; + + event_pool->count = count; + event_pool->reg = CALLOC (event_pool->count, + sizeof (*event_pool->reg)); + + if (!event_pool->reg) { + gf_log ("epoll", GF_LOG_CRITICAL, + "event registry allocation failed"); + free (event_pool); + return NULL; + } + + epfd = epoll_create (count); + + if (epfd == -1) { + gf_log ("epoll", GF_LOG_ERROR, "epoll fd creation failed (%s)", + strerror (errno)); + free (event_pool->reg); + free (event_pool); + return NULL; + } + + event_pool->fd = epfd; + + event_pool->count = count; + + pthread_mutex_init (&event_pool->mutex, NULL); + pthread_cond_init (&event_pool->cond, NULL); + + return event_pool; +} + + +int +event_register_epoll (struct event_pool *event_pool, int fd, + event_handler_t handler, + void *data, int poll_in, int poll_out) +{ + int idx = -1; + int ret = -1; + struct epoll_event epoll_event = {0, }; + struct event_data *ev_data = (void *)&epoll_event.data; + + + if (event_pool == NULL) { + gf_log ("event", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + pthread_mutex_lock (&event_pool->mutex); + { + if (event_pool->count == event_pool->used) { + event_pool->count *= 2; + + event_pool->reg = realloc (event_pool->reg, + event_pool->count * + sizeof (*event_pool->reg)); + + if (!event_pool->reg) { + gf_log ("epoll", GF_LOG_ERROR, + "event registry re-allocation failed"); + goto unlock; + } + } + + idx = event_pool->used; + event_pool->used++; + + event_pool->reg[idx].fd = fd; + event_pool->reg[idx].events = EPOLLPRI; + event_pool->reg[idx].handler = handler; + event_pool->reg[idx].data = data; + + switch (poll_in) { + case 1: + event_pool->reg[idx].events |= EPOLLIN; + break; + case 0: + event_pool->reg[idx].events &= ~EPOLLIN; + break; + case -1: + /* do nothing */ + break; + default: + gf_log ("epoll", GF_LOG_ERROR, + "invalid poll_in value %d", poll_in); + break; + } + + switch (poll_out) { + case 1: + event_pool->reg[idx].events |= EPOLLOUT; + break; + case 0: + event_pool->reg[idx].events &= ~EPOLLOUT; + break; + case -1: + /* do nothing */ + break; + default: + gf_log ("epoll", GF_LOG_ERROR, + "invalid poll_out value %d", poll_in); + break; + } + + event_pool->changed = 1; + + epoll_event.events = event_pool->reg[idx].events; + ev_data->fd = fd; + ev_data->idx = idx; + + ret = epoll_ctl (event_pool->fd, EPOLL_CTL_ADD, fd, + &epoll_event); + + if (ret == -1) { + gf_log ("epoll", GF_LOG_ERROR, + "failed to add fd(=%d) to epoll fd(=%d) (%s)", + fd, event_pool->fd, strerror (errno)); + goto unlock; + } + + pthread_cond_broadcast (&event_pool->cond); + } +unlock: + pthread_mutex_unlock (&event_pool->mutex); + + return ret; +} + + +static int +event_unregister_epoll (struct event_pool *event_pool, int fd, int idx_hint) +{ + int idx = -1; + int ret = -1; + + struct epoll_event epoll_event = {0, }; + struct event_data *ev_data = (void *)&epoll_event.data; + int lastidx = -1; + + if (event_pool == NULL) { + gf_log ("event", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + pthread_mutex_lock (&event_pool->mutex); + { + idx = __event_getindex (event_pool, fd, idx_hint); + + if (idx == -1) { + gf_log ("epoll", GF_LOG_ERROR, + "index not found for fd=%d (idx_hint=%d)", + fd, idx_hint); + errno = ENOENT; + goto unlock; + } + + ret = epoll_ctl (event_pool->fd, EPOLL_CTL_DEL, fd, NULL); + + /* if ret is -1, this array member should never be accessed */ + /* if it is 0, the array member might be used by idx_cache + * in which case the member should not be accessed till + * it is reallocated + */ + + event_pool->reg[idx].fd = -1; + + if (ret == -1) { + gf_log ("epoll", GF_LOG_ERROR, + "fail to del fd(=%d) from epoll fd(=%d) (%s)", + fd, event_pool->fd, strerror (errno)); + goto unlock; + } + + lastidx = event_pool->used - 1; + if (lastidx == idx) { + event_pool->used--; + goto unlock; + } + + epoll_event.events = event_pool->reg[lastidx].events; + ev_data->fd = event_pool->reg[lastidx].fd; + ev_data->idx = idx; + + ret = epoll_ctl (event_pool->fd, EPOLL_CTL_MOD, ev_data->fd, + &epoll_event); + if (ret == -1) { + gf_log ("epoll", GF_LOG_ERROR, + "fail to modify fd(=%d) index %d to %d (%s)", + ev_data->fd, event_pool->used, idx, + strerror (errno)); + goto unlock; + } + + /* just replace the unregistered idx by last one */ + event_pool->reg[idx] = event_pool->reg[lastidx]; + event_pool->used--; + } +unlock: + pthread_mutex_unlock (&event_pool->mutex); + + return ret; +} + + +static int +event_select_on_epoll (struct event_pool *event_pool, int fd, int idx_hint, + int poll_in, int poll_out) +{ + int idx = -1; + int ret = -1; + + struct epoll_event epoll_event = {0, }; + struct event_data *ev_data = (void *)&epoll_event.data; + + + if (event_pool == NULL) { + gf_log ("event", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + pthread_mutex_lock (&event_pool->mutex); + { + idx = __event_getindex (event_pool, fd, idx_hint); + + if (idx == -1) { + gf_log ("epoll", GF_LOG_ERROR, + "index not found for fd=%d (idx_hint=%d)", + fd, idx_hint); + errno = ENOENT; + goto unlock; + } + + switch (poll_in) { + case 1: + event_pool->reg[idx].events |= EPOLLIN; + break; + case 0: + event_pool->reg[idx].events &= ~EPOLLIN; + break; + case -1: + /* do nothing */ + break; + default: + gf_log ("epoll", GF_LOG_ERROR, + "invalid poll_in value %d", poll_in); + break; + } + + switch (poll_out) { + case 1: + event_pool->reg[idx].events |= EPOLLOUT; + break; + case 0: + event_pool->reg[idx].events &= ~EPOLLOUT; + break; + case -1: + /* do nothing */ + break; + default: + gf_log ("epoll", GF_LOG_ERROR, + "invalid poll_out value %d", poll_in); + break; + } + + epoll_event.events = event_pool->reg[idx].events; + ev_data->fd = fd; + ev_data->idx = idx; + + ret = epoll_ctl (event_pool->fd, EPOLL_CTL_MOD, fd, + &epoll_event); + if (ret == -1) { + gf_log ("epoll", GF_LOG_ERROR, + "failed to modify fd(=%d) events to %d", + fd, epoll_event.events); + } + } +unlock: + pthread_mutex_unlock (&event_pool->mutex); + + return ret; +} + + +static int +event_dispatch_epoll_handler (struct event_pool *event_pool, + struct epoll_event *events, int i) +{ + struct event_data *event_data = NULL; + event_handler_t handler = NULL; + void *data = NULL; + int idx = -1; + int ret = -1; + + + event_data = (void *)&events[i].data; + handler = NULL; + data = NULL; + idx = -1; + + pthread_mutex_lock (&event_pool->mutex); + { + idx = __event_getindex (event_pool, event_data->fd, + event_data->idx); + + if (idx == -1) { + gf_log ("epoll", GF_LOG_ERROR, + "index not found for fd(=%d) (idx_hint=%d)", + event_data->fd, event_data->idx); + goto unlock; + } + + handler = event_pool->reg[idx].handler; + data = event_pool->reg[idx].data; + } +unlock: + pthread_mutex_unlock (&event_pool->mutex); + + if (handler) + ret = handler (event_data->fd, event_data->idx, data, + (events[i].events & (EPOLLIN|EPOLLPRI)), + (events[i].events & (EPOLLOUT)), + (events[i].events & (EPOLLERR|EPOLLHUP))); + return ret; +} + + +static int +event_dispatch_epoll (struct event_pool *event_pool) +{ + struct epoll_event *events = NULL; + int size = 0; + int i = 0; + int ret = -1; + + + if (event_pool == NULL) { + gf_log ("event", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + while (1) { + pthread_mutex_lock (&event_pool->mutex); + { + while (event_pool->used == 0) + pthread_cond_wait (&event_pool->cond, + &event_pool->mutex); + + if (event_pool->used > event_pool->evcache_size) { + if (event_pool->evcache) + free (event_pool->evcache); + + event_pool->evcache = events = NULL; + + event_pool->evcache_size = + event_pool->used + 256; + + events = CALLOC (event_pool->evcache_size, + sizeof (struct epoll_event)); + + event_pool->evcache = events; + } + } + pthread_mutex_unlock (&event_pool->mutex); + + ret = epoll_wait (event_pool->fd, event_pool->evcache, + event_pool->evcache_size, -1); + + if (ret == 0) + /* timeout */ + continue; + + if (ret == -1 && errno == EINTR) + /* sys call */ + continue; + + size = ret; + + for (i = 0; i < size; i++) { + if (!events[i].events) + continue; + + ret = event_dispatch_epoll_handler (event_pool, + events, i); + } + } + + return -1; +} + + +static struct event_ops event_ops_epoll = { + .new = event_pool_new_epoll, + .event_register = event_register_epoll, + .event_select_on = event_select_on_epoll, + .event_unregister = event_unregister_epoll, + .event_dispatch = event_dispatch_epoll +}; + +#endif + + +struct event_pool * +event_pool_new (int count) +{ + struct event_pool *event_pool = NULL; + +#ifdef HAVE_SYS_EPOLL_H + event_pool = event_ops_epoll.new (count); + + if (event_pool) { + event_pool->ops = &event_ops_epoll; + } else { + gf_log ("event", GF_LOG_WARNING, + "failing back to poll based event handling"); + } +#endif + + if (!event_pool) { + event_pool = event_ops_poll.new (count); + + if (event_pool) + event_pool->ops = &event_ops_poll; + } + + return event_pool; +} + + +int +event_register (struct event_pool *event_pool, int fd, + event_handler_t handler, + void *data, int poll_in, int poll_out) +{ + int ret = -1; + + if (event_pool == NULL) { + gf_log ("event", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + ret = event_pool->ops->event_register (event_pool, fd, handler, data, + poll_in, poll_out); + return ret; +} + + +int +event_unregister (struct event_pool *event_pool, int fd, int idx) +{ + int ret = -1; + + if (event_pool == NULL) { + gf_log ("event", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + ret = event_pool->ops->event_unregister (event_pool, fd, idx); + + return ret; +} + + +int +event_select_on (struct event_pool *event_pool, int fd, int idx_hint, + int poll_in, int poll_out) +{ + int ret = -1; + + if (event_pool == NULL) { + gf_log ("event", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + ret = event_pool->ops->event_select_on (event_pool, fd, idx_hint, + poll_in, poll_out); + return ret; +} + + +int +event_dispatch (struct event_pool *event_pool) +{ + int ret = -1; + + if (event_pool == NULL) { + gf_log ("event", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + ret = event_pool->ops->event_dispatch (event_pool); + + return ret; +} diff --git a/libglusterfs/src/event.h b/libglusterfs/src/event.h new file mode 100644 index 000000000..ec80e2a58 --- /dev/null +++ b/libglusterfs/src/event.h @@ -0,0 +1,90 @@ +/* + Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _EVENT_H_ +#define _EVENT_H_ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> + +struct event_pool; +struct event_ops; +struct event_data { + int fd; + int idx; +} __attribute__ ((__packed__)); + + +typedef int (*event_handler_t) (int fd, int idx, void *data, + int poll_in, int poll_out, int poll_err); + +struct event_pool { + struct event_ops *ops; + + int fd; + int breaker[2]; + + int count; + struct { + int fd; + int events; + void *data; + event_handler_t handler; + } *reg; + + int used; + int idx_cache; + int changed; + + pthread_mutex_t mutex; + pthread_cond_t cond; + + void *evcache; + int evcache_size; +}; + +struct event_ops { + struct event_pool * (*new) (int count); + + int (*event_register) (struct event_pool *event_pool, int fd, + event_handler_t handler, + void *data, int poll_in, int poll_out); + + int (*event_select_on) (struct event_pool *event_pool, int fd, int idx, + int poll_in, int poll_out); + + int (*event_unregister) (struct event_pool *event_pool, int fd, int idx); + + int (*event_dispatch) (struct event_pool *event_pool); +}; + +struct event_pool * event_pool_new (int count); +int event_select_on (struct event_pool *event_pool, int fd, int idx, + int poll_in, int poll_out); +int event_register (struct event_pool *event_pool, int fd, + event_handler_t handler, + void *data, int poll_in, int poll_out); +int event_unregister (struct event_pool *event_pool, int fd, int idx); +int event_dispatch (struct event_pool *event_pool); + +#endif /* _EVENT_H_ */ diff --git a/libglusterfs/src/fd.c b/libglusterfs/src/fd.c new file mode 100644 index 000000000..78c578842 --- /dev/null +++ b/libglusterfs/src/fd.c @@ -0,0 +1,611 @@ +/* + Copyright (c) 2007, 2008, 2009 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#include "fd.h" +#include "glusterfs.h" +#include "inode.h" +#include "dict.h" + + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + + +static uint32_t +gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr); + +static fd_t * +_fd_ref (fd_t *fd); + +/* + Allocate in memory chunks of power of 2 starting from 1024B + Assumes fdtable->lock is held +*/ +static inline uint32_t +gf_roundup_power_of_two (uint32_t nr) +{ + uint32_t result = nr; + + if (nr < 0) { + gf_log ("server-protocol/fd", + GF_LOG_ERROR, + "Negative number passed"); + return -1; + } + + switch (nr) { + case 0: + case 1: + result = 1; + break; + + default: + { + uint32_t cnt = 0, tmp = nr; + uint8_t remainder = 0; + while (tmp != 1){ + if (tmp % 2) + remainder = 1; + tmp /= 2; + cnt++; + } + + if (remainder) + result = 0x1 << (cnt + 1); + break; + } + } + + return result; +} + +static uint32_t +gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr) +{ + fd_t **oldfds = NULL; + uint32_t oldmax_fds = -1; + + if (fdtable == NULL || nr < 0) + { + gf_log ("fd", GF_LOG_ERROR, "invalid argument"); + return EINVAL; + } + + nr /= (1024 / sizeof (fd_t *)); + nr = gf_roundup_power_of_two (nr + 1); + nr *= (1024 / sizeof (fd_t *)); + + oldfds = fdtable->fds; + oldmax_fds = fdtable->max_fds; + + fdtable->fds = CALLOC (nr, sizeof (fd_t *)); + ERR_ABORT (fdtable->fds); + fdtable->max_fds = nr; + + if (oldfds) { + uint32_t cpy = oldmax_fds * sizeof (fd_t *); + memcpy (fdtable->fds, oldfds, cpy); + } + + FREE (oldfds); + return 0; +} + +fdtable_t * +gf_fd_fdtable_alloc (void) +{ + fdtable_t *fdtable = NULL; + + fdtable = CALLOC (1, sizeof (*fdtable)); + if (!fdtable) + return NULL; + + pthread_mutex_init (&fdtable->lock, NULL); + + pthread_mutex_lock (&fdtable->lock); + { + gf_fd_fdtable_expand (fdtable, 0); + } + pthread_mutex_unlock (&fdtable->lock); + + return fdtable; +} + +void +gf_fd_fdtable_destroy (fdtable_t *fdtable) +{ + + int32_t i = 0; + + if (fdtable) { + pthread_mutex_lock (&fdtable->lock); + { + for (i=0; i < fdtable->max_fds; i++) { + if (fdtable->fds[i]) { + fd_t *fd = fdtable->fds[i]; + + fd_unref (fd); + } + } + + FREE (fdtable->fds); + } + pthread_mutex_unlock (&fdtable->lock); + pthread_mutex_destroy (&fdtable->lock); + FREE (fdtable); + } +} + +int32_t +gf_fd_unused_get2 (fdtable_t *fdtable, fd_t *fdptr, int32_t fd) +{ + int32_t ret = -1; + + if (fdtable == NULL || fdptr == NULL || fd < 0) + { + gf_log ("fd", GF_LOG_ERROR, "invalid argument"); + errno = EINVAL; + return -1; + } + + pthread_mutex_lock (&fdtable->lock); + { + while (fdtable->max_fds < fd) { + int error = 0; + error = gf_fd_fdtable_expand (fdtable, fdtable->max_fds + 1); + if (error) + { + gf_log ("fd.c", + GF_LOG_ERROR, + "Cannot expand fdtable:%s", strerror (error)); + goto err; + } + } + + if (!fdtable->fds[fd]) + { + fdtable->fds[fd] = fdptr; + fd_ref (fdptr); + ret = fd; + } + else + { + gf_log ("fd.c", + GF_LOG_ERROR, + "Cannot allocate fd %d (slot not empty in fdtable)", fd); + } + } +err: + pthread_mutex_unlock (&fdtable->lock); + + return ret; +} + + +int32_t +gf_fd_unused_get (fdtable_t *fdtable, fd_t *fdptr) +{ + int32_t fd = -1, i = 0; + + if (fdtable == NULL || fdptr == NULL) + { + gf_log ("fd", GF_LOG_ERROR, "invalid argument"); + return EINVAL; + } + + pthread_mutex_lock (&fdtable->lock); + { + for (i = 0; i<fdtable->max_fds; i++) + { + if (!fdtable->fds[i]) + break; + } + + if (i < fdtable->max_fds) { + fdtable->fds[i] = fdptr; + fd = i; + } else { + int32_t error; + error = gf_fd_fdtable_expand (fdtable, fdtable->max_fds + 1); + if (error) { + gf_log ("server-protocol.c", + GF_LOG_ERROR, + "Cannot expand fdtable:%s", strerror (error)); + } else { + fdtable->fds[i] = fdptr; + fd = i; + } + } + } + pthread_mutex_unlock (&fdtable->lock); + + return fd; +} + + +inline void +gf_fd_put (fdtable_t *fdtable, int32_t fd) +{ + fd_t *fdptr = NULL; + if (fdtable == NULL || fd < 0) + { + gf_log ("fd", GF_LOG_ERROR, "invalid argument"); + return; + } + + if (!(fd < fdtable->max_fds)) + { + gf_log ("fd", GF_LOG_ERROR, "invalid argument"); + return; + } + + pthread_mutex_lock (&fdtable->lock); + { + fdptr = fdtable->fds[fd]; + fdtable->fds[fd] = NULL; + } + pthread_mutex_unlock (&fdtable->lock); + + if (fdptr) { + fd_unref (fdptr); + } +} + + +fd_t * +gf_fd_fdptr_get (fdtable_t *fdtable, int64_t fd) +{ + fd_t *fdptr = NULL; + + if (fdtable == NULL || fd < 0) + { + gf_log ("fd", GF_LOG_ERROR, "invalid argument"); + errno = EINVAL; + return NULL; + } + + if (!(fd < fdtable->max_fds)) + { + gf_log ("fd", GF_LOG_ERROR, "invalid argument"); + errno = EINVAL; + return NULL; + } + + pthread_mutex_lock (&fdtable->lock); + { + fdptr = fdtable->fds[fd]; + if (fdptr) { + fd_ref (fdptr); + } + } + pthread_mutex_unlock (&fdtable->lock); + + return fdptr; +} + +fd_t * +_fd_ref (fd_t *fd) +{ + ++fd->refcount; + + return fd; +} + +fd_t * +fd_ref (fd_t *fd) +{ + fd_t *refed_fd = NULL; + + if (!fd) { + gf_log ("fd", GF_LOG_ERROR, "@fd=%p", fd); + return NULL; + } + + LOCK (&fd->inode->lock); + refed_fd = _fd_ref (fd); + UNLOCK (&fd->inode->lock); + + return refed_fd; +} + +fd_t * +_fd_unref (fd_t *fd) +{ + assert (fd->refcount); + + --fd->refcount; + + if (fd->refcount == 0){ + list_del_init (&fd->inode_list); + } + + return fd; +} + +static void +fd_destroy (fd_t *fd) +{ + data_pair_t *pair = NULL; + xlator_t *xl = NULL; + int i = 0; + + if (fd == NULL){ + gf_log ("xlator", GF_LOG_ERROR, "invalid arugument"); + goto out; + } + + if (fd->inode == NULL){ + gf_log ("xlator", GF_LOG_ERROR, "fd->inode is NULL"); + goto out; + } + if (!fd->_ctx) + goto out; + + if (S_ISDIR (fd->inode->st_mode)) { + for (pair = fd->ctx->members_list; pair; pair = pair->next) { + /* notify all xlators which have a context */ + xl = xlator_search_by_name (fd->inode->table->xl, + pair->key); + + if (!xl) { + gf_log ("fd", GF_LOG_CRITICAL, + "fd(%p)->ctx has invalid key(%s)", + fd, pair->key); + continue; + } + if (xl->cbks->releasedir) { + xl->cbks->releasedir (xl, fd); + } else { + gf_log ("fd", GF_LOG_CRITICAL, + "xlator(%s) in fd(%p) no RELEASE cbk", + xl->name, fd); + } + + } + for (i = 0; i < fd->inode->table->xl->ctx->xl_count; i++) { + if (fd->_ctx[i].key) { + xl = (xlator_t *)(long)fd->_ctx[i].key; + if (xl->cbks->releasedir) + xl->cbks->releasedir (xl, fd); + } + } + } else { + for (pair = fd->ctx->members_list; pair; pair = pair->next) { + /* notify all xlators which have a context */ + xl = xlator_search_by_name (fd->inode->table->xl, + pair->key); + + if (!xl) { + gf_log ("fd", GF_LOG_CRITICAL, + "fd(%p)->ctx has invalid key(%s)", + fd, pair->key); + continue; + } + if (xl->cbks->release) { + xl->cbks->release (xl, fd); + } else { + gf_log ("fd", GF_LOG_CRITICAL, + "xlator(%s) in fd(%p) no RELEASE cbk", + xl->name, fd); + } + } + for (i = 0; i < fd->inode->table->xl->ctx->xl_count; i++) { + if (fd->_ctx[i].key) { + xl = (xlator_t *)(long)fd->_ctx[i].key; + if (xl->cbks->release) + xl->cbks->release (xl, fd); + } + } + } + + FREE (fd->_ctx); + inode_unref (fd->inode); + fd->inode = (inode_t *)0xaaaaaaaa; + dict_destroy (fd->ctx); + FREE (fd); + +out: + return; +} + +void +fd_unref (fd_t *fd) +{ + int32_t refcount = 0; + + if (!fd) { + gf_log ("fd.c", GF_LOG_ERROR, "fd is NULL"); + return; + } + + LOCK (&fd->inode->lock); + { + _fd_unref (fd); + refcount = fd->refcount; + } + UNLOCK (&fd->inode->lock); + + if (refcount == 0) { + fd_destroy (fd); + } + + return ; +} + +fd_t * +fd_bind (fd_t *fd) +{ + inode_t *inode = fd->inode; + + if (!fd) { + gf_log ("fd.c", GF_LOG_ERROR, "fd is NULL"); + return NULL; + } + + LOCK (&inode->lock); + { + list_add (&fd->inode_list, &inode->fd_list); + } + UNLOCK (&inode->lock); + + return fd; +} + +fd_t * +fd_create (inode_t *inode, pid_t pid) +{ + fd_t *fd = NULL; + + if (inode == NULL) { + gf_log ("fd", GF_LOG_ERROR, "invalid argument"); + return NULL; + } + + fd = CALLOC (1, sizeof (fd_t)); + ERR_ABORT (fd); + + fd->_ctx = CALLOC (1, (sizeof (struct _fd_ctx) * + inode->table->xl->ctx->xl_count)); + fd->ctx = get_new_dict (); + fd->inode = inode_ref (inode); + fd->pid = pid; + INIT_LIST_HEAD (&fd->inode_list); + + LOCK (&inode->lock); + fd = _fd_ref (fd); + UNLOCK (&inode->lock); + + return fd; +} + +fd_t * +fd_lookup (inode_t *inode, pid_t pid) +{ + fd_t *fd = NULL; + fd_t *iter_fd = NULL; + + LOCK (&inode->lock); + { + if (list_empty (&inode->fd_list)) { + fd = NULL; + } else { + list_for_each_entry (iter_fd, &inode->fd_list, inode_list) { + if (pid) { + if (iter_fd->pid == pid) { + fd = _fd_ref (iter_fd); + break; + } + } else { + fd = _fd_ref (iter_fd); + break; + } + } + } + } + UNLOCK (&inode->lock); + + return fd; +} + +uint8_t +fd_list_empty (inode_t *inode) +{ + uint8_t empty = 0; + + LOCK (&inode->lock); + { + empty = list_empty (&inode->fd_list); + } + UNLOCK (&inode->lock); + + return empty; +} + +int +fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value) +{ + int index = 0; + + if (!fd || !xlator) + return -1; + + for (index = 0; index < xlator->ctx->xl_count; index++) { + if (!fd->_ctx[index].key || + (fd->_ctx[index].key == (uint64_t)(long)xlator)) + break; + } + + if (index == xlator->ctx->xl_count) + return -1; + + fd->_ctx[index].key = (uint64_t)(long) xlator; + fd->_ctx[index].value = value; + + return 0; +} + +int +fd_ctx_get (fd_t *fd, xlator_t *xlator, uint64_t *value) +{ + int index = 0; + + if (!fd || !xlator) + return -1; + + for (index = 0; index < xlator->ctx->xl_count; index++) { + if (fd->_ctx[index].key == (uint64_t)(long)xlator) + break; + } + + if (index == xlator->ctx->xl_count) + return -1; + + if (value) + *value = fd->_ctx[index].value; + + return 0; +} + + +int +fd_ctx_del (fd_t *fd, xlator_t *xlator, uint64_t *value) +{ + int index = 0; + + if (!fd || !xlator) + return -1; + + for (index = 0; index < xlator->ctx->xl_count; index++) { + if (fd->_ctx[index].key == (uint64_t)(long)xlator) + break; + } + + if (index == xlator->ctx->xl_count) + return -1; + + if (value) + *value = fd->_ctx[index].value; + + fd->_ctx[index].key = 0; + fd->_ctx[index].value = 0; + + return 0; +} diff --git a/libglusterfs/src/fd.h b/libglusterfs/src/fd.h new file mode 100644 index 000000000..8b8effdc3 --- /dev/null +++ b/libglusterfs/src/fd.h @@ -0,0 +1,107 @@ +/* + Copyright (c) 2007, 2008, 2009 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _FD_H +#define _FD_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "list.h" +#include <sys/types.h> +#include <unistd.h> +#include "glusterfs.h" + +struct _inode; +struct _dict; +struct _fd_ctx { + uint64_t key; + uint64_t value; +}; + +struct _fd { + pid_t pid; + int32_t flags; + int32_t refcount; + struct list_head inode_list; + struct _inode *inode; + struct _dict *ctx; + struct _fd_ctx *_ctx; +}; +typedef struct _fd fd_t; + +struct _fdtable { + int refcount; + uint32_t max_fds; + pthread_mutex_t lock; + fd_t **fds; +}; +typedef struct _fdtable fdtable_t; + +#include "logging.h" +#include "xlator.h" + +inline void +gf_fd_put (fdtable_t *fdtable, int32_t fd); + +fd_t * +gf_fd_fdptr_get (fdtable_t *fdtable, int64_t fd); + +fdtable_t * +gf_fd_fdtable_alloc (void); + +int32_t +gf_fd_unused_get (fdtable_t *fdtable, fd_t *fdptr); + +int32_t +gf_fd_unused_get2 (fdtable_t *fdtable, fd_t *fdptr, int32_t fd); + +void +gf_fd_fdtable_destroy (fdtable_t *fdtable); + +fd_t * +fd_ref (fd_t *fd); + +void +fd_unref (fd_t *fd); + +fd_t * +fd_create (struct _inode *inode, pid_t pid); + +fd_t * +fd_lookup (struct _inode *inode, pid_t pid); + +uint8_t +fd_list_empty (struct _inode *inode); + +fd_t * +fd_bind (fd_t *fd); + +int +fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value); + +int +fd_ctx_get (fd_t *fd, xlator_t *xlator, uint64_t *value); + +int +fd_ctx_del (fd_t *fd, xlator_t *xlator, uint64_t *value); + +#endif /* _FD_H */ diff --git a/libglusterfs/src/gf-dirent.c b/libglusterfs/src/gf-dirent.c new file mode 100644 index 000000000..28d1ab425 --- /dev/null +++ b/libglusterfs/src/gf-dirent.c @@ -0,0 +1,157 @@ +/* + Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + + +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include "compat.h" +#include "xlator.h" +#include "byte-order.h" + + +struct gf_dirent_nb { + uint64_t d_ino; + uint64_t d_off; + uint32_t d_len; + uint32_t d_type; + char d_name[0]; +} __attribute__((packed)); + + +int +gf_dirent_nb_size (gf_dirent_t *entries) +{ + return (sizeof (struct gf_dirent_nb) + strlen (entries->d_name) + 1); +} + + +gf_dirent_t * +gf_dirent_for_name (const char *name) +{ + gf_dirent_t *gf_dirent = NULL; + + /* TODO: use mem-pool */ + gf_dirent = CALLOC (gf_dirent_size (name), 1); + if (!gf_dirent) + return NULL; + + INIT_LIST_HEAD (&gf_dirent->list); + strcpy (gf_dirent->d_name, name); + + gf_dirent->d_off = 0; + gf_dirent->d_ino = -1; + gf_dirent->d_type = 0; + gf_dirent->d_len = strlen (name); + + return gf_dirent; +} + + +void +gf_dirent_free (gf_dirent_t *entries) +{ + gf_dirent_t *entry = NULL; + gf_dirent_t *tmp = NULL; + + list_for_each_entry_safe (entry, tmp, &entries->list, list) { + list_del (&entry->list); + FREE (entry); + } +} + + +int +gf_dirent_serialize (gf_dirent_t *entries, char *buf, size_t buf_size) +{ + struct gf_dirent_nb *entry_nb = NULL; + gf_dirent_t *entry = NULL; + int size = 0; + int entry_size = 0; + + + list_for_each_entry (entry, &entries->list, list) { + entry_size = gf_dirent_nb_size (entry); + + if (buf && (size + entry_size <= buf_size)) { + entry_nb = (void *) (buf + size); + + entry_nb->d_ino = hton64 (entry->d_ino); + entry_nb->d_off = hton64 (entry->d_off); + entry_nb->d_len = hton32 (entry->d_len); + entry_nb->d_type = hton32 (entry->d_type); + + strcpy (entry_nb->d_name, entry->d_name); + } + size += entry_size; + } + + return size; +} + + +int +gf_dirent_unserialize (gf_dirent_t *entries, const char *buf, size_t buf_size) +{ + struct gf_dirent_nb *entry_nb = NULL; + int remaining_size = 0; + int least_dirent_size = 0; + int count = 0; + gf_dirent_t *entry = NULL; + int entry_strlen = 0; + int entry_len = 0; + + + remaining_size = buf_size; + least_dirent_size = (sizeof (struct gf_dirent_nb) + 2); + + while (remaining_size >= least_dirent_size) { + entry_nb = (void *)(buf + (buf_size - remaining_size)); + + entry_strlen = strnlen (entry_nb->d_name, remaining_size); + if (entry_strlen == remaining_size) { + break; + } + + entry_len = sizeof (gf_dirent_t) + entry_strlen + 1; + entry = CALLOC (1, entry_len); + if (!entry) { + break; + } + + entry->d_ino = ntoh64 (entry_nb->d_ino); + entry->d_off = ntoh64 (entry_nb->d_off); + entry->d_len = ntoh32 (entry_nb->d_len); + entry->d_type = ntoh32 (entry_nb->d_type); + strcpy (entry->d_name, entry_nb->d_name); + + list_add_tail (&entry->list, &entries->list); + + remaining_size -= (sizeof (*entry_nb) + entry_strlen + 1); + count++; + } + + return count; +} diff --git a/libglusterfs/src/gf-dirent.h b/libglusterfs/src/gf-dirent.h new file mode 100644 index 000000000..fa0a8a625 --- /dev/null +++ b/libglusterfs/src/gf-dirent.h @@ -0,0 +1,60 @@ +/* + Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + + +#ifndef _GF_DIRENT_H +#define _GF_DIRENT_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#define gf_dirent_size(name) (sizeof (gf_dirent_t) + strlen (name) + 1) + +struct _dir_entry_t { + struct _dir_entry_t *next; + char *name; + char *link; + struct stat buf; +}; + + +struct _gf_dirent_t { + union { + struct list_head list; + struct { + struct _gf_dirent_t *next; + struct _gf_dirent_t *prev; + }; + }; + uint64_t d_ino; + uint64_t d_off; + uint32_t d_len; + uint32_t d_type; + char d_name[0]; +}; + + +gf_dirent_t *gf_dirent_for_name (const char *name); +void gf_dirent_free (gf_dirent_t *entries); +int gf_dirent_serialize (gf_dirent_t *entries, char *buf, size_t size); +int gf_dirent_unserialize (gf_dirent_t *entries, const char *buf, size_t size); + +#endif /* _GF_DIRENT_H */ diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h new file mode 100644 index 000000000..76891f5b0 --- /dev/null +++ b/libglusterfs/src/glusterfs.h @@ -0,0 +1,277 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _GLUSTERFS_H +#define _GLUSTERFS_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/statvfs.h> +#include <netdb.h> +#include <errno.h> +#include <dirent.h> +#include <unistd.h> +#include <fcntl.h> +#include <arpa/inet.h> +#include <sys/poll.h> +#include <pthread.h> + +#include "list.h" +#include "logging.h" + +#define GF_YES 1 +#define GF_NO 0 + +#ifndef O_LARGEFILE +/* savannah bug #20053, patch for compiling on darwin */ +#define O_LARGEFILE 0 +#endif + +#ifndef O_DIRECT +/* savannah bug #20050, #20052 */ +#define O_DIRECT 0 /* From asm/fcntl.h */ +#endif + +#ifndef O_DIRECTORY +/* FreeBSD does not need O_DIRECTORY */ +#define O_DIRECTORY 0 +#endif + +#define ZR_FILE_CONTENT_STR "glusterfs.file." +#define ZR_FILE_CONTENT_STRLEN 15 + +#define GLUSTERFS_OPEN_FD_COUNT "glusterfs.open-fd-count" + +#define ZR_FILE_CONTENT_REQUEST(key) (!strncmp(key, ZR_FILE_CONTENT_STR, \ + ZR_FILE_CONTENT_STRLEN)) + +/* TODO: Should we use PATH-MAX? On some systems it may save space */ +#define ZR_PATH_MAX 4096 + +/* This is used as the maximum permitted filename length over FS. + * If the backend FS supports higher than this, it should be changed. + */ +#define ZR_FILENAME_MAX 256 + + +/* NOTE: add members ONLY at the end (just before _MAXVALUE) */ +typedef enum { + GF_FOP_STAT, /* 0 */ + GF_FOP_READLINK, /* 1 */ + GF_FOP_MKNOD, /* 2 */ + GF_FOP_MKDIR, + GF_FOP_UNLINK, + GF_FOP_RMDIR, /* 5 */ + GF_FOP_SYMLINK, + GF_FOP_RENAME, + GF_FOP_LINK, + GF_FOP_CHMOD, + GF_FOP_CHOWN, /* 10 */ + GF_FOP_TRUNCATE, + GF_FOP_OPEN, + GF_FOP_READ, + GF_FOP_WRITE, + GF_FOP_STATFS, /* 15 */ + GF_FOP_FLUSH, + GF_FOP_FSYNC, + GF_FOP_SETXATTR, + GF_FOP_GETXATTR, + GF_FOP_REMOVEXATTR,/* 20 */ + GF_FOP_OPENDIR, + GF_FOP_GETDENTS, + GF_FOP_FSYNCDIR, + GF_FOP_ACCESS, + GF_FOP_CREATE, /* 25 */ + GF_FOP_FTRUNCATE, + GF_FOP_FSTAT, + GF_FOP_LK, + GF_FOP_UTIMENS, + GF_FOP_FCHMOD, /* 30 */ + GF_FOP_FCHOWN, + GF_FOP_LOOKUP, + GF_FOP_SETDENTS, + GF_FOP_READDIR, + GF_FOP_INODELK, /* 35 */ + GF_FOP_FINODELK, + GF_FOP_ENTRYLK, + GF_FOP_FENTRYLK, + GF_FOP_CHECKSUM, + GF_FOP_XATTROP, /* 40 */ + GF_FOP_FXATTROP, + GF_FOP_MAXVALUE, +} glusterfs_fop_t; + +/* NOTE: add members ONLY at the end (just before _MAXVALUE) */ +typedef enum { + GF_MOP_SETVOLUME, /* 0 */ + GF_MOP_GETVOLUME, /* 1 */ + GF_MOP_STATS, + GF_MOP_SETSPEC, + GF_MOP_GETSPEC, + GF_MOP_PING, + GF_MOP_MAXVALUE /* 5 */ +} glusterfs_mop_t; + +typedef enum { + GF_CBK_FORGET, /* 0 */ + GF_CBK_RELEASE, /* 1 */ + GF_CBK_RELEASEDIR, /* 2 */ + GF_CBK_MAXVALUE /* 3 */ +} glusterfs_cbk_t; + +typedef enum { + GF_OP_TYPE_FOP_REQUEST = 1, + GF_OP_TYPE_MOP_REQUEST, + GF_OP_TYPE_CBK_REQUEST, + GF_OP_TYPE_FOP_REPLY, + GF_OP_TYPE_MOP_REPLY, + GF_OP_TYPE_CBK_REPLY +} glusterfs_op_type_t; + +/* NOTE: all the miscellaneous flags used by GlusterFS should be listed here */ +typedef enum { + GF_LK_GETLK = 0, + GF_LK_SETLK, + GF_LK_SETLKW, +} glusterfs_lk_cmds_t; + +typedef enum { + GF_LK_F_RDLCK = 0, + GF_LK_F_WRLCK, + GF_LK_F_UNLCK +} glusterfs_lk_types_t; + +typedef enum { + GF_LOCK_POSIX, + GF_LOCK_INTERNAL +} gf_lk_domain_t; + +typedef enum { + ENTRYLK_LOCK, + ENTRYLK_UNLOCK, + ENTRYLK_LOCK_NB +} entrylk_cmd; + +typedef enum { + ENTRYLK_RDLCK, + ENTRYLK_WRLCK +} entrylk_type; + +typedef enum { + GF_GET_ALL = 1, + GF_GET_DIR_ONLY, + GF_GET_SYMLINK_ONLY, + GF_GET_REGULAR_FILES_ONLY, +} glusterfs_getdents_flags_t; + +typedef enum { + GF_XATTROP_ADD_ARRAY, +} gf_xattrop_flags_t; + +#define GF_SET_IF_NOT_PRESENT 0x1 /* default behaviour */ +#define GF_SET_OVERWRITE 0x2 /* Overwrite with the buf given */ +#define GF_SET_DIR_ONLY 0x4 +#define GF_SET_EPOCH_TIME 0x8 /* used by afr dir lookup selfheal */ + + +struct _xlator_cmdline_option { + struct list_head cmd_args; + char *volume; + char *key; + char *value; +}; +typedef struct _xlator_cmdline_option xlator_cmdline_option_t; + +struct _cmd_args { + /* basic options */ + char *volfile_server; + char *volume_file; + gf_loglevel_t log_level; + char *log_file; + /* advanced options */ + uint32_t volfile_server_port; + char *volfile_server_transport; + char *pid_file; + int no_daemon_mode; + char *run_id; + int debug_mode; + struct list_head xlator_options; /* list of xlator_option_t */ + + /* fuse options */ + int fuse_direct_io_mode_flag; + unsigned int fuse_entry_timeout; + unsigned int fuse_attribute_timeout; + char *volume_name; + int non_local; /* Used only by darwin os, + used for '-o local' option */ + char *icon_name; /* This string will appear as + Desktop icon name when mounted + on darwin */ + int fuse_nodev; + int fuse_nosuid; + + /* key args */ + char *mount_point; + char *volfile_id; +}; +typedef struct _cmd_args cmd_args_t; + +struct _glusterfs_ctx { + cmd_args_t cmd_args; + char *process_uuid; + FILE *specfp; + FILE *pidfp; + char fin; + void *timer; + void *ib; + void *pool; + void *graph; + void *top; /* either fuse or server protocol */ + void *event_pool; + pthread_mutex_t lock; + int xl_count; +}; + +typedef struct _glusterfs_ctx glusterfs_ctx_t; + +typedef enum { + GF_EVENT_PARENT_UP = 1, + GF_EVENT_POLLIN, + GF_EVENT_POLLOUT, + GF_EVENT_POLLERR, + GF_EVENT_CHILD_UP, + GF_EVENT_CHILD_DOWN, + GF_EVENT_CHILD_CONNECTING, + GF_EVENT_TRANSPORT_CLEANUP, + GF_EVENT_TRANSPORT_CONNECTED, +} glusterfs_event_t; + +#define GF_MUST_CHECK __attribute__((warn_unused_result)) + +#endif /* _GLUSTERFS_H */ diff --git a/libglusterfs/src/hashfn.c b/libglusterfs/src/hashfn.c new file mode 100644 index 000000000..edc49678f --- /dev/null +++ b/libglusterfs/src/hashfn.c @@ -0,0 +1,89 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <stdint.h> +#include <stdlib.h> + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "hashfn.h" + +#define get16bits(d) (*((const uint16_t *) (d))) + +/* + This is apparently the "fastest hash function for strings". + Written by Paul Hsieh <http://www.azillionmonkeys.com/qed/hash.html> +*/ + +/* In any case make sure, you return 1 */ + +uint32_t SuperFastHash (const char * data, int32_t len) { + uint32_t hash = len, tmp; + int32_t rem; + + if (len <= 1 || data == NULL) return 1; + + + for (;len > 0; len--) { + hash ^= data[len]; + + return hash; + } + + rem = len & 3; + len >>= 2; + + /* Main loop */ + for (;len > 0; len--) { + hash += get16bits (data); + tmp = (get16bits (data+2) << 11) ^ hash; + hash = (hash << 16) ^ tmp; + data += 2*sizeof (uint16_t); + hash += hash >> 11; + } + + /* Handle end cases */ + switch (rem) { + case 3: hash += get16bits (data); + hash ^= hash << 16; + hash ^= data[sizeof (uint16_t)] << 18; + hash += hash >> 11; + break; + case 2: hash += get16bits (data); + hash ^= hash << 11; + hash += hash >> 17; + break; + case 1: hash += *data; + hash ^= hash << 10; + hash += hash >> 1; + } + + /* Force "avalanching" of final 127 bits */ + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + + return hash; +} diff --git a/libglusterfs/src/hashfn.h b/libglusterfs/src/hashfn.h new file mode 100644 index 000000000..13673f6e6 --- /dev/null +++ b/libglusterfs/src/hashfn.h @@ -0,0 +1,33 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef __HASHFN_H__ +#define __HASHFN_H__ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> +#include <stdint.h> + +uint32_t SuperFastHash (const char * data, int32_t len); + +#endif /* __HASHFN_H__ */ diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c new file mode 100644 index 000000000..6c527fc75 --- /dev/null +++ b/libglusterfs/src/inode.c @@ -0,0 +1,1174 @@ +/* + Copyright (c) 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "inode.h" +#include "common-utils.h" +#include <pthread.h> +#include <sys/types.h> +#include <stdint.h> +#include "list.h" +#include <time.h> +#include <assert.h> + +/* TODO: + move latest accessed dentry to list_head of inode +*/ + +static inode_t * +__inode_unref (inode_t *inode); + +static int +inode_table_prune (inode_table_t *table); + +static int +hash_name (ino_t par, + const char *name, + int mod) +{ + int hash = 0; + int ret = 0; + + hash = *name; + if (hash) { + for (name += 1; *name != '\0'; name++) { + hash = (hash << 5) - hash + *name; + } + } + ret = (hash + par) % mod; + + return ret; +} + + +static int +hash_inode (ino_t ino, + int mod) +{ + int hash = 0; + + hash = ino % mod; + + return hash; +} + + +static void +__dentry_hash (dentry_t *dentry) +{ + inode_table_t *table = NULL; + int hash = 0; + + table = dentry->inode->table; + hash = hash_name (dentry->parent->ino, dentry->name, + table->hashsize); + + list_del_init (&dentry->hash); + list_add (&dentry->hash, &table->name_hash[hash]); + + list_del_init (&dentry->parent_list); + list_add (&dentry->parent_list, &dentry->parent->child_list); + + gf_log (table->name, GF_LOG_DEBUG, + "dentry hashed %s (%"PRId64")", + dentry->name, dentry->inode->ino); +} + + +static int +__is_dentry_hashed (dentry_t *dentry) +{ + return !list_empty (&dentry->hash); +} + + +static void +__dentry_unhash (dentry_t *dentry) +{ + list_del_init (&dentry->hash); + + gf_log (dentry->inode->table->name, GF_LOG_DEBUG, + "dentry unhashed %s (%"PRId64")", + dentry->name, dentry->inode->ino); +} + + +static void +__dentry_unset (dentry_t *dentry) +{ + __dentry_unhash (dentry); + + list_del_init (&dentry->inode_list); + + gf_log (dentry->inode->table->name, GF_LOG_DEBUG, + "unset dentry %s (%"PRId64")", + dentry->name, dentry->inode->ino); + + if (dentry->name) + FREE (dentry->name); + + if (dentry->parent) { + list_del_init (&dentry->parent_list); + __inode_unref (dentry->parent); + dentry->parent = NULL; + } + + FREE (dentry); +} + + +static void +__inode_unhash (inode_t *inode) +{ + list_del_init (&inode->hash); +} + + +static int +__is_inode_hashed (inode_t *inode) +{ + return !list_empty (&inode->hash); +} + + +static void +__inode_hash (inode_t *inode) +{ + inode_table_t *table = NULL; + int hash = 0; + + table = inode->table; + hash = hash_inode (inode->ino, table->hashsize); + + list_del_init (&inode->hash); + list_add (&inode->hash, &table->inode_hash[hash]); +} + + +static inode_t * +__inode_search (inode_table_t *table, + ino_t ino) +{ + int hash = 0; + inode_t *inode = NULL; + inode_t *tmp = NULL; + + hash = hash_inode (ino, table->hashsize); + + list_for_each_entry (tmp, &table->inode_hash[hash], hash) { + if (tmp->ino == ino) { + inode = tmp; + break; + } + } + + return inode; +} + + +static dentry_t * +__dentry_search_for_inode (inode_t *inode, + ino_t par, + const char *name) +{ + dentry_t *dentry = NULL; + dentry_t *tmp = NULL; + + list_for_each_entry (tmp, &inode->dentry_list, inode_list) { + if (tmp->parent->ino == par && !strcmp (tmp->name, name)) { + dentry = tmp; + break; + } + } + + return dentry; +} + + +static dentry_t * +__dentry_search (inode_table_t *table, + ino_t par, + const char *name) +{ + int hash = 0; + dentry_t *dentry = NULL; + dentry_t *tmp = NULL; + + hash = hash_name (par, name, table->hashsize); + + list_for_each_entry (tmp, &table->name_hash[hash], hash) { + if (tmp->parent->ino == par && !strcmp (tmp->name, name)) { + dentry = tmp; + break; + } + } + + return dentry; +} + + +static void +__inode_destroy (inode_t *inode) +{ + int index = 0; + data_pair_t *pair = NULL; + xlator_t *xl = NULL; + + if (!inode->ctx) { + goto noctx; + } + for (pair = inode->ctx->members_list; pair; pair = pair->next) { + /* notify all xlators which have a context */ + xl = xlator_search_by_name (inode->table->xl, pair->key); + + if (!xl) { + gf_log (inode->table->name, GF_LOG_CRITICAL, + "inode(%"PRId64")->ctx has invalid key(%s)", + inode->ino, pair->key); + continue; + } + + if (xl->cbks->forget) + xl->cbks->forget (xl, inode); + else + gf_log (inode->table->name, GF_LOG_CRITICAL, + "xlator(%s) in inode(%"PRId64") no FORGET fop", + xl->name, inode->ino); + } + dict_destroy (inode->ctx); + + if (!inode->_ctx) + goto noctx; + + for (index = 0; index < inode->table->xl->ctx->xl_count; index++) { + if (inode->_ctx[index].key) { + xl = (xlator_t *)(long)inode->_ctx[index].key; + if (xl->cbks->forget) + xl->cbks->forget (xl, inode); + } + } + + FREE (inode->_ctx); +noctx: + + if (inode->ino) + gf_log (inode->table->name, GF_LOG_DEBUG, + "destroy inode(%"PRId64") [@%p]", inode->ino, inode); + + LOCK_DESTROY (&inode->lock); + // memset (inode, 0xb, sizeof (*inode)); + FREE (inode); +} + + +static void +__inode_activate (inode_t *inode) +{ + list_move (&inode->list, &inode->table->active); + inode->table->active_size++; + + gf_log (inode->table->name, GF_LOG_DEBUG, + "activating inode(%"PRId64"), lru=%d/%d active=%d purge=%d", + inode->ino, inode->table->lru_size, inode->table->lru_limit, + inode->table->active_size, inode->table->purge_size); +} + + +static void +__inode_passivate (inode_t *inode) +{ + dentry_t *dentry = NULL; + dentry_t *t = NULL; + inode_table_t *table = NULL; + + table = inode->table; + + list_move_tail (&inode->list, &inode->table->lru); + inode->table->lru_size++; + + gf_log (table->name, GF_LOG_DEBUG, + "passivating inode(%"PRId64") lru=%d/%d active=%d purge=%d", + inode->ino, table->lru_size, table->lru_limit, + table->active_size, table->purge_size); + + list_for_each_entry_safe (dentry, t, &inode->dentry_list, inode_list) { + if (!__is_dentry_hashed (dentry)) + __dentry_unset (dentry); + } +} + + +static void +__inode_retire (inode_t *inode) +{ + dentry_t *dentry = NULL; + dentry_t *t = NULL; + inode_table_t *table = NULL; + + table = inode->table; + + list_move_tail (&inode->list, &inode->table->purge); + inode->table->purge_size++; + + gf_log (table->name, GF_LOG_DEBUG, + "retiring inode(%"PRId64") lru=%d/%d active=%d purge=%d", + inode->ino, table->lru_size, table->lru_limit, + table->active_size, table->purge_size); + + __inode_unhash (inode); + assert (list_empty (&inode->child_list)); + + list_for_each_entry_safe (dentry, t, &inode->dentry_list, inode_list) { + __dentry_unset (dentry); + } +} + + +static inode_t * +__inode_unref (inode_t *inode) +{ + if (inode->ino == 1) + return inode; + + assert (inode->ref); + + --inode->ref; + + if (!inode->ref) { + inode->table->active_size--; + + if (inode->nlookup && __is_inode_hashed (inode)) + __inode_passivate (inode); + else + __inode_retire (inode); + } + + return inode; +} + + +static inode_t * +__inode_ref (inode_t *inode) +{ + if (!inode->ref) { + inode->table->lru_size--; + __inode_activate (inode); + } + inode->ref++; + + return inode; +} + + +inode_t * +inode_unref (inode_t *inode) +{ + inode_table_t *table = NULL; + + table = inode->table; + + pthread_mutex_lock (&table->lock); + { + inode = __inode_unref (inode); + } + pthread_mutex_unlock (&table->lock); + + inode_table_prune (table); + + return inode; +} + + +inode_t * +inode_ref (inode_t *inode) +{ + inode_table_t *table = NULL; + + table = inode->table; + + pthread_mutex_lock (&table->lock); + { + inode = __inode_ref (inode); + } + pthread_mutex_unlock (&table->lock); + + return inode; +} + + +static dentry_t * +__dentry_create (inode_t *inode, + inode_t *parent, + const char *name) +{ + dentry_t *newd = NULL; + + newd = (void *) CALLOC (1, sizeof (*newd)); + + INIT_LIST_HEAD (&newd->inode_list); + INIT_LIST_HEAD (&newd->parent_list); + INIT_LIST_HEAD (&newd->hash); + + list_add (&newd->parent_list, &parent->child_list); + newd->parent = __inode_ref (parent); + newd->name = strdup (name); + + list_add (&newd->inode_list, &inode->dentry_list); + newd->inode = inode; + + return newd; +} + + +static inode_t * +__inode_create (inode_table_t *table) +{ + inode_t *newi = NULL; + + newi = (void *) CALLOC (1, sizeof (*newi)); + if (!newi) + return NULL; + + newi->table = table; + + LOCK_INIT (&newi->lock); + + INIT_LIST_HEAD (&newi->fd_list); + INIT_LIST_HEAD (&newi->list); + INIT_LIST_HEAD (&newi->hash); + INIT_LIST_HEAD (&newi->dentry_list); + INIT_LIST_HEAD (&newi->child_list); + + + list_add (&newi->list, &table->lru); + table->lru_size++; + + newi->_ctx = CALLOC (1, (sizeof (struct _inode_ctx) * + table->xl->ctx->xl_count)); + + newi->ctx = get_new_dict (); + gf_log (table->name, GF_LOG_DEBUG, + "create inode(%"PRId64")", newi->ino); + + return newi; +} + + +inode_t * +inode_new (inode_table_t *table) +{ + inode_t *inode = NULL; + + pthread_mutex_lock (&table->lock); + { + inode = __inode_create (table); + __inode_ref (inode); + } + pthread_mutex_unlock (&table->lock); + + return inode; +} + + +static inode_t * +__inode_lookup (inode_t *inode) +{ + inode->nlookup++; + + return inode; +} + + +static inode_t * +__inode_forget (inode_t *inode, uint64_t nlookup) +{ + assert (inode->nlookup >= nlookup); + + inode->nlookup -= nlookup; + + if (!nlookup) + inode->nlookup = 0; + + return inode; +} + + +inode_t * +inode_search (inode_table_t *table, + ino_t ino, + const char *name) +{ + inode_t *inode = NULL; + dentry_t *dentry = NULL; + + pthread_mutex_lock (&table->lock); + { + if (!name) { + inode = __inode_search (table, ino); + } else { + dentry = __dentry_search (table, ino, name); + + if (dentry) + inode = dentry->inode; + } + + if (inode) + __inode_ref (inode); + } + pthread_mutex_unlock (&table->lock); + + return inode; +} + + +static void +__copy_dentries (inode_t *oldi, inode_t *newi) +{ + dentry_t *dentry = NULL; + dentry_t *newd = NULL; + dentry_t *tmp = NULL; + + list_for_each_entry (dentry, &oldi->dentry_list, inode_list) { + tmp = __dentry_search_for_inode (newi, dentry->parent->ino, + dentry->name); + + if (!tmp) { + newd = __dentry_create (newi, dentry->parent, + dentry->name); + } else { + newd = tmp; + } + + if (__is_dentry_hashed (dentry)) { + __dentry_unhash (dentry); + __dentry_hash (newd); + } + } +} + + +static void +__adopt_children (inode_t *oldi, inode_t *newi) +{ + dentry_t *dentry = NULL; + + list_for_each_entry (dentry, &oldi->child_list, parent_list) { + assert (dentry->parent == oldi); + __inode_unref (dentry->parent); + dentry->parent = __inode_ref (newi); + } + + list_splice_init (&oldi->child_list, &newi->child_list); +} + + +static void +__inode_replace (inode_t *oldi, inode_t *newi) +{ + gf_log (oldi->table->name, GF_LOG_DEBUG, + "inode(%"PRId64") replaced (%"PRId64"", + oldi->ino, newi->ino); + + __copy_dentries (oldi, newi); + __adopt_children (oldi, newi); + + newi->nlookup = oldi->nlookup; + newi->generation = oldi->generation; + + oldi->nlookup = 0; + oldi->generation = 0; + + __inode_unhash (oldi); + + if (newi->ino == 1) + newi->table->root = newi; +} + + +static inode_t * +__inode_link (inode_t *inode, + inode_t *parent, + const char *name, + struct stat *stbuf) +{ + dentry_t *dentry = NULL; + dentry_t *old_dentry = NULL; + inode_t *old_inode = NULL; + inode_table_t *table = NULL; + + table = inode->table; + + if (inode->ino) + assert (inode->ino == stbuf->st_ino); + + inode->ino = stbuf->st_ino; + inode->st_mode = stbuf->st_mode; + + old_inode = __inode_search (table, stbuf->st_ino); + + if (old_inode && old_inode != inode) { + __inode_ref (old_inode); + __inode_replace (old_inode, inode); + __inode_unref (old_inode); + } + __inode_hash (inode); + + if (parent) { + dentry = __dentry_search_for_inode (inode, parent->ino, name); + if (!dentry) { + dentry = __dentry_create (inode, parent, name); + } + + old_dentry = __dentry_search (table, parent->ino, name); + if (old_dentry) { + __dentry_unhash (old_dentry); + } + + __dentry_hash (dentry); + } else if (inode->ino != 1) { + gf_log (table->name, GF_LOG_ERROR, + "child (%"PRId64") without a parent :O", inode->ino); + } + + return inode; +} + + +int +inode_link (inode_t *inode, + inode_t *parent, + const char *name, + struct stat *stbuf) +{ + inode_table_t *table = NULL; + + table = inode->table; + + pthread_mutex_lock (&table->lock); + { + inode = __inode_link (inode, parent, name, stbuf); + } + pthread_mutex_unlock (&table->lock); + + inode_table_prune (table); + + return 0; +} + + +int +inode_lookup (inode_t *inode) +{ + inode_table_t *table = NULL; + inode_t *lookup_inode = NULL; + + table = inode->table; + lookup_inode = inode; + + pthread_mutex_lock (&table->lock); + { + if (!__is_inode_hashed (inode)) { + lookup_inode = __inode_search (table, inode->ino); + } + + __inode_lookup (lookup_inode); + } + pthread_mutex_unlock (&table->lock); + + return 0; +} + + +int +inode_forget (inode_t *inode, uint64_t nlookup) +{ + inode_table_t *table = NULL; + inode_t *forget_inode = NULL; + + table = inode->table; + forget_inode = inode; + + pthread_mutex_lock (&table->lock); + { + if (!__is_inode_hashed (inode)) { + forget_inode = __inode_search (table, inode->ino); + } + + __inode_forget (forget_inode, nlookup); + } + pthread_mutex_unlock (&table->lock); + + inode_table_prune (table); + + return 0; +} + + +static void +__inode_unlink (inode_t *inode, + inode_t *parent, + const char *name) +{ + dentry_t *dentry = NULL; + + dentry = __dentry_search_for_inode (inode, parent->ino, name); + + /* dentry NULL for corrupted backend */ + if (dentry) + __dentry_unset (dentry); +} + + +void +inode_unlink (inode_t *inode, + inode_t *parent, + const char *name) +{ + inode_table_t *table = NULL; + inode_t *unlink_inode = NULL; + + table = inode->table; + unlink_inode = inode; + + pthread_mutex_lock (&table->lock); + { + if (!__is_inode_hashed (inode)) { + unlink_inode = __inode_search (table, inode->ino); + } + + __inode_unlink (unlink_inode, parent, name); + } + pthread_mutex_unlock (&table->lock); + + inode_table_prune (table); +} + + +int +inode_rename (inode_table_t *table, + inode_t *srcdir, + const char *srcname, + inode_t *dstdir, + const char *dstname, + inode_t *inode, + struct stat *stbuf) +{ + dentry_t *old_dst = NULL; + inode_t *rename_inode = NULL; + + rename_inode = inode; + + pthread_mutex_lock (&table->lock); + { + if (!__is_inode_hashed (inode)) { + rename_inode = __inode_search (table, inode->ino); + } + + old_dst = __dentry_search (table, dstdir->ino, dstname); + if (old_dst) + __dentry_unset (old_dst); + + __inode_unlink (rename_inode, srcdir, srcname); + __inode_link (rename_inode, dstdir, dstname, stbuf); + } + pthread_mutex_unlock (&table->lock); + + inode_table_prune (table); + + return 0; +} + + +static dentry_t * +__dentry_search_arbit (inode_t *inode) +{ + dentry_t *dentry = NULL; + dentry_t *trav = NULL; + + list_for_each_entry (trav, &inode->dentry_list, inode_list) { + if (__is_dentry_hashed (trav)) { + dentry = trav; + break; + } + } + + if (!dentry) { + list_for_each_entry (trav, &inode->dentry_list, inode_list) { + dentry = trav; + break; + } + } + + return dentry; +} + + +inode_t * +inode_parent (inode_t *inode, ino_t par, const char *name) +{ + inode_t *parent = NULL; + inode_table_t *table = NULL; + dentry_t *dentry = NULL; + + table = inode->table; + + pthread_mutex_lock (&table->lock); + { + if (par && name) { + dentry = __dentry_search_for_inode (inode, par, name); + } else { + dentry = __dentry_search_arbit (inode); + } + + if (dentry) + parent = __inode_ref (dentry->parent); + } + pthread_mutex_unlock (&table->lock); + + return parent; +} + + +int32_t +inode_path (inode_t *inode, + const char *name, + char **bufp) +{ + inode_table_t *table = NULL; + dentry_t *trav = NULL; + size_t i = 0, size = 0; + int64_t ret = 0; + int len = 0; + char *buf = NULL; + + table = inode->table; + + pthread_mutex_lock (&table->lock); + { + for (trav = __dentry_search_arbit (inode); trav; + trav = __dentry_search_arbit (trav->parent)) { + i ++; /* "/" */ + i += strlen (trav->name); + } + + if ((inode->ino != 1) && + (i == 0)) { + gf_log (table->name, GF_LOG_DEBUG, + "no dentry for non-root inode %"PRId64, + inode->ino); + ret = -ENOENT; + goto unlock; + } + + if (name) { + i++; + i += strlen (name); + } + + ret = i; + size = i + 1; + buf = CALLOC (size, sizeof (char)); + if (buf) { + + buf[size - 1] = 0; + + if (name) { + len = strlen (name); + strncpy (buf + (i - len), name, len); + buf[i-len-1] = '/'; + i -= (len + 1); + } + + for (trav = __dentry_search_arbit (inode); trav; + trav = __dentry_search_arbit (trav->parent)) { + len = strlen (trav->name); + strncpy (buf + (i - len), trav->name, len); + buf[i-len-1] = '/'; + i -= (len + 1); + } + *bufp = buf; + } else { + gf_log (table->name, GF_LOG_ERROR, + "out of memory"); + ret = -ENOMEM; + } + } +unlock: + pthread_mutex_unlock (&table->lock); + + if (inode->ino == 1 && !name) { + ret = 1; + if (buf) { + FREE (buf); + } + buf = CALLOC (ret + 1, sizeof (char)); + if (buf) { + strcpy (buf, "/"); + *bufp = buf; + } else { + gf_log (table->name, GF_LOG_ERROR, + "out of memory"); + ret = -ENOMEM; + } + } + + return ret; +} + +static int +inode_table_prune (inode_table_t *table) +{ + int ret = 0; + struct list_head purge = {0, }; + inode_t *del = NULL; + inode_t *tmp = NULL; + inode_t *entry = NULL; + + + INIT_LIST_HEAD (&purge); + + pthread_mutex_lock (&table->lock); + { + while (table->lru_limit + && table->lru_size > (table->lru_limit)) { + + entry = list_entry (table->lru.next, inode_t, list); + + table->lru_size--; + __inode_retire (entry); + + ret++; + } + + list_splice_init (&table->purge, &purge); + table->purge_size = 0; + } + pthread_mutex_unlock (&table->lock); + + { + list_for_each_entry_safe (del, tmp, &purge, list) { + list_del_init (&del->list); + __inode_forget (del, 0); + __inode_destroy (del); + } + } + + return ret; +} + + +static void +__inode_table_init_root (inode_table_t *table) +{ + inode_t *root = NULL; + struct stat stbuf = {0, }; + + root = __inode_create (table); + + stbuf.st_ino = 1; + stbuf.st_mode = S_IFDIR|0755; + + __inode_link (root, NULL, NULL, &stbuf); + table->root = root; +} + + +inode_table_t * +inode_table_new (size_t lru_limit, xlator_t *xl) +{ + inode_table_t *new = NULL; + int i = 0; + + + new = (void *)calloc (1, sizeof (*new)); + if (!new) + return NULL; + + gf_log (xl->name, GF_LOG_DEBUG, + "creating new inode table with lru_limit=%"GF_PRI_SIZET"", lru_limit); + + new->xl = xl; + + new->lru_limit = lru_limit; + + new->hashsize = 14057; /* TODO: Random Number?? */ + + new->inode_hash = (void *)calloc (new->hashsize, + sizeof (struct list_head)); + if (!new->inode_hash) { + FREE (new); + return NULL; + } + + new->name_hash = (void *)calloc (new->hashsize, + sizeof (struct list_head)); + if (!new->name_hash) { + FREE (new->inode_hash); + FREE (new); + return NULL; + } + + for (i=0; i<new->hashsize; i++) { + INIT_LIST_HEAD (&new->inode_hash[i]); + } + + + for (i=0; i<new->hashsize; i++) { + INIT_LIST_HEAD (&new->name_hash[i]); + } + + INIT_LIST_HEAD (&new->active); + INIT_LIST_HEAD (&new->lru); + INIT_LIST_HEAD (&new->purge); + + asprintf (&new->name, "%s/inode", xl->name); + + __inode_table_init_root (new); + + pthread_mutex_init (&new->lock, NULL); + + return new; +} + + +inode_t * +inode_from_path (inode_table_t *itable, const char *path) +{ + inode_t *inode = NULL; + inode_t *parent = NULL; + inode_t *root = NULL; + inode_t *curr = NULL; + char *pathname = NULL; + char *component = NULL, *next_component = NULL; + char *strtokptr = NULL; + + /* top-down approach */ + root = itable->root; + parent = inode_ref (root); + pathname = strdup (path); + component = strtok_r (pathname, "/", &strtokptr); + + if (component == NULL) + /* root inode */ + inode = inode_ref (parent); + + while (component) { + curr = inode_search (itable, parent->ino, component); + + if (curr == NULL) { + component = strtok_r (NULL, "/", &strtokptr); + break; + } + + next_component = strtok_r (NULL, "/", &strtokptr); + + if (next_component) { + inode_unref (parent); + parent = curr; + curr = NULL; + } else { + inode = curr; + } + + component = next_component; + } + + if (parent) + inode_unref (parent); + + if (pathname) + free (pathname); + + return inode; +} + +int +inode_ctx_put (inode_t *inode, xlator_t *xlator, uint64_t value) +{ + int index = 0; + + if (!inode || !xlator) + return -1; + + for (index = 0; index < xlator->ctx->xl_count; index++) { + if (!inode->_ctx[index].key || + (inode->_ctx[index].key == (uint64_t)(long)xlator)) + break; + } + + if (index == xlator->ctx->xl_count) + return -1; + + inode->_ctx[index].key = (uint64_t)(long) xlator; + inode->_ctx[index].value = value; + + return 0; +} + +int +inode_ctx_get (inode_t *inode, xlator_t *xlator, uint64_t *value) +{ + int index = 0; + + if (!inode || !xlator) + return -1; + + for (index = 0; index < xlator->ctx->xl_count; index++) { + if (inode->_ctx[index].key == (uint64_t)(long)xlator) + break; + } + + if (index == xlator->ctx->xl_count) + return -1; + + if (value) + *value = inode->_ctx[index].value; + + return 0; +} + + +int +inode_ctx_del (inode_t *inode, xlator_t *xlator, uint64_t *value) +{ + int index = 0; + + if (!inode || !xlator) + return -1; + + for (index = 0; index < xlator->ctx->xl_count; index++) { + if (inode->_ctx[index].key == (uint64_t)(long)xlator) + break; + } + + if (index == xlator->ctx->xl_count) + return -1; + + if (value) + *value = inode->_ctx[index].value; + + inode->_ctx[index].key = 0; + inode->_ctx[index].value = 0; + + return 0; +} diff --git a/libglusterfs/src/inode.h b/libglusterfs/src/inode.h new file mode 100644 index 000000000..67490f0ee --- /dev/null +++ b/libglusterfs/src/inode.h @@ -0,0 +1,160 @@ +/* + Copyright (c) 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _INODE_H +#define _INODE_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <stdint.h> +#include <sys/types.h> + +struct _inode_table; +typedef struct _inode_table inode_table_t; + +struct _inode; +typedef struct _inode inode_t; + +struct _dentry; +typedef struct _dentry dentry_t; + +#include "list.h" +#include "xlator.h" + + +struct _inode_table { + pthread_mutex_t lock; + size_t hashsize; /* bucket size of inode hash and dentry hash */ + char *name; /* name of the inode table, just for gf_log() */ + inode_t *root; /* root directory inode, with number 1 */ + xlator_t *xl; /* xlator to be called to do purge */ + uint32_t lru_limit; /* maximum LRU cache size */ + struct list_head *inode_hash; /* buckets for inode hash table */ + struct list_head *name_hash; /* buckets for dentry hash table */ + struct list_head active; /* list of inodes currently active (in an fop) */ + uint32_t active_size; /* count of inodes in active list */ + struct list_head lru; /* list of inodes recently used. + lru.next most recent */ + uint32_t lru_size; /* count of inodes in lru list */ + struct list_head purge; /* list of inodes to be purged soon */ + uint32_t purge_size; /* count of inodes in purge list */ +}; + + +struct _dentry { + struct list_head inode_list; /* list of dentries of inode */ + struct list_head hash; /* hash table pointers */ + struct list_head parent_list; /* list of dentries under the parent */ + inode_t *inode; /* inode of this directory entry */ + char *name; /* name of the directory entry */ + inode_t *parent; /* directory of the entry */ +}; + +//#define ZR_INODE_CTX_VALUE_LEN 2 +struct _inode_ctx { + uint64_t key; + uint64_t value; + //uint64_t value[ZR_INODE_CTX_VALUE_LEN]; +}; + +struct _inode { + inode_table_t *table; /* the table this inode belongs to */ + gf_lock_t lock; + uint64_t nlookup; + uint64_t generation; + uint32_t ref; /* reference count on this inode */ + ino_t ino; /* inode number in the storage (persistent) */ + dict_t *ctx; /* per xlator private */ + mode_t st_mode; /* what kind of file */ + struct list_head fd_list; /* list of open files on this inode */ + struct list_head dentry_list; /* list of directory entries for this inode */ + struct list_head child_list; /* list of directory entries under this inode */ + struct list_head hash; /* hash table pointers */ + struct list_head list; /* active/lru/purge */ + + struct _inode_ctx *_ctx; /* replacement for dict_t *(inode->ctx) */ +}; + + +inode_table_t * +inode_table_new (size_t lru_limit, xlator_t *xl); + +inode_t * +inode_new (inode_table_t *table); + +inode_t * +inode_search (inode_table_t *table, ino_t ino, const char *name); + +int +inode_link (inode_t *inode, inode_t *parent, + const char *name, struct stat *stbuf); + +void +inode_unlink (inode_t *inode, + inode_t *parent, + const char *name); + +inode_t * +inode_parent (inode_t *inode, ino_t par, const char *name); + +inode_t * +inode_ref (inode_t *inode); + +inode_t * +inode_unref (inode_t *inode); + +int +inode_lookup (inode_t *inode); + +int +inode_forget (inode_t *inode, + uint64_t nlookup); + +int +inode_rename (inode_table_t *table, + inode_t *olddir, + const char *oldname, + inode_t *newdir, + const char *newname, + inode_t *inode, + struct stat *stbuf); + + +int32_t +inode_path (inode_t *inode, + const char *name, + char **bufp); + +inode_t * +inode_from_path (inode_table_t *table, + const char *path); + +int +inode_ctx_put (inode_t *inode, xlator_t *xlator, uint64_t value); + +int +inode_ctx_get (inode_t *inode, xlator_t *xlator, uint64_t *value); + +int +inode_ctx_del (inode_t *inode, xlator_t *xlator, uint64_t *value); + +#endif /* _INODE_H */ diff --git a/libglusterfs/src/list.h b/libglusterfs/src/list.h new file mode 100644 index 000000000..0d862f09c --- /dev/null +++ b/libglusterfs/src/list.h @@ -0,0 +1,154 @@ +/* + Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _LLIST_H +#define _LLIST_H + + +struct list_head { + struct list_head *next; + struct list_head *prev; +}; + + +#define INIT_LIST_HEAD(head) do { \ + (head)->next = (head)->prev = head; \ + } while (0) + + +static inline void +list_add (struct list_head *new, struct list_head *head) +{ + new->prev = head; + new->next = head->next; + + new->prev->next = new; + new->next->prev = new; +} + + +static inline void +list_add_tail (struct list_head *new, struct list_head *head) +{ + new->next = head; + new->prev = head->prev; + + new->prev->next = new; + new->next->prev = new; +} + + +static inline void +list_del (struct list_head *old) +{ + old->prev->next = old->next; + old->next->prev = old->prev; + + old->next = (void *)0xbabebabe; + old->prev = (void *)0xcafecafe; +} + + +static inline void +list_del_init (struct list_head *old) +{ + old->prev->next = old->next; + old->next->prev = old->prev; + + old->next = old; + old->prev = old; +} + + +static inline void +list_move (struct list_head *list, struct list_head *head) +{ + list_del (list); + list_add (list, head); +} + + +static inline void +list_move_tail (struct list_head *list, struct list_head *head) +{ + list_del (list); + list_add_tail (list, head); +} + + +static inline int +list_empty (struct list_head *head) +{ + return (head->next == head); +} + + +static inline void +__list_splice (struct list_head *list, struct list_head *head) +{ + (list->prev)->next = (head->next); + (head->next)->prev = (list->prev); + + (head)->next = (list->next); + (list->next)->prev = (head); +} + + +static inline void +list_splice (struct list_head *list, struct list_head *head) +{ + if (list_empty (list)) + return; + + __list_splice (list, head); +} + + +static inline void +list_splice_init (struct list_head *list, struct list_head *head) +{ + if (list_empty (list)) + return; + + __list_splice (list, head); + INIT_LIST_HEAD (list); +} + + +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + + +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + + +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + + +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +#endif /* _LLIST_H */ diff --git a/libglusterfs/src/locking.h b/libglusterfs/src/locking.h new file mode 100644 index 000000000..c5c5163d1 --- /dev/null +++ b/libglusterfs/src/locking.h @@ -0,0 +1,49 @@ +/* + Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _LOCKING_H +#define _LOCKING_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <pthread.h> + +#if HAVE_SPINLOCK +#define LOCK_INIT(x) pthread_spin_init (x, 0) +#define LOCK(x) pthread_spin_lock (x) +#define TRY_LOCK(x) pthread_spin_trylock (x) +#define UNLOCK(x) pthread_spin_unlock (x) +#define LOCK_DESTROY(x) pthread_spin_destroy (x) + +typedef pthread_spinlock_t gf_lock_t; +#else +#define LOCK_INIT(x) pthread_mutex_init (x, 0) +#define LOCK(x) pthread_mutex_lock (x) +#define TRY_LOCK(x) pthread_mutex_trylock (x) +#define UNLOCK(x) pthread_mutex_unlock (x) +#define LOCK_DESTROY(x) pthread_mutex_destroy (x) + +typedef pthread_mutex_t gf_lock_t; +#endif /* HAVE_SPINLOCK */ + + +#endif /* _LOCKING_H */ diff --git a/libglusterfs/src/logging.c b/libglusterfs/src/logging.c new file mode 100644 index 000000000..c0b10edca --- /dev/null +++ b/libglusterfs/src/logging.c @@ -0,0 +1,207 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> +#include <stdio.h> +#include <stdarg.h> +#include <time.h> +#include <locale.h> +#include <string.h> +#include <stdlib.h> +#include "logging.h" + + +static pthread_mutex_t logfile_mutex; +static char *filename = NULL; +static uint8_t logrotate = 0; + +static FILE *logfile = NULL; +static gf_loglevel_t loglevel = GF_LOG_MAX; + +gf_loglevel_t gf_log_loglevel; /* extern'd */ +FILE *gf_log_logfile; + + +void +gf_log_logrotate (int signum) +{ + logrotate = 1; +} + + +gf_loglevel_t +gf_log_get_loglevel (void) +{ + return loglevel; +} + + +void +gf_log_set_loglevel (gf_loglevel_t level) +{ + gf_log_loglevel = loglevel = level; +} + + +void +gf_log_fini (void) +{ + pthread_mutex_destroy (&logfile_mutex); +} + + +int +gf_log_init (const char *file) +{ + if (!file){ + fprintf (stderr, "gf_log_init: no filename specified\n"); + return -1; + } + + pthread_mutex_init (&logfile_mutex, NULL); + + filename = strdup (file); + if (!filename) { + fprintf (stderr, "gf_log_init: strdup error\n"); + return -1; + } + + logfile = fopen (file, "a"); + if (!logfile){ + fprintf (stderr, + "gf_log_init: failed to open logfile \"%s\" (%s)\n", + file, + strerror (errno)); + return -1; + } + + gf_log_logfile = logfile; + + return 0; +} + + +void +gf_log_lock (void) +{ + pthread_mutex_lock (&logfile_mutex); +} + + +void +gf_log_unlock (void) +{ + pthread_mutex_unlock (&logfile_mutex); +} + + +void +gf_log_cleanup (void) +{ + pthread_mutex_destroy (&logfile_mutex); +} + + +int +_gf_log (const char *domain, const char *file, const char *function, int line, + gf_loglevel_t level, const char *fmt, ...) +{ + const char *basename = NULL; + FILE *new_logfile = NULL; + va_list ap; + time_t utime = 0; + struct tm *tm = NULL; + char timestr[256]; + static char *level_strings[] = {"N", /* NONE */ + "T", /* TRACE */ + "C", /* CRITICAL */ + "E", /* ERROR */ + "W", /* WARNING */ + "N", /* TRACE (GF_LOG_NORMAL) */ + "D", /* DEBUG */ + ""}; + + if (!domain || !file || !function || !fmt) { + fprintf (stderr, + "logging: %s:%s():%d: invalid argument\n", + __FILE__, __PRETTY_FUNCTION__, __LINE__); + return -1; + } + + if (!logfile) { + fprintf (stderr, "no logfile set\n"); + return (-1); + } + + if (logrotate) { + logrotate = 0; + + new_logfile = fopen (filename, "a"); + if (!new_logfile) { + gf_log ("logrotate", GF_LOG_CRITICAL, + "failed to open logfile %s (%s)", + filename, strerror (errno)); + goto log; + } + + fclose (logfile); + gf_log_logfile = logfile = new_logfile; + } + +log: + utime = time (NULL); + tm = localtime (&utime); + + if (level > loglevel) { + goto out; + } + + pthread_mutex_lock (&logfile_mutex); + { + va_start (ap, fmt); + + strftime (timestr, 256, "%Y-%m-%d %H:%M:%S", tm); + + basename = strrchr (file, '/'); + if (basename) + basename++; + else + basename = file; + + fprintf (logfile, "%s %s [%s:%d:%s] %s: ", + timestr, level_strings[level], + basename, line, function, + domain); + + vfprintf (logfile, fmt, ap); + va_end (ap); + fprintf (logfile, "\n"); + fflush (logfile); + } + pthread_mutex_unlock (&logfile_mutex); + +out: + return (0); +} diff --git a/libglusterfs/src/logging.h b/libglusterfs/src/logging.h new file mode 100644 index 000000000..7a0deb6e8 --- /dev/null +++ b/libglusterfs/src/logging.h @@ -0,0 +1,132 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + + +#ifndef __LOGGING_H__ +#define __LOGGING_H__ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <stdint.h> +#include <stdio.h> + +#define GF_PRI_FSBLK PRId64 +#define GF_PRI_BLKSIZE "ld" +#if GF_LINUX_HOST_OS + +# if __WORDSIZE == 64 +# define GF_PRI_SIZET "lu" +# define GF_PRI_NLINK "lu" +# else +# define GF_PRI_SIZET "u" +# define GF_PRI_NLINK "u" +# endif /* __WORDSIZE */ + +#elif GF_DARWIN_HOST_OS + +/* Noticed that size_t and ino_t are different on OSX, need to fix the warnings */ +# define GF_PRI_SIZET "lu" +# define GF_PRI_NLINK "u" + +# undef GF_PRI_FSBLK +# define GF_PRI_FSBLK "u" + +# undef GF_PRI_BLKSIZE +# define GF_PRI_BLKSIZE "u" + +# if __DARWIN_64_BIT_INO_T == 0 +# error '64 bit ino_t is must for GlusterFS to work, Compile with "CFLAGS=-D__DARWIN_64_BIT_INO_T"' +# endif /* __DARWIN_64_BIT_INO_T */ + +#else /* !LINUX && !DARWIN */ + +/* BSD and Solaris : Change as per testing there.. */ +# define GF_PRI_SIZET "lu" +# define GF_PRI_NLINK "u" + +#endif /* LINUX_OS */ + +#define GF_PRI_DEV GF_PRI_FSBLK + +typedef enum { + GF_LOG_NONE, + GF_LOG_TRACE, + GF_LOG_CRITICAL, /* fatal errors */ + GF_LOG_ERROR, /* major failures (not necessarily fatal) */ + GF_LOG_WARNING, /* info about normal operation */ + GF_LOG_INFO, /* Normal information */ +#define GF_LOG_NORMAL GF_LOG_INFO + GF_LOG_DEBUG, /* all other junk */ +} gf_loglevel_t; + +#define GF_LOG_MAX GF_LOG_DEBUG + +extern gf_loglevel_t gf_log_loglevel; + +#define gf_log(dom, levl, fmt...) do { \ + if (levl <= gf_log_loglevel) \ + _gf_log (dom, __FILE__, __FUNCTION__, __LINE__, \ + levl, ##fmt); \ + if (0) { \ + printf (fmt); \ + } \ +} while (0) + +/* Log once in GF_UNIVERSAL_ANSWER times */ +#define GF_LOG_OCCASIONALLY(var, args...) if (!(var++%GF_UNIVERSAL_ANSWER)) { \ + gf_log (args); \ + } + + +void +gf_log_logrotate (int signum); + +int gf_log_init (const char *filename); + +int +_gf_log (const char *domain, const char *file, const char *function, + int32_t line, gf_loglevel_t level, const char *fmt, ...); + +void gf_log_lock (void); +void gf_log_unlock (void); + +gf_loglevel_t +gf_log_get_loglevel (void); +void +gf_log_set_loglevel (gf_loglevel_t level); + +#define GF_DEBUG(xl, format, args...) \ + gf_log ((xl)->name, GF_LOG_DEBUG, format, ##args) +#define GF_INFO(xl, format, args...) \ + gf_log ((xl)->name, GF_LOG_INFO, format, ##args) +#define GF_WARNING(xl, format, args...) \ + gf_log ((xl)->name, GF_LOG_WARNING, format, ##args) +#define GF_ERROR(xl, format, args...) \ + gf_log ((xl)->name, GF_LOG_ERROR, format, ##args) + +#define GF_TRACE(xl, args...) do { \ + if ((xl)->trace) \ + _gf_log ((xl)->name, __FILE__, __FUNCTION__, \ + __LINE__, GF_LOG_TRACE, ##args); \ + } while(0); \ + +#endif /* __LOGGING_H__ */ diff --git a/libglusterfs/src/mem-pool.c b/libglusterfs/src/mem-pool.c new file mode 100644 index 000000000..c3646f350 --- /dev/null +++ b/libglusterfs/src/mem-pool.c @@ -0,0 +1,174 @@ +/* + Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#include "mem-pool.h" +#include "logging.h" +#include <stdlib.h> + + +#define GF_MEM_POOL_PAD_BOUNDRY 16 + + +struct mem_pool * +mem_pool_new_fn (unsigned long sizeof_type, + unsigned long count) +{ + struct mem_pool *mem_pool = NULL; + int pad = 0; + unsigned long padded_sizeof_type = 0; + void *pool = NULL; + int i = 0; + struct list_head *list = NULL; + + if (!sizeof_type || !count) { + gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument"); + return NULL; + } + + pad = GF_MEM_POOL_PAD_BOUNDRY - + (sizeof_type % GF_MEM_POOL_PAD_BOUNDRY); + padded_sizeof_type = sizeof_type + pad; + + mem_pool = CALLOC (sizeof (*mem_pool), 1); + if (!mem_pool) + return NULL; + + LOCK_INIT (&mem_pool->lock); + INIT_LIST_HEAD (&mem_pool->list); + + mem_pool->padded_sizeof_type = padded_sizeof_type; + mem_pool->cold_count = count; + + pool = CALLOC (count, sizeof_type + pad); + if (!pool) + return NULL; + + for (i = 0; i < count; i++) { + list = pool + (i * (sizeof_type + pad)); + INIT_LIST_HEAD (list); + list_add_tail (list, &mem_pool->list); + } + + mem_pool->pool = pool; + mem_pool->pool_end = pool + (count * (sizeof_type + pad)); + + return mem_pool; +} + + +void * +mem_get (struct mem_pool *mem_pool) +{ + struct list_head *list = NULL; + void *ptr = NULL; + + if (!mem_pool) { + gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument"); + return NULL; + } + + LOCK (&mem_pool->lock); + { + if (mem_pool->cold_count) { + list = mem_pool->list.next; + list_del (list); + + mem_pool->hot_count++; + mem_pool->cold_count--; + + ptr = list; + } + } + UNLOCK (&mem_pool->lock); + + if (ptr == NULL) { + ptr = MALLOC (mem_pool->padded_sizeof_type); + + if (!ptr) { + return NULL; + } + + LOCK (&mem_pool->lock); + { + mem_pool->hot_count ++; + } + UNLOCK (&mem_pool->lock); + } + + return ptr; +} + + +static int +__is_member (struct mem_pool *pool, void *ptr) +{ + if (!pool || !ptr) { + gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + if (ptr < pool->pool || ptr >= pool->pool_end) + return 0; + + if ((ptr - pool->pool) % pool->padded_sizeof_type) + return -1; + + return 1; +} + + +void +mem_put (struct mem_pool *pool, void *ptr) +{ + struct list_head *list = NULL; + + if (!pool || !ptr) { + gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument"); + return; + } + + list = ptr; + + LOCK (&pool->lock); + { + pool->hot_count--; + + switch (__is_member (pool, ptr)) + { + case 1: + pool->cold_count++; + list_add (list, &pool->list); + break; + case -1: + /* log error */ + abort (); + break; + case 0: + free (ptr); + break; + default: + /* log error */ + break; + } + } + UNLOCK (&pool->lock); + + if (ptr) + free (ptr); +} diff --git a/libglusterfs/src/mem-pool.h b/libglusterfs/src/mem-pool.h new file mode 100644 index 000000000..b36c24477 --- /dev/null +++ b/libglusterfs/src/mem-pool.h @@ -0,0 +1,54 @@ +/* + Copyright (c) 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _MEM_POOL_H_ +#define _MEM_POOL_H_ + +#include "list.h" +#include "locking.h" + + +#define MALLOC(size) malloc(size) +#define CALLOC(size,cnt) calloc(size,cnt) + +#define FREE(ptr) \ + if (ptr != NULL) { \ + free ((void *)ptr); \ + ptr = (void *)0xeeeeeeee; \ + } + +struct mem_pool { + struct list_head list; + int hot_count; + int cold_count; + gf_lock_t lock; + unsigned long padded_sizeof_type; + void *pool; + void *pool_end; +}; + +struct mem_pool * +mem_pool_new_fn (unsigned long sizeof_type, unsigned long count); + +#define mem_pool_new(type,count) mem_pool_new_fn (sizeof(type), count) + +void mem_put (struct mem_pool *pool, void *ptr); +void *mem_get (struct mem_pool *pool); + +#endif /* _MEM_POOL_H */ diff --git a/libglusterfs/src/protocol.h b/libglusterfs/src/protocol.h new file mode 100644 index 000000000..4ba869dee --- /dev/null +++ b/libglusterfs/src/protocol.h @@ -0,0 +1,777 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _PROTOCOL_H +#define _PROTOCOL_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <inttypes.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/statvfs.h> +#include <unistd.h> +#include <fcntl.h> + +#include "byte-order.h" + + +struct gf_stat { + uint64_t ino; + uint64_t size; + uint64_t blocks; + uint32_t dev; + uint32_t rdev; + uint32_t mode; + uint32_t nlink; + uint32_t uid; + uint32_t gid; + uint32_t blksize; + uint32_t atime; + uint32_t atime_nsec; + uint32_t mtime; + uint32_t mtime_nsec; + uint32_t ctime; + uint32_t ctime_nsec; +} __attribute__((packed)); + + +static inline void +gf_stat_to_stat (struct gf_stat *gf_stat, struct stat *stat) +{ + stat->st_dev = ntoh32 (gf_stat->dev); + stat->st_ino = ntoh64 (gf_stat->ino); + stat->st_mode = ntoh32 (gf_stat->mode); + stat->st_nlink = ntoh32 (gf_stat->nlink); + stat->st_uid = ntoh32 (gf_stat->uid); + stat->st_gid = ntoh32 (gf_stat->gid); + stat->st_rdev = ntoh32 (gf_stat->rdev); + stat->st_size = ntoh64 (gf_stat->size); + stat->st_blksize = ntoh32 (gf_stat->blksize); + stat->st_blocks = ntoh64 (gf_stat->blocks); + stat->st_atime = ntoh32 (gf_stat->atime); + stat->st_mtime = ntoh32 (gf_stat->mtime); + stat->st_ctime = ntoh32 (gf_stat->ctime); + /* TODO: handle nsec */ +} + + +static inline void +gf_stat_from_stat (struct gf_stat *gf_stat, struct stat *stat) +{ + gf_stat->dev = hton32 (stat->st_dev); + gf_stat->ino = hton64 (stat->st_ino); + gf_stat->mode = hton32 (stat->st_mode); + gf_stat->nlink = hton32 (stat->st_nlink); + gf_stat->uid = hton32 (stat->st_uid); + gf_stat->gid = hton32 (stat->st_gid); + gf_stat->rdev = hton32 (stat->st_rdev); + gf_stat->size = hton64 (stat->st_size); + gf_stat->blksize = hton32 (stat->st_blksize); + gf_stat->blocks = hton64 (stat->st_blocks); + gf_stat->atime = hton32 (stat->st_atime); + gf_stat->mtime = hton32 (stat->st_mtime); + gf_stat->ctime = hton32 (stat->st_ctime); + /* TODO: handle nsec */ +} + + +struct gf_statfs { + uint64_t bsize; + uint64_t frsize; + uint64_t blocks; + uint64_t bfree; + uint64_t bavail; + uint64_t files; + uint64_t ffree; + uint64_t favail; + uint64_t fsid; + uint64_t flag; + uint64_t namemax; +} __attribute__((packed)); + + +static inline void +gf_statfs_to_statfs (struct gf_statfs *gf_stat, struct statvfs *stat) +{ + stat->f_bsize = ntoh64 (gf_stat->bsize); + stat->f_frsize = ntoh64 (gf_stat->frsize); + stat->f_blocks = ntoh64 (gf_stat->blocks); + stat->f_bfree = ntoh64 (gf_stat->bfree); + stat->f_bavail = ntoh64 (gf_stat->bavail); + stat->f_files = ntoh64 (gf_stat->files); + stat->f_ffree = ntoh64 (gf_stat->ffree); + stat->f_favail = ntoh64 (gf_stat->favail); + stat->f_fsid = ntoh64 (gf_stat->fsid); + stat->f_flag = ntoh64 (gf_stat->flag); + stat->f_namemax = ntoh64 (gf_stat->namemax); +} + + +static inline void +gf_statfs_from_statfs (struct gf_statfs *gf_stat, struct statvfs *stat) +{ + gf_stat->bsize = hton64 (stat->f_bsize); + gf_stat->frsize = hton64 (stat->f_frsize); + gf_stat->blocks = hton64 (stat->f_blocks); + gf_stat->bfree = hton64 (stat->f_bfree); + gf_stat->bavail = hton64 (stat->f_bavail); + gf_stat->files = hton64 (stat->f_files); + gf_stat->ffree = hton64 (stat->f_ffree); + gf_stat->favail = hton64 (stat->f_favail); + gf_stat->fsid = hton64 (stat->f_fsid); + gf_stat->flag = hton64 (stat->f_flag); + gf_stat->namemax = hton64 (stat->f_namemax); +} + + +struct gf_flock { + uint16_t type; + uint16_t whence; + uint64_t start; + uint64_t len; + uint32_t pid; +} __attribute__((packed)); + + +static inline void +gf_flock_to_flock (struct gf_flock *gf_flock, struct flock *flock) +{ + flock->l_type = ntoh16 (gf_flock->type); + flock->l_whence = ntoh16 (gf_flock->whence); + flock->l_start = ntoh64 (gf_flock->start); + flock->l_len = ntoh64 (gf_flock->len); + flock->l_pid = ntoh32 (gf_flock->pid); +} + + +static inline void +gf_flock_from_flock (struct gf_flock *gf_flock, struct flock *flock) +{ + gf_flock->type = hton16 (flock->l_type); + gf_flock->whence = hton16 (flock->l_whence); + gf_flock->start = hton64 (flock->l_start); + gf_flock->len = hton64 (flock->l_len); + gf_flock->pid = hton32 (flock->l_pid); +} + + +struct gf_timespec { + uint32_t tv_sec; + uint32_t tv_nsec; +} __attribute__((packed)); + + +static inline void +gf_timespec_to_timespec (struct gf_timespec *gf_ts, struct timespec *ts) +{ + + ts[0].tv_sec = ntoh32 (gf_ts[0].tv_sec); + ts[0].tv_nsec = ntoh32 (gf_ts[0].tv_nsec); + ts[1].tv_sec = ntoh32 (gf_ts[1].tv_sec); + ts[1].tv_nsec = ntoh32 (gf_ts[1].tv_nsec); +} + + +static inline void +gf_timespec_from_timespec (struct gf_timespec *gf_ts, struct timespec *ts) +{ + gf_ts[0].tv_sec = hton32 (ts[0].tv_sec); + gf_ts[0].tv_nsec = hton32 (ts[0].tv_nsec); + gf_ts[1].tv_sec = hton32 (ts[1].tv_sec); + gf_ts[1].tv_nsec = hton32 (ts[1].tv_nsec); +} + + +typedef struct { + uint64_t ino; + char path[0]; /* NULL terminated */ +} __attribute__((packed)) gf_fop_stat_req_t;; +typedef struct { + struct gf_stat stat; +} __attribute__((packed)) gf_fop_stat_rsp_t; + + +typedef struct { + uint64_t ino; + uint32_t size; + char path[0]; /* NULL terminated */ +} __attribute__((packed)) gf_fop_readlink_req_t; +typedef struct { + char path[0]; /* NULL terminated */ +} __attribute__((packed)) gf_fop_readlink_rsp_t; + + +typedef struct { + uint64_t par; + uint64_t dev; + uint32_t mode; + char path[0]; /* NULL terminated */ + char bname[0]; /* NULL terminated */ +} __attribute__((packed)) gf_fop_mknod_req_t; +typedef struct { + struct gf_stat stat; +} __attribute__((packed)) gf_fop_mknod_rsp_t; + + +typedef struct { + uint64_t par; + uint32_t mode; + char path[0]; /* NULL terminated */ + char bname[0]; /* NULL terminated */ +} __attribute__((packed)) gf_fop_mkdir_req_t; +typedef struct { + struct gf_stat stat; +} __attribute__((packed)) gf_fop_mkdir_rsp_t; + + +typedef struct { + uint64_t par; + char path[0]; /* NULL terminated */ + char bname[0]; /* NULL terminated */ +} __attribute__((packed)) gf_fop_unlink_req_t; +typedef struct { +} __attribute__((packed)) gf_fop_unlink_rsp_t; + + +typedef struct { + uint64_t par; + char path[0]; + char bname[0]; /* NULL terminated */ +} __attribute__((packed)) gf_fop_rmdir_req_t; +typedef struct { +} __attribute__((packed)) gf_fop_rmdir_rsp_t; + + +typedef struct { + uint64_t par; + char path[0]; + char bname[0]; + char linkname[0]; +} __attribute__((packed)) gf_fop_symlink_req_t; +typedef struct { + struct gf_stat stat; +}__attribute__((packed)) gf_fop_symlink_rsp_t; + + +typedef struct { + uint64_t oldpar; + uint64_t newpar; + char oldpath[0]; + char oldbname[0]; /* NULL terminated */ + char newpath[0]; + char newbname[0]; /* NULL terminated */ +} __attribute__((packed)) gf_fop_rename_req_t; +typedef struct { + struct gf_stat stat; +} __attribute__((packed)) gf_fop_rename_rsp_t; + + +typedef struct { + uint64_t oldino; + uint64_t newpar; + char oldpath[0]; + char newpath[0]; + char newbname[0]; +}__attribute__((packed)) gf_fop_link_req_t; +typedef struct { + struct gf_stat stat; +} __attribute__((packed)) gf_fop_link_rsp_t; + + +typedef struct { + uint64_t ino; + uint32_t mode; + char path[0]; +} __attribute__((packed)) gf_fop_chmod_req_t; +typedef struct { + struct gf_stat stat; +} __attribute__((packed)) gf_fop_chmod_rsp_t; + + +typedef struct { + uint64_t ino; + uint32_t uid; + uint32_t gid; + char path[0]; +} __attribute__((packed)) gf_fop_chown_req_t; +typedef struct { + struct gf_stat stat; +} __attribute__((packed)) gf_fop_chown_rsp_t; + + +typedef struct { + uint64_t ino; + uint64_t offset; + char path[0]; +} __attribute__((packed)) gf_fop_truncate_req_t; +typedef struct { + struct gf_stat stat; +} __attribute__((packed)) gf_fop_truncate_rsp_t; + + +typedef struct { + uint64_t ino; + uint32_t flags; + char path[0]; +} __attribute__((packed)) gf_fop_open_req_t; +typedef struct { + int64_t fd; +} __attribute__((packed)) gf_fop_open_rsp_t; + + +typedef struct { + uint64_t ino; + int64_t fd; + uint64_t offset; + uint32_t size; +} __attribute__((packed)) gf_fop_read_req_t; +typedef struct { + struct gf_stat stat; + char buf[0]; +} __attribute__((packed)) gf_fop_read_rsp_t; + + +typedef struct { + uint64_t ino; + int64_t fd; + uint64_t offset; + uint32_t size; +} __attribute__((packed)) gf_fop_write_req_t; +typedef struct { + struct gf_stat stat; +} __attribute__((packed)) gf_fop_write_rsp_t; + + +typedef struct { + uint64_t ino; + char path[0]; +} __attribute__((packed)) gf_fop_statfs_req_t; +typedef struct { + struct gf_statfs statfs; +} __attribute__((packed)) gf_fop_statfs_rsp_t; + + +typedef struct { + uint64_t ino; + int64_t fd; +} __attribute__((packed)) gf_fop_flush_req_t; +typedef struct { } __attribute__((packed)) gf_fop_flush_rsp_t; + + +typedef struct fsync_req { + uint64_t ino; + int64_t fd; + uint32_t data; +} __attribute__((packed)) gf_fop_fsync_req_t; +typedef struct { +} __attribute__((packed)) gf_fop_fsync_rsp_t; + + +typedef struct { + uint64_t ino; + uint32_t flags; + uint32_t dict_len; + char dict[0]; + char path[0]; +} __attribute__((packed)) gf_fop_setxattr_req_t; +typedef struct { } __attribute__((packed)) gf_fop_setxattr_rsp_t; + +typedef struct { + uint64_t ino; + uint32_t flags; + uint32_t dict_len; + char dict[0]; + char path[0]; +} __attribute__((packed)) gf_fop_xattrop_req_t; + +typedef struct { + uint32_t dict_len; + char dict[0]; +} __attribute__((packed)) gf_fop_xattrop_rsp_t; + + +typedef struct { + uint64_t ino; + int64_t fd; + uint32_t flags; + uint32_t dict_len; + char dict[0]; +} __attribute__((packed)) gf_fop_fxattrop_req_t; + +typedef struct { + uint32_t dict_len; + char dict[0]; +} __attribute__((packed)) gf_fop_fxattrop_rsp_t; + + +typedef struct { + uint64_t ino; + uint32_t namelen; + char path[0]; + char name[0]; +} __attribute__((packed)) gf_fop_getxattr_req_t; +typedef struct { + uint32_t dict_len; + char dict[0]; +} __attribute__((packed)) gf_fop_getxattr_rsp_t; + + +typedef struct { + uint64_t ino; + char path[0]; + char name[0]; +} __attribute__((packed)) gf_fop_removexattr_req_t; +typedef struct { } __attribute__((packed)) gf_fop_removexattr_rsp_t; + + +typedef struct { + uint64_t ino; + char path[0]; +} __attribute__((packed)) gf_fop_opendir_req_t; +typedef struct { + int64_t fd; +} __attribute__((packed)) gf_fop_opendir_rsp_t; + + +typedef struct fsyncdir_req { + uint64_t ino; + int64_t fd; + int32_t data; +} __attribute__((packed)) gf_fop_fsyncdir_req_t; +typedef struct { +} __attribute__((packed)) gf_fop_fsyncdir_rsp_t; + + +typedef struct { + uint64_t ino; + int64_t fd; + uint64_t offset; + uint32_t size; +} __attribute__((packed)) gf_fop_readdir_req_t; +typedef struct { + uint32_t size; + char buf[0]; +} __attribute__((packed)) gf_fop_readdir_rsp_t; + + +typedef struct { + uint64_t ino; + uint32_t mask; + char path[0]; +} __attribute__((packed)) gf_fop_access_req_t; +typedef struct { +} __attribute__((packed)) gf_fop_access_rsp_t; + + +typedef struct { + uint64_t par; + uint32_t flags; + uint32_t mode; + char path[0]; + char bname[0]; +} __attribute__((packed)) gf_fop_create_req_t; +typedef struct { + struct gf_stat stat; + uint64_t fd; +} __attribute__((packed)) gf_fop_create_rsp_t; + + + +typedef struct { + uint64_t ino; + int64_t fd; + uint64_t offset; +} __attribute__((packed)) gf_fop_ftruncate_req_t; +typedef struct { + struct gf_stat stat; +} __attribute__((packed)) gf_fop_ftruncate_rsp_t; + + +typedef struct { + uint64_t ino; + int64_t fd; +} __attribute__((packed)) gf_fop_fstat_req_t; +typedef struct { + struct gf_stat stat; +} __attribute__((packed)) gf_fop_fstat_rsp_t; + + +typedef struct { + uint64_t ino; + int64_t fd; + uint32_t cmd; + uint32_t type; + struct gf_flock flock; +} __attribute__((packed)) gf_fop_lk_req_t; +typedef struct { + struct gf_flock flock; +} __attribute__((packed)) gf_fop_lk_rsp_t; + +typedef struct { + uint64_t ino; + uint32_t cmd; + uint32_t type; + struct gf_flock flock; + char path[0]; +} __attribute__((packed)) gf_fop_inodelk_req_t; +typedef struct { +} __attribute__((packed)) gf_fop_inodelk_rsp_t; + +typedef struct { + uint64_t ino; + int64_t fd; + uint32_t cmd; + uint32_t type; + struct gf_flock flock; +} __attribute__((packed)) gf_fop_finodelk_req_t; +typedef struct { +} __attribute__((packed)) gf_fop_finodelk_rsp_t; + +typedef struct { + uint64_t ino; + uint32_t cmd; + uint32_t type; + uint64_t namelen; + char path[0]; + char name[0]; +} __attribute__((packed)) gf_fop_entrylk_req_t; +typedef struct { +} __attribute__((packed)) gf_fop_entrylk_rsp_t; + +typedef struct { + uint64_t ino; + int64_t fd; + uint32_t cmd; + uint32_t type; + uint64_t namelen; + char name[0]; +} __attribute__((packed)) gf_fop_fentrylk_req_t; +typedef struct { +} __attribute__((packed)) gf_fop_fentrylk_rsp_t; + +typedef struct { + uint64_t ino; + struct gf_timespec tv[2]; + char path[0]; +} __attribute__((packed)) gf_fop_utimens_req_t; +typedef struct { + struct gf_stat stat; +} __attribute__((packed)) gf_fop_utimens_rsp_t; + +typedef struct { + uint64_t ino; + uint64_t fd; + uint32_t mode; +} __attribute__((packed)) gf_fop_fchmod_req_t; +typedef struct { + struct gf_stat stat; +} __attribute__((packed)) gf_fop_fchmod_rsp_t; + + +typedef struct { + uint64_t ino; + int64_t fd; + uint32_t uid; + uint32_t gid; +} __attribute__((packed)) gf_fop_fchown_req_t; +typedef struct { + struct gf_stat stat; +} __attribute__((packed)) gf_fop_fchown_rsp_t; + + +typedef struct { + uint64_t ino; /* NOTE: used only in case of 'root' lookup */ + uint64_t par; + uint32_t flags; + uint32_t dictlen; + char path[0]; + char bname[0]; + char dict[0]; +} __attribute__((packed)) gf_fop_lookup_req_t; +typedef struct { + struct gf_stat stat; + uint32_t dict_len; + char dict[0]; +} __attribute__((packed)) gf_fop_lookup_rsp_t; + + +typedef struct { + uint64_t ino; + int64_t fd; + uint32_t flags; + uint32_t count; + char buf[0]; +} __attribute__((packed)) gf_fop_setdents_req_t; +typedef struct { } __attribute__((packed)) gf_fop_setdents_rsp_t; + + +typedef struct { + uint64_t ino; + int64_t fd; + uint64_t offset; + uint32_t size; + uint32_t flags; +} __attribute__((packed)) gf_fop_getdents_req_t; +typedef struct { + uint32_t count; + char buf[0]; +} __attribute__((packed)) gf_fop_getdents_rsp_t; + + +typedef struct { + uint64_t ino; + uint32_t flag; + char path[0]; +} __attribute__((packed)) gf_fop_checksum_req_t; +typedef struct { + unsigned char fchecksum[0]; + unsigned char dchecksum[0]; +} __attribute__((packed)) gf_fop_checksum_rsp_t; + + +typedef struct { + char name[0]; +} __attribute__((packed)) gf_mop_lock_req_t; +typedef struct {} __attribute__((packed)) gf_mop_lock_rsp_t; + +typedef struct { + char name[0]; +} __attribute__((packed)) gf_mop_unlock_req_t; +typedef struct {} __attribute__((packed)) gf_mop_unlock_rsp_t; + +typedef struct { + char pattern[0]; +} __attribute__((packed)) gf_mop_listlocks_req_t; +typedef struct {} __attribute__((packed)) gf_mop_listlocks_rsp_t; + +typedef struct { + uint32_t flags; +} __attribute__((packed)) gf_mop_stats_req_t; +typedef struct { + char buf[0]; +} __attribute__((packed)) gf_mop_stats_rsp_t; + +typedef struct { + uint32_t flags; + uint32_t keylen; + char key[0]; +} __attribute__((packed)) gf_mop_getspec_req_t; +typedef struct { + char spec[0]; +} __attribute__((packed)) gf_mop_getspec_rsp_t; + + +typedef struct { + uint32_t dict_len; + char buf[0]; +} __attribute__((packed)) gf_mop_setvolume_req_t; +typedef struct { + uint32_t dict_len; + char buf[0]; +} __attribute__((packed)) gf_mop_setvolume_rsp_t; + + +typedef struct { +} __attribute__((packed)) gf_mop_ping_req_t; +typedef struct { +} __attribute__((packed)) gf_mop_ping_rsp_t; + + +typedef struct { + uint64_t ino; + int64_t fd; +} __attribute__((packed)) gf_cbk_releasedir_req_t; +typedef struct { +} __attribute__((packed)) gf_cbk_releasedir_rsp_t; + + +typedef struct { + uint64_t ino; + int64_t fd; +} __attribute__((packed)) gf_cbk_release_req_t; +typedef struct { +} __attribute__((packed)) gf_cbk_release_rsp_t; + + +typedef struct { + uint32_t count; + uint64_t ino_array[0]; +} __attribute__((packed)) gf_cbk_forget_req_t; +typedef struct { } __attribute__((packed)) gf_cbk_forget_rsp_t; + + +typedef struct { + uint32_t pid; + uint32_t uid; + uint32_t gid; +} __attribute__ ((packed)) gf_hdr_req_t; + + +typedef struct { + uint32_t op_ret; + uint32_t op_errno; +} __attribute__ ((packed)) gf_hdr_rsp_t; + + +typedef struct { + uint64_t callid; + uint32_t type; + uint32_t op; + uint32_t size; + union { + gf_hdr_req_t req; + gf_hdr_rsp_t rsp; + } __attribute__ ((packed)); +} __attribute__ ((packed)) gf_hdr_common_t; + + +static inline gf_hdr_common_t * +__gf_hdr_new (int size) +{ + gf_hdr_common_t *hdr = NULL; + + /* TODO: use mem-pool */ + hdr = CALLOC (sizeof (gf_hdr_common_t) + size, 1); + + if (!hdr) { + return NULL; + } + + hdr->size = hton32 (size); + + return hdr; +} + + +#define gf_hdr_len(type, x) (sizeof (gf_hdr_common_t) + sizeof (*type) + x) +#define gf_hdr_new(type, x) __gf_hdr_new (sizeof (*type) + x) + + +static inline void * +gf_param (gf_hdr_common_t *hdr) +{ + return ((void *)hdr) + sizeof (*hdr); +} + +#endif diff --git a/libglusterfs/src/revision.h b/libglusterfs/src/revision.h new file mode 100644 index 000000000..30742cd5e --- /dev/null +++ b/libglusterfs/src/revision.h @@ -0,0 +1 @@ +#define GLUSTERFS_REPOSITORY_REVISION "glusterfs--mainline--3.0--patch-928" diff --git a/libglusterfs/src/scheduler.c b/libglusterfs/src/scheduler.c new file mode 100644 index 000000000..3478a9385 --- /dev/null +++ b/libglusterfs/src/scheduler.c @@ -0,0 +1,80 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <dlfcn.h> +#include <netdb.h> +#include "xlator.h" +#include "scheduler.h" +#include "list.h" + +struct sched_ops * +get_scheduler (xlator_t *xl, const char *name) +{ + struct sched_ops *tmp_sched = NULL; + volume_opt_list_t *vol_opt = NULL; + char *sched_file = NULL; + void *handle = NULL; + + if (name == NULL) { + gf_log ("scheduler", GF_LOG_ERROR, + "'name' not specified, EINVAL"); + return NULL; + } + + asprintf (&sched_file, "%s/%s.so", SCHEDULERDIR, name); + + gf_log ("scheduler", GF_LOG_DEBUG, + "attempt to load file %s.so", name); + + handle = dlopen (sched_file, RTLD_LAZY); + if (!handle) { + gf_log ("scheduler", GF_LOG_ERROR, + "dlopen(%s): %s", sched_file, dlerror ()); + return NULL; + } + + tmp_sched = dlsym (handle, "sched"); + if (!tmp_sched) { + gf_log ("scheduler", GF_LOG_ERROR, + "dlsym(sched) on %s", dlerror ()); + return NULL; + } + + vol_opt = CALLOC (1, sizeof (volume_opt_list_t)); + vol_opt->given_opt = dlsym (handle, "options"); + if (vol_opt->given_opt == NULL) { + gf_log ("scheduler", GF_LOG_DEBUG, + "volume option validation not specified"); + } else { + list_add_tail (&vol_opt->list, &xl->volume_options); + if (validate_xlator_volume_options (xl, vol_opt->given_opt) + == -1) { + gf_log ("scheduler", GF_LOG_ERROR, + "volume option validation failed"); + return NULL; + } + } + + return tmp_sched; +} diff --git a/libglusterfs/src/scheduler.h b/libglusterfs/src/scheduler.h new file mode 100644 index 000000000..5ff1a624f --- /dev/null +++ b/libglusterfs/src/scheduler.h @@ -0,0 +1,40 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _SCHEDULER_H +#define _SCHEDULER_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "xlator.h" + +struct sched_ops { + int32_t (*init) (xlator_t *this); + void (*fini) (xlator_t *this); + void (*update) (xlator_t *this); + xlator_t *(*schedule) (xlator_t *this, const void *path); + void (*notify) (xlator_t *xl, int32_t event, void *data); +}; + +extern struct sched_ops *get_scheduler (xlator_t *xl, const char *name); + +#endif /* _SCHEDULER_H */ diff --git a/libglusterfs/src/spec.l b/libglusterfs/src/spec.l new file mode 100644 index 000000000..0345730b2 --- /dev/null +++ b/libglusterfs/src/spec.l @@ -0,0 +1,94 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + + +%x STRING +%option prefix="yy" +%option yylineno +%{ + +#define YYSTYPE char * +#include "xlator.h" +#include "y.tab.h" +#include <string.h> +#define START_STRSIZE 32 + +static char *text; +static int text_asize; +static int text_size; + +void new_string(void) +{ + text = malloc(START_STRSIZE); + text_asize = START_STRSIZE; + text_size = 0; + *text = 0; +} + +void append_string(const char *str, int size) +{ + int new_size = text_size + size + 1; + if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; + text = realloc(text, new_size); + text_asize = new_size; + } + memcpy(text + text_size, str, size); + text_size += size; + text[text_size] = 0; +} + +void alloc_string(const char *str, int size) +{ + text = malloc(size + 1); + memcpy(text, str, size); + text[size] = 0; +} + +%} + +VOLUME [v][o][l][u][m][e] +END [e][n][d] +SUB [s][u][b] +OPTION [o][p][t][i][o][n] +TYPE [t][y][p][e] +%% +\#.* ; +{VOLUME} return SECTION_BEGIN; +{TYPE} return TYPE; +{END}[-]{VOLUME} return SECTION_END; +{SUB}{VOLUME}[Ss] return SUBSECTION; +{OPTION} return OPTION; +\" BEGIN(STRING); +<STRING>{ + [^\n\"\\]* { append_string (yytext, yyleng); } + \\. { append_string (yytext + 1, yyleng - 1); } + \" { + if (0) { + yyunput (0, NULL); + } + BEGIN (INITIAL); + yylval = text; + return STRING_TOK; + } +} +[^ \t\r\n\"\\]+ { yylval = strdup (yytext) ; return ID; } +[ \t\r\n]+ ; +%% diff --git a/libglusterfs/src/spec.y b/libglusterfs/src/spec.y new file mode 100644 index 000000000..c6491e28d --- /dev/null +++ b/libglusterfs/src/spec.y @@ -0,0 +1,613 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + + +%token SECTION_BEGIN SECTION_END OPTION NEWLINE SUBSECTION ID WHITESPACE COMMENT TYPE STRING_TOK +%name-prefix="yy" + +%{ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/mman.h> + +#include "xlator.h" +#include "logging.h" + +static int new_section (char *name); +static int section_type (char *type); +static int section_option (char *key, char *value); +static int section_sub (char *sub); +static int section_end (void); +static void sub_error (void); +static void type_error (void); +static void option_error (void); + +#define YYSTYPE char * +#define GF_CMD_BUFFER_LEN (32 * GF_UNIT_KB) + +int yyerror (const char *); +int yylex (); +%} + + +%% +SECTIONS: SECTION | SECTIONS SECTION; + +SECTION: SECTION_HEADER SECTION_DATA SECTION_FOOTER; +SECTION_HEADER: SECTION_BEGIN WORD {if( -1 == new_section ($2)) { YYABORT; } }; +SECTION_FOOTER: SECTION_END {if( -1 == section_end ()) { YYABORT; } }; + +SECTION_DATA: TYPE_LINE OPTIONS_LINE SUBSECTION_LINE OPTIONS_LINE | + TYPE_LINE SUBSECTION_LINE OPTIONS_LINE | + TYPE_LINE OPTIONS_LINE SUBSECTION_LINE | + TYPE_LINE SUBSECTION_LINE | + TYPE_LINE OPTIONS_LINE | + OPTIONS_LINE SUBSECTION_LINE OPTIONS_LINE | /* error case */ + OPTIONS_LINE; /* error case */ + +TYPE_LINE: TYPE WORD {if ( -1 == section_type ($2)) { YYABORT; }} | TYPE { type_error(); YYABORT; }; + +SUBSECTION_LINE: SUBSECTION WORDS | SUBSECTION { sub_error (); YYABORT; }; + +OPTIONS_LINE: OPTION_LINE | OPTIONS_LINE OPTION_LINE; + +OPTION_LINE: OPTION WORD WORD {if(-1 == section_option($2,$3)){YYABORT;} } | + OPTION WORD { option_error (); YYABORT; } | + OPTION { option_error (); YYABORT; }; + +WORDS: WORD {if (-1 == section_sub ($1)) {YYABORT; } } | WORDS WORD { if (-1 == section_sub ($2)) { YYABORT; } }; +WORD: ID | STRING_TOK ; +%% + +xlator_t *complete_tree = NULL; +xlator_t *tree = NULL; +glusterfs_ctx_t *gctx; + +static void +type_error (void) +{ + extern int yylineno; + + fprintf (stderr, "volume %s, before line %d: specify which 'type' " + "you need\n", + complete_tree->name, yylineno); + gf_log ("parser", GF_LOG_ERROR, + "volume %s, before line %d: specify which 'type' you need", + complete_tree->name, yylineno); + return; +} + +static void +sub_error (void) +{ + extern int yylineno; + + fprintf (stderr, "volume %s, before line %d: specify what all " + "'subvolumes' you need for volume\n", + complete_tree->name, yylineno); + gf_log ("parser", GF_LOG_ERROR, + "volume %s, before line %d: specify what all 'subvolumes' " + "you need for volume", + complete_tree->name, yylineno); + return; +} + +static void +option_error (void) +{ + extern int yylineno; + + fprintf (stderr, "volume %s, before line %d: you need to specify " + "<key> <value> pair for 'option' token\n", + complete_tree->name, yylineno); + gf_log ("parser", GF_LOG_ERROR, + "volume %s, before line %d: you need to specify <key> " + "<value> pair for 'option' token", + complete_tree->name, yylineno); + return; +} + +static int +cut_tree (xlator_t *tree) +{ + xlator_t *trav = tree, *prev = tree; + + if (!tree) { + gf_log ("parser", GF_LOG_DEBUG, "Translator tree not found"); + return -1; + } + + gf_log ("parser", GF_LOG_DEBUG, "Failed to build translator graph"); + + while (prev) { + trav = prev->next; + dict_destroy (prev->options); + FREE (prev->name); + FREE (prev); + prev = trav; + } + + return 0; +} + + +static int +new_section (char *name) +{ + extern int yylineno; + xlator_t *trav = complete_tree; + xlator_t *node = (void *) calloc (1, sizeof (*node)); + + if (!name) { + gf_log ("parser", GF_LOG_DEBUG, + "invalid argument name '%s'", name); + return -1; + } + + while (trav) { + if (!strcmp (name, trav->name)) { + fprintf (stderr, + "line %d: volume '%s' defined again\n", + yylineno, name); + gf_log ("parser", GF_LOG_ERROR, + "line %d: volume '%s' defined again", + yylineno, name); + return -1; + } + trav = trav->next; + } + + node->ctx = gctx; + node->name = name; + node->next = complete_tree; + if (complete_tree) + complete_tree->prev = node; + node->options = get_new_dict (); + complete_tree = node; + + tree = node; + gf_log ("parser", GF_LOG_DEBUG, "New node for '%s'", name); + + return 0; +} + +static int +section_type (char *type) +{ + extern int yylineno; + int32_t ret = -1; + if (!type) { + gf_log ("parser", GF_LOG_DEBUG, "invalid argument type"); + return -1; + } + + ret = xlator_set_type (tree, type); + if (ret) { + fprintf (stderr, "volume '%s', line %d: type '%s' is not " + "valid or not found on this machine\n", + complete_tree->name, yylineno, type); + gf_log ("parser", GF_LOG_ERROR, + "volume '%s', line %d: type '%s' is not valid or " + "not found on this machine", + complete_tree->name, yylineno, type); + return -1; + } + gf_log ("parser", GF_LOG_DEBUG, "Type:%s:%s", tree->name, type); + + return 0; +} + + +static int +section_option (char *key, char *value) +{ + extern int yylineno; + + int ret = 0; + + if (!key || !value){ + fprintf (stderr, "invalid argument\n"); + gf_log ("parser", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + ret = dict_set (tree->options, key, str_to_data (value)); + + if (ret == 1) { + gf_log ("parser", GF_LOG_ERROR, + "volume '%s', line %d: duplicate entry " + "('option %s') present", + tree->name, yylineno, key); + return -1; + } + gf_log ("parser", GF_LOG_DEBUG, "Option:%s:%s:%s", + tree->name, key, value); + + return 0; +} + +static int +section_sub (char *sub) +{ + extern int yylineno; + xlator_t *trav = complete_tree; + xlator_list_t *xlchild, *tmp, *xlparent; + + if (!sub) { + fprintf (stderr, "invalid subvolumes argument\n"); + gf_log ("parser", GF_LOG_ERROR, "invalid subvolumes argument"); + return -1; + } + + while (trav) { + if (!strcmp (sub, trav->name)) + break; + trav = trav->next; + } + if (!trav) { + fprintf (stderr, + "volume '%s', line %d: subvolume '%s' is not " + "defined prior to usage\n", + complete_tree->name, yylineno, sub); + gf_log ("parser", GF_LOG_ERROR, + "volume '%s', line %d: subvolume '%s' is not defined " + "prior to usage", + complete_tree->name, yylineno, sub); + return -1; + } + + if (trav == tree) { + fprintf (stderr, "volume '%s', line %d: has '%s' itself as " + "subvolume\n", + complete_tree->name, yylineno, sub); + gf_log ("parser", GF_LOG_ERROR, + "volume '%s', line %d: has '%s' itself as subvolume", + complete_tree->name, yylineno, sub); + return -1; + } + + xlparent = (void *) calloc (1, sizeof (*xlparent)); + xlparent->xlator = tree; + + tmp = trav->parents; + if (tmp == NULL) { + trav->parents = xlparent; + } else { + while (tmp->next) + tmp = tmp->next; + tmp->next = xlparent; + } + + xlchild = (void *) calloc (1, sizeof(*xlchild)); + xlchild->xlator = trav; + + tmp = tree->children; + if (tmp == NULL) { + tree->children = xlchild; + } else { + while (tmp->next) + tmp = tmp->next; + tmp->next = xlchild; + } + + gf_log ("parser", GF_LOG_DEBUG, "child:%s->%s", tree->name, sub); + + return 0; +} + +static int +section_end (void) +{ + if (!tree->fops || !tree->mops) { + fprintf (stderr, + "\"type\" not specified for volume %s\n", tree->name); + gf_log ("parser", GF_LOG_ERROR, + "\"type\" not specified for volume %s", tree->name); + return -1; + } + gf_log ("parser", GF_LOG_DEBUG, "end:%s", tree->name); + + tree = NULL; + return 0; +} + +int +yywrap () +{ + return 1; +} + +int +yyerror (const char *str) +{ + extern char *yytext; + extern int yylineno; + + if (complete_tree && complete_tree->name) + { + if (!strcmp (yytext, "volume")) + { + fprintf (stderr, + "'end-volume' not defined for volume '%s'\n", + complete_tree->name); + gf_log ("parser", GF_LOG_ERROR, + "'end-volume' not defined for volume '%s'", + complete_tree->name); + } + else if (!strcmp (yytext, "type")) + { + fprintf (stderr, "line %d: duplicate 'type' defined " + "for volume '%s'", + yylineno, complete_tree->name); + gf_log ("parser", GF_LOG_ERROR, + "line %d: duplicate 'type' defined for " + "volume '%s'", + yylineno, complete_tree->name); + } + else if (!strcmp (yytext, "subvolumes")) + { + fprintf (stderr, "line %d: duplicate 'subvolumes' " + "defined for volume '%s'", + yylineno, complete_tree->name); + gf_log ("parser", GF_LOG_ERROR, + "line %d: duplicate 'subvolumes' defined for " + "volume '%s'", + yylineno, complete_tree->name); + } + else if (tree) + { + fprintf (stderr, + "syntax error: line %d (volume '%s'): \"%s\"" + "\nallowed tokens are 'volume', 'type', " + "'subvolumes', 'option', 'end-volume'", + yylineno, complete_tree->name, + yytext); + + gf_log ("parser", GF_LOG_ERROR, + "syntax error: line %d (volume '%s'): \"%s\"" + "\nallowed tokens are 'volume', 'type', " + "'subvolumes', 'option', 'end-volume'()", + yylineno, complete_tree->name, + yytext); + } + else + { + fprintf (stderr, + "syntax error: line %d (just after volume " + "'%s'): \"%s\"\n(%s)", + yylineno, complete_tree->name, + yytext, + "allowed tokens are 'volume', 'type', " + "'subvolumes', 'option', 'end-volume'"); + gf_log ("parser", GF_LOG_ERROR, + "syntax error: line %d (just after volume " + "'%s'): \"%s\"\n(%s)", + yylineno, complete_tree->name, + yytext, + "allowed tokens are 'volume', 'type', " + "'subvolumes', 'option', 'end-volume'"); + } + } + else + { + fprintf (stderr, + "syntax error in line %d: \"%s\" \n" + "(allowed tokens are 'volume', 'type', " + "'subvolumes', 'option', 'end-volume')\n", + yylineno, yytext); + gf_log ("parser", GF_LOG_ERROR, + "syntax error in line %d: \"%s\" \n" + "(allowed tokens are 'volume', 'type', " + "'subvolumes', 'option', 'end-volume')\n", + yylineno, yytext); + } + + cut_tree (tree); + complete_tree = NULL; + return 0; +} + +static int +execute_cmd (char *cmd, char *result, int size) +{ + FILE *fpp = NULL; + int ret = 0; + + fpp = popen (cmd, "r"); + if (!fpp) + { + gf_log ("parser", GF_LOG_ERROR, "%s: failed to popen", cmd); + return -1; + } + + if (!fgets (result, GF_UNIT_KB, fpp)) + { + gf_log ("parser", GF_LOG_ERROR, "failed to read output of cmd (%s)", cmd); + pclose (fpp); + return -1; + } + + ret = strlen (result); + result[ret - 1] = '\0'; + ret--; + pclose (fpp); + + return ret; +} + +static int +find_and_execute_cmds (char *src, char *dst) +{ + char escaped = 0; + char *cmd = NULL; + char in_backtick = 0; + int size = 0, ret = 0; + + if (!src || !dst) { + ret = -1; + goto out; + } + + while (*src) { + if (*src == '`' && !escaped) { + if (in_backtick) { + *src = '\0'; + ret = execute_cmd (cmd, dst, GF_UNIT_KB); + if (ret < 0) { + ret = -1; + size = -1; + goto out; + } + + dst += ret; + size += ret; + } else { + cmd = src + 1; + } + + in_backtick = !in_backtick; + } else if (!in_backtick) { + *dst++ = *src; + size++; + } + + if (*src == '\\') { + escaped = !escaped; + } else { + escaped = 0; + } + + src++; + } + +out: + return size; +} + + +static int +parse_backtick (FILE *srcfp, FILE *dstfp) +{ + char srcbuf[8 * GF_UNIT_KB] = {0, }; + char *dstbuf = NULL; + int ret = 0; + int size = 0; + + dstbuf = calloc (32 * GF_UNIT_KB, 1); + + fseek (srcfp, 0L, SEEK_SET); + fseek (dstfp, 0L, SEEK_SET); + + while (!feof (srcfp)) { + if (fgets (srcbuf, 8 * GF_UNIT_KB, srcfp) == NULL) { + break; + } + + size = find_and_execute_cmds (srcbuf, dstbuf); + if (size < 0) { + ret = -1; + break; + } + fwrite (dstbuf, size, 1, dstfp); + } + + fseek (srcfp, 0L, SEEK_SET); + fseek (dstfp, 0L, SEEK_SET); + FREE (dstbuf); + return ret; +} + +extern FILE *yyin; +xlator_t * +file_to_xlator_tree (glusterfs_ctx_t *ctx, + FILE *fp) +{ + int32_t ret = 0; + xlator_t *tmp_tree = NULL; + FILE *tmp_file = NULL; + int fd = -1, tmp_fd = -1; + struct stat stbuf = {0, }; + char *buffer = NULL; + + tmp_file = tmpfile (); + if (NULL == tmp_file) { + gf_log ("parser", GF_LOG_ERROR, + "cannot create temparory file"); + return NULL; + } + + fd = fileno (fp); + if (fd == -1) { + gf_log ("parser", GF_LOG_ERROR, + "cannot get file descriptor from volume specification file stream pointer"); + fclose (tmp_file); + return NULL; + } + + ret = fstat (fd, &stbuf); + if (ret == -1) { + gf_log ("parser", GF_LOG_ERROR, + "getting the size of volume specification file failed"); + fclose (tmp_file); + return NULL; + } + + buffer = calloc (stbuf.st_size + GF_CMD_BUFFER_LEN, 1); + + tmp_fd = fileno (tmp_file); + if (!mmap (buffer, stbuf.st_size + GF_CMD_BUFFER_LEN, + PROT_NONE, 0, tmp_fd, 0)) { + gf_log ("parser", GF_LOG_ERROR, + "mmap of volume specification file failed"); + fclose (tmp_file); + FREE (buffer); + return NULL; + } + + ret = parse_backtick (fp, tmp_file); + if (ret < 0) { + gf_log ("parser", GF_LOG_ERROR, + "parsing of backticks failed"); + fclose (tmp_file); + FREE (buffer); + return NULL; + } + + gctx = ctx; + yyin = tmp_file; + ret = yyparse (); + + fclose (tmp_file); + FREE (buffer); + + if (1 == ret) { + gf_log ("parser", GF_LOG_DEBUG, + "parsing of volfile failed, please review it " + "once more"); + tree = complete_tree = NULL; + return NULL; + } + + tmp_tree = complete_tree; + tree = complete_tree = NULL; + + return tmp_tree; +} diff --git a/libglusterfs/src/stack.h b/libglusterfs/src/stack.h new file mode 100644 index 000000000..f014a4a27 --- /dev/null +++ b/libglusterfs/src/stack.h @@ -0,0 +1,266 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +/* + This file defines MACROS and static inlines used to emulate a function + call over asynchronous communication with remote server +*/ + +#ifndef _STACK_H +#define _STACK_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +struct _call_stack_t; +typedef struct _call_stack_t call_stack_t; +struct _call_frame_t; +typedef struct _call_frame_t call_frame_t; +struct _call_pool_t; +typedef struct _call_pool_t call_pool_t; + +#include "xlator.h" +#include "dict.h" +#include "list.h" +#include "common-utils.h" + + +typedef int32_t (*ret_fn_t) (call_frame_t *frame, + call_frame_t *prev_frame, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + ...); + +struct _call_pool_t { + union { + struct list_head all_frames; + struct { + call_stack_t *next_call; + call_stack_t *prev_call; + } all_stacks; + }; + int64_t cnt; + gf_lock_t lock; +}; + +struct _call_frame_t { + call_stack_t *root; /* stack root */ + call_frame_t *parent; /* previous BP */ + call_frame_t *next; + call_frame_t *prev; /* maintainence list */ + void *local; /* local variables */ + xlator_t *this; /* implicit object */ + ret_fn_t ret; /* op_return address */ + int32_t ref_count; + gf_lock_t lock; + void *cookie; /* unique cookie */ +}; + +struct _call_stack_t { + union { + struct list_head all_frames; + struct { + call_stack_t *next_call; + call_stack_t *prev_call; + }; + }; + call_pool_t *pool; + void *trans; + uint64_t unique; + void *state; /* pointer to request state */ + uid_t uid; + gid_t gid; + pid_t pid; + call_frame_t frames; + dict_t *req_refs; + dict_t *rsp_refs; + + int32_t op; + int8_t type; +}; + + +static inline void +FRAME_DESTROY (call_frame_t *frame) +{ + if (frame->next) + frame->next->prev = frame->prev; + if (frame->prev) + frame->prev->next = frame->next; + if (frame->local) + FREE (frame->local); + LOCK_DESTROY (&frame->lock); + FREE (frame); +} + + +static inline void +STACK_DESTROY (call_stack_t *stack) +{ + LOCK (&stack->pool->lock); + { + list_del_init (&stack->all_frames); + stack->pool->cnt--; + } + UNLOCK (&stack->pool->lock); + + if (stack->frames.local) + FREE (stack->frames.local); + + LOCK_DESTROY (&stack->frames.lock); + + while (stack->frames.next) { + FRAME_DESTROY (stack->frames.next); + } + FREE (stack); +} + + +#define cbk(x) cbk_##x + + +/* make a call */ +#define STACK_WIND(frame, rfn, obj, fn, params ...) \ + do { \ + call_frame_t *_new = NULL; \ + \ + _new = CALLOC (1, sizeof (call_frame_t)); \ + ERR_ABORT (_new); \ + typeof(fn##_cbk) tmp_cbk = rfn; \ + _new->root = frame->root; \ + _new->next = frame->root->frames.next; \ + _new->prev = &frame->root->frames; \ + if (frame->root->frames.next) \ + frame->root->frames.next->prev = _new; \ + frame->root->frames.next = _new; \ + _new->this = obj; \ + _new->ret = (ret_fn_t) tmp_cbk; \ + _new->parent = frame; \ + _new->cookie = _new; \ + LOCK_INIT (&_new->lock); \ + frame->ref_count++; \ + \ + fn (_new, obj, params); \ + } while (0) + + +/* make a call with a cookie */ +#define STACK_WIND_COOKIE(frame, rfn, cky, obj, fn, params ...) \ + do { \ + call_frame_t *_new = CALLOC (1, \ + sizeof (call_frame_t)); \ + ERR_ABORT (_new); \ + typeof(fn##_cbk) tmp_cbk = rfn; \ + _new->root = frame->root; \ + _new->next = frame->root->frames.next; \ + _new->prev = &frame->root->frames; \ + if (frame->root->frames.next) \ + frame->root->frames.next->prev = _new; \ + frame->root->frames.next = _new; \ + _new->this = obj; \ + _new->ret = (ret_fn_t) tmp_cbk; \ + _new->parent = frame; \ + _new->cookie = cky; \ + LOCK_INIT (&_new->lock); \ + frame->ref_count++; \ + fn##_cbk = rfn; \ + \ + fn (_new, obj, params); \ + } while (0) + + +/* return from function */ +#define STACK_UNWIND(frame, params ...) \ + do { \ + ret_fn_t fn = frame->ret; \ + call_frame_t *_parent = frame->parent; \ + _parent->ref_count--; \ + fn (_parent, frame->cookie, _parent->this, params); \ + } while (0) + + +static inline call_frame_t * +copy_frame (call_frame_t *frame) +{ + call_stack_t *newstack = NULL; + call_stack_t *oldstack = NULL; + + if (!frame) { + return NULL; + } + + newstack = (void *) CALLOC (1, sizeof (*newstack)); + oldstack = frame->root; + + newstack->uid = oldstack->uid; + newstack->gid = oldstack->gid; + newstack->pid = oldstack->pid; + newstack->unique = oldstack->unique; + + newstack->frames.this = frame->this; + newstack->frames.root = newstack; + newstack->pool = oldstack->pool; + + LOCK_INIT (&newstack->frames.lock); + + LOCK (&oldstack->pool->lock); + { + list_add (&newstack->all_frames, &oldstack->all_frames); + newstack->pool->cnt++; + + } + UNLOCK (&oldstack->pool->lock); + + return &newstack->frames; +} + +static inline call_frame_t * +create_frame (xlator_t *xl, call_pool_t *pool) +{ + call_stack_t *stack = NULL; + + if (!xl || !pool) { + return NULL; + } + + stack = CALLOC (1, sizeof (*stack)); + if (!stack) + return NULL; + + stack->pool = pool; + stack->frames.root = stack; + stack->frames.this = xl; + + LOCK (&pool->lock); + { + list_add (&stack->all_frames, &pool->all_frames); + pool->cnt++; + } + UNLOCK (&pool->lock); + + LOCK_INIT (&stack->frames.lock); + + return &stack->frames; +} + + +#endif /* _STACK_H */ diff --git a/libglusterfs/src/timer.c b/libglusterfs/src/timer.c new file mode 100644 index 000000000..a6dbaaa83 --- /dev/null +++ b/libglusterfs/src/timer.c @@ -0,0 +1,220 @@ +/* + Copyright (c) 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "timer.h" +#include "logging.h" +#include "common-utils.h" + +#define TS(tv) ((((unsigned long long) tv.tv_sec) * 1000000) + (tv.tv_usec)) + +gf_timer_t * +gf_timer_call_after (glusterfs_ctx_t *ctx, + struct timeval delta, + gf_timer_cbk_t cbk, + void *data) +{ + gf_timer_registry_t *reg = NULL; + gf_timer_t *event = NULL; + gf_timer_t *trav = NULL; + unsigned long long at = 0L; + + if (ctx == NULL) + { + gf_log ("timer", GF_LOG_ERROR, "invalid argument"); + return NULL; + } + + reg = gf_timer_registry_init (ctx); + + if (!reg) { + gf_log ("timer", GF_LOG_ERROR, "!reg"); + return NULL; + } + + event = CALLOC (1, sizeof (*event)); + if (!event) { + gf_log ("timer", GF_LOG_CRITICAL, "Not enough memory"); + return NULL; + } + gettimeofday (&event->at, NULL); + event->at.tv_usec = ((event->at.tv_usec + delta.tv_usec) % 1000000); + event->at.tv_sec += ((event->at.tv_usec + delta.tv_usec) / 1000000); + event->at.tv_sec += delta.tv_sec; + at = TS (event->at); + event->cbk = cbk; + event->data = data; + pthread_mutex_lock (®->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 000000000..5152900f3 --- /dev/null +++ b/libglusterfs/src/timer.h @@ -0,0 +1,68 @@ +/* + Copyright (c) 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _TIMER_H +#define _TIMER_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "glusterfs.h" +#include <sys/time.h> +#include <pthread.h> + +typedef void (*gf_timer_cbk_t) (void *); + +struct _gf_timer { + struct _gf_timer *next, *prev; + struct timeval at; + gf_timer_cbk_t cbk; + void *data; +}; + +struct _gf_timer_registry { + pthread_t th; + char fin; + struct _gf_timer stale; + struct _gf_timer active; + pthread_mutex_t lock; +}; + +typedef struct _gf_timer gf_timer_t; +typedef struct _gf_timer_registry gf_timer_registry_t; + +gf_timer_t * +gf_timer_call_after (glusterfs_ctx_t *ctx, + struct timeval delta, + gf_timer_cbk_t cbk, + void *data); + +int32_t +gf_timer_call_cancel (glusterfs_ctx_t *ctx, + gf_timer_t *event); + +void * +gf_timer_proc (void *data); + +gf_timer_registry_t * +gf_timer_registry_init (glusterfs_ctx_t *ctx); + +#endif /* _TIMER_H */ diff --git a/libglusterfs/src/transport.c b/libglusterfs/src/transport.c new file mode 100644 index 000000000..8bd4ff010 --- /dev/null +++ b/libglusterfs/src/transport.c @@ -0,0 +1,339 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#include <dlfcn.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/poll.h> +#include <fnmatch.h> +#include <stdint.h> + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "logging.h" +#include "transport.h" +#include "glusterfs.h" +#include "xlator.h" +#include "list.h" + + +transport_t * +transport_load (dict_t *options, + xlator_t *xl) +{ + struct transport *trans = NULL, *return_trans = NULL; + char *addr_family = NULL; + char *name = NULL; + void *handle = NULL; + char *type = NULL; + char str[] = "ERROR"; + int32_t ret = -1; + int8_t is_tcp = 0, is_unix = 0, is_ibsdp = 0; + volume_opt_list_t *vol_opt = NULL; + + GF_VALIDATE_OR_GOTO("transport", options, fail); + GF_VALIDATE_OR_GOTO("transport", xl, fail); + + trans = CALLOC (1, sizeof (struct transport)); + GF_VALIDATE_OR_GOTO("transport", trans, fail); + + trans->xl = xl; + type = str; + + /* Backward compatibility */ + ret = dict_get_str (options, "transport-type", &type); + if (ret < 0) { + ret = dict_set_str (options, "transport-type", "socket"); + if (ret < 0) + gf_log ("dict", GF_LOG_DEBUG, + "setting transport-type failed"); + ret = dict_get_str (options, "transport.address-family", + &addr_family); + if (ret < 0) { + ret = dict_get_str (options, "address-family", + &addr_family); + } + + if (ret < 0) { + ret = dict_set_str (options, + "transport.address-family", + "inet"); + if (ret < 0) { + gf_log ("dict", GF_LOG_ERROR, + "setting address-family failed"); + } + } + + gf_log ("transport", GF_LOG_WARNING, + "missing 'option transport-type'. defaulting to " + "\"socket\" (%s)", addr_family?addr_family:"inet"); + } else { + { + /* Backword compatibility to handle * /client, + * * /server. + */ + char *tmp = strchr (type, '/'); + if (tmp) + *tmp = '\0'; + } + + is_tcp = strcmp (type, "tcp"); + is_unix = strcmp (type, "unix"); + is_ibsdp = strcmp (type, "ib-sdp"); + if ((is_tcp == 0) || + (is_unix == 0) || + (is_ibsdp == 0)) { + if (is_tcp == 0) + ret = dict_set_str (options, + "transport.address-family", + "inet"); + if (is_unix == 0) + ret = dict_set_str (options, + "transport.address-family", + "unix"); + if (is_ibsdp == 0) + ret = dict_set_str (options, + "transport.address-family", + "inet-sdp"); + + if (ret < 0) + gf_log ("dict", GF_LOG_DEBUG, + "setting address-family failed"); + + ret = dict_set_str (options, + "transport-type", "socket"); + if (ret < 0) + gf_log ("dict", GF_LOG_DEBUG, + "setting transport-type failed"); + } + } + + ret = dict_get_str (options, "transport-type", &type); + if (ret < 0) { + FREE (trans); + gf_log ("transport", GF_LOG_ERROR, + "'option transport-type <xx>' missing in volume '%s'", + xl->name); + goto fail; + } + + asprintf (&name, "%s/%s.so", TRANSPORTDIR, type); + gf_log ("transport", GF_LOG_DEBUG, + "attempt to load file %s", name); + + handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL); + if (handle == NULL) { + gf_log ("transport", GF_LOG_ERROR, "%s", dlerror ()); + gf_log ("transport", GF_LOG_ERROR, + "volume '%s': transport-type '%s' is not valid or " + "not found on this machine", + xl->name, type); + FREE (name); + FREE (trans); + goto fail; + } + FREE (name); + + trans->ops = dlsym (handle, "tops"); + if (trans->ops == NULL) { + gf_log ("transport", GF_LOG_ERROR, + "dlsym (transport_ops) on %s", dlerror ()); + FREE (trans); + goto fail; + } + + trans->init = dlsym (handle, "init"); + if (trans->init == NULL) { + gf_log ("transport", GF_LOG_ERROR, + "dlsym (gf_transport_init) on %s", dlerror ()); + FREE (trans); + goto fail; + } + + trans->fini = dlsym (handle, "fini"); + if (trans->fini == NULL) { + gf_log ("transport", GF_LOG_ERROR, + "dlsym (gf_transport_fini) on %s", dlerror ()); + FREE (trans); + goto fail; + } + + vol_opt = CALLOC (1, sizeof (volume_opt_list_t)); + vol_opt->given_opt = dlsym (handle, "options"); + if (vol_opt->given_opt == NULL) { + gf_log ("transport", GF_LOG_DEBUG, + "volume option validation not specified"); + } else { + list_add_tail (&vol_opt->list, &xl->volume_options); + if (-1 == + validate_xlator_volume_options (xl, + vol_opt->given_opt)) { + gf_log ("transport", GF_LOG_ERROR, + "volume option validation failed"); + FREE (trans); + goto fail; + } + } + + ret = trans->init (trans); + if (ret != 0) { + gf_log ("transport", GF_LOG_ERROR, + "'%s' initialization failed", type); + FREE (trans); + goto fail; + } + + pthread_mutex_init (&trans->lock, NULL); + return_trans = trans; +fail: + return return_trans; +} + + +int32_t +transport_submit (transport_t *this, char *buf, int32_t len, + struct iovec *vector, int count, dict_t *refs) +{ + int32_t ret = -1; + + GF_VALIDATE_OR_GOTO("transport", this, fail); + GF_VALIDATE_OR_GOTO("transport", this->ops, fail); + + ret = this->ops->submit (this, buf, len, vector, count, refs); +fail: + return ret; +} + + +int32_t +transport_connect (transport_t *this) +{ + int ret = -1; + + GF_VALIDATE_OR_GOTO("transport", this, fail); + + ret = this->ops->connect (this); +fail: + return ret; +} + + +int32_t +transport_listen (transport_t *this) +{ + int ret = -1; + + GF_VALIDATE_OR_GOTO("transport", this, fail); + + ret = this->ops->listen (this); +fail: + return ret; +} + + +int32_t +transport_disconnect (transport_t *this) +{ + int32_t ret = -1; + + GF_VALIDATE_OR_GOTO("transport", this, fail); + + ret = this->ops->disconnect (this); +fail: + return ret; +} + + +int32_t +transport_destroy (transport_t *this) +{ + int32_t ret = -1; + + GF_VALIDATE_OR_GOTO("transport", this, fail); + + if (this->fini) + this->fini (this); + + pthread_mutex_destroy (&this->lock); + FREE (this); +fail: + return ret; +} + + +transport_t * +transport_ref (transport_t *this) +{ + transport_t *return_this = NULL; + + GF_VALIDATE_OR_GOTO("transport", this, fail); + + pthread_mutex_lock (&this->lock); + { + this->refcount ++; + } + pthread_mutex_unlock (&this->lock); + + return_this = this; +fail: + return return_this; +} + + +int32_t +transport_receive (transport_t *this, char **hdr_p, size_t *hdrlen_p, + char **buf_p, size_t *buflen_p) +{ + int32_t ret = -1; + + GF_VALIDATE_OR_GOTO("transport", this, fail); + + ret = this->ops->receive (this, hdr_p, hdrlen_p, buf_p, buflen_p); +fail: + return ret; +} + + +int32_t +transport_unref (transport_t *this) +{ + int32_t refcount = 0; + int32_t ret = -1; + + GF_VALIDATE_OR_GOTO("transport", this, fail); + + pthread_mutex_lock (&this->lock); + { + refcount = --this->refcount; + } + pthread_mutex_unlock (&this->lock); + + if (refcount == 0) { + this->xl->notify (this->xl, GF_EVENT_TRANSPORT_CLEANUP, this); + transport_destroy (this); + } + + ret = 0; +fail: + return ret; +} + diff --git a/libglusterfs/src/transport.h b/libglusterfs/src/transport.h new file mode 100644 index 000000000..be5c8b5df --- /dev/null +++ b/libglusterfs/src/transport.h @@ -0,0 +1,85 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef __TRANSPORT_H__ +#define __TRANSPORT_H__ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <inttypes.h> + +struct transport_ops; +typedef struct transport transport_t; + +#include "xlator.h" +#include "dict.h" +#include "compat.h" + +typedef struct peer_info { + struct sockaddr_storage sockaddr; + socklen_t sockaddr_len; + char identifier[UNIX_PATH_MAX]; +}peer_info_t; + +struct transport { + struct transport_ops *ops; + void *private; + void *xl_private; + pthread_mutex_t lock; + int32_t refcount; + + xlator_t *xl; + void *dnscache; + data_t *buf; + int32_t (*init) (transport_t *this); + void (*fini) (transport_t *this); + /* int (*notify) (transport_t *this, int event, void *data); */ + peer_info_t peerinfo; + peer_info_t myinfo; +}; + +struct transport_ops { + int32_t (*receive) (transport_t *this, char **hdr_p, size_t *hdrlen_p, + char **buf_p, size_t *buflen_p); + int32_t (*submit) (transport_t *this, char *buf, int len, + struct iovec *vector, int count, dict_t *refs); + int32_t (*connect) (transport_t *this); + int32_t (*listen) (transport_t *this); + int32_t (*disconnect) (transport_t *this); +}; + + +int32_t transport_listen (transport_t *this); +int32_t transport_connect (transport_t *this); +int32_t transport_disconnect (transport_t *this); +int32_t transport_notify (transport_t *this, int event); +int32_t transport_submit (transport_t *this, char *buf, int len, + struct iovec *vector, int count, dict_t *refs); +int32_t transport_receive (transport_t *this, char **hdr_p, size_t *hdrlen_p, + char **buf_p, size_t *buflen_p); +int32_t transport_destroy (transport_t *this); + +transport_t *transport_load (dict_t *options, xlator_t *xl); +transport_t *transport_ref (transport_t *trans); +int32_t transport_unref (transport_t *trans); + +#endif /* __TRANSPORT_H__ */ diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c new file mode 100644 index 000000000..2b17cc7f6 --- /dev/null +++ b/libglusterfs/src/xlator.c @@ -0,0 +1,728 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "xlator.h" +#include <dlfcn.h> +#include <netdb.h> +#include <fnmatch.h> +#include "defaults.h" + + +#define SET_DEFAULT_FOP(fn) do { \ + if (!xl->fops->fn) \ + xl->fops->fn = default_##fn; \ + } while (0) + +#define SET_DEFAULT_MOP(fn) do { \ + if (!xl->mops->fn) \ + xl->mops->fn = default_##fn; \ + } while (0) + +#define SET_DEFAULT_CBK(fn) do { \ + if (!xl->cbks->fn) \ + xl->cbks->fn = default_##fn; \ + } while (0) + + +static void +fill_defaults (xlator_t *xl) +{ + if (xl == NULL) { + gf_log ("xlator", GF_LOG_ERROR, "invalid argument"); + return; + } + + SET_DEFAULT_FOP (create); + SET_DEFAULT_FOP (open); + SET_DEFAULT_FOP (stat); + SET_DEFAULT_FOP (readlink); + SET_DEFAULT_FOP (mknod); + SET_DEFAULT_FOP (mkdir); + SET_DEFAULT_FOP (unlink); + SET_DEFAULT_FOP (rmdir); + SET_DEFAULT_FOP (symlink); + SET_DEFAULT_FOP (rename); + SET_DEFAULT_FOP (link); + SET_DEFAULT_FOP (chmod); + SET_DEFAULT_FOP (chown); + SET_DEFAULT_FOP (truncate); + SET_DEFAULT_FOP (utimens); + SET_DEFAULT_FOP (readv); + SET_DEFAULT_FOP (writev); + SET_DEFAULT_FOP (statfs); + SET_DEFAULT_FOP (flush); + SET_DEFAULT_FOP (fsync); + SET_DEFAULT_FOP (setxattr); + SET_DEFAULT_FOP (getxattr); + SET_DEFAULT_FOP (removexattr); + SET_DEFAULT_FOP (opendir); + SET_DEFAULT_FOP (readdir); + SET_DEFAULT_FOP (fsyncdir); + SET_DEFAULT_FOP (access); + SET_DEFAULT_FOP (ftruncate); + SET_DEFAULT_FOP (fstat); + SET_DEFAULT_FOP (lk); + SET_DEFAULT_FOP (inodelk); + SET_DEFAULT_FOP (finodelk); + SET_DEFAULT_FOP (entrylk); + SET_DEFAULT_FOP (fentrylk); + SET_DEFAULT_FOP (lookup); + SET_DEFAULT_FOP (fchown); + SET_DEFAULT_FOP (fchmod); + SET_DEFAULT_FOP (setdents); + SET_DEFAULT_FOP (getdents); + SET_DEFAULT_FOP (checksum); + SET_DEFAULT_FOP (xattrop); + SET_DEFAULT_FOP (fxattrop); + + SET_DEFAULT_MOP (stats); + + SET_DEFAULT_CBK (release); + SET_DEFAULT_CBK (releasedir); + SET_DEFAULT_CBK (forget); + + if (!xl->notify) + xl->notify = default_notify; + + return; +} + +int +_volume_option_value_validate (xlator_t *xl, + data_pair_t *pair, + volume_option_t *opt) +{ + int i = 0; + int ret = -1; + uint64_t input_size = 0; + long long inputll = 0; + + /* Key is valid, validate the option */ + switch (opt->type) { + case GF_OPTION_TYPE_PATH: + { + /* Make sure the given path is valid */ + if (pair->value->data[0] != '/') { + gf_log (xl->name, GF_LOG_WARNING, + "option %s %s: '%s' is not an " + "absolute path name", + pair->key, pair->value->data, + pair->value->data); + } + ret = 0; + } + break; + case GF_OPTION_TYPE_INT: + { + /* Check the range */ + if (gf_string2longlong (pair->value->data, + &inputll) != 0) { + gf_log (xl->name, GF_LOG_ERROR, + "invalid number format \"%s\" in " + "\"option %s\"", + pair->value->data, pair->key); + goto out; + } + + if ((opt->min == 0) && (opt->max == 0)) { + gf_log (xl->name, GF_LOG_DEBUG, + "no range check required for " + "'option %s %s'", + pair->key, pair->value->data); + ret = 0; + break; + } + if ((inputll < opt->min) || + (inputll > opt->max)) { + gf_log (xl->name, GF_LOG_WARNING, + "'%lld' in 'option %s %s' is out of " + "range [%"PRId64" - %"PRId64"]", + inputll, pair->key, + pair->value->data, + opt->min, opt->max); + } + ret = 0; + } + break; + case GF_OPTION_TYPE_SIZET: + { + /* Check the range */ + if (gf_string2bytesize (pair->value->data, + &input_size) != 0) { + gf_log (xl->name, GF_LOG_ERROR, + "invalid size format \"%s\" in " + "\"option %s\"", + pair->value->data, pair->key); + goto out; + } + + if ((opt->min == 0) && (opt->max == 0)) { + gf_log (xl->name, GF_LOG_DEBUG, + "no range check required for " + "'option %s %s'", + pair->key, pair->value->data); + ret = 0; + break; + } + if ((input_size < opt->min) || + (input_size > opt->max)) { + gf_log (xl->name, GF_LOG_ERROR, + "'%"PRId64"' in 'option %s %s' is " + "out of range [%"PRId64" - %"PRId64"]", + input_size, pair->key, + pair->value->data, + opt->min, opt->max); + } + ret = 0; + } + break; + case GF_OPTION_TYPE_BOOL: + { + /* Check if the value is one of + '0|1|on|off|no|yes|true|false|enable|disable' */ + gf_boolean_t bool_value; + if (gf_string2boolean (pair->value->data, + &bool_value) != 0) { + gf_log (xl->name, GF_LOG_ERROR, + "option %s %s: '%s' is not a valid " + "boolean value", + pair->key, pair->value->data, + pair->value->data); + goto out; + } + ret = 0; + } + break; + case GF_OPTION_TYPE_XLATOR: + { + /* Check if the value is one of the xlators */ + xlator_t *xlopt = xl; + while (xlopt->prev) + xlopt = xlopt->prev; + + while (xlopt) { + if (strcmp (pair->value->data, + xlopt->name) == 0) { + ret = 0; + break; + } + xlopt = xlopt->next; + } + if (!xlopt) { + gf_log (xl->name, GF_LOG_ERROR, + "option %s %s: '%s' is not a " + "valid volume name", + pair->key, pair->value->data, + pair->value->data); + } + ret = 0; + } + break; + case GF_OPTION_TYPE_STR: + { + /* Check if the '*str' is valid */ + if (!opt->value) { + ret = 0; + goto out; + } + + for (i = 0; (i < ZR_OPTION_MAX_ARRAY_SIZE) && + opt->value[i]; i++) { + if (strcasecmp (opt->value[i], + pair->value->data) == 0) { + ret = 0; + break; + } + } + + if ((i == ZR_OPTION_MAX_ARRAY_SIZE) + || ((i < ZR_OPTION_MAX_ARRAY_SIZE) + && (!opt->value[i]))) { + /* enter here only if + * 1. reached end of opt->value array and haven't validated input + * OR + * 2. valid input list is less than ZR_OPTION_MAX_ARRAY_SIZE and + * input has not matched all possible input values. + */ + char given_array[4096] = {0,}; + for (i = 0; (i < ZR_OPTION_MAX_ARRAY_SIZE) && + opt->value[i]; i++) { + strcat (given_array, opt->value[i]); + strcat (given_array, ", "); + } + + gf_log (xl->name, GF_LOG_ERROR, + "option %s %s: '%s' is not valid " + "(possible options are %s)", + pair->key, pair->value->data, + pair->value->data, given_array); + + goto out; + } + } + break; + case GF_OPTION_TYPE_PERCENT: + { + uint32_t percent = 0; + + /* Check if the value is valid percentage */ + if (gf_string2percent (pair->value->data, + &percent) != 0) { + gf_log (xl->name, GF_LOG_ERROR, + "invalid percent format \"%s\" " + "in \"option %s\"", + pair->value->data, pair->key); + goto out; + } + + if ((percent < 0) || (percent > 100)) { + gf_log (xl->name, GF_LOG_ERROR, + "'%d' in 'option %s %s' is out of " + "range [0 - 100]", + percent, pair->key, + pair->value->data); + } + ret = 0; + } + break; + case GF_OPTION_TYPE_TIME: + { + uint32_t input_time = 0; + + /* Check if the value is valid percentage */ + if (gf_string2time (pair->value->data, + &input_time) != 0) { + gf_log (xl->name, + GF_LOG_ERROR, + "invalid time format \"%s\" in " + "\"option %s\"", + pair->value->data, pair->key); + goto out; + } + + if ((opt->min == 0) && (opt->max == 0)) { + gf_log (xl->name, GF_LOG_DEBUG, + "no range check required for " + "'option %s %s'", + pair->key, pair->value->data); + ret = 0; + goto out; + } + if ((input_time < opt->min) || + (input_time > opt->max)) { + gf_log (xl->name, GF_LOG_ERROR, + "'%"PRIu32"' in 'option %s %s' is " + "out of range [%"PRId64" - %"PRId64"]", + input_time, pair->key, + pair->value->data, + opt->min, opt->max); + } + ret = 0; + } + break; + case GF_OPTION_TYPE_ANY: + /* NO CHECK */ + ret = 0; + break; + } + + out: + return ret; +} + +int +validate_xlator_volume_options (xlator_t *xl, volume_option_t *opt) +{ + int i = 0; + int ret = -1; + int index = 0; + volume_option_t *trav = NULL; + data_pair_t *pairs = NULL; + + if (!opt) { + ret = 0; + goto out; + } + + /* First search for not supported options, if any report error */ + pairs = xl->options->members_list; + while (pairs) { + ret = -1; + for (index = 0; + opt[index].key && opt[index].key[0] ; index++) { + trav = &(opt[index]); + for (i = 0 ; + (i < ZR_VOLUME_MAX_NUM_KEY) && + trav->key[i]; i++) { + /* Check if the key is valid */ + if (fnmatch (trav->key[i], + pairs->key, FNM_NOESCAPE) == 0) { + ret = 0; + break; + } + } + if (!ret) { + if (i) { + gf_log (xl->name, GF_LOG_WARNING, + "option '%s' is deprecated, " + "preferred is '%s', continuing" + " with correction", + trav->key[i], trav->key[0]); + /* TODO: some bytes lost */ + pairs->key = strdup (trav->key[0]); + } + break; + } + } + if (!ret) { + ret = _volume_option_value_validate (xl, pairs, trav); + if (-1 == ret) { + goto out; + } + } + + pairs = pairs->next; + } + + ret = 0; + out: + return ret; +} + +int32_t +xlator_set_type (xlator_t *xl, + const char *type) +{ + char *name = NULL; + void *handle = NULL; + volume_opt_list_t *vol_opt = NULL; + + if (xl == NULL || type == NULL) { + gf_log ("xlator", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + xl->type = strdup (type); + + asprintf (&name, "%s/%s.so", XLATORDIR, type); + + gf_log ("xlator", GF_LOG_DEBUG, "attempt to load file %s", name); + + handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL); + if (!handle) { + gf_log ("xlator", GF_LOG_ERROR, "%s", dlerror ()); + return -1; + } + + if (!(xl->fops = dlsym (handle, "fops"))) { + gf_log ("xlator", GF_LOG_ERROR, "dlsym(fops) on %s", + dlerror ()); + return -1; + } + + if (!(xl->mops = dlsym (handle, "mops"))) { + gf_log ("xlator", GF_LOG_ERROR, "dlsym(mops) on %s", + dlerror ()); + return -1; + } + + if (!(xl->cbks = dlsym (handle, "cbks"))) { + gf_log ("xlator", GF_LOG_ERROR, "dlsym(cbks) on %s", + dlerror ()); + return -1; + } + + if (!(xl->init = dlsym (handle, "init"))) { + gf_log ("xlator", GF_LOG_ERROR, "dlsym(init) on %s", + dlerror ()); + return -1; + } + + if (!(xl->fini = dlsym (handle, "fini"))) { + gf_log ("xlator", GF_LOG_ERROR, "dlsym(fini) on %s", + dlerror ()); + return -1; + } + + if (!(xl->notify = dlsym (handle, "notify"))) { + gf_log ("xlator", GF_LOG_DEBUG, + "dlsym(notify) on %s -- neglecting", dlerror ()); + } + + INIT_LIST_HEAD (&xl->volume_options); + + vol_opt = CALLOC (1, sizeof (volume_opt_list_t)); + + if (!(vol_opt->given_opt = dlsym (handle, "options"))) { + dlerror (); + gf_log (xl->name, GF_LOG_DEBUG, + "strict option validation not enforced -- neglecting"); + } + list_add_tail (&vol_opt->list, &xl->volume_options); + + fill_defaults (xl); + + FREE (name); + return 0; +} + + +void +xlator_foreach (xlator_t *this, + void (*fn)(xlator_t *each, + void *data), + void *data) +{ + xlator_t *first = NULL; + + if (this == NULL || fn == NULL || data == NULL) { + gf_log ("xlator", GF_LOG_ERROR, "invalid argument"); + return; + } + + first = this; + + while (first->prev) + first = first->prev; + + while (first) { + fn (first, data); + first = first->next; + } +} + + +xlator_t * +xlator_search_by_name (xlator_t *any, const char *name) +{ + xlator_t *search = NULL; + + if (any == NULL || name == NULL) { + gf_log ("xlator", GF_LOG_ERROR, "invalid argument"); + return NULL; + } + + search = any; + + while (search->prev) + search = search->prev; + + while (search) { + if (!strcmp (search->name, name)) + break; + search = search->next; + } + + return search; +} + + +static int32_t +xlator_init_rec (xlator_t *xl) +{ + xlator_list_t *trav = NULL; + int32_t ret = 0; + + if (xl == NULL) { + gf_log ("xlator", GF_LOG_ERROR, "invalid argument"); + return 0; + } + + trav = xl->children; + + while (trav) { + ret = 0; + ret = xlator_init_rec (trav->xlator); + if (ret != 0) + break; + gf_log (trav->xlator->name, GF_LOG_DEBUG, + "Initialization done"); + trav = trav->next; + } + + if (!ret && !xl->ready) { + ret = -1; + if (xl->init) { + ret = xl->init (xl); + if (ret) { + gf_log ("xlator", GF_LOG_ERROR, + "initialization of volume '%s' failed," + " review your volfile again", + xl->name); + } else { + xl->init_succeeded = 1; + } + } else { + gf_log (xl->name, GF_LOG_ERROR, "No init() found"); + } + /* This 'xl' is checked */ + xl->ready = 1; + } + + return ret; +} + + +int32_t +xlator_tree_init (xlator_t *xl) +{ + xlator_t *top = NULL; + int32_t ret = 0; + + if (xl == NULL) { + gf_log ("xlator", GF_LOG_ERROR, "invalid argument"); + return 0; + } + + top = xl; +/* + while (top->parents) + top = top->parents->xlator; +*/ + ret = xlator_init_rec (top); + + if (ret == 0 && top->notify) { + top->notify (top, GF_EVENT_PARENT_UP, NULL); + } + + return ret; +} + + +static void +xlator_fini_rec (xlator_t *xl) +{ + xlator_list_t *trav = NULL; + + if (xl == NULL) { + gf_log ("xlator", GF_LOG_ERROR, "invalid argument"); + return; + } + + trav = xl->children; + + while (trav) { + if (!trav->xlator->init_succeeded) { + break; + } + + xlator_fini_rec (trav->xlator); + gf_log (trav->xlator->name, GF_LOG_DEBUG, "fini done"); + trav = trav->next; + } + + if (xl->init_succeeded) { + if (xl->fini) { + xl->fini (xl); + } else { + gf_log (xl->name, GF_LOG_ERROR, "No fini() found"); + } + xl->init_succeeded = 0; + } +} + + +void +xlator_tree_fini (xlator_t *xl) +{ + xlator_t *top = NULL; + + if (xl == NULL) { + gf_log ("xlator", GF_LOG_ERROR, "invalid argument"); + return; + } + + top = xl; + xlator_fini_rec (top); +} + + +int +xlator_tree_free (xlator_t *tree) +{ + xlator_t *trav = tree, *prev = tree; + + if (!tree) { + gf_log ("parser", GF_LOG_ERROR, "Translator tree not found"); + return -1; + } + + while (prev) { + trav = prev->next; + dict_destroy (prev->options); + FREE (prev->name); + FREE (prev->type); + FREE (prev); + prev = trav; + } + + return 0; +} + + +void +loc_wipe (loc_t *loc) +{ + if (loc->inode) { + inode_unref (loc->inode); + loc->inode = NULL; + } + if (loc->path) { + FREE (loc->path); + loc->path = NULL; + } + + if (loc->parent) { + inode_unref (loc->parent); + loc->parent = NULL; + } +} + + +int +loc_copy (loc_t *dst, loc_t *src) +{ + int ret = -1; + + dst->ino = src->ino; + + if (src->inode) + dst->inode = inode_ref (src->inode); + + if (src->parent) + dst->parent = inode_ref (src->parent); + + dst->path = strdup (src->path); + + if (!dst->path) + goto out; + + dst->name = strrchr (dst->path, '/'); + if (dst->name) + dst->name++; + + ret = 0; +out: + return ret; +} diff --git a/libglusterfs/src/xlator.h b/libglusterfs/src/xlator.h new file mode 100644 index 000000000..eadc9fd1a --- /dev/null +++ b/libglusterfs/src/xlator.h @@ -0,0 +1,842 @@ +/* + Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> + This file is part of GlusterFS. + + GlusterFS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + GlusterFS is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see + <http://www.gnu.org/licenses/>. +*/ + +#ifndef _XLATOR_H +#define _XLATOR_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdint.h> +#include <inttypes.h> + + +#include "glusterfs.h" +#include "logging.h" +#include "common-utils.h" +#include "dict.h" +#include "compat.h" +#include "list.h" + +#define FIRST_CHILD(xl) (xl->children->xlator) + +struct _xlator; +typedef struct _xlator xlator_t; +struct _dir_entry_t; +typedef struct _dir_entry_t dir_entry_t; +struct _gf_dirent_t; +typedef struct _gf_dirent_t gf_dirent_t; +struct _loc; +typedef struct _loc loc_t; + + +typedef int32_t (*event_notify_fn_t) (xlator_t *this, + int32_t event, + void *data, + ...); + +#include "list.h" +#include "gf-dirent.h" +#include "stack.h" +#include "inode.h" +#include "fd.h" + +struct _loc { + const char *path; + const char *name; + ino_t ino; + inode_t *inode; + inode_t *parent; +}; + + +struct xlator_stats { + uint64_t nr_files; /* Number of files open via this xlator */ + uint64_t free_disk; /* Mega bytes */ + uint64_t total_disk_size; /* Mega Bytes */ + uint64_t disk_usage; /* Mega bytes */ + uint64_t disk_speed; /* MHz or Mbps */ + uint64_t nr_clients; /* Number of client nodes */ + uint64_t write_usage; + uint64_t read_usage; /* add more stats here */ +}; + + + +typedef int32_t (*mop_stats_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct xlator_stats *stats); + +typedef int32_t (*mop_getspec_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + char *spec_data); + +typedef int32_t (*fop_checksum_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + uint8_t *file_checksum, + uint8_t *dir_checksum); + +typedef int32_t (*mop_setvolume_t) (call_frame_t *frame, + xlator_t *this, + const char *volume); + +typedef int32_t (*mop_stats_t) (call_frame_t *frame, + xlator_t *this, + int32_t flags); + +typedef int32_t (*mop_getspec_t) (call_frame_t *frame, + xlator_t *this, + const char *key, + int32_t flag); + +typedef int32_t (*fop_checksum_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + int32_t flag); + +struct xlator_mops { + mop_stats_t stats; + mop_getspec_t getspec; + + mop_stats_cbk_t stats_cbk; + mop_getspec_cbk_t getspec_cbk; +}; + + +typedef int32_t (*fop_lookup_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf, + dict_t *xattr); + +typedef int32_t (*fop_stat_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); + +typedef int32_t (*fop_fstat_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); + +typedef int32_t (*fop_chmod_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); + +typedef int32_t (*fop_fchmod_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); + +typedef int32_t (*fop_chown_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); + +typedef int32_t (*fop_fchown_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); + +typedef int32_t (*fop_truncate_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); + +typedef int32_t (*fop_ftruncate_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); + +typedef int32_t (*fop_utimens_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); + +typedef int32_t (*fop_access_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno); + +typedef int32_t (*fop_readlink_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + const char *path); + +typedef int32_t (*fop_mknod_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf); + +typedef int32_t (*fop_mkdir_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf); + +typedef int32_t (*fop_unlink_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno); + +typedef int32_t (*fop_rmdir_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno); + +typedef int32_t (*fop_symlink_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf); + +typedef int32_t (*fop_rename_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *buf); + +typedef int32_t (*fop_link_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct stat *buf); + +typedef int32_t (*fop_create_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + fd_t *fd, + inode_t *inode, + struct stat *buf); + +typedef int32_t (*fop_open_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + fd_t *fd); + +typedef int32_t (*fop_readv_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct iovec *vector, + int32_t count, + struct stat *stbuf); + +typedef int32_t (*fop_writev_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct stat *stbuf); + +typedef int32_t (*fop_flush_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno); + +typedef int32_t (*fop_fsync_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno); + +typedef int32_t (*fop_opendir_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + fd_t *fd); + +typedef int32_t (*fop_getdents_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + dir_entry_t *entries, + int32_t count); + +typedef int32_t (*fop_fsyncdir_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno); + +typedef int32_t (*fop_statfs_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct statvfs *buf); + +typedef int32_t (*fop_setxattr_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno); + +typedef int32_t (*fop_getxattr_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + dict_t *dict); + +typedef int32_t (*fop_removexattr_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno); + +typedef int32_t (*fop_lk_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct flock *flock); + +typedef int32_t (*fop_inodelk_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno); + +typedef int32_t (*fop_finodelk_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno); + +typedef int32_t (*fop_entrylk_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno); + +typedef int32_t (*fop_fentrylk_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno); + +typedef int32_t (*fop_setdents_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno); + +typedef int32_t (*fop_readdir_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + gf_dirent_t *entries); + +typedef int32_t (*fop_xattrop_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + dict_t *xattr); + +typedef int32_t (*fop_fxattrop_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + dict_t *xattr); + +typedef int32_t (*fop_lookup_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + dict_t *xattr_req); + +typedef int32_t (*fop_stat_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc); + +typedef int32_t (*fop_fstat_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd); + +typedef int32_t (*fop_chmod_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + mode_t mode); + +typedef int32_t (*fop_fchmod_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + mode_t mode); + +typedef int32_t (*fop_chown_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + uid_t uid, + gid_t gid); + +typedef int32_t (*fop_fchown_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + uid_t uid, + gid_t gid); + +typedef int32_t (*fop_truncate_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + off_t offset); + +typedef int32_t (*fop_ftruncate_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + off_t offset); + +typedef int32_t (*fop_utimens_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + struct timespec tv[2]); + +typedef int32_t (*fop_access_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + int32_t mask); + +typedef int32_t (*fop_readlink_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + size_t size); + +typedef int32_t (*fop_mknod_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + mode_t mode, + dev_t rdev); + +typedef int32_t (*fop_mkdir_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + mode_t mode); + +typedef int32_t (*fop_unlink_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc); + +typedef int32_t (*fop_rmdir_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc); + +typedef int32_t (*fop_symlink_t) (call_frame_t *frame, + xlator_t *this, + const char *linkname, + loc_t *loc); + +typedef int32_t (*fop_rename_t) (call_frame_t *frame, + xlator_t *this, + loc_t *oldloc, + loc_t *newloc); + +typedef int32_t (*fop_link_t) (call_frame_t *frame, + xlator_t *this, + loc_t *oldloc, + loc_t *newloc); + +typedef int32_t (*fop_create_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + int32_t flags, + mode_t mode, + fd_t *fd); + +typedef int32_t (*fop_open_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + int32_t flags, + fd_t *fd); + +typedef int32_t (*fop_readv_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + size_t size, + off_t offset); + +typedef int32_t (*fop_writev_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + struct iovec *vector, + int32_t count, + off_t offset); + +typedef int32_t (*fop_flush_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd); + +typedef int32_t (*fop_fsync_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t datasync); + +typedef int32_t (*fop_opendir_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + fd_t *fd); + +typedef int32_t (*fop_getdents_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + size_t size, + off_t offset, + int32_t flag); + +typedef int32_t (*fop_fsyncdir_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t datasync); + +typedef int32_t (*fop_statfs_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc); + +typedef int32_t (*fop_setxattr_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + dict_t *dict, + int32_t flags); + +typedef int32_t (*fop_getxattr_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + const char *name); + +typedef int32_t (*fop_removexattr_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + const char *name); + +typedef int32_t (*fop_lk_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t cmd, + struct flock *flock); + +typedef int32_t (*fop_inodelk_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + int32_t cmd, + struct flock *flock); + +typedef int32_t (*fop_finodelk_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t cmd, + struct flock *flock); + +typedef int32_t (*fop_entrylk_t) (call_frame_t *frame, + xlator_t *this, loc_t *loc, + const char *basename, entrylk_cmd cmd, + entrylk_type type); + +typedef int32_t (*fop_fentrylk_t) (call_frame_t *frame, + xlator_t *this, fd_t *fd, + const char *basename, entrylk_cmd cmd, + entrylk_type type); + +typedef int32_t (*fop_setdents_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t flags, + dir_entry_t *entries, + int32_t count); + +typedef int32_t (*fop_readdir_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + size_t size, + off_t offset); + +typedef int32_t (*fop_xattrop_t) (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + gf_xattrop_flags_t optype, + dict_t *xattr); + +typedef int32_t (*fop_fxattrop_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + gf_xattrop_flags_t optype, + dict_t *xattr); + +struct xlator_fops { + fop_lookup_t lookup; + fop_stat_t stat; + fop_fstat_t fstat; + fop_chmod_t chmod; + fop_fchmod_t fchmod; + fop_chown_t chown; + fop_fchown_t fchown; + fop_truncate_t truncate; + fop_ftruncate_t ftruncate; + fop_utimens_t utimens; + fop_access_t access; + fop_readlink_t readlink; + fop_mknod_t mknod; + fop_mkdir_t mkdir; + fop_unlink_t unlink; + fop_rmdir_t rmdir; + fop_symlink_t symlink; + fop_rename_t rename; + fop_link_t link; + fop_create_t create; + fop_open_t open; + fop_readv_t readv; + fop_writev_t writev; + fop_flush_t flush; + fop_fsync_t fsync; + fop_opendir_t opendir; + fop_readdir_t readdir; + fop_fsyncdir_t fsyncdir; + fop_statfs_t statfs; + fop_setxattr_t setxattr; + fop_getxattr_t getxattr; + fop_removexattr_t removexattr; + fop_lk_t lk; + fop_inodelk_t inodelk; + fop_finodelk_t finodelk; + fop_entrylk_t entrylk; + fop_fentrylk_t fentrylk; + fop_setdents_t setdents; + fop_getdents_t getdents; + fop_checksum_t checksum; + fop_xattrop_t xattrop; + fop_fxattrop_t fxattrop; + + /* these entries are used for a typechecking hack in STACK_WIND _only_ */ + fop_lookup_cbk_t lookup_cbk; + fop_stat_cbk_t stat_cbk; + fop_fstat_cbk_t fstat_cbk; + fop_chmod_cbk_t chmod_cbk; + fop_fchmod_cbk_t fchmod_cbk; + fop_chown_cbk_t chown_cbk; + fop_fchown_cbk_t fchown_cbk; + fop_truncate_cbk_t truncate_cbk; + fop_ftruncate_cbk_t ftruncate_cbk; + fop_utimens_cbk_t utimens_cbk; + fop_access_cbk_t access_cbk; + fop_readlink_cbk_t readlink_cbk; + fop_mknod_cbk_t mknod_cbk; + fop_mkdir_cbk_t mkdir_cbk; + fop_unlink_cbk_t unlink_cbk; + fop_rmdir_cbk_t rmdir_cbk; + fop_symlink_cbk_t symlink_cbk; + fop_rename_cbk_t rename_cbk; + fop_link_cbk_t link_cbk; + fop_create_cbk_t create_cbk; + fop_open_cbk_t open_cbk; + fop_readv_cbk_t readv_cbk; + fop_writev_cbk_t writev_cbk; + fop_flush_cbk_t flush_cbk; + fop_fsync_cbk_t fsync_cbk; + fop_opendir_cbk_t opendir_cbk; + fop_readdir_cbk_t readdir_cbk; + fop_fsyncdir_cbk_t fsyncdir_cbk; + fop_statfs_cbk_t statfs_cbk; + fop_setxattr_cbk_t setxattr_cbk; + fop_getxattr_cbk_t getxattr_cbk; + fop_removexattr_cbk_t removexattr_cbk; + fop_lk_cbk_t lk_cbk; + fop_inodelk_cbk_t inodelk_cbk; + fop_finodelk_cbk_t finodelk_cbk; + fop_entrylk_cbk_t entrylk_cbk; + fop_fentrylk_cbk_t fentrylk_cbk; + fop_setdents_cbk_t setdents_cbk; + fop_getdents_cbk_t getdents_cbk; + fop_checksum_cbk_t checksum_cbk; + fop_xattrop_cbk_t xattrop_cbk; + fop_fxattrop_cbk_t fxattrop_cbk; +}; + +typedef int32_t (*cbk_forget_t) (xlator_t *this, + inode_t *inode); + +typedef int32_t (*cbk_release_t) (xlator_t *this, + fd_t *fd); + +struct xlator_cbks { + cbk_forget_t forget; + cbk_release_t release; + cbk_release_t releasedir; +}; + +typedef struct xlator_list { + xlator_t *xlator; + struct xlator_list *next; +} xlator_list_t; + +/* Add possible new type of option you may need */ +typedef enum { + GF_OPTION_TYPE_ANY = 0, + GF_OPTION_TYPE_STR, + GF_OPTION_TYPE_INT, + GF_OPTION_TYPE_SIZET, + GF_OPTION_TYPE_PERCENT, + GF_OPTION_TYPE_BOOL, + GF_OPTION_TYPE_XLATOR, + GF_OPTION_TYPE_PATH, + GF_OPTION_TYPE_TIME, +} volume_option_type_t; + +#define ZR_VOLUME_MAX_NUM_KEY 4 +#define ZR_OPTION_MAX_ARRAY_SIZE 64 + +/* Each translator should define this structure */ +typedef struct volume_options { + char *key[ZR_VOLUME_MAX_NUM_KEY]; + /* different key, same meaning */ + volume_option_type_t type; + int64_t min; /* -1 means no range */ + int64_t max; /* -1 means no range */ + char *value[ZR_OPTION_MAX_ARRAY_SIZE]; + /* If specified, will check for one of + the value from this array */ + char *description; /* about the key */ +} volume_option_t; + +typedef struct vol_opt_list { + struct list_head list; + volume_option_t *given_opt; +} volume_opt_list_t; + +struct _xlator { + /* Built during parsing */ + char *name; + char *type; + xlator_t *next; + xlator_t *prev; + xlator_list_t *parents; + xlator_list_t *children; + dict_t *options; + + /* Set after doing dlopen() */ + struct xlator_fops *fops; + struct xlator_mops *mops; + struct xlator_cbks *cbks; + struct list_head volume_options; /* list of volume_option_t */ + + void (*fini) (xlator_t *this); + int32_t (*init) (xlator_t *this); + event_notify_fn_t notify; + + /* Misc */ + glusterfs_ctx_t *ctx; + inode_table_t *itable; + char ready; + char trace; + char init_succeeded; + void *private; +}; + +int validate_xlator_volume_options (xlator_t *xl, volume_option_t *opt); + +int32_t xlator_set_type (xlator_t *xl, const char *type); + +xlator_t *file_to_xlator_tree (glusterfs_ctx_t *ctx, + FILE *fp); + + +int32_t xlator_tree_init (xlator_t *xl); +int32_t xlator_tree_free (xlator_t *xl); + +void xlator_tree_fini (xlator_t *xl); + +void xlator_foreach (xlator_t *this, + void (*fn) (xlator_t *each, + void *data), + void *data); + +xlator_t *xlator_search_by_name (xlator_t *any, const char *name); + +void inode_destroy_notify (inode_t *inode, const char *xlname); + +int loc_copy (loc_t *dst, loc_t *src); +#define loc_dup(src, dst) loc_copy(dst, src) +void loc_wipe (loc_t *loc); + +#define GF_STAT_PRINT_FMT_STR "%"PRIx64",%"PRIx64",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx64",%"PRIx64",%"PRIx32",%"PRIx64",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32",%"PRIx32"\n" + +#define GF_STAT_SCAN_FMT_STR "%"SCNx64",%"SCNx64",%"SCNx32",%"SCNx32",%"SCNx32",%"SCNx32",%"SCNx64",%"SCNx64",%"SCNx32",%"SCNx64",%"SCNx32",%"SCNx32",%"SCNx32",%"SCNx32",%"SCNx32",%"SCNx32"\n" + +#define GF_STATFS_PRINT_FMT_STR "%"PRIx32",%"PRIx32",%"PRIx64",%"PRIx64",%"PRIx64",%"PRIx64",%"PRIx64",%"PRIx64",%"PRIx32",%"PRIx32",%"PRIx32"\n" + +#define GF_STATFS_SCAN_FMT_STR "%"SCNx32",%"SCNx32",%"SCNx64",%"SCNx64",%"SCNx64",%"SCNx64",%"SCNx64",%"SCNx64",%"SCNx32",%"SCNx32",%"SCNx32"\n" + +#endif /* _XLATOR_H */ + |