diff options
Diffstat (limited to 'libglusterfs/src')
99 files changed, 31229 insertions, 18975 deletions
diff --git a/libglusterfs/src/Makefile.am b/libglusterfs/src/Makefile.am index 05d124aee..907399ae6 100644 --- a/libglusterfs/src/Makefile.am +++ b/libglusterfs/src/Makefile.am @@ -1,21 +1,56 @@ -libglusterfs_la_CFLAGS = -fPIC -Wall -g -shared -nostartfiles $(GF_CFLAGS) $(GF_DARWIN_LIBGLUSTERFS_CFLAGS) +libglusterfs_la_CFLAGS = -Wall $(GF_CFLAGS) \ + $(GF_DARWIN_LIBGLUSTERFS_CFLAGS) \ + -DDATADIR=\"$(localstatedir)\" -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_CPPFLAGS = $(GF_CPPFLAGS) -D__USE_FILE_OFFSET64 \ + -DXLATORDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator\" \ + -I$(top_srcdir)/rpc/rpc-lib/src/ -I$(CONTRIBDIR)/rbtree 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 syscall.c iobuf.c globals.c statedump.c stack.c checksum.c md5.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 syscall.h iobuf.h globals.h statedump.h checksum.h md5.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 +CONTRIB_BUILDDIR = $(top_builddir)/contrib + +libglusterfs_la_SOURCES = dict.c xlator.c logging.c \ + hashfn.c defaults.c common-utils.c timer.c inode.c call-stub.c \ + compat.c fd.c compat-errno.c event.c mem-pool.c gf-dirent.c syscall.c \ + iobuf.c globals.c statedump.c stack.c checksum.c daemon.c timespec.c \ + $(CONTRIBDIR)/rbtree/rb.c rbthash.c store.c latency.c \ + graph.c $(CONTRIBDIR)/uuid/clear.c $(CONTRIBDIR)/uuid/copy.c \ + $(CONTRIBDIR)/uuid/gen_uuid.c $(CONTRIBDIR)/uuid/pack.c \ + $(CONTRIBDIR)/uuid/parse.c $(CONTRIBDIR)/uuid/unparse.c \ + $(CONTRIBDIR)/uuid/uuid_time.c $(CONTRIBDIR)/uuid/compare.c \ + $(CONTRIBDIR)/uuid/isnull.c $(CONTRIBDIR)/uuid/unpack.c syncop.c \ + graph-print.c trie.c run.c options.c fd-lk.c circ-buff.c \ + event-history.c gidcache.c ctx.c client_t.c event-poll.c event-epoll.c \ + $(CONTRIBDIR)/libgen/basename_r.c $(CONTRIBDIR)/libgen/dirname_r.c \ + $(CONTRIBDIR)/stdlib/gf_mkostemp.c + + +nodist_libglusterfs_la_SOURCES = y.tab.c graph.lex.c gf-error-codes.h + +BUILT_SOURCES = graph.lex.c + +noinst_HEADERS = common-utils.h defaults.h dict.h glusterfs.h hashfn.h timespec.h \ + logging.h xlator.h stack.h timer.h list.h inode.h call-stub.h compat.h \ + fd.h revision.h compat-errno.h event.h mem-pool.h byte-order.h \ + gf-dirent.h locking.h syscall.h iobuf.h globals.h statedump.h \ + checksum.h daemon.h $(CONTRIBDIR)/rbtree/rb.h store.h\ + rbthash.h iatt.h latency.h mem-types.h $(CONTRIBDIR)/uuid/uuidd.h \ + $(CONTRIBDIR)/uuid/uuid.h $(CONTRIBDIR)/uuid/uuidP.h \ + $(CONTRIB_BUILDDIR)/uuid/uuid_types.h syncop.h graph-utils.h trie.h \ + run.h options.h lkowner.h fd-lk.h circ-buff.h event-history.h \ + gidcache.h client_t.h glusterfs-acl.h + +EXTRA_DIST = graph.l graph.y + +graph.lex.c: graph.l y.tab.h + $(LEX) -Pgraphyy -t $(srcdir)/graph.l > $@ + +y.tab.c: y.tab.h +y.tab.h: graph.y + $(YACC) -p graphyy -d $(srcdir)/graph.y + +CLEANFILES = graph.lex.c y.tab.c y.tab.h +CONFIG_CLEAN_FILES = $(CONTRIB_BUILDDIR)/uuid/uuid_types.h diff --git a/libglusterfs/src/authenticate.c b/libglusterfs/src/authenticate.c deleted file mode 100644 index 24c840b5e..000000000 --- a/libglusterfs/src/authenticate.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - Copyright (c) 2007-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 _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; - int ret = 0; - - /* 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"; - } - - ret = asprintf (&auth_file, "%s/%s.so", LIBDIR, key); - if (-1 == ret) { - gf_log ("authenticate", GF_LOG_ERROR, "asprintf failed"); - dict_set (this, key, data_from_dynptr (NULL, 0)); - *error = -1; - return; - } - - 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 deleted file mode 100644 index 253989b51..000000000 --- a/libglusterfs/src/authenticate.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copyright (c) 2007-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 _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 index cf93a6738..4101db2c7 100644 --- a/libglusterfs/src/byte-order.h +++ b/libglusterfs/src/byte-order.h @@ -1,20 +1,11 @@ /* - Copyright (c) 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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _BYTE_ORDER_H @@ -38,6 +29,23 @@ static uint64_t (*hton64) (uint64_t); #define ntoh32 hton32 #define ntoh64 hton64 +static uint16_t (*htole16) (uint16_t); +static uint32_t (*htole32) (uint32_t); +static uint64_t (*htole64) (uint64_t); + +#define letoh16 htole16 +#define letoh32 htole32 +#define letoh64 htole64 + +static uint16_t (*htobe16) (uint16_t); +static uint32_t (*htobe32) (uint32_t); +static uint64_t (*htobe64) (uint64_t); + +#define betoh16 htobe16 +#define betoh32 htobe32 +#define betoh64 htobe64 + + #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))) @@ -86,15 +94,17 @@ __noswap64 (uint64_t x) static inline uint16_t -__byte_order_init16 (uint16_t i) +__byte_order_n16 (uint16_t i) { uint32_t num = 1; if (((char *)(&num))[0] == 1) { + /* cpu is le */ hton16 = __swap16; hton32 = __swap32; hton64 = __swap64; } else { + /* cpu is be */ hton16 = __noswap16; hton32 = __noswap32; hton64 = __noswap64; @@ -105,15 +115,17 @@ __byte_order_init16 (uint16_t i) static inline uint32_t -__byte_order_init32 (uint32_t i) +__byte_order_n32 (uint32_t i) { uint32_t num = 1; if (((char *)(&num))[0] == 1) { + /* cpu is le */ hton16 = __swap16; hton32 = __swap32; hton64 = __swap64; } else { + /* cpu is be */ hton16 = __noswap16; hton32 = __noswap32; hton64 = __noswap64; @@ -124,15 +136,17 @@ __byte_order_init32 (uint32_t i) static inline uint64_t -__byte_order_init64 (uint64_t i) +__byte_order_n64 (uint64_t i) { uint32_t num = 1; if (((char *)(&num))[0] == 1) { + /* cpu is le */ hton16 = __swap16; hton32 = __swap32; hton64 = __swap64; } else { + /* cpu is be */ hton16 = __noswap16; hton32 = __noswap32; hton64 = __noswap64; @@ -142,9 +156,146 @@ __byte_order_init64 (uint64_t 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; +static uint16_t (*hton16) (uint16_t) = __byte_order_n16; +static uint32_t (*hton32) (uint32_t) = __byte_order_n32; +static uint64_t (*hton64) (uint64_t) = __byte_order_n64; + + +static inline uint16_t +__byte_order_le16 (uint16_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + /* cpu is le */ + htole16 = __noswap16; + htole32 = __noswap32; + htole64 = __noswap64; + } else { + /* cpu is be */ + htole16 = __swap16; + htole32 = __swap32; + htole64 = __swap64; + } + + return htole16 (i); +} + + +static inline uint32_t +__byte_order_le32 (uint32_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + /* cpu is le */ + htole16 = __noswap16; + htole32 = __noswap32; + htole64 = __noswap64; + } else { + /* cpu is be */ + htole16 = __swap16; + htole32 = __swap32; + htole64 = __swap64; + } + + return htole32 (i); +} + + +static inline uint64_t +__byte_order_le64 (uint64_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + /* cpu is le */ + htole16 = __noswap16; + htole32 = __noswap32; + htole64 = __noswap64; + } else { + /* cpu is be */ + htole16 = __swap16; + htole32 = __swap32; + htole64 = __swap64; + } + + return htole64 (i); +} + + +static uint16_t (*htole16) (uint16_t) = __byte_order_le16; +static uint32_t (*htole32) (uint32_t) = __byte_order_le32; +static uint64_t (*htole64) (uint64_t) = __byte_order_le64; + + +static inline uint16_t +__byte_order_be16 (uint16_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + /* cpu is le */ + htobe16 = __swap16; + htobe32 = __swap32; + htobe64 = __swap64; + } else { + /* cpu is be */ + htobe16 = __noswap16; + htobe32 = __noswap32; + htobe64 = __noswap64; + } + + return htobe16 (i); +} + + +static inline uint32_t +__byte_order_be32 (uint32_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + /* cpu is le */ + htobe16 = __swap16; + htobe32 = __swap32; + htobe64 = __swap64; + } else { + /* cpu is be */ + htobe16 = __noswap16; + htobe32 = __noswap32; + htobe64 = __noswap64; + } + + return htobe32 (i); +} + + +static inline uint64_t +__byte_order_be64 (uint64_t i) +{ + uint32_t num = 1; + + if (((char *)(&num))[0] == 1) { + /* cpu is le */ + htobe16 = __swap16; + htobe32 = __swap32; + htobe64 = __swap64; + } else { + /* cpu is be */ + htobe16 = __noswap16; + htobe32 = __noswap32; + htobe64 = __noswap64; + } + + return htobe64 (i); +} + + +static uint16_t (*htobe16) (uint16_t) = __byte_order_be16; +static uint32_t (*htobe32) (uint32_t) = __byte_order_be32; +static uint64_t (*htobe64) (uint64_t) = __byte_order_be64; + #endif /* _BYTE_ORDER_H */ diff --git a/libglusterfs/src/call-stub.c b/libglusterfs/src/call-stub.c index a56ed95f0..ac79cf071 100644 --- a/libglusterfs/src/call-stub.c +++ b/libglusterfs/src/call-stub.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -22,4694 +13,2826 @@ #include "config.h" #endif +#include <openssl/md5.h> #include <inttypes.h> -#include "md5.h" #include "call-stub.h" +#include "mem-types.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, - struct stat *postparent) + char wind, + glusterfs_fop_t fop) { - 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); - if (postparent) - stub->args.lookup_cbk.postparent = *postparent; -out: - return stub; -} - + call_stub_t *new = NULL; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); -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); + new = mem_get0 (frame->this->ctx->stub_mem_pool); + GF_VALIDATE_OR_GOTO ("call-stub", new, out); - stub = stub_new (frame, 1, GF_FOP_STAT); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + new->frame = frame; + new->wind = wind; + new->fop = fop; + new->stub_mem_pool = frame->this->ctx->stub_mem_pool; + INIT_LIST_HEAD (&new->list); - stub->args.stat.fn = fn; - loc_copy (&stub->args.stat.loc, loc); + INIT_LIST_HEAD (&new->args_cbk.entries); out: - return stub; + return new; } 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) +fop_lookup_stub (call_frame_t *frame, fop_lookup_t fn, loc_t *loc, + dict_t *xdata) { - 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 *stub = NULL; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); -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; + stub = stub_new (frame, 1, GF_FOP_LOOKUP); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + stub->fn.lookup = fn; - stub = stub_new (frame, 0, GF_FOP_CHMOD); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + loc_copy (&stub->args.loc, loc); + if (xdata) + stub->args.xdata = dict_ref (xdata); - 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; + return stub; } call_stub_t * -fop_fchmod_stub (call_frame_t *frame, - fop_fchmod_t fn, - fd_t *fd, - mode_t mode) +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 iatt *buf, + dict_t *xdata, struct iatt *postparent) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = stub_new (frame, 0, GF_FOP_LOOKUP); + 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; + stub->fn_cbk.lookup = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (inode) + stub->args_cbk.inode = inode_ref (inode); + if (buf) + stub->args_cbk.stat = *buf; + if (postparent) + stub->args_cbk.postparent = *postparent; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_stat_stub (call_frame_t *frame, fop_stat_t fn, + loc_t *loc, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); - stub = stub_new (frame, 0, GF_FOP_FCHMOD); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub = stub_new (frame, 1, GF_FOP_STAT); + 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; + stub->fn.stat = fn; + loc_copy (&stub->args.loc, loc); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_stat_cbk_stub (call_frame_t *frame, fop_stat_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *buf, dict_t *xdata) { - call_stub_t *stub = NULL; + 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", frame, out); - stub = stub_new (frame, 1, GF_FOP_CHOWN); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub = stub_new (frame, 0, GF_FOP_STAT); + 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; + stub->fn_cbk.stat = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (op_ret == 0) + stub->args_cbk.stat = *buf; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_fstat_stub (call_frame_t *frame, fop_fstat_t fn, + fd_t *fd, dict_t *xdata) { - 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 *stub = NULL; -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); - 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 = stub_new (frame, 1, GF_FOP_FCHOWN); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub->fn.fstat = fn; - stub->args.fchown.fn = fn; - if (fd) - stub->args.fchown.fd = fd_ref (fd); - stub->args.fchown.uid = uid; - stub->args.fchown.gid = gid; + if (fd) + stub->args.fd = fd_ref (fd); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_fstat_cbk_stub (call_frame_t *frame, fop_fstat_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *buf, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = stub_new (frame, 0, GF_FOP_FSTAT); + 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; + stub->fn_cbk.fstat = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (buf) + stub->args_cbk.stat = *buf; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } -/* truncate */ - call_stub_t * -fop_truncate_stub (call_frame_t *frame, - fop_truncate_t fn, - loc_t *loc, - off_t off) +fop_truncate_stub (call_frame_t *frame, fop_truncate_t fn, + loc_t *loc, off_t off, dict_t *xdata) { - call_stub_t *stub = NULL; + 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", 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 = 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; + stub->fn.truncate = fn; + loc_copy (&stub->args.loc, loc); + stub->args.offset = off; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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 *prebuf, - struct stat *postbuf) +fop_truncate_cbk_stub (call_frame_t *frame, fop_truncate_cbk_t fn, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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 (prebuf) - stub->args.truncate_cbk.prebuf = *prebuf; + stub->fn_cbk.truncate = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (prebuf) + stub->args_cbk.prestat = *prebuf; if (postbuf) - stub->args.truncate_cbk.postbuf = *postbuf; + stub->args_cbk.poststat = *postbuf; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_ftruncate_stub (call_frame_t *frame, - fop_ftruncate_t fn, - fd_t *fd, - off_t off) +fop_ftruncate_stub (call_frame_t *frame, fop_ftruncate_t fn, + fd_t *fd, off_t off, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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->fn.ftruncate = fn; + if (fd) + stub->args.fd = fd_ref (fd); - stub->args.ftruncate.off = off; + stub->args.offset = off; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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 *prebuf, - struct stat *postbuf) +fop_ftruncate_cbk_stub (call_frame_t *frame, fop_ftruncate_cbk_t fn, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) { - 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); + call_stub_t *stub = NULL; - stub->args.ftruncate_cbk.fn = fn; - stub->args.ftruncate_cbk.op_ret = op_ret; - stub->args.ftruncate_cbk.op_errno = op_errno; - if (prebuf) - stub->args.ftruncate_cbk.prebuf = *prebuf; - if (postbuf) - stub->args.ftruncate_cbk.postbuf = *postbuf; -out: - return stub; -} + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + stub = stub_new (frame, 0, GF_FOP_FTRUNCATE); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); -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->fn_cbk.ftruncate = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (prebuf) + stub->args_cbk.prestat = *prebuf; + if (postbuf) + stub->args_cbk.poststat = *postbuf; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); - 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; + 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) +fop_access_stub (call_frame_t *frame, fop_access_t fn, + loc_t *loc, int32_t mask, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); - stub = stub_new (frame, 0, GF_FOP_UTIMENS); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub = stub_new (frame, 1, GF_FOP_ACCESS); + 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; + stub->fn.access = fn; + loc_copy (&stub->args.loc, loc); + stub->args.mask = mask; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_access_stub (call_frame_t *frame, - fop_access_t fn, - loc_t *loc, - int32_t mask) +fop_access_cbk_stub (call_frame_t *frame, fop_access_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { - call_stub_t *stub = NULL; + 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", frame, out); - stub = stub_new (frame, 1, GF_FOP_ACCESS); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub = stub_new (frame, 0, 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; + stub->fn_cbk.access = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_readlink_stub (call_frame_t *frame, fop_readlink_t fn, + loc_t *loc, size_t size, dict_t *xdata) { - 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 *stub = NULL; -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); - 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 = 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; + stub->fn.readlink = fn; + loc_copy (&stub->args.loc, loc); + stub->args.size = size; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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, - struct stat *sbuf) +fop_readlink_cbk_stub (call_frame_t *frame, fop_readlink_cbk_t fn, + int32_t op_ret, int32_t op_errno, + const char *path, struct iatt *stbuf, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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); - if (sbuf) - stub->args.readlink_cbk.sbuf = *sbuf; + stub->fn_cbk.readlink = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (path) + stub->args_cbk.buf = gf_strdup (path); + if (stbuf) + stub->args_cbk.stat = *stbuf; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_mknod_stub (call_frame_t *frame, fop_mknod_t fn, loc_t *loc, mode_t mode, + dev_t rdev, mode_t umask, dict_t *xdata) { - call_stub_t *stub = NULL; + 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", 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 = 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; + stub->fn.mknod = fn; + loc_copy (&stub->args.loc, loc); + stub->args.mode = mode; + stub->args.rdev = rdev; + stub->args.umask = umask; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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, - struct stat *preparent, - struct stat *postparent) +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 iatt *buf, + struct iatt *preparent, struct iatt *postparent, + dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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; + stub->fn_cbk.mknod = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (inode) + stub->args_cbk.inode = inode_ref (inode); + if (buf) + stub->args_cbk.stat = *buf; if (preparent) - stub->args.mknod_cbk.preparent = *preparent; + stub->args_cbk.preparent = *preparent; if (postparent) - stub->args.mknod_cbk.postparent = *postparent; + stub->args_cbk.postparent = *postparent; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); + out: - return stub; + return stub; } call_stub_t * -fop_mkdir_stub (call_frame_t *frame, - fop_mkdir_t fn, - loc_t *loc, - mode_t mode) +fop_mkdir_stub (call_frame_t *frame, fop_mkdir_t fn, + loc_t *loc, mode_t mode, mode_t umask, dict_t *xdata) { - call_stub_t *stub = NULL; + 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", 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 = stub_new (frame, 1, GF_FOP_MKDIR); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub->fn.mkdir = fn; + loc_copy (&stub->args.loc, loc); + stub->args.mode = mode; + stub->args.umask = umask; - stub->args.mkdir.fn = fn; - loc_copy (&stub->args.mkdir.loc, loc); - stub->args.mkdir.mode = mode; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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, - struct stat *preparent, - struct stat *postparent) +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 iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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; + stub->fn_cbk.mkdir = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (inode) + stub->args_cbk.inode = inode_ref (inode); + if (buf) + stub->args_cbk.stat = *buf; if (preparent) - stub->args.mkdir_cbk.preparent = *preparent; + stub->args_cbk.preparent = *preparent; if (postparent) - stub->args.mkdir_cbk.postparent = *postparent; + stub->args_cbk.postparent = *postparent; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_unlink_stub (call_frame_t *frame, - fop_unlink_t fn, - loc_t *loc) +fop_unlink_stub (call_frame_t *frame, fop_unlink_t fn, + loc_t *loc, int xflag, dict_t *xdata) { - call_stub_t *stub = NULL; + 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", 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 = 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); + stub->fn.unlink = fn; + loc_copy (&stub->args.loc, loc); + stub->args.xflag = xflag; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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, - struct stat *preparent, - struct stat *postparent) +fop_unlink_cbk_stub (call_frame_t *frame, fop_unlink_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *preparent, struct iatt *postparent, + dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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; + stub->fn_cbk.unlink = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (preparent) - stub->args.unlink_cbk.preparent = *preparent; + stub->args_cbk.preparent = *preparent; if (postparent) - stub->args.unlink_cbk.postparent = *postparent; + stub->args_cbk.postparent = *postparent; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_rmdir_stub (call_frame_t *frame, - fop_rmdir_t fn, - loc_t *loc) +fop_rmdir_stub (call_frame_t *frame, fop_rmdir_t fn, + loc_t *loc, int flags, dict_t *xdata) { - call_stub_t *stub = NULL; + 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", 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 = 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); + stub->fn.rmdir = fn; + loc_copy (&stub->args.loc, loc); + stub->args.flags = flags; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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, - struct stat *preparent, - struct stat *postparent) +fop_rmdir_cbk_stub (call_frame_t *frame, fop_rmdir_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *preparent, struct iatt *postparent, + dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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; + stub->fn_cbk.rmdir = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (preparent) - stub->args.rmdir_cbk.preparent = *preparent; + stub->args_cbk.preparent = *preparent; if (postparent) - stub->args.rmdir_cbk.postparent = *postparent; + stub->args_cbk.postparent = *postparent; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_symlink_stub (call_frame_t *frame, - fop_symlink_t fn, - const char *linkname, - loc_t *loc) +fop_symlink_stub (call_frame_t *frame, fop_symlink_t fn, + const char *linkname, loc_t *loc, mode_t umask, dict_t *xdata) { - call_stub_t *stub = NULL; + 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); + 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 = 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); + stub->fn.symlink = fn; + stub->args.linkname = gf_strdup (linkname); + stub->args.umask = umask; + loc_copy (&stub->args.loc, loc); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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, - struct stat *preparent, - struct stat *postparent) +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 iatt *buf, + struct iatt *preparent, struct iatt *postparent, + dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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; + stub->fn_cbk.symlink = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (inode) + stub->args_cbk.inode = inode_ref (inode); + if (buf) + stub->args_cbk.stat = *buf; if (preparent) - stub->args.symlink_cbk.preparent = *preparent; + stub->args_cbk.preparent = *preparent; if (postparent) - stub->args.symlink_cbk.postparent = *postparent; + stub->args_cbk.postparent = *postparent; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_rename_stub (call_frame_t *frame, - fop_rename_t fn, - loc_t *oldloc, - loc_t *newloc) +fop_rename_stub (call_frame_t *frame, fop_rename_t fn, + loc_t *oldloc, loc_t *newloc, dict_t *xdata) { - call_stub_t *stub = NULL; + 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); + 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 = 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); + stub->fn.rename = fn; + loc_copy (&stub->args.loc, oldloc); + loc_copy (&stub->args.loc2, newloc); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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, - struct stat *preoldparent, - struct stat *postoldparent, - struct stat *prenewparent, - struct stat *postnewparent) +fop_rename_cbk_stub (call_frame_t *frame, fop_rename_cbk_t fn, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + struct iatt *preoldparent, struct iatt *postoldparent, + struct iatt *prenewparent, struct iatt *postnewparent, + dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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; + stub->fn_cbk.rename = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (buf) + stub->args_cbk.stat = *buf; if (preoldparent) - stub->args.rename_cbk.preoldparent = *preoldparent; + stub->args_cbk.preparent = *preoldparent; if (postoldparent) - stub->args.rename_cbk.postoldparent = *postoldparent; + stub->args_cbk.postparent = *postoldparent; if (prenewparent) - stub->args.rename_cbk.prenewparent = *prenewparent; + stub->args_cbk.preparent2 = *prenewparent; if (postnewparent) - stub->args.rename_cbk.postnewparent = *postnewparent; + stub->args_cbk.postparent2 = *postnewparent; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_link_stub (call_frame_t *frame, - fop_link_t fn, - loc_t *oldloc, - loc_t *newloc) +fop_link_stub (call_frame_t *frame, fop_link_t fn, + loc_t *oldloc, loc_t *newloc, dict_t *xdata) { - call_stub_t *stub = NULL; + 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); + 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 = 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); + stub->fn.link = fn; + loc_copy (&stub->args.loc, oldloc); + loc_copy (&stub->args.loc2, newloc); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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, - struct stat *preparent, - struct stat *postparent) +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 iatt *buf, + struct iatt *preparent, struct iatt *postparent, + dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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; + stub->fn_cbk.link = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (inode) + stub->args_cbk.inode = inode_ref (inode); + if (buf) + stub->args_cbk.stat = *buf; if (preparent) - stub->args.link_cbk.preparent = *preparent; + stub->args_cbk.preparent = *preparent; if (postparent) - stub->args.link_cbk.postparent = *postparent; + stub->args_cbk.postparent = *postparent; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_create_stub (call_frame_t *frame, fop_create_t fn, + loc_t *loc, int32_t flags, mode_t mode, + mode_t umask, fd_t *fd, dict_t *xdata) { - call_stub_t *stub = NULL; + 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", 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 = 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); + stub->fn.create = fn; + loc_copy (&stub->args.loc, loc); + stub->args.flags = flags; + stub->args.mode = mode; + stub->args.umask = umask; + if (fd) + stub->args.fd = fd_ref (fd); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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, - struct stat *preparent, - struct stat *postparent) +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 iatt *buf, + struct iatt *preparent, struct iatt *postparent, + dict_t *xdata) { - 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; + 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->fn_cbk.create = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (fd) + stub->args_cbk.fd = fd_ref (fd); + if (inode) + stub->args_cbk.inode = inode_ref (inode); + if (buf) + stub->args_cbk.stat = *buf; if (preparent) - stub->args.create_cbk.preparent = *preparent; + stub->args_cbk.preparent = *preparent; if (postparent) - stub->args.create_cbk.postparent = *postparent; + stub->args_cbk.postparent = *postparent; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + 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, - int32_t wbflags) +fop_open_stub (call_frame_t *frame, fop_open_t fn, + loc_t *loc, int32_t flags, fd_t *fd, dict_t *xdata) { - call_stub_t *stub = NULL; + 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", 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 = 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; - stub->args.open.wbflags = wbflags; - if (fd) - stub->args.open.fd = fd_ref (fd); + stub->fn.open = fn; + loc_copy (&stub->args.loc, loc); + stub->args.flags = flags; + if (fd) + stub->args.fd = fd_ref (fd); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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) - +fop_open_cbk_stub (call_frame_t *frame, fop_open_cbk_t fn, + int32_t op_ret, int32_t op_errno, + fd_t *fd, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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); + stub->fn_cbk.open = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (fd) + stub->args_cbk.fd = fd_ref (fd); + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_readv_stub (call_frame_t *frame, fop_readv_t fn, + fd_t *fd, size_t size, off_t off, uint32_t flags, + dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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; + stub->fn.readv = fn; + if (fd) + stub->args.fd = fd_ref (fd); + stub->args.size = size; + stub->args.offset = off; + stub->args.flags = flags; + + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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, - struct iobref *iobref) - +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 iatt *stbuf, + struct iobref *iobref, dict_t *xdata) { - 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.iobref = iobref_ref (iobref); - } + 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->fn_cbk.readv = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (op_ret >= 0) { + stub->args_cbk.vector = iov_dup (vector, count); + stub->args_cbk.count = count; + stub->args_cbk.stat = *stbuf; + stub->args_cbk.iobref = iobref_ref (iobref); + } + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + 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, - struct iobref *iobref) +fop_writev_stub (call_frame_t *frame, fop_writev_t fn, + fd_t *fd, struct iovec *vector, int32_t count, off_t off, + uint32_t flags, struct iobref *iobref, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - GF_VALIDATE_OR_GOTO ("call-stub", vector, out); + 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 = 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; - stub->args.writev.iobref = iobref_ref (iobref); + stub->fn.writev = fn; + if (fd) + stub->args.fd = fd_ref (fd); + stub->args.vector = iov_dup (vector, count); + stub->args.count = count; + stub->args.offset = off; + stub->args.flags = flags; + stub->args.iobref = iobref_ref (iobref); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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 *prebuf, - struct stat *postbuf) - +fop_writev_cbk_stub (call_frame_t *frame, fop_writev_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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.postbuf = *postbuf; + stub->fn_cbk.writev = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (op_ret >= 0) + stub->args_cbk.poststat = *postbuf; if (prebuf) - stub->args.writev_cbk.prebuf = *prebuf; + stub->args_cbk.prestat = *prebuf; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } - call_stub_t * -fop_flush_stub (call_frame_t *frame, - fop_flush_t fn, - fd_t *fd) +fop_flush_stub (call_frame_t *frame, fop_flush_t fn, + fd_t *fd, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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); + stub->fn.flush = fn; + if (fd) + stub->args.fd = fd_ref (fd); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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) - +fop_flush_cbk_stub (call_frame_t *frame, fop_flush_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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; + stub->fn_cbk.flush = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } - - call_stub_t * -fop_fsync_stub (call_frame_t *frame, - fop_fsync_t fn, - fd_t *fd, - int32_t datasync) +fop_fsync_stub (call_frame_t *frame, fop_fsync_t fn, + fd_t *fd, int32_t datasync, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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; + stub->fn.fsync = fn; + if (fd) + stub->args.fd = fd_ref (fd); + stub->args.datasync = datasync; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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, - struct stat *prebuf, - struct stat *postbuf) +fop_fsync_cbk_stub (call_frame_t *frame, fop_fsync_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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; + stub->fn_cbk.fsync = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (prebuf) - stub->args.fsync_cbk.prebuf = *prebuf; + stub->args_cbk.prestat = *prebuf; if (postbuf) - stub->args.fsync_cbk.postbuf = *postbuf; + stub->args_cbk.poststat = *postbuf; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_opendir_stub (call_frame_t *frame, - fop_opendir_t fn, - loc_t *loc, fd_t *fd) +fop_opendir_stub (call_frame_t *frame, fop_opendir_t fn, + loc_t *loc, fd_t *fd, dict_t *xdata) { - call_stub_t *stub = NULL; + 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", 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 = 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 (fd) - stub->args.opendir.fd = fd_ref (fd); + stub->fn.opendir = fn; + loc_copy (&stub->args.loc, loc); + if (fd) + stub->args.fd = fd_ref (fd); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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) - +fop_opendir_cbk_stub (call_frame_t *frame, fop_opendir_cbk_t fn, + int32_t op_ret, int32_t op_errno, + fd_t *fd, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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; + stub->fn_cbk.opendir = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; - if (fd) - stub->args.opendir_cbk.fd = fd_ref (fd); + if (fd) + stub->args_cbk.fd = fd_ref (fd); + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_fsyncdir_stub (call_frame_t *frame, fop_fsyncdir_t fn, + fd_t *fd, int32_t datasync, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = stub_new (frame, 1, GF_FOP_FSYNCDIR); + 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; + stub->fn.fsyncdir = fn; + if (fd) + stub->args.fd = fd_ref (fd); + stub->args.datasync = datasync; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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) - +fop_fsyncdir_cbk_stub (call_frame_t *frame, fop_fsyncdir_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { - call_stub_t *stub = NULL; - - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + call_stub_t *stub = NULL; - stub = stub_new (frame, 0, GF_FOP_GETDENTS); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + GF_VALIDATE_OR_GOTO ("call-stub", frame, 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 = stub_new (frame, 0, GF_FOP_FSYNCDIR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.getdents_cbk.count = count; + stub->fn_cbk.fsyncdir = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } - call_stub_t * -fop_fsyncdir_stub (call_frame_t *frame, - fop_fsyncdir_t fn, - fd_t *fd, - int32_t datasync) +fop_statfs_stub (call_frame_t *frame, fop_statfs_t fn, + loc_t *loc, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); - stub = stub_new (frame, 1, GF_FOP_FSYNCDIR); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub = stub_new (frame, 1, GF_FOP_STATFS); + 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; + stub->fn.statfs = fn; + loc_copy (&stub->args.loc, loc); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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) - +fop_statfs_cbk_stub (call_frame_t *frame, fop_statfs_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct statvfs *buf, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = stub_new (frame, 0, GF_FOP_STATFS); + 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; + stub->fn_cbk.statfs = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (op_ret == 0) + stub->args_cbk.statvfs = *buf; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_statfs_stub (call_frame_t *frame, - fop_statfs_t fn, - loc_t *loc) +fop_setxattr_stub (call_frame_t *frame, fop_setxattr_t fn, + loc_t *loc, dict_t *dict, + int32_t flags, dict_t *xdata) { - call_stub_t *stub = NULL; + 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", 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 = stub_new (frame, 1, GF_FOP_SETXATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.statfs.fn = fn; - loc_copy (&stub->args.statfs.loc, loc); + stub->fn.setxattr = fn; + loc_copy (&stub->args.loc, loc); + /* TODO */ + if (dict) + stub->args.xattr = dict_ref (dict); + stub->args.flags = flags; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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) - +fop_setxattr_cbk_stub (call_frame_t *frame, + fop_setxattr_cbk_t fn, + int32_t op_ret, + int32_t op_errno, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = stub_new (frame, 0, GF_FOP_SETXATTR); + 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; + stub->fn_cbk.setxattr = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_getxattr_stub (call_frame_t *frame, fop_getxattr_t fn, + loc_t *loc, const char *name, dict_t *xdata) { - call_stub_t *stub = NULL; + 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", 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 = stub_new (frame, 1, GF_FOP_GETXATTR); + 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; + stub->fn.getxattr = fn; + loc_copy (&stub->args.loc, loc); + + if (name) + stub->args.name = gf_strdup (name); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_getxattr_cbk_stub (call_frame_t *frame, fop_getxattr_cbk_t fn, + int32_t op_ret, int32_t op_errno, + dict_t *dict, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = stub_new (frame, 0, GF_FOP_GETXATTR); + 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; + stub->fn_cbk.getxattr = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + /* TODO */ + if (dict) + stub->args_cbk.xattr = dict_ref (dict); + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } + call_stub_t * -fop_getxattr_stub (call_frame_t *frame, - fop_getxattr_t fn, - loc_t *loc, - const char *name) +fop_fsetxattr_stub (call_frame_t *frame, fop_fsetxattr_t fn, + fd_t *fd, dict_t *dict, int32_t flags, dict_t *xdata) { - call_stub_t *stub = NULL; + 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", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fd, out); - stub = stub_new (frame, 1, GF_FOP_GETXATTR); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub = stub_new (frame, 1, GF_FOP_FSETXATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.getxattr.fn = fn; - loc_copy (&stub->args.getxattr.loc, loc); + stub->fn.fsetxattr = fn; + stub->args.fd = fd_ref (fd); - if (name) - stub->args.getxattr.name = strdup (name); + if (dict) + stub->args.xattr = dict_ref (dict); + stub->args.flags = flags; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_fsetxattr_cbk_stub (call_frame_t *frame, fop_fsetxattr_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = stub_new (frame, 0, GF_FOP_FSETXATTR); + 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); + stub->fn_cbk.fsetxattr = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_fsetxattr_stub (call_frame_t *frame, - fop_fsetxattr_t fn, - fd_t *fd, - dict_t *dict, - int32_t flags) +fop_fgetxattr_stub (call_frame_t *frame, fop_fgetxattr_t fn, + fd_t *fd, const char *name, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - GF_VALIDATE_OR_GOTO ("call-stub", fd, out); + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fd, out); - stub = stub_new (frame, 1, GF_FOP_FSETXATTR); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub = stub_new (frame, 1, GF_FOP_FGETXATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.fsetxattr.fn = fn; - stub->args.fsetxattr.fd = fd_ref (fd); + stub->fn.fgetxattr = fn; + stub->args.fd = fd_ref (fd); - /* TODO */ - if (dict) - stub->args.fsetxattr.dict = dict_ref (dict); - stub->args.fsetxattr.flags = flags; + if (name) + stub->args.name = gf_strdup (name); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_fsetxattr_cbk_stub (call_frame_t *frame, - fop_fsetxattr_cbk_t fn, - int32_t op_ret, - int32_t op_errno) +fop_fgetxattr_cbk_stub (call_frame_t *frame, fop_fgetxattr_cbk_t fn, + int32_t op_ret, int32_t op_errno, + dict_t *dict, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - 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 = stub_new (frame, 0, GF_FOP_FSETXATTR); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub->fn_cbk.fgetxattr = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; - stub->args.fsetxattr_cbk.fn = fn; - stub->args.fsetxattr_cbk.op_ret = op_ret; - stub->args.fsetxattr_cbk.op_errno = op_errno; + if (dict) + stub->args_cbk.xattr = dict_ref (dict); + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_fgetxattr_stub (call_frame_t *frame, - fop_fgetxattr_t fn, - fd_t *fd, - const char *name) +fop_removexattr_stub (call_frame_t *frame, fop_removexattr_t fn, + loc_t *loc, const char *name, dict_t *xdata) { - call_stub_t *stub = NULL; - - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - GF_VALIDATE_OR_GOTO ("call-stub", fd, out); + call_stub_t *stub = NULL; - stub = stub_new (frame, 1, GF_FOP_FGETXATTR); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + 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->args.fgetxattr.fn = fn; - stub->args.fgetxattr.fd = fd_ref (fd); + stub = stub_new (frame, 1, GF_FOP_REMOVEXATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - if (name) - stub->args.fgetxattr.name = strdup (name); + stub->fn.removexattr = fn; + loc_copy (&stub->args.loc, loc); + stub->args.name = gf_strdup (name); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_fgetxattr_cbk_stub (call_frame_t *frame, - fop_fgetxattr_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - dict_t *dict) +fop_removexattr_cbk_stub (call_frame_t *frame, fop_removexattr_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { - call_stub_t *stub = NULL; - - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + call_stub_t *stub = NULL; - stub = stub_new (frame, 0, GF_FOP_GETXATTR); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - stub->args.fgetxattr_cbk.fn = fn; - stub->args.fgetxattr_cbk.op_ret = op_ret; - stub->args.fgetxattr_cbk.op_errno = op_errno; + stub = stub_new (frame, 0, GF_FOP_REMOVEXATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - /* TODO */ - if (dict) - stub->args.fgetxattr_cbk.dict = dict_ref (dict); + stub->fn_cbk.removexattr = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_removexattr_stub (call_frame_t *frame, - fop_removexattr_t fn, - loc_t *loc, - const char *name) +fop_fremovexattr_stub (call_frame_t *frame, fop_fremovexattr_t fn, + fd_t *fd, const char *name, dict_t *xdata) { - call_stub_t *stub = NULL; + 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); + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fd, 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 = stub_new (frame, 1, GF_FOP_FREMOVEXATTR); + 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); + stub->fn.fremovexattr = fn; + stub->args.fd = fd_ref (fd); + stub->args.name = gf_strdup (name); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_fremovexattr_cbk_stub (call_frame_t *frame, fop_fremovexattr_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = stub_new (frame, 0, GF_FOP_FREMOVEXATTR); + 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; + stub->fn_cbk.fremovexattr = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_lk_stub (call_frame_t *frame, fop_lk_t fn, + fd_t *fd, int32_t cmd, + struct gf_flock *lock, dict_t *xdata) { - 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; + 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->fn.lk = fn; + if (fd) + stub->args.fd = fd_ref (fd); + stub->args.cmd = cmd; + stub->args.lock = *lock; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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) - +fop_lk_cbk_stub (call_frame_t *frame, fop_lk_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct gf_flock *lock, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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; + stub->fn_cbk.lk = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (op_ret == 0) + stub->args_cbk.lock = *lock; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } + call_stub_t * fop_inodelk_stub (call_frame_t *frame, fop_inodelk_t fn, - const char *volume, loc_t *loc, int32_t cmd, struct flock *lock) + const char *volume, loc_t *loc, int32_t cmd, + struct gf_flock *lock, dict_t *xdata) { - call_stub_t *stub = NULL; - - if (!frame || !lock) - return NULL; + call_stub_t *stub = NULL; - stub = stub_new (frame, 1, GF_FOP_INODELK); - if (!stub) - return NULL; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", lock, out); - stub->args.inodelk.fn = fn; + stub = stub_new (frame, 1, GF_FOP_INODELK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - if (volume) - stub->args.inodelk.volume = strdup (volume); + stub->fn.inodelk = fn; - loc_copy (&stub->args.inodelk.loc, loc); - stub->args.inodelk.cmd = cmd; - stub->args.inodelk.lock = *lock; + if (volume) + stub->args.volume = gf_strdup (volume); - return stub; + loc_copy (&stub->args.loc, loc); + stub->args.cmd = cmd; + stub->args.lock = *lock; + if (xdata) + stub->args.xdata = dict_ref (xdata); +out: + 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) + int32_t op_ret, int32_t op_errno, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - if (!frame) - return NULL; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - stub = stub_new (frame, 0, GF_FOP_INODELK); - if (!stub) - return NULL; + stub = stub_new (frame, 0, GF_FOP_INODELK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.inodelk_cbk.fn = fn; - stub->args.inodelk_cbk.op_ret = op_ret; - stub->args.inodelk_cbk.op_errno = op_errno; + stub->fn_cbk.inodelk = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; - return stub; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); +out: + return stub; } call_stub_t * fop_finodelk_stub (call_frame_t *frame, fop_finodelk_t fn, - const char *volume, fd_t *fd, int32_t cmd, struct flock *lock) + const char *volume, fd_t *fd, int32_t cmd, + struct gf_flock *lock, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - if (!frame || !lock) - return NULL; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", lock, out); - stub = stub_new (frame, 1, GF_FOP_FINODELK); - if (!stub) - return NULL; + stub = stub_new (frame, 1, GF_FOP_FINODELK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.finodelk.fn = fn; + stub->fn.finodelk = fn; - if (fd) - stub->args.finodelk.fd = fd_ref (fd); + if (fd) + stub->args.fd = fd_ref (fd); - if (volume) - stub->args.finodelk.volume = strdup (volume); + if (volume) + stub->args.volume = gf_strdup (volume); - stub->args.finodelk.cmd = cmd; - stub->args.finodelk.lock = *lock; + stub->args.cmd = cmd; + stub->args.lock = *lock; - return stub; + if (xdata) + stub->args.xdata = dict_ref (xdata); +out: + 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) + int32_t op_ret, int32_t op_errno, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - if (!frame) - return NULL; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - stub = stub_new (frame, 0, GF_FOP_FINODELK); - if (!stub) - return NULL; + stub = stub_new (frame, 0, GF_FOP_FINODELK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.finodelk_cbk.fn = fn; - stub->args.finodelk_cbk.op_ret = op_ret; - stub->args.finodelk_cbk.op_errno = op_errno; + stub->fn_cbk.finodelk = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; - return stub; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); +out: + return stub; } call_stub_t * fop_entrylk_stub (call_frame_t *frame, fop_entrylk_t fn, - const char *volume, loc_t *loc, const char *name, - entrylk_cmd cmd, entrylk_type type) + const char *volume, loc_t *loc, const char *name, + entrylk_cmd cmd, entrylk_type type, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - if (!frame) - return NULL; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - stub = stub_new (frame, 1, GF_FOP_ENTRYLK); - if (!stub) - return NULL; + stub = stub_new (frame, 1, GF_FOP_ENTRYLK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.entrylk.fn = fn; + stub->fn.entrylk = fn; - if (volume) - stub->args.entrylk.volume = strdup (volume); + if (volume) + stub->args.volume = gf_strdup (volume); - loc_copy (&stub->args.entrylk.loc, loc); + loc_copy (&stub->args.loc, loc); - stub->args.entrylk.cmd = cmd; - stub->args.entrylk.type = type; - if (name) - stub->args.entrylk.name = strdup (name); + stub->args.entrylkcmd = cmd; + stub->args.entrylktype = type; - return stub; + if (name) + stub->args.name = gf_strdup (name); + + if (xdata) + stub->args.xdata = dict_ref (xdata); +out: + 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) + int32_t op_ret, int32_t op_errno, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - if (!frame) - return NULL; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - stub = stub_new (frame, 0, GF_FOP_ENTRYLK); - if (!stub) - return NULL; + stub = stub_new (frame, 0, GF_FOP_ENTRYLK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.entrylk_cbk.fn = fn; - stub->args.entrylk_cbk.op_ret = op_ret; - stub->args.entrylk_cbk.op_errno = op_errno; + stub->fn_cbk.entrylk = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; - return stub; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); +out: + return stub; } call_stub_t * fop_fentrylk_stub (call_frame_t *frame, fop_fentrylk_t fn, - const char *volume, fd_t *fd, const char *name, - entrylk_cmd cmd, entrylk_type type) + const char *volume, fd_t *fd, const char *name, + entrylk_cmd cmd, entrylk_type type, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - if (!frame) - return NULL; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - stub = stub_new (frame, 1, GF_FOP_FENTRYLK); - if (!stub) - return NULL; + stub = stub_new (frame, 1, GF_FOP_FENTRYLK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.fentrylk.fn = fn; + stub->fn.fentrylk = fn; - if (volume) - stub->args.fentrylk.volume = strdup (volume); + if (volume) + stub->args.volume = gf_strdup (volume); - 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); + if (fd) + stub->args.fd = fd_ref (fd); + stub->args.entrylkcmd = cmd; + stub->args.entrylktype = type; + if (name) + stub->args.name = gf_strdup (name); - return stub; + if (xdata) + stub->args.xdata = dict_ref (xdata); +out: + 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) + int32_t op_ret, int32_t op_errno, dict_t *xdata) { - call_stub_t *stub = NULL; - - if (!frame) - return NULL; - - stub = stub_new (frame, 0, GF_FOP_FENTRYLK); - if (!stub) - return NULL; + call_stub_t *stub = NULL; - stub->args.fentrylk_cbk.fn = fn; - stub->args.fentrylk_cbk.op_ret = op_ret; - stub->args.fentrylk_cbk.op_errno = op_errno; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - return stub; -} + stub = stub_new (frame, 0, GF_FOP_FENTRYLK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub->fn_cbk.fentrylk = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; -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; - } + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + 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_readdirp_cbk_stub (call_frame_t *frame, - fop_readdirp_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - gf_dirent_t *entries) +fop_readdirp_cbk_stub (call_frame_t *frame, fop_readdirp_cbk_t fn, + int32_t op_ret, int32_t op_errno, + gf_dirent_t *entries, dict_t *xdata) { - 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_READDIRP); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - - stub->args.readdirp_cbk.fn = fn; - stub->args.readdirp_cbk.op_ret = op_ret; - stub->args.readdirp_cbk.op_errno = op_errno; - INIT_LIST_HEAD (&stub->args.readdirp_cbk.entries.list); - - /* This check must come after the init of head above - * so we're sure the list is empty for list_empty. - */ - if (!entries) - goto out; - - 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.readdirp_cbk.entries.list); - } - } + 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_READDIRP); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->fn_cbk.readdirp = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + + GF_VALIDATE_OR_GOTO ("call-stub", entries, out); + + if (op_ret > 0) { + list_for_each_entry (entry, &entries->list, list) { + stub_entry = gf_dirent_for_name (entry->d_name); + if (!stub_entry) + goto out; + stub_entry->d_off = entry->d_off; + stub_entry->d_ino = entry->d_ino; + stub_entry->d_stat = entry->d_stat; + if (entry->inode) + stub_entry->inode = inode_ref (entry->inode); + list_add_tail (&stub_entry->list, + &stub->args_cbk.entries.list); + } + } + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + 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) +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, dict_t *xdata) { - 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); - - /* This check must come after the init of head above - * so we're sure the list is empty for list_empty. - */ - if (!entries) - goto out; - - 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 *stub = NULL; + gf_dirent_t *stub_entry = NULL, *entry = NULL; -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; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - 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; + stub = stub_new (frame, 0, GF_FOP_READDIR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - return stub; -} + stub->fn_cbk.readdir = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; -call_stub_t * -fop_readdirp_stub (call_frame_t *frame, - fop_readdirp_t fn, - fd_t *fd, - size_t size, - off_t off) -{ - call_stub_t *stub = NULL; + GF_VALIDATE_OR_GOTO ("call-stub", entries, out); - stub = stub_new (frame, 1, GF_FOP_READDIRP); - stub->args.readdirp.fn = fn; - stub->args.readdirp.fd = fd_ref (fd); - stub->args.readdirp.size = size; - stub->args.readdirp.off = off; + if (op_ret > 0) { + list_for_each_entry (entry, &entries->list, list) { + stub_entry = gf_dirent_for_name (entry->d_name); + if (!stub_entry) + goto out; + stub_entry->d_off = entry->d_off; + stub_entry->d_ino = entry->d_ino; - return stub; + list_add_tail (&stub_entry->list, + &stub->args_cbk.entries.list); + } + } + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); +out: + return stub; } + call_stub_t * -fop_checksum_stub (call_frame_t *frame, - fop_checksum_t fn, - loc_t *loc, - int32_t flags) +fop_readdir_stub (call_frame_t *frame, fop_readdir_t fn, + fd_t *fd, size_t size, + off_t off, dict_t *xdata) { - call_stub_t *stub = NULL; + 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_READDIR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub = stub_new (frame, 1, GF_FOP_CHECKSUM); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub->fn.readdir = fn; + stub->args.fd = fd_ref (fd); + stub->args.size = size; + stub->args.offset = off; - stub->args.checksum.fn = fn; - loc_copy (&stub->args.checksum.loc, loc); - stub->args.checksum.flags = flags; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_readdirp_stub (call_frame_t *frame, fop_readdirp_t fn, + fd_t *fd, size_t size, off_t off, dict_t *xdata) { - 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); + call_stub_t *stub = NULL; - 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, NAME_MAX); + stub = stub_new (frame, 1, GF_FOP_READDIRP); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.checksum_cbk.dir_checksum = - memdup (dir_checksum, NAME_MAX); - } + stub->fn.readdirp = fn; + stub->args.fd = fd_ref (fd); + stub->args.size = size; + stub->args.offset = off; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_rchecksum_stub (call_frame_t *frame, - fop_rchecksum_t fn, - fd_t *fd, off_t offset, - int32_t len) +fop_rchecksum_stub (call_frame_t *frame, fop_rchecksum_t fn, + fd_t *fd, off_t offset, int32_t len, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - GF_VALIDATE_OR_GOTO ("call-stub", fd, out); + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fd, out); - stub = stub_new (frame, 1, GF_FOP_RCHECKSUM); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub = stub_new (frame, 1, GF_FOP_RCHECKSUM); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.rchecksum.fn = fn; - stub->args.rchecksum.fd = fd_ref (fd); - stub->args.rchecksum.offset = offset; - stub->args.rchecksum.len = len; + stub->fn.rchecksum = fn; + stub->args.fd = fd_ref (fd); + stub->args.offset = offset; + stub->args.size = len; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_rchecksum_cbk_stub (call_frame_t *frame, - fop_rchecksum_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - uint32_t weak_checksum, - uint8_t *strong_checksum) +fop_rchecksum_cbk_stub (call_frame_t *frame, fop_rchecksum_cbk_t fn, + int32_t op_ret, int32_t op_errno, + uint32_t weak_checksum, uint8_t *strong_checksum, + dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - stub = stub_new (frame, 0, GF_FOP_RCHECKSUM); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub = stub_new (frame, 0, GF_FOP_RCHECKSUM); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.rchecksum_cbk.fn = fn; - stub->args.rchecksum_cbk.op_ret = op_ret; - stub->args.rchecksum_cbk.op_errno = op_errno; + stub->fn_cbk.rchecksum = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; - if (op_ret >= 0) - { - stub->args.rchecksum_cbk.weak_checksum = + if (op_ret >= 0) { + stub->args_cbk.weak_checksum = weak_checksum; + stub->args_cbk.strong_checksum = + memdup (strong_checksum, MD5_DIGEST_LENGTH); + } - stub->args.rchecksum_cbk.strong_checksum = - memdup (strong_checksum, MD5_DIGEST_LEN); - } + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_xattrop_cbk_stub (call_frame_t *frame, fop_xattrop_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - 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 = 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; + stub->fn_cbk.xattrop = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_fxattrop_cbk_stub (call_frame_t *frame, fop_fxattrop_cbk_t fn, + int32_t op_ret, int32_t op_errno, + dict_t *xattr, dict_t *xdata) { - call_stub_t *stub = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + call_stub_t *stub = NULL; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_FXATTROP); + GF_VALIDATE_OR_GOTO ("call-stub", stub, 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); + stub->fn_cbk.fxattrop = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (xattr) + stub->args_cbk.xattr = dict_ref (xattr); + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + 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) +fop_xattrop_stub (call_frame_t *frame, fop_xattrop_t fn, + loc_t *loc, gf_xattrop_flags_t optype, + dict_t *xattr, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", xattr, out); - if (!frame || !xattr) - return NULL; + stub = stub_new (frame, 1, GF_FOP_XATTROP); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub = stub_new (frame, 1, GF_FOP_XATTROP); - if (!stub) - return NULL; + stub->fn.xattrop = fn; - stub->args.xattrop.fn = fn; - - loc_copy (&stub->args.xattrop.loc, loc); + loc_copy (&stub->args.loc, loc); - stub->args.xattrop.optype = optype; - stub->args.xattrop.xattr = dict_ref (xattr); + stub->args.optype = optype; + stub->args.xattr = dict_ref (xattr); - return stub; + if (xdata) + stub->args.xdata = dict_ref (xdata); +out: + 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) +fop_fxattrop_stub (call_frame_t *frame, fop_fxattrop_t fn, + fd_t *fd, gf_xattrop_flags_t optype, + dict_t *xattr, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", xattr, out); - if (!frame || !xattr) - return NULL; + stub = stub_new (frame, 1, GF_FOP_FXATTROP); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub = stub_new (frame, 1, GF_FOP_FXATTROP); - if (!stub) - return NULL; + stub->fn.fxattrop = fn; - stub->args.fxattrop.fn = fn; - - stub->args.fxattrop.fd = fd_ref (fd); + stub->args.fd = fd_ref (fd); - stub->args.fxattrop.optype = optype; - stub->args.fxattrop.xattr = dict_ref (xattr); + stub->args.optype = optype; + stub->args.xattr = dict_ref (xattr); - return stub; + if (xdata) + stub->args.xdata = dict_ref (xdata); +out: + return stub; } call_stub_t * -fop_lock_notify_cbk_stub (call_frame_t *frame, fop_lock_notify_cbk_t fn, - int32_t op_ret, int32_t op_errno) +fop_setattr_cbk_stub (call_frame_t *frame, fop_setattr_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *statpre, struct iatt *statpost, + dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - - stub = stub_new (frame, 0, GF_FOP_LOCK_NOTIFY); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub = stub_new (frame, 0, GF_FOP_SETATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.lock_notify_cbk.fn = fn; - stub->args.lock_notify_cbk.op_ret = op_ret; - stub->args.lock_notify_cbk.op_errno = op_errno; + stub->fn_cbk.setattr = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + + if (statpre) + stub->args_cbk.prestat = *statpre; + if (statpost) + stub->args_cbk.poststat = *statpost; + + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_lock_notify_stub (call_frame_t *frame, fop_lock_notify_t fn, - loc_t *loc, int32_t timeout) +fop_fsetattr_cbk_stub (call_frame_t *frame, fop_setattr_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *statpre, struct iatt *statpost, + dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; - if (!frame) - return NULL; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - stub = stub_new (frame, 1, GF_FOP_LOCK_NOTIFY); - if (!stub) - return NULL; + stub = stub_new (frame, 0, GF_FOP_FSETATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.lock_notify.fn = fn; - - loc_copy (&stub->args.lock_notify.loc, loc); + stub->fn_cbk.fsetattr = fn; - stub->args.lock_notify.timeout = timeout; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; - return stub; + if (statpre) + stub->args_cbk.prestat = *statpre; + if (statpost) + stub->args_cbk.poststat = *statpost; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); +out: + return stub; } call_stub_t * -fop_lock_fnotify_cbk_stub (call_frame_t *frame, fop_lock_fnotify_cbk_t fn, - int32_t op_ret, int32_t op_errno) +fop_setattr_stub (call_frame_t *frame, fop_setattr_t fn, + loc_t *loc, struct iatt *stbuf, + int32_t valid, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fn, out); - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - - stub = stub_new (frame, 0, GF_FOP_LOCK_FNOTIFY); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub = stub_new (frame, 1, GF_FOP_SETATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->fn.setattr = fn; + + loc_copy (&stub->args.loc, loc); + + if (stbuf) + stub->args.stat = *stbuf; - stub->args.lock_fnotify_cbk.fn = fn; - stub->args.lock_fnotify_cbk.op_ret = op_ret; - stub->args.lock_fnotify_cbk.op_errno = op_errno; + stub->args.valid = valid; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_lock_fnotify_stub (call_frame_t *frame, fop_lock_fnotify_t fn, - fd_t *fd, int32_t timeout) +fop_fsetattr_stub (call_frame_t *frame, fop_fsetattr_t fn, + fd_t *fd, struct iatt *stbuf, + int32_t valid, dict_t *xdata) { - call_stub_t *stub = NULL; + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fn, out); - if (!frame) - return NULL; + stub = stub_new (frame, 1, GF_FOP_FSETATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub = stub_new (frame, 1, GF_FOP_LOCK_FNOTIFY); - if (!stub) - return NULL; + stub->fn.fsetattr = fn; - stub->args.lock_fnotify.fn = fn; + if (fd) + stub->args.fd = fd_ref (fd); + + if (stbuf) + stub->args.stat = *stbuf; - stub->args.lock_fnotify.fd = fd_ref (fd); - stub->args.lock_fnotify.timeout = timeout; + stub->args.valid = valid; - return stub; + if (xdata) + stub->args.xdata = dict_ref (xdata); +out: + return stub; } call_stub_t * -fop_setattr_cbk_stub (call_frame_t *frame, - fop_setattr_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct stat *statpre, - struct stat *statpost) +fop_fallocate_cbk_stub(call_frame_t *frame, fop_fallocate_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *statpre, struct iatt *statpost, + dict_t *xdata) { call_stub_t *stub = NULL; - if (frame == NULL) - goto out; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - stub = stub_new (frame, 1, GF_FOP_SETATTR); - if (stub == NULL) - goto out; + stub = stub_new (frame, 0, GF_FOP_FALLOCATE); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.setattr_cbk.fn = fn; + stub->fn_cbk.fallocate = fn; - stub->args.setattr_cbk.op_ret = op_ret; - stub->args.setattr_cbk.op_errno = op_errno; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (statpre) - stub->args.setattr_cbk.statpre = *statpre; + stub->args_cbk.prestat = *statpre; if (statpost) - stub->args.setattr_cbk.statpost = *statpost; - + stub->args_cbk.poststat = *statpost; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_fsetattr_cbk_stub (call_frame_t *frame, - fop_setattr_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct stat *statpre, - struct stat *statpost) +fop_fallocate_stub(call_frame_t *frame, fop_fallocate_t fn, fd_t *fd, + int32_t mode, off_t offset, size_t len, dict_t *xdata) { call_stub_t *stub = NULL; - if (frame == NULL) - goto out; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fn, out); + + stub = stub_new (frame, 1, GF_FOP_FALLOCATE); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub = stub_new (frame, 1, GF_FOP_FSETATTR); - if (stub == NULL) - goto out; + stub->fn.fallocate = fn; - stub->args.fsetattr_cbk.fn = fn; + if (fd) + stub->args.fd = fd_ref (fd); - stub->args.fsetattr_cbk.op_ret = op_ret; - stub->args.fsetattr_cbk.op_errno = op_errno; + stub->args.flags = mode; + stub->args.offset = offset; + stub->args.size = len; - if (statpre) - stub->args.setattr_cbk.statpre = *statpre; - if (statpost) - stub->args.fsetattr_cbk.statpost = *statpost; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + return stub; + } call_stub_t * -fop_setattr_stub (call_frame_t *frame, - fop_setattr_t fn, - loc_t *loc, - struct stat *stbuf, - int32_t valid) +fop_discard_cbk_stub(call_frame_t *frame, fop_discard_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *statpre, struct iatt *statpost, + dict_t *xdata) { call_stub_t *stub = NULL; - if (frame == NULL) - goto out; - - if (fn == NULL) - goto out; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - stub = stub_new (frame, 1, GF_FOP_SETATTR); - if (stub == NULL) - goto out; + stub = stub_new (frame, 0, GF_FOP_DISCARD); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.setattr.fn = fn; + stub->fn_cbk.discard = fn; - loc_copy (&stub->args.setattr.loc, loc); - - if (stbuf) - stub->args.setattr.stbuf = *stbuf; - - stub->args.setattr.valid = valid; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (statpre) + stub->args_cbk.prestat = *statpre; + if (statpost) + stub->args_cbk.poststat = *statpost; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return stub; + return stub; } call_stub_t * -fop_fsetattr_stub (call_frame_t *frame, - fop_fsetattr_t fn, - fd_t *fd, - struct stat *stbuf, - int32_t valid) +fop_discard_stub(call_frame_t *frame, fop_discard_t fn, fd_t *fd, + off_t offset, size_t len, dict_t *xdata) { call_stub_t *stub = NULL; - if (frame == NULL) - goto out; - - if (fn == NULL) - goto out; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fn, out); - stub = stub_new (frame, 1, GF_FOP_FSETATTR); - if (stub == NULL) - goto out; + stub = stub_new (frame, 1, GF_FOP_DISCARD); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.fsetattr.fn = fn; + stub->fn.discard = fn; if (fd) - stub->args.fsetattr.fd = fd_ref (fd); + stub->args.fd = fd_ref (fd); - if (stbuf) - stub->args.fsetattr.stbuf = *stbuf; - - stub->args.fsetattr.valid = valid; + stub->args.offset = offset; + stub->args.size = len; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return stub; + return stub; + } -static void -call_resume_wind (call_stub_t *stub) +call_stub_t * +fop_zerofill_cbk_stub(call_frame_t *frame, fop_zerofill_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *statpre, struct iatt *statpost, + dict_t *xdata) { - 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, - stub->args.open.wbflags); - 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, - stub->args.writev.iobref); - 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_FSETXATTR: - { - stub->args.fsetxattr.fn (stub->frame, - stub->frame->this, - stub->args.fsetxattr.fd, - stub->args.fsetxattr.dict, - stub->args.fsetxattr.flags); - break; - } - - case GF_FOP_FGETXATTR: - { - stub->args.fgetxattr.fn (stub->frame, - stub->frame->this, - stub->args.fgetxattr.fd, - stub->args.fgetxattr.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.volume, - &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.volume, - 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.volume, - &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.volume, - 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_RCHECKSUM: - { - stub->args.rchecksum.fn (stub->frame, - stub->frame->this, - stub->args.rchecksum.fd, - stub->args.rchecksum.offset, - stub->args.rchecksum.len); - 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; - } + call_stub_t *stub = NULL; - case GF_FOP_READDIRP: - { - stub->args.readdirp.fn (stub->frame, - stub->frame->this, - stub->args.readdirp.fd, - stub->args.readdirp.size, - stub->args.readdirp.off); - break; - } + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - 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); + stub = stub_new (frame, 0, GF_FOP_ZEROFILL); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - 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); + stub->fn_cbk.zerofill = fn; - break; - } - case GF_FOP_LOCK_NOTIFY: - { - stub->args.lock_notify.fn (stub->frame, - stub->frame->this, - &stub->args.lock_notify.loc, - stub->args.lock_notify.timeout); - break; - } - case GF_FOP_LOCK_FNOTIFY: - { - stub->args.lock_fnotify.fn (stub->frame, - stub->frame->this, - stub->args.lock_fnotify.fd, - stub->args.lock_fnotify.timeout); - break; - } - case GF_FOP_SETATTR: - { - stub->args.setattr.fn (stub->frame, - stub->frame->this, - &stub->args.setattr.loc, - &stub->args.setattr.stbuf, - stub->args.setattr.valid); - break; - } - case GF_FOP_FSETATTR: - { - stub->args.fsetattr.fn (stub->frame, - stub->frame->this, - stub->args.fsetattr.fd, - &stub->args.fsetattr.stbuf, - stub->args.fsetattr.valid); - break; - } - default: - { - gf_log ("call-stub", - GF_LOG_DEBUG, - "Invalid value of FOP"); - } - break; - } + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + + if (statpre) + stub->args_cbk.prestat = *statpre; + if (statpost) + stub->args_cbk.poststat = *statpost; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: - return; + return stub; } - - -static void -call_resume_unwind (call_stub_t *stub) +call_stub_t * +fop_zerofill_stub(call_frame_t *frame, fop_zerofill_t fn, fd_t *fd, + off_t offset, size_t len, dict_t *xdata) { - 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, - &stub->args.create_cbk.preparent, - &stub->args.create_cbk.postparent); - 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, - &stub->args.create_cbk.preparent, - &stub->args.create_cbk.postparent); - - 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); + call_stub_t *stub = NULL; - 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, - &stub->args.readlink_cbk.sbuf); - 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, - &stub->args.readlink_cbk.sbuf); + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fn, out); - 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, - &stub->args.mknod_cbk.preparent, - &stub->args.mknod_cbk.postparent); - 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, - &stub->args.mknod_cbk.preparent, - &stub->args.mknod_cbk.postparent); - 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, - &stub->args.mkdir_cbk.preparent, - &stub->args.mkdir_cbk.postparent); - 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, - &stub->args.mkdir_cbk.preparent, - &stub->args.mkdir_cbk.postparent); - - if (stub->args.mkdir_cbk.inode) - inode_unref (stub->args.mkdir_cbk.inode); + stub = stub_new (frame, 1, GF_FOP_ZEROFILL); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - 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, - &stub->args.unlink_cbk.preparent, - &stub->args.unlink_cbk.postparent); - 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, - &stub->args.unlink_cbk.preparent, - &stub->args.unlink_cbk.postparent); - 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, - &stub->args.rmdir_cbk.preparent, - &stub->args.rmdir_cbk.postparent); - 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, - &stub->args.rmdir_cbk.preparent, - &stub->args.rmdir_cbk.postparent); - 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, - &stub->args.symlink_cbk.preparent, - &stub->args.symlink_cbk.postparent); - 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, - &stub->args.symlink_cbk.preparent, - &stub->args.symlink_cbk.postparent); - } - 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, - &stub->args.rename_cbk.preoldparent, - &stub->args.rename_cbk.postoldparent, - &stub->args.rename_cbk.prenewparent, - &stub->args.rename_cbk.postnewparent); - 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, - &stub->args.rename_cbk.preoldparent, - &stub->args.rename_cbk.postoldparent, - &stub->args.rename_cbk.prenewparent, - &stub->args.rename_cbk.postnewparent); -#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, - &stub->args.link_cbk.preparent, - &stub->args.link_cbk.postparent); - 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.prebuf, - &stub->args.truncate_cbk.postbuf); - 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.prebuf, - &stub->args.truncate_cbk.postbuf); - 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, - stub->args.readv_cbk.iobref); - 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, - stub->args.readv_cbk.iobref); - } - 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.prebuf, - &stub->args.writev_cbk.postbuf); - 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.prebuf, - &stub->args.writev_cbk.postbuf); - 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, - &stub->args.fsync_cbk.prebuf, - &stub->args.fsync_cbk.postbuf); - 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, - &stub->args.fsync_cbk.prebuf, - &stub->args.fsync_cbk.postbuf); - 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); + stub->fn.zerofill = fn; - 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_FSETXATTR: - { - if (!stub->args.fsetxattr_cbk.fn) - STACK_UNWIND (stub->frame, - stub->args.fsetxattr_cbk.op_ret, - stub->args.fsetxattr_cbk.op_errno); - - else - stub->args.fsetxattr_cbk.fn (stub->frame, - stub->frame->cookie, - stub->frame->this, - stub->args.fsetxattr_cbk.op_ret, - stub->args.fsetxattr_cbk.op_errno); - - break; - } - - case GF_FOP_FGETXATTR: - { - if (!stub->args.fgetxattr_cbk.fn) - STACK_UNWIND (stub->frame, - stub->args.fgetxattr_cbk.op_ret, - stub->args.fgetxattr_cbk.op_errno, - stub->args.fgetxattr_cbk.dict); - else - stub->args.fgetxattr_cbk.fn (stub->frame, - stub->frame->cookie, - stub->frame->this, - stub->args.fgetxattr_cbk.op_ret, - stub->args.fgetxattr_cbk.op_errno, - stub->args.fgetxattr_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); + if (fd) + stub->args.fd = fd_ref (fd); - 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); + stub->args.offset = offset; + stub->args.size = len; - 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.prebuf, - &stub->args.ftruncate_cbk.postbuf); - 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.prebuf, - &stub->args.ftruncate_cbk.postbuf); - 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, - &stub->args.lookup_cbk.postparent); - 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, - &stub->args.lookup_cbk.postparent); - /* 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); + if (xdata) + stub->args.xdata = dict_ref (xdata); +out: + return stub; - 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_RCHECKSUM: - { - if (!stub->args.rchecksum_cbk.fn) - STACK_UNWIND (stub->frame, - stub->args.rchecksum_cbk.op_ret, - stub->args.rchecksum_cbk.op_errno, - stub->args.rchecksum_cbk.weak_checksum, - stub->args.rchecksum_cbk.strong_checksum); - else - stub->args.rchecksum_cbk.fn (stub->frame, - stub->frame->cookie, - stub->frame->this, - stub->args.rchecksum_cbk.op_ret, - stub->args.rchecksum_cbk.op_errno, - stub->args.rchecksum_cbk.weak_checksum, - stub->args.rchecksum_cbk.strong_checksum); - if (stub->args.rchecksum_cbk.op_ret >= 0) - { - FREE (stub->args.rchecksum_cbk.strong_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); +static void +call_resume_wind (call_stub_t *stub) +{ + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - break; - } + switch (stub->fop) { + case GF_FOP_OPEN: + stub->fn.open (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.flags, + stub->args.fd, stub->args.xdata); + break; + case GF_FOP_CREATE: + stub->fn.create (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.flags, + stub->args.mode, stub->args.umask, + stub->args.fd, stub->args.xdata); + break; + case GF_FOP_STAT: + stub->fn.stat (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.xdata); + break; + case GF_FOP_READLINK: + stub->fn.readlink (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.size, + stub->args.xdata); + break; + case GF_FOP_MKNOD: + stub->fn.mknod (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.mode, + stub->args.rdev, stub->args.umask, + stub->args.xdata); + break; + case GF_FOP_MKDIR: + stub->fn.mkdir (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.mode, + stub->args.umask, stub->args.xdata); + break; + case GF_FOP_UNLINK: + stub->fn.unlink (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.xflag, + stub->args.xdata); + break; + case GF_FOP_RMDIR: + stub->fn.rmdir (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.flags, + stub->args.xdata); + break; + case GF_FOP_SYMLINK: + stub->fn.symlink (stub->frame, stub->frame->this, + stub->args.linkname, &stub->args.loc, + stub->args.umask, stub->args.xdata); + break; + case GF_FOP_RENAME: + stub->fn.rename (stub->frame, stub->frame->this, + &stub->args.loc, &stub->args.loc2, + stub->args.xdata); + break; + case GF_FOP_LINK: + stub->fn.link (stub->frame, stub->frame->this, + &stub->args.loc, &stub->args.loc2, + stub->args.xdata); + break; + case GF_FOP_TRUNCATE: + stub->fn.truncate (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.offset, + stub->args.xdata); + break; + case GF_FOP_READ: + stub->fn.readv (stub->frame, stub->frame->this, + stub->args.fd, stub->args.size, + stub->args.offset, stub->args.flags, + stub->args.xdata); + break; + case GF_FOP_WRITE: + stub->fn.writev (stub->frame, stub->frame->this, + stub->args.fd, stub->args.vector, + stub->args.count, stub->args.offset, + stub->args.flags, stub->args.iobref, + stub->args.xdata); + break; + case GF_FOP_STATFS: + stub->fn.statfs (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.xdata); + break; + case GF_FOP_FLUSH: + stub->fn.flush (stub->frame, stub->frame->this, + stub->args.fd, stub->args.xdata); + break; + case GF_FOP_FSYNC: + stub->fn.fsync (stub->frame, stub->frame->this, + stub->args.fd, stub->args.datasync, + stub->args.xdata); + break; + case GF_FOP_SETXATTR: + stub->fn.setxattr (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.xattr, + stub->args.flags, stub->args.xdata); + break; + case GF_FOP_GETXATTR: + stub->fn.getxattr (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.name, + stub->args.xdata); + break; + case GF_FOP_FSETXATTR: + stub->fn.fsetxattr (stub->frame, stub->frame->this, + stub->args.fd, stub->args.xattr, + stub->args.flags, stub->args.xdata); + break; + case GF_FOP_FGETXATTR: + stub->fn.fgetxattr (stub->frame, stub->frame->this, + stub->args.fd, stub->args.name, + stub->args.xdata); + break; + case GF_FOP_REMOVEXATTR: + stub->fn.removexattr (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.name, + stub->args.xdata); + break; + case GF_FOP_FREMOVEXATTR: + stub->fn.fremovexattr (stub->frame, stub->frame->this, + stub->args.fd, stub->args.name, + stub->args.xdata); + break; + case GF_FOP_OPENDIR: + stub->fn.opendir (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.fd, + stub->args.xdata); + break; + case GF_FOP_FSYNCDIR: + stub->fn.fsyncdir (stub->frame, stub->frame->this, + stub->args.fd, stub->args.datasync, + stub->args.xdata); + break; + case GF_FOP_ACCESS: + stub->fn.access (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.mask, + stub->args.xdata); + break; + case GF_FOP_FTRUNCATE: + stub->fn.ftruncate (stub->frame, stub->frame->this, + stub->args.fd, stub->args.offset, + stub->args.xdata); + break; + case GF_FOP_FSTAT: + stub->fn.fstat (stub->frame, stub->frame->this, + stub->args.fd, stub->args.xdata); + break; + case GF_FOP_LK: + stub->fn.lk (stub->frame, stub->frame->this, + stub->args.fd, stub->args.cmd, + &stub->args.lock, stub->args.xdata); + break; + case GF_FOP_INODELK: + stub->fn.inodelk (stub->frame, stub->frame->this, + stub->args.volume, &stub->args.loc, + stub->args.cmd, &stub->args.lock, + stub->args.xdata); + break; + case GF_FOP_FINODELK: + stub->fn.finodelk (stub->frame, stub->frame->this, + stub->args.volume, stub->args.fd, + stub->args.cmd, &stub->args.lock, + stub->args.xdata); + break; + case GF_FOP_ENTRYLK: + stub->fn.entrylk (stub->frame, stub->frame->this, + stub->args.volume, &stub->args.loc, + stub->args.name, stub->args.entrylkcmd, + stub->args.entrylktype, stub->args.xdata); + break; + case GF_FOP_FENTRYLK: + stub->fn.fentrylk (stub->frame, stub->frame->this, + stub->args.volume, stub->args.fd, + stub->args.name, stub->args.entrylkcmd, + stub->args.entrylktype, stub->args.xdata); + break; + case GF_FOP_LOOKUP: + stub->fn.lookup (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.xdata); + break; + case GF_FOP_RCHECKSUM: + stub->fn.rchecksum (stub->frame, stub->frame->this, + stub->args.fd, stub->args.offset, + stub->args.size, stub->args.xdata); + break; + case GF_FOP_READDIR: + stub->fn.readdir (stub->frame, stub->frame->this, + stub->args.fd, stub->args.size, + stub->args.offset, stub->args.xdata); + break; case GF_FOP_READDIRP: - { - if (!stub->args.readdirp_cbk.fn) - STACK_UNWIND (stub->frame, - stub->args.readdirp_cbk.op_ret, - stub->args.readdirp_cbk.op_errno, - &stub->args.readdirp_cbk.entries); - else - stub->args.readdirp_cbk.fn (stub->frame, - stub->frame->cookie, - stub->frame->this, - stub->args.readdirp_cbk.op_ret, - stub->args.readdirp_cbk.op_errno, - &stub->args.readdirp_cbk.entries); - - if (stub->args.readdirp_cbk.op_ret > 0) - gf_dirent_free (&stub->args.readdirp_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_LOCK_NOTIFY: - { - if (!stub->args.lock_notify_cbk.fn) - STACK_UNWIND (stub->frame, - stub->args.lock_notify_cbk.op_ret, - stub->args.lock_notify_cbk.op_errno); - else - stub->args.lock_notify_cbk.fn (stub->frame, - stub->frame->cookie, - stub->frame->this, - stub->args.lock_notify_cbk.op_ret, - stub->args.lock_notify_cbk.op_errno); - break; - } - case GF_FOP_LOCK_FNOTIFY: - { - if (!stub->args.lock_fnotify_cbk.fn) - STACK_UNWIND (stub->frame, - stub->args.lock_fnotify_cbk.op_ret, - stub->args.lock_fnotify_cbk.op_errno); - else - stub->args.lock_fnotify_cbk.fn (stub->frame, - stub->frame->cookie, - stub->frame->this, - stub->args.lock_fnotify_cbk.op_ret, - stub->args.lock_fnotify_cbk.op_errno); - break; - } + stub->fn.readdirp (stub->frame, stub->frame->this, + stub->args.fd, stub->args.size, + stub->args.offset, stub->args.xdata); + break; + case GF_FOP_XATTROP: + stub->fn.xattrop (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.optype, + stub->args.xattr, stub->args.xdata); + break; + case GF_FOP_FXATTROP: + stub->fn.fxattrop (stub->frame, stub->frame->this, + stub->args.fd, stub->args.optype, + stub->args.xattr, stub->args.xdata); + break; case GF_FOP_SETATTR: - { - if (!stub->args.setattr_cbk.fn) - STACK_UNWIND (stub->frame, - stub->args.setattr_cbk.op_ret, - stub->args.setattr_cbk.op_errno, - &stub->args.setattr_cbk.statpre, - &stub->args.setattr_cbk.statpost); - else - stub->args.setattr_cbk.fn ( - stub->frame, - stub->frame->cookie, - stub->frame->this, - stub->args.setattr_cbk.op_ret, - stub->args.setattr_cbk.op_errno, - &stub->args.setattr_cbk.statpre, - &stub->args.setattr_cbk.statpost); + stub->fn.setattr (stub->frame, stub->frame->this, + &stub->args.loc, &stub->args.stat, + stub->args.valid, stub->args.xdata); break; - } case GF_FOP_FSETATTR: - { - if (!stub->args.fsetattr_cbk.fn) - STACK_UNWIND (stub->frame, - stub->args.fsetattr_cbk.op_ret, - stub->args.fsetattr_cbk.op_errno, - &stub->args.fsetattr_cbk.statpre, - &stub->args.fsetattr_cbk.statpost); - else - stub->args.fsetattr_cbk.fn ( - stub->frame, - stub->frame->cookie, - stub->frame->this, - stub->args.fsetattr_cbk.op_ret, - stub->args.fsetattr_cbk.op_errno, - &stub->args.fsetattr_cbk.statpre, - &stub->args.fsetattr_cbk.statpost); + stub->fn.fsetattr (stub->frame, stub->frame->this, + stub->args.fd, &stub->args.stat, + stub->args.valid, stub->args.xdata); + break; + case GF_FOP_FALLOCATE: + stub->fn.fallocate(stub->frame, stub->frame->this, + stub->args.fd, stub->args.flags, + stub->args.offset, stub->args.size, + stub->args.xdata); + break; + case GF_FOP_DISCARD: + stub->fn.discard(stub->frame, stub->frame->this, + stub->args.fd, stub->args.offset, + stub->args.size, stub->args.xdata); + break; + case GF_FOP_ZEROFILL: + stub->fn.zerofill(stub->frame, stub->frame->this, + stub->args.fd, stub->args.offset, + stub->args.size, stub->args.xdata); + break; + + default: + gf_log_callingfn ("call-stub", GF_LOG_ERROR, + "Invalid value of FOP (%d)", + stub->fop); break; } - case GF_FOP_MAXVALUE: - { - gf_log ("call-stub", - GF_LOG_DEBUG, - "Invalid value of FOP"); - } - break; - } out: - return; + 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: - { - struct iobref *iobref = stub->args.writev.iobref; - if (stub->args.writev.fd) - fd_unref (stub->args.writev.fd); - FREE (stub->args.writev.vector); - if (iobref) - iobref_unref (iobref); - 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_FSETXATTR: - { - fd_unref (stub->args.fsetxattr.fd); - if (stub->args.fsetxattr.dict) - dict_unref (stub->args.fsetxattr.dict); - break; - } +#define STUB_UNWIND(stb, fop, args ...) do { \ + if (stb->fn_cbk.fop) \ + stb->fn_cbk.fop (stb->frame, stb->frame->cookie, \ + stb->frame->this, stb->args_cbk.op_ret, \ + stb->args_cbk.op_errno, args); \ + else \ + STACK_UNWIND_STRICT (fop, stb->frame, stb->args_cbk.op_ret, \ + stb->args_cbk.op_errno, args); \ + } while (0) - case GF_FOP_FGETXATTR: - { - if (stub->args.fgetxattr.name) - FREE (stub->args.fgetxattr.name); - fd_unref (stub->args.fgetxattr.fd); - 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: - { - if (stub->args.inodelk.volume) - FREE (stub->args.inodelk.volume); - - loc_wipe (&stub->args.inodelk.loc); - break; - } - case GF_FOP_FINODELK: - { - if (stub->args.finodelk.volume) - FREE (stub->args.finodelk.volume); - - if (stub->args.finodelk.fd) - fd_unref (stub->args.finodelk.fd); - break; - } - case GF_FOP_ENTRYLK: - { - if (stub->args.entrylk.volume) - FREE (stub->args.entrylk.volume); - - 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.volume) - FREE (stub->args.fentrylk.volume); - - if (stub->args.fentrylk.name) - FREE (stub->args.fentrylk.name); +static void +call_resume_unwind (call_stub_t *stub) +{ + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - 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; - } + switch (stub->fop) { + case GF_FOP_OPEN: + STUB_UNWIND (stub, open, stub->args_cbk.fd, + stub->args_cbk.xdata); + break; + case GF_FOP_CREATE: + STUB_UNWIND (stub, create, stub->args_cbk.fd, + stub->args_cbk.inode, &stub->args_cbk.stat, + &stub->args_cbk.preparent, + &stub->args_cbk.postparent, + stub->args_cbk.xdata); + break; + case GF_FOP_STAT: + STUB_UNWIND (stub, stat, &stub->args_cbk.stat, + stub->args_cbk.xdata); + break; + case GF_FOP_READLINK: + STUB_UNWIND (stub, readlink, stub->args_cbk.buf, + &stub->args_cbk.stat, stub->args.xdata); + break; + case GF_FOP_MKNOD: + STUB_UNWIND (stub, mknod, stub->args_cbk.inode, + &stub->args_cbk.stat, &stub->args_cbk.preparent, + &stub->args_cbk.postparent, stub->args_cbk.xdata); + break; + case GF_FOP_MKDIR: + STUB_UNWIND (stub, mkdir, stub->args_cbk.inode, + &stub->args_cbk.stat, &stub->args_cbk.preparent, + &stub->args_cbk.postparent, stub->args_cbk.xdata); + break; + case GF_FOP_UNLINK: + STUB_UNWIND (stub, unlink, &stub->args_cbk.preparent, + &stub->args_cbk.postparent, stub->args_cbk.xdata); + break; + case GF_FOP_RMDIR: + STUB_UNWIND (stub, rmdir, &stub->args_cbk.preparent, + &stub->args_cbk.postparent, stub->args_cbk.xdata); + break; + case GF_FOP_SYMLINK: + STUB_UNWIND (stub, symlink, stub->args_cbk.inode, + &stub->args_cbk.stat, &stub->args_cbk.preparent, + &stub->args_cbk.postparent, stub->args_cbk.xdata); + break; + case GF_FOP_RENAME: + STUB_UNWIND (stub, rename, &stub->args_cbk.stat, + &stub->args_cbk.preparent, + &stub->args_cbk.postparent, + &stub->args_cbk.preparent2, + &stub->args_cbk.postparent2, + stub->args_cbk.xdata); + break; + case GF_FOP_LINK: + STUB_UNWIND (stub, link, stub->args_cbk.inode, + &stub->args_cbk.stat, &stub->args_cbk.preparent, + &stub->args_cbk.postparent, stub->args_cbk.xdata); + break; + case GF_FOP_TRUNCATE: + STUB_UNWIND (stub, truncate, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); + break; + case GF_FOP_READ: + STUB_UNWIND (stub, readv, stub->args_cbk.vector, + stub->args_cbk.count, &stub->args_cbk.stat, + stub->args_cbk.iobref, stub->args_cbk.xdata); + break; + case GF_FOP_WRITE: + STUB_UNWIND (stub, writev, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); + break; + case GF_FOP_STATFS: + STUB_UNWIND (stub, statfs, &stub->args_cbk.statvfs, + stub->args_cbk.xdata); + break; + case GF_FOP_FLUSH: + STUB_UNWIND (stub, flush, stub->args_cbk.xdata); + break; + case GF_FOP_FSYNC: + STUB_UNWIND (stub, fsync, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); + break; + case GF_FOP_SETXATTR: + STUB_UNWIND (stub, setxattr, stub->args_cbk.xdata); + break; + case GF_FOP_GETXATTR: + STUB_UNWIND (stub, getxattr, stub->args_cbk.xattr, + stub->args_cbk.xdata); + break; + case GF_FOP_FSETXATTR: + STUB_UNWIND (stub, fsetxattr, stub->args_cbk.xdata); + break; + case GF_FOP_FGETXATTR: + STUB_UNWIND (stub, fgetxattr, stub->args_cbk.xattr, + stub->args_cbk.xdata); + break; + case GF_FOP_REMOVEXATTR: + STUB_UNWIND (stub, removexattr, stub->args_cbk.xdata); + break; + case GF_FOP_FREMOVEXATTR: + STUB_UNWIND (stub, fremovexattr, stub->args_cbk.xdata); + break; + case GF_FOP_OPENDIR: + STUB_UNWIND (stub, opendir, stub->args_cbk.fd, + stub->args_cbk.xdata); + break; + case GF_FOP_FSYNCDIR: + STUB_UNWIND (stub, fsyncdir, stub->args_cbk.xdata); + break; + case GF_FOP_ACCESS: + STUB_UNWIND (stub, access, stub->args_cbk.xdata); + break; + case GF_FOP_FTRUNCATE: + STUB_UNWIND (stub, ftruncate, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); + break; + case GF_FOP_FSTAT: + STUB_UNWIND (stub, fstat, &stub->args_cbk.stat, + stub->args_cbk.xdata); + break; + case GF_FOP_LK: + STUB_UNWIND (stub, lk, &stub->args_cbk.lock, + stub->args_cbk.xdata); break; - } - - case GF_FOP_CHECKSUM: - { - loc_wipe (&stub->args.checksum.loc); + case GF_FOP_INODELK: + STUB_UNWIND (stub, inodelk, stub->args_cbk.xdata); + break; + case GF_FOP_FINODELK: + STUB_UNWIND (stub, finodelk, stub->args_cbk.xdata); + break; + case GF_FOP_ENTRYLK: + STUB_UNWIND (stub, entrylk, stub->args_cbk.xdata); break; - } - - case GF_FOP_RCHECKSUM: - { - if (stub->args.rchecksum.fd) - fd_unref (stub->args.rchecksum.fd); + case GF_FOP_FENTRYLK: + STUB_UNWIND (stub, fentrylk, stub->args_cbk.xdata); + break; + case GF_FOP_LOOKUP: + STUB_UNWIND (stub, lookup, stub->args_cbk.inode, + &stub->args_cbk.stat, stub->args_cbk.xdata, + &stub->args_cbk.postparent); + break; + case GF_FOP_RCHECKSUM: + STUB_UNWIND (stub, rchecksum, stub->args_cbk.weak_checksum, + stub->args_cbk.strong_checksum, stub->args_cbk.xdata); break; - } - - case GF_FOP_READDIR: - { - if (stub->args.readdir.fd) - fd_unref (stub->args.readdir.fd); + case GF_FOP_READDIR: + STUB_UNWIND (stub, readdir, &stub->args_cbk.entries, + stub->args_cbk.xdata); break; - } - case GF_FOP_READDIRP: - { - if (stub->args.readdirp.fd) - fd_unref (stub->args.readdirp.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_LOCK_NOTIFY: - { - loc_wipe (&stub->args.lock_notify.loc); + STUB_UNWIND (stub, readdir, &stub->args_cbk.entries, + stub->args_cbk.xdata); + break; + case GF_FOP_XATTROP: + STUB_UNWIND (stub, xattrop, stub->args_cbk.xattr, + stub->args_cbk.xdata); break; - } - case GF_FOP_LOCK_FNOTIFY: - { - if (stub->args.lock_fnotify.fd) - fd_unref (stub->args.lock_fnotify.fd); + case GF_FOP_FXATTROP: + STUB_UNWIND (stub, fxattrop, stub->args_cbk.xattr, + stub->args_cbk.xdata); break; - } case GF_FOP_SETATTR: - { - loc_wipe (&stub->args.setattr.loc); + STUB_UNWIND (stub, setattr, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); break; - } case GF_FOP_FSETATTR: - { - if (stub->args.fsetattr.fd) - fd_unref (stub->args.fsetattr.fd); + STUB_UNWIND (stub, fsetattr, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); break; - } - case GF_FOP_MAXVALUE: - { - gf_log ("call-stub", - GF_LOG_DEBUG, - "Invalid value of FOP"); - } - break; - default: + case GF_FOP_FALLOCATE: + STUB_UNWIND(stub, fallocate, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); + break; + case GF_FOP_DISCARD: + STUB_UNWIND(stub, discard, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); break; - } + case GF_FOP_ZEROFILL: + STUB_UNWIND(stub, zerofill, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); + break; + + default: + gf_log_callingfn ("call-stub", GF_LOG_ERROR, + "Invalid value of FOP (%d)", + stub->fop); + break; + } +out: + return; } static void -call_stub_destroy_unwind (call_stub_t *stub) +call_stub_wipe_args (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; + loc_wipe (&stub->args.loc); - 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; + loc_wipe (&stub->args.loc2); - 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; + if (stub->args.fd) + fd_unref (stub->args.fd); - case GF_FOP_LINK: - { - if (stub->args.link_cbk.inode) - inode_unref (stub->args.link_cbk.inode); - } - break; - - case GF_FOP_CHMOD: - break; + GF_FREE ((char *)stub->args.linkname); - case GF_FOP_CHOWN: - break; + GF_FREE (stub->args.vector); - case GF_FOP_TRUNCATE: - break; + if (stub->args.iobref) + iobref_unref (stub->args.iobref); - case GF_FOP_READ: - { - if (stub->args.readv_cbk.op_ret >= 0) { - struct iobref *iobref = stub->args.readv_cbk.iobref; - FREE (stub->args.readv_cbk.vector); - - if (iobref) { - iobref_unref (iobref); - } - } - } - 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_FSETXATTR: - break; - - case GF_FOP_FGETXATTR: - { - if (stub->args.fgetxattr_cbk.dict) - dict_unref (stub->args.fgetxattr_cbk.dict); - } - break; + if (stub->args.xattr) + dict_unref (stub->args.xattr); - case GF_FOP_REMOVEXATTR: - break; + GF_FREE ((char *)stub->args.name); - 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; + GF_FREE ((char *)stub->args.volume); - case GF_FOP_INODELK: - break; + if (stub->args.xdata) + dict_unref (stub->args.xdata); +} - case GF_FOP_FINODELK: - break; - case GF_FOP_ENTRYLK: - break; +static void +call_stub_wipe_args_cbk (call_stub_t *stub) +{ + if (stub->args_cbk.inode) + inode_unref (stub->args_cbk.inode); - case GF_FOP_FENTRYLK: - break; + GF_FREE ((char *)stub->args_cbk.buf); - case GF_FOP_UTIMENS: - break; + GF_FREE (stub->args_cbk.vector); - 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; + if (stub->args_cbk.iobref) + iobref_unref (stub->args_cbk.iobref); - 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_RCHECKSUM: - { - if (stub->args.rchecksum_cbk.op_ret >= 0) { - FREE (stub->args.rchecksum_cbk.strong_checksum); - } - } - break; - - case GF_FOP_READDIR: - { - if (stub->args.readdir_cbk.op_ret > 0) { - gf_dirent_free (&stub->args.readdir_cbk.entries); - } - } - break; + if (stub->args_cbk.fd) + fd_unref (stub->args_cbk.fd); - case GF_FOP_READDIRP: - { - if (stub->args.readdirp_cbk.op_ret > 0) { - gf_dirent_free (&stub->args.readdirp_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_SETATTR: - { - break; - } + if (stub->args_cbk.xattr) + dict_unref (stub->args_cbk.xattr); - case GF_FOP_FSETATTR: - { - break; - } + GF_FREE (stub->args_cbk.strong_checksum); - case GF_FOP_MAXVALUE: - { - gf_log ("call-stub", - GF_LOG_DEBUG, - "Invalid value of FOP"); - } - break; + if (stub->args_cbk.xdata) + dict_unref (stub->args_cbk.xdata); - default: - break; - } + if (!list_empty (&stub->args_cbk.entries.list)) + gf_dirent_free (&stub->args_cbk.entries); } - + 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); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + if (stub->wind) + call_stub_wipe_args (stub); + else + call_stub_wipe_args_cbk (stub); + + stub->stub_mem_pool = NULL; + + mem_put (stub); out: - return; + return; } + void call_resume (call_stub_t *stub) { xlator_t *old_THIS = NULL; - errno = EINVAL; - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + errno = EINVAL; + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - list_del_init (&stub->list); + list_del_init (&stub->list); old_THIS = THIS; THIS = stub->frame->this; @@ -4721,9 +2844,30 @@ call_resume (call_stub_t *stub) } THIS = old_THIS; - call_stub_destroy (stub); + call_stub_destroy (stub); out: - return; + return; } +void +call_unwind_error (call_stub_t *stub, int op_ret, int op_errno) +{ + xlator_t *old_THIS = NULL; + + list_del_init (&stub->list); + + old_THIS = THIS; + THIS = stub->frame->this; + { + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + call_resume_unwind (stub); + } + THIS = old_THIS; + + call_stub_destroy (stub); + + return; + +} diff --git a/libglusterfs/src/call-stub.h b/libglusterfs/src/call-stub.h index ae414026f..45bef8044 100644 --- a/libglusterfs/src/call-stub.h +++ b/libglusterfs/src/call-stub.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CALL_STUB_H_ @@ -34,681 +25,164 @@ typedef struct { char wind; call_frame_t *frame; glusterfs_fop_t fop; + struct mem_pool *stub_mem_pool; /* pointer to stub mempool in ctx_t */ 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; - struct stat postparent; - } 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 prebuf; - struct stat postbuf; - } 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 prebuf; - struct stat postbuf; - } 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; - struct stat sbuf; - } 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; - struct stat preparent; - struct stat postparent; - } 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; - struct stat preparent; - struct stat postparent; - } mkdir_cbk; - - /* unlink */ - struct { - fop_unlink_t fn; - loc_t loc; - } unlink; - struct { - fop_unlink_cbk_t fn; - int32_t op_ret, op_errno; - struct stat preparent; - struct stat postparent; - } unlink_cbk; - - /* rmdir */ - struct { - fop_rmdir_t fn; - loc_t loc; - } rmdir; - struct { - fop_rmdir_cbk_t fn; - int32_t op_ret, op_errno; - struct stat preparent; - struct stat postparent; - } 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; - struct stat preparent; - struct stat postparent; - } 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; - struct stat preoldparent; - struct stat postoldparent; - struct stat prenewparent; - struct stat postnewparent; - } 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; - struct stat preparent; - struct stat postparent; - } 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; - struct stat preparent; - struct stat postparent; - } create_cbk; - - /* open */ - struct { - fop_open_t fn; - loc_t loc; - int32_t flags; - fd_t *fd; - int32_t wbflags; - } 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; - struct iobref *iobref; - } readv_cbk; - - /* writev */ - struct { - fop_writev_t fn; - fd_t *fd; - struct iovec *vector; - int32_t count; - off_t off; - struct iobref *iobref; - } writev; - struct { - fop_writev_cbk_t fn; - int32_t op_ret, op_errno; - struct stat prebuf; - struct stat postbuf; - } 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; - struct stat prebuf; - struct stat postbuf; - } 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; - - /* fsetxattr */ - struct { - fop_fsetxattr_t fn; - fd_t *fd; - dict_t *dict; - int32_t flags; - } fsetxattr; - struct { - fop_fsetxattr_cbk_t fn; - int32_t op_ret, op_errno; - } fsetxattr_cbk; - - /* fgetxattr */ - struct { - fop_fgetxattr_t fn; - fd_t *fd; - const char *name; - } fgetxattr; - struct { - fop_fgetxattr_cbk_t fn; - int32_t op_ret, op_errno; - dict_t *dict; - } fgetxattr_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; - const char *volume; - 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; - const char *volume; - 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 *volume; - 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 *volume; - 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; - - /* readdirp */ - struct { - fop_readdirp_t fn; - fd_t *fd; - size_t size; - off_t off; - } readdirp; - struct { - fop_readdirp_cbk_t fn; - int32_t op_ret, op_errno; - gf_dirent_t entries; - } readdirp_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; - - /* rchecksum */ - struct { - fop_rchecksum_t fn; - fd_t *fd; - off_t offset; - int32_t len; - } rchecksum; - struct { - fop_rchecksum_cbk_t fn; - int32_t op_ret, op_errno; - uint32_t weak_checksum; - uint8_t *strong_checksum; - } rchecksum_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; - - struct { - fop_lock_notify_t fn; - loc_t loc; - int32_t timeout; - } lock_notify; - struct { - fop_lock_notify_cbk_t fn; - int32_t op_ret; - int32_t op_errno; - } lock_notify_cbk; - - struct { - fop_lock_fnotify_t fn; - fd_t *fd; - int32_t timeout; - } lock_fnotify; - struct { - fop_lock_fnotify_cbk_t fn; - int32_t op_ret; - int32_t op_errno; - } lock_fnotify_cbk; - - /* setattr */ - struct { - fop_setattr_t fn; - loc_t loc; - struct stat stbuf; - int32_t valid; - } setattr; - struct { - fop_setattr_cbk_t fn; - int32_t op_ret; - int32_t op_errno; - struct stat statpre; - struct stat statpost; - } setattr_cbk; - - /* fsetattr */ - struct { - fop_fsetattr_t fn; - fd_t *fd; - struct stat stbuf; - int32_t valid; - } fsetattr; - struct { - fop_fsetattr_cbk_t fn; - int32_t op_ret; - int32_t op_errno; - struct stat statpre; - struct stat statpost; - } fsetattr_cbk; + fop_lookup_t lookup; + fop_stat_t stat; + fop_fstat_t fstat; + fop_truncate_t truncate; + fop_ftruncate_t ftruncate; + 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_fsyncdir_t fsyncdir; + fop_statfs_t statfs; + fop_setxattr_t setxattr; + fop_getxattr_t getxattr; + fop_fgetxattr_t fgetxattr; + fop_fsetxattr_t fsetxattr; + fop_removexattr_t removexattr; + fop_fremovexattr_t fremovexattr; + fop_lk_t lk; + fop_inodelk_t inodelk; + fop_finodelk_t finodelk; + fop_entrylk_t entrylk; + fop_fentrylk_t fentrylk; + fop_readdir_t readdir; + fop_readdirp_t readdirp; + fop_rchecksum_t rchecksum; + fop_xattrop_t xattrop; + fop_fxattrop_t fxattrop; + fop_setattr_t setattr; + fop_fsetattr_t fsetattr; + fop_fallocate_t fallocate; + fop_discard_t discard; + fop_zerofill_t zerofill; + } fn; + union { + fop_lookup_cbk_t lookup; + fop_stat_cbk_t stat; + fop_fstat_cbk_t fstat; + fop_truncate_cbk_t truncate; + fop_ftruncate_cbk_t ftruncate; + fop_access_cbk_t access; + fop_readlink_cbk_t readlink; + fop_mknod_cbk_t mknod; + fop_mkdir_cbk_t mkdir; + fop_unlink_cbk_t unlink; + fop_rmdir_cbk_t rmdir; + fop_symlink_cbk_t symlink; + fop_rename_cbk_t rename; + fop_link_cbk_t link; + fop_create_cbk_t create; + fop_open_cbk_t open; + fop_readv_cbk_t readv; + fop_writev_cbk_t writev; + fop_flush_cbk_t flush; + fop_fsync_cbk_t fsync; + fop_opendir_cbk_t opendir; + fop_fsyncdir_cbk_t fsyncdir; + fop_statfs_cbk_t statfs; + fop_setxattr_cbk_t setxattr; + fop_getxattr_cbk_t getxattr; + fop_fgetxattr_cbk_t fgetxattr; + fop_fsetxattr_cbk_t fsetxattr; + fop_removexattr_cbk_t removexattr; + fop_fremovexattr_cbk_t fremovexattr; + fop_lk_cbk_t lk; + fop_inodelk_cbk_t inodelk; + fop_finodelk_cbk_t finodelk; + fop_entrylk_cbk_t entrylk; + fop_fentrylk_cbk_t fentrylk; + fop_readdir_cbk_t readdir; + fop_readdirp_cbk_t readdirp; + fop_rchecksum_cbk_t rchecksum; + fop_xattrop_cbk_t xattrop; + fop_fxattrop_cbk_t fxattrop; + fop_setattr_cbk_t setattr; + fop_fsetattr_cbk_t fsetattr; + fop_fallocate_cbk_t fallocate; + fop_discard_cbk_t discard; + fop_zerofill_cbk_t zerofill; + } fn_cbk; + + struct { + loc_t loc; // @old in rename(), link() + loc_t loc2; // @new in rename(), link() + fd_t *fd; + off_t offset; + int mask; + size_t size; + mode_t mode; + dev_t rdev; + mode_t umask; + int xflag; + int flags; + const char *linkname; + struct iovec *vector; + int count; + struct iobref *iobref; + int datasync; + dict_t *xattr; + const char *name; + int cmd; + struct gf_flock lock; + const char *volume; + entrylk_cmd entrylkcmd; + entrylk_type entrylktype; + gf_xattrop_flags_t optype; + int valid; + struct iatt stat; + dict_t *xdata; } args; + + struct { + int op_ret; + int op_errno; + inode_t *inode; + struct iatt stat; + struct iatt prestat; + struct iatt poststat; + struct iatt preparent; // @preoldparent in rename_cbk + struct iatt postparent; // @postoldparent in rename_cbk + struct iatt preparent2; // @prenewparent in rename_cbk + struct iatt postparent2; // @postnewparent in rename_cbk + const char *buf; + struct iovec *vector; + int count; + struct iobref *iobref; + fd_t *fd; + struct statvfs statvfs; + dict_t *xattr; + struct gf_flock lock; + gf_dirent_t entries; + uint32_t weak_checksum; + uint8_t *strong_checksum; + dict_t *xdata; + } args_cbk; } call_stub_t; + call_stub_t * fop_lookup_stub (call_frame_t *frame, fop_lookup_t fn, loc_t *loc, - dict_t *xattr_req); + dict_t *xdata); call_stub_t * fop_lookup_cbk_stub (call_frame_t *frame, @@ -716,137 +190,75 @@ fop_lookup_cbk_stub (call_frame_t *frame, int32_t op_ret, int32_t op_errno, inode_t *inode, - struct stat *buf, - dict_t *dict, - struct stat *postparent); + struct iatt *buf, + dict_t *xdata, + struct iatt *postparent); call_stub_t * fop_stat_stub (call_frame_t *frame, fop_stat_t fn, - loc_t *loc); + loc_t *loc, dict_t *xdata); 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); + struct iatt *buf, dict_t *xdata); call_stub_t * fop_fstat_stub (call_frame_t *frame, fop_fstat_t fn, - fd_t *fd); + fd_t *fd, dict_t *xdata); 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); + struct iatt *buf, dict_t *xdata); call_stub_t * fop_truncate_stub (call_frame_t *frame, fop_truncate_t fn, loc_t *loc, - off_t off); + off_t off, dict_t *xdata); 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 *prebuf, - struct stat *postbuf); + struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); call_stub_t * fop_ftruncate_stub (call_frame_t *frame, fop_ftruncate_t fn, fd_t *fd, - off_t off); + off_t off, dict_t *xdata); 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 *prebuf, - struct stat *postbuf); - -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); + struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); call_stub_t * fop_access_stub (call_frame_t *frame, fop_access_t fn, loc_t *loc, - int32_t mask); + int32_t mask, dict_t *xdata); call_stub_t * fop_access_cbk_stub (call_frame_t *frame, fop_access_cbk_t fn, int32_t op_ret, - int32_t op_errno); + int32_t op_errno, dict_t *xdata); call_stub_t * fop_readlink_stub (call_frame_t *frame, fop_readlink_t fn, loc_t *loc, - size_t size); + size_t size, dict_t *xdata); call_stub_t * fop_readlink_cbk_stub (call_frame_t *frame, @@ -854,14 +266,11 @@ fop_readlink_cbk_stub (call_frame_t *frame, int32_t op_ret, int32_t op_errno, const char *path, - struct stat *buf); + struct iatt *buf, dict_t *xdata); call_stub_t * -fop_mknod_stub (call_frame_t *frame, - fop_mknod_t fn, - loc_t *loc, - mode_t mode, - dev_t rdev); +fop_mknod_stub (call_frame_t *frame, fop_mknod_t fn, loc_t *loc, mode_t mode, + dev_t rdev, mode_t umask, dict_t *xdata); call_stub_t * fop_mknod_cbk_stub (call_frame_t *frame, @@ -869,15 +278,13 @@ fop_mknod_cbk_stub (call_frame_t *frame, int32_t op_ret, int32_t op_errno, inode_t *inode, - struct stat *buf, - struct stat *preparent, - struct stat *postparent); + struct iatt *buf, + struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); call_stub_t * -fop_mkdir_stub (call_frame_t *frame, - fop_mkdir_t fn, - loc_t *loc, - mode_t mode); +fop_mkdir_stub (call_frame_t *frame, fop_mkdir_t fn, loc_t *loc, mode_t mode, + mode_t umask, dict_t *xdata); call_stub_t * fop_mkdir_cbk_stub (call_frame_t *frame, @@ -885,41 +292,37 @@ fop_mkdir_cbk_stub (call_frame_t *frame, int32_t op_ret, int32_t op_errno, inode_t *inode, - struct stat *buf, - struct stat *preparent, - struct stat *postparent); + struct iatt *buf, + struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); call_stub_t * -fop_unlink_stub (call_frame_t *frame, - fop_unlink_t fn, - loc_t *loc); +fop_unlink_stub (call_frame_t *frame, fop_unlink_t fn, + loc_t *loc, int xflag, dict_t *xdata); call_stub_t * fop_unlink_cbk_stub (call_frame_t *frame, fop_unlink_cbk_t fn, int32_t op_ret, int32_t op_errno, - struct stat *preparent, - struct stat *postparent); + struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); call_stub_t * -fop_rmdir_stub (call_frame_t *frame, - fop_rmdir_t fn, - loc_t *loc); +fop_rmdir_stub (call_frame_t *frame, fop_rmdir_t fn, + loc_t *loc, int flags, dict_t *xdata); call_stub_t * fop_rmdir_cbk_stub (call_frame_t *frame, fop_rmdir_cbk_t fn, int32_t op_ret, int32_t op_errno, - struct stat *preparent, - struct stat *postparent); + struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); call_stub_t * -fop_symlink_stub (call_frame_t *frame, - fop_symlink_t fn, - const char *linkname, - loc_t *loc); +fop_symlink_stub (call_frame_t *frame, fop_symlink_t fn, + const char *linkname, loc_t *loc, mode_t umask, dict_t *xdata); call_stub_t * fop_symlink_cbk_stub (call_frame_t *frame, @@ -927,32 +330,32 @@ fop_symlink_cbk_stub (call_frame_t *frame, int32_t op_ret, int32_t op_errno, inode_t *inode, - struct stat *buf, - struct stat *preparent, - struct stat *postparent); + struct iatt *buf, + struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); call_stub_t * fop_rename_stub (call_frame_t *frame, fop_rename_t fn, loc_t *oldloc, - loc_t *newloc); + loc_t *newloc, dict_t *xdata); 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, - struct stat *preoldparent, - struct stat *postoldparent, - struct stat *prenewparent, - struct stat *postnewparent); + struct iatt *buf, + struct iatt *preoldparent, + struct iatt *postoldparent, + struct iatt *prenewparent, + struct iatt *postnewparent, dict_t *xdata); call_stub_t * fop_link_stub (call_frame_t *frame, fop_link_t fn, loc_t *oldloc, - loc_t *newloc); + loc_t *newloc, dict_t *xdata); call_stub_t * fop_link_cbk_stub (call_frame_t *frame, @@ -960,16 +363,14 @@ fop_link_cbk_stub (call_frame_t *frame, int32_t op_ret, int32_t op_errno, inode_t *inode, - struct stat *buf, - struct stat *preparent, - struct stat *postparent); + struct iatt *buf, + struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); 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); +fop_create_stub (call_frame_t *frame, fop_create_t fn, + loc_t *loc, int32_t flags, mode_t mode, + mode_t umask, fd_t *fd, dict_t *xdata); call_stub_t * fop_create_cbk_stub (call_frame_t *frame, @@ -978,9 +379,9 @@ fop_create_cbk_stub (call_frame_t *frame, int32_t op_errno, fd_t *fd, inode_t *inode, - struct stat *buf, - struct stat *preparent, - struct stat *postparent); + struct iatt *buf, + struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); call_stub_t * fop_open_stub (call_frame_t *frame, @@ -988,21 +389,21 @@ fop_open_stub (call_frame_t *frame, loc_t *loc, int32_t flags, fd_t *fd, - int32_t wbflags); + dict_t *xdata); 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); + fd_t *fd, dict_t *xdata); call_stub_t * fop_readv_stub (call_frame_t *frame, fop_readv_t fn, fd_t *fd, size_t size, - off_t off); + off_t off, uint32_t flags, dict_t *xdata); call_stub_t * fop_readv_cbk_stub (call_frame_t *frame, @@ -1011,8 +412,8 @@ fop_readv_cbk_stub (call_frame_t *frame, int32_t op_errno, struct iovec *vector, int32_t count, - struct stat *stbuf, - struct iobref *iobref); + struct iatt *stbuf, + struct iobref *iobref, dict_t *xdata); call_stub_t * fop_writev_stub (call_frame_t *frame, @@ -1020,268 +421,239 @@ fop_writev_stub (call_frame_t *frame, fd_t *fd, struct iovec *vector, int32_t count, - off_t off, - struct iobref *iobref); + off_t off, uint32_t flags, + struct iobref *iobref, dict_t *xdata); 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 *prebuf, - struct stat *postbuf); + struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); call_stub_t * fop_flush_stub (call_frame_t *frame, fop_flush_t fn, - fd_t *fd); + fd_t *fd, dict_t *xdata); call_stub_t * fop_flush_cbk_stub (call_frame_t *frame, fop_flush_cbk_t fn, int32_t op_ret, - int32_t op_errno); + int32_t op_errno, dict_t *xdata); call_stub_t * fop_fsync_stub (call_frame_t *frame, fop_fsync_t fn, fd_t *fd, - int32_t datasync); + int32_t datasync, dict_t *xdata); call_stub_t * fop_fsync_cbk_stub (call_frame_t *frame, fop_fsync_cbk_t fn, int32_t op_ret, int32_t op_errno, - struct stat *prebuf, - struct stat *postbuf); + struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); call_stub_t * fop_opendir_stub (call_frame_t *frame, fop_opendir_t fn, - loc_t *loc, fd_t *fd); + loc_t *loc, fd_t *fd, dict_t *xdata); 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); + fd_t *fd, dict_t *xdata); call_stub_t * fop_fsyncdir_stub (call_frame_t *frame, fop_fsyncdir_t fn, fd_t *fd, - int32_t datasync); + int32_t datasync, dict_t *xdata); call_stub_t * fop_fsyncdir_cbk_stub (call_frame_t *frame, fop_fsyncdir_cbk_t fn, int32_t op_ret, - int32_t op_errno); + int32_t op_errno, dict_t *xdata); call_stub_t * fop_statfs_stub (call_frame_t *frame, fop_statfs_t fn, - loc_t *loc); + loc_t *loc, dict_t *xdata); 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); + struct statvfs *buf, dict_t *xdata); call_stub_t * fop_setxattr_stub (call_frame_t *frame, fop_setxattr_t fn, loc_t *loc, dict_t *dict, - int32_t flags); + int32_t flags, dict_t *xdata); call_stub_t * fop_setxattr_cbk_stub (call_frame_t *frame, fop_setxattr_cbk_t fn, int32_t op_ret, - int32_t op_errno); + int32_t op_errno, dict_t *xdata); call_stub_t * fop_getxattr_stub (call_frame_t *frame, fop_getxattr_t fn, loc_t *loc, - const char *name); + const char *name, dict_t *xdata); 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); + dict_t *value, dict_t *xdata); call_stub_t * fop_fsetxattr_stub (call_frame_t *frame, fop_fsetxattr_t fn, fd_t *fd, dict_t *dict, - int32_t flags); + int32_t flags, dict_t *xdata); call_stub_t * fop_fsetxattr_cbk_stub (call_frame_t *frame, fop_fsetxattr_cbk_t fn, int32_t op_ret, - int32_t op_errno); + int32_t op_errno, dict_t *xdata); call_stub_t * fop_fgetxattr_stub (call_frame_t *frame, fop_fgetxattr_t fn, fd_t *fd, - const char *name); + const char *name, dict_t *xdata); call_stub_t * fop_fgetxattr_cbk_stub (call_frame_t *frame, fop_fgetxattr_cbk_t fn, int32_t op_ret, int32_t op_errno, - dict_t *value); + dict_t *value, dict_t *xdata); call_stub_t * fop_removexattr_stub (call_frame_t *frame, fop_removexattr_t fn, loc_t *loc, - const char *name); + const char *name, dict_t *xdata); call_stub_t * fop_removexattr_cbk_stub (call_frame_t *frame, fop_removexattr_cbk_t fn, int32_t op_ret, - int32_t op_errno); + int32_t op_errno, dict_t *xdata); + + +call_stub_t * +fop_fremovexattr_stub (call_frame_t *frame, + fop_fremovexattr_t fn, + fd_t *fd, + const char *name, dict_t *xdata); + +call_stub_t * +fop_fremovexattr_cbk_stub (call_frame_t *frame, + fop_fremovexattr_cbk_t fn, + int32_t op_ret, + int32_t op_errno, dict_t *xdata); + call_stub_t * fop_lk_stub (call_frame_t *frame, fop_lk_t fn, fd_t *fd, int32_t cmd, - struct flock *lock); + struct gf_flock *lock, dict_t *xdata); 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); + struct gf_flock *lock, dict_t *xdata); call_stub_t * fop_inodelk_stub (call_frame_t *frame, fop_inodelk_t fn, - const char *volume, loc_t *loc, int32_t cmd, - struct flock *lock); + const char *volume, loc_t *loc, int32_t cmd, + struct gf_flock *lock, dict_t *xdata); call_stub_t * fop_finodelk_stub (call_frame_t *frame, fop_finodelk_t fn, - const char *volume, fd_t *fd, int32_t cmd, - struct flock *lock); + const char *volume, fd_t *fd, int32_t cmd, + struct gf_flock *lock, dict_t *xdata); call_stub_t * fop_entrylk_stub (call_frame_t *frame, fop_entrylk_t fn, const char *volume, loc_t *loc, const char *basename, - entrylk_cmd cmd, entrylk_type type); + entrylk_cmd cmd, entrylk_type type, dict_t *xdata); call_stub_t * fop_fentrylk_stub (call_frame_t *frame, fop_fentrylk_t fn, const char *volume, fd_t *fd, const char *basename, - entrylk_cmd cmd, entrylk_type type); + entrylk_cmd cmd, entrylk_type type, dict_t *xdata); call_stub_t * fop_inodelk_cbk_stub (call_frame_t *frame, fop_inodelk_cbk_t fn, - int32_t op_ret, int32_t op_errno); + int32_t op_ret, int32_t op_errno, dict_t *xdata); call_stub_t * fop_finodelk_cbk_stub (call_frame_t *frame, fop_inodelk_cbk_t fn, - int32_t op_ret, int32_t op_errno); + int32_t op_ret, int32_t op_errno, dict_t *xdata); call_stub_t * fop_entrylk_cbk_stub (call_frame_t *frame, fop_entrylk_cbk_t fn, - int32_t op_ret, int32_t op_errno); + int32_t op_ret, int32_t op_errno, dict_t *xdata); call_stub_t * fop_fentrylk_cbk_stub (call_frame_t *frame, fop_entrylk_cbk_t fn, - int32_t op_ret, int32_t op_errno); + int32_t op_ret, int32_t op_errno, dict_t *xdata); call_stub_t * fop_readdir_stub (call_frame_t *frame, fop_readdir_t fn, fd_t *fd, size_t size, - off_t off); + off_t off, dict_t *xdata); call_stub_t * fop_readdirp_stub (call_frame_t *frame, - fop_readdir_t fn, + fop_readdirp_t fn, fd_t *fd, size_t size, - off_t off); + off_t off, + dict_t *xdata); call_stub_t * fop_readdirp_cbk_stub (call_frame_t *frame, fop_readdir_cbk_t fn, int32_t op_ret, int32_t op_errno, - gf_dirent_t *entries); + gf_dirent_t *entries, dict_t *xdata); 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); + gf_dirent_t *entries, dict_t *xdata); call_stub_t * fop_rchecksum_stub (call_frame_t *frame, fop_rchecksum_t fn, fd_t *fd, off_t offset, - int32_t len); + int32_t len, dict_t *xdata); call_stub_t * fop_rchecksum_cbk_stub (call_frame_t *frame, @@ -1289,88 +661,107 @@ fop_rchecksum_cbk_stub (call_frame_t *frame, int32_t op_ret, int32_t op_errno, uint32_t weak_checksum, - uint8_t *strong_checksum); + uint8_t *strong_checksum, dict_t *xdata); 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); + dict_t *xattr, dict_t *xdata); 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); + int32_t op_errno, dict_t *xdata); 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); + dict_t *xattr, dict_t *xdata); 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); - -call_stub_t * -fop_lock_notify_stub_cbk_stub (call_frame_t *frame, - fop_lock_notify_cbk_t fn, - int32_t op_ret, - int32_t op_errno); - -call_stub_t * -fop_lock_notify_stub (call_frame_t *frame, - fop_lock_notify_t fn, - loc_t *loc, - int32_t timeout); - -call_stub_t * -fop_lock_fnotify_stub_cbk_stub (call_frame_t *frame, - fop_lock_fnotify_cbk_t fn, - int32_t op_ret, - int32_t op_errno); - -call_stub_t * -fop_lock_fnotify_stub (call_frame_t *frame, - fop_lock_fnotify_t fn, - fd_t *fd, - int32_t timeout); + int32_t op_errno, dict_t *xdata); call_stub_t * fop_setattr_stub (call_frame_t *frame, fop_setattr_t fn, loc_t *loc, - struct stat *stbuf, - int32_t valid); + struct iatt *stbuf, + int32_t valid, dict_t *xdata); call_stub_t * fop_setattr_cbk_stub (call_frame_t *frame, fop_setattr_cbk_t fn, int32_t op_ret, int32_t op_errno, - struct stat *statpre, - struct stat *statpost); + struct iatt *statpre, + struct iatt *statpost, dict_t *xdata); call_stub_t * fop_fsetattr_stub (call_frame_t *frame, fop_fsetattr_t fn, fd_t *fd, - struct stat *stbuf, - int32_t valid); + struct iatt *stbuf, + int32_t valid, dict_t *xdata); call_stub_t * fop_fsetattr_cbk_stub (call_frame_t *frame, fop_setattr_cbk_t fn, int32_t op_ret, int32_t op_errno, - struct stat *statpre, - struct stat *statpost); + struct iatt *statpre, + struct iatt *statpost, dict_t *xdata); + +call_stub_t * +fop_fallocate_stub(call_frame_t *frame, + fop_fallocate_t fn, + fd_t *fd, + int32_t mode, off_t offset, + size_t len, dict_t *xdata); + +call_stub_t * +fop_fallocate_cbk_stub(call_frame_t *frame, + fop_fallocate_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *statpre, struct iatt *statpost, + dict_t *xdata); + +call_stub_t * +fop_discard_stub(call_frame_t *frame, + fop_discard_t fn, + fd_t *fd, + off_t offset, + size_t len, dict_t *xdata); + +call_stub_t * +fop_discard_cbk_stub(call_frame_t *frame, + fop_discard_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *statpre, struct iatt *statpost, + dict_t *xdata); + +call_stub_t * +fop_zerofill_stub(call_frame_t *frame, + fop_zerofill_t fn, + fd_t *fd, + off_t offset, + size_t len, dict_t *xdata); + +call_stub_t * +fop_zerofill_cbk_stub(call_frame_t *frame, + fop_zerofill_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *statpre, struct iatt *statpost, + dict_t *xdata); void call_resume (call_stub_t *stub); void call_stub_destroy (call_stub_t *stub); +void call_unwind_error (call_stub_t *stub, int op_ret, int op_errno); #endif diff --git a/libglusterfs/src/checksum.c b/libglusterfs/src/checksum.c index 2040fe73b..e14a3044c 100644 --- a/libglusterfs/src/checksum.c +++ b/libglusterfs/src/checksum.c @@ -1,28 +1,17 @@ /* - Copyright (c) 2009 Z RESEARCH, Inc. <http://www.zresearch.com> - This file is part of GlusterFS. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ -#include <inttypes.h> +#include <openssl/md5.h> +#include <stdint.h> #include "glusterfs.h" -#include "md5.h" -#include "checksum.h" - /* * The "weak" checksum required for the rsync algorithm, @@ -31,22 +20,26 @@ * * "a simple 32 bit checksum that can be upadted from either end * (inspired by Mark Adler's Adler-32 checksum)" + * + * Note: these functions are only called to compute checksums on + * pathnames; they don't need to handle arbitrarily long strings of + * data. Thus int32_t and uint32_t are sufficient */ uint32_t -gf_rsync_weak_checksum (char *buf1, int32_t len) +gf_rsync_weak_checksum (unsigned char *buf, size_t len) { - int32_t i; + int32_t i = 0; uint32_t s1, s2; - signed char *buf = (signed char *) buf1; uint32_t csum; s1 = s2 = 0; - for (i = 0; i < (len-4); i+=4) { - s2 += 4*(s1 + buf[i]) + 3*buf[i+1] + 2*buf[i+2] + buf[i+3]; - - s1 += buf[i+0] + buf[i+1] + buf[i+2] + buf[i+3]; + if (len >= 4) { + for (; i < (len-4); i+=4) { + s2 += 4*(s1 + buf[i]) + 3*buf[i+1] + 2*buf[i+2] + buf[i+3]; + s1 += buf[i+0] + buf[i+1] + buf[i+2] + buf[i+3]; + } } for (; i < len; i++) { @@ -66,13 +59,7 @@ gf_rsync_weak_checksum (char *buf1, int32_t len) */ void -gf_rsync_strong_checksum (char *buf, int32_t len, uint8_t *sum) +gf_rsync_strong_checksum (unsigned char *data, size_t len, unsigned char *md5) { - md_context m; - - md5_begin (&m); - md5_update (&m, (unsigned char *) buf, len); - md5_result (&m, (unsigned char *) sum); - - return; + MD5(data, len, md5); } diff --git a/libglusterfs/src/checksum.h b/libglusterfs/src/checksum.h index e79340904..bf7eeede8 100644 --- a/libglusterfs/src/checksum.h +++ b/libglusterfs/src/checksum.h @@ -1,29 +1,20 @@ /* - Copyright (c) 2009 Z RESEARCH, Inc. <http://www.zresearch.com> - This file is part of GlusterFS. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef __CHECKSUM_H__ #define __CHECKSUM_H__ uint32_t -gf_rsync_weak_checksum (char *buf, int32_t len); +gf_rsync_weak_checksum (unsigned char *buf, size_t len); void -gf_rsync_strong_checksum (char *buf, int32_t len, uint8_t *sum); +gf_rsync_strong_checksum (unsigned char *buf, size_t len, unsigned char *sum); #endif /* __CHECKSUM_H__ */ diff --git a/libglusterfs/src/circ-buff.c b/libglusterfs/src/circ-buff.c new file mode 100644 index 000000000..484ce7dc9 --- /dev/null +++ b/libglusterfs/src/circ-buff.c @@ -0,0 +1,202 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include "circ-buff.h" + +void +cb_destroy_data (circular_buffer_t *cb, + void (*destroy_buffer_data) (void *data)) +{ + if (destroy_buffer_data) + destroy_buffer_data (cb->data); + GF_FREE (cb->data); + return; +} + + +/* hold lock while calling this function */ +int +__cb_add_entry_buffer (buffer_t *buffer, void *item) +{ + circular_buffer_t *ptr = NULL; + int ret = -1; + //DO we really need the assert here? + GF_ASSERT (buffer->used_len <= buffer->size_buffer); + + if (buffer->use_once == _gf_true && + buffer->used_len == buffer->size_buffer) { + gf_log ("", GF_LOG_WARNING, "buffer %p is use once buffer", + buffer); + return -1; + } else { + if (buffer->used_len == buffer->size_buffer) { + if (buffer->cb[buffer->w_index]) { + ptr = buffer->cb[buffer->w_index]; + if (ptr->data) { + cb_destroy_data (ptr, + buffer->destroy_buffer_data); + ptr->data = NULL; + GF_FREE (ptr); + } + buffer->cb[buffer->w_index] = NULL; + ptr = NULL; + } + } + + buffer->cb[buffer->w_index] = + GF_CALLOC (1, sizeof (circular_buffer_t), + gf_common_mt_circular_buffer_t); + if (!buffer->cb[buffer->w_index]) + return -1; + + buffer->cb[buffer->w_index]->data = item; + ret = gettimeofday (&buffer->cb[buffer->w_index]->tv, NULL); + if (ret == -1) + gf_log_callingfn ("", GF_LOG_WARNING, "getting time of" + "the day failed"); + buffer->w_index++; + buffer->w_index %= buffer->size_buffer; + //used_buffer size cannot be greater than the total buffer size + + if (buffer->used_len < buffer->size_buffer) + buffer->used_len++; + return buffer->w_index; + } +} + +int +cb_add_entry_buffer (buffer_t *buffer, void *item) +{ + int write_index = -1; + + pthread_mutex_lock (&buffer->lock); + { + write_index = __cb_add_entry_buffer (buffer, item); + } + pthread_mutex_unlock (&buffer->lock); + + return write_index; +} + +void +cb_buffer_show (buffer_t *buffer) +{ + pthread_mutex_lock (&buffer->lock); + { + gf_log ("", GF_LOG_DEBUG, "w_index: %d, size: %"GF_PRI_SIZET + " used_buffer: %d", buffer->w_index, + buffer->size_buffer, + buffer->used_len); + } + pthread_mutex_unlock (&buffer->lock); +} + +void +cb_buffer_dump (buffer_t *buffer, void *data, + int (fn) (circular_buffer_t *buffer, void *data)) +{ + int index = 0; + circular_buffer_t *entry = NULL; + int entries = 0; + int ul = 0; + int w_ind = 0; + int size_buff = 0; + int i = 0; + + ul = buffer->used_len; + w_ind = buffer->w_index; + size_buff = buffer->size_buffer; + + pthread_mutex_lock (&buffer->lock); + { + if (buffer->use_once == _gf_false) { + index = (size_buff + (w_ind - ul))%size_buff; + for (entries = 0; entries < buffer->used_len; + entries++) { + entry = buffer->cb[index]; + if (entry) + fn (entry, data); + else + gf_log_callingfn ("", GF_LOG_WARNING, + "Null entry in " + "circular buffer at " + "index %d.", index); + + index++; + index %= buffer->size_buffer; + } + } else { + for (i = 0; i < buffer->used_len ; i++) { + entry = buffer->cb[i]; + fn (entry, data); + } + } + } + pthread_mutex_unlock (&buffer->lock); +} + +buffer_t * +cb_buffer_new (size_t buffer_size, gf_boolean_t use_once, + void (*destroy_buffer_data) (void *data)) +{ + buffer_t *buffer = NULL; + + buffer = GF_CALLOC (1, sizeof (*buffer), gf_common_mt_buffer_t); + if (!buffer) { + gf_log ("", GF_LOG_ERROR, "could not allocate the " + "buffer"); + goto out; + } + + buffer->cb = GF_CALLOC (buffer_size, + sizeof (circular_buffer_t *), + gf_common_mt_circular_buffer_t); + if (!buffer->cb) { + gf_log ("", GF_LOG_ERROR, "could not allocate the " + "memory for the circular buffer"); + GF_FREE (buffer); + buffer = NULL; + goto out; + } + + buffer->w_index = 0; + buffer->size_buffer = buffer_size; + buffer->use_once = use_once; + buffer->used_len = 0; + buffer->destroy_buffer_data = destroy_buffer_data; + pthread_mutex_init (&buffer->lock, NULL); + +out: + return buffer; +} + +void +cb_buffer_destroy (buffer_t *buffer) +{ + int i = 0; + circular_buffer_t *ptr = NULL; + if (buffer) { + if (buffer->cb) { + for (i = 0; i < buffer->used_len ; i++) { + ptr = buffer->cb[i]; + if (ptr->data) { + cb_destroy_data (ptr, + buffer->destroy_buffer_data); + ptr->data = NULL; + GF_FREE (ptr); + } + } + GF_FREE (buffer->cb); + } + pthread_mutex_destroy (&buffer->lock); + GF_FREE (buffer); + } +} + diff --git a/libglusterfs/src/circ-buff.h b/libglusterfs/src/circ-buff.h new file mode 100644 index 000000000..e3459f5e3 --- /dev/null +++ b/libglusterfs/src/circ-buff.h @@ -0,0 +1,64 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _CB_H +#define _CB_H + +#include "common-utils.h" +#include "logging.h" +#include "mem-types.h" + +#define BUFFER_SIZE 10 +#define TOTAL_SIZE BUFFER_SIZE + 1 + + +struct _circular_buffer { + struct timeval tv; + void *data; +}; + +typedef struct _circular_buffer circular_buffer_t; + +struct _buffer { + unsigned int w_index; + size_t size_buffer; + gf_boolean_t use_once; + /* This variable is assigned the proper value at the time of initing */ + /* the buffer. It indicates, whether the buffer should be used once */ + /* it becomes full. */ + + int used_len; + /* indicates the amount of circular buffer used. */ + + circular_buffer_t **cb; + void (*destroy_buffer_data) (void *data); + pthread_mutex_t lock; +}; + +typedef struct _buffer buffer_t; + +int +cb_add_entry_buffer (buffer_t *buffer, void *item); + +void +cb_buffer_show (buffer_t *buffer); + +buffer_t * +cb_buffer_new (size_t buffer_size,gf_boolean_t use_buffer_once, + void (*destroy_data) (void *data)); + +void +cb_buffer_destroy (buffer_t *buffer); + +void +cb_buffer_dump (buffer_t *buffer, void *data, + int (fn) (circular_buffer_t *buffer, void *data)); + +#endif /* _CB_H */ diff --git a/libglusterfs/src/client_t.c b/libglusterfs/src/client_t.c new file mode 100644 index 000000000..06447dc5d --- /dev/null +++ b/libglusterfs/src/client_t.c @@ -0,0 +1,890 @@ +/* + Copyright (c) 2008-2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include "glusterfs.h" +#include "dict.h" +#include "statedump.h" +#include "client_t.h" +#include "list.h" +#include "rpcsvc.h" + + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + + +static int +gf_client_chain_client_entries (cliententry_t *entries, uint32_t startidx, + uint32_t endcount) +{ + uint32_t i = 0; + + if (!entries) { + gf_log_callingfn ("client_t", GF_LOG_WARNING, "!entries"); + return -1; + } + + /* Chain only till the second to last entry because we want to + * ensure that the last entry has GF_CLIENTTABLE_END. + */ + for (i = startidx; i < (endcount - 1); i++) + entries[i].next_free = i + 1; + + /* i has already been incremented upto the last entry. */ + entries[i].next_free = GF_CLIENTTABLE_END; + + return 0; +} + + +static int +gf_client_clienttable_expand (clienttable_t *clienttable, uint32_t nr) +{ + cliententry_t *oldclients = NULL; + uint32_t oldmax_clients = -1; + int ret = -1; + + if (clienttable == NULL || nr < 0) { + gf_log_callingfn ("client_t", GF_LOG_ERROR, "invalid argument"); + ret = EINVAL; + goto out; + } + + /* expand size by power-of-two... + this originally came from .../xlators/protocol/server/src/server.c + where it was not commented */ + nr /= (1024 / sizeof (cliententry_t)); + nr = gf_roundup_next_power_of_two (nr + 1); + nr *= (1024 / sizeof (cliententry_t)); + + oldclients = clienttable->cliententries; + oldmax_clients = clienttable->max_clients; + + clienttable->cliententries = GF_CALLOC (nr, sizeof (cliententry_t), + gf_common_mt_cliententry_t); + if (!clienttable->cliententries) { + ret = ENOMEM; + goto out; + } + clienttable->max_clients = nr; + + if (oldclients) { + uint32_t cpy = oldmax_clients * sizeof (cliententry_t); + memcpy (clienttable->cliententries, oldclients, cpy); + } + + gf_client_chain_client_entries (clienttable->cliententries, oldmax_clients, + clienttable->max_clients); + + /* Now that expansion is done, we must update the client list + * head pointer so that the client allocation functions can continue + * using the expanded table. + */ + clienttable->first_free = oldmax_clients; + GF_FREE (oldclients); + ret = 0; +out: + return ret; +} + + +clienttable_t * +gf_clienttable_alloc (void) +{ + clienttable_t *clienttable = NULL; + + clienttable = + GF_CALLOC (1, sizeof (clienttable_t), gf_common_mt_clienttable_t); + if (!clienttable) + return NULL; + + LOCK_INIT (&clienttable->lock); + gf_client_clienttable_expand (clienttable, GF_CLIENTTABLE_INITIAL_SIZE); + return clienttable; +} + + +void +gf_client_clienttable_destroy (clienttable_t *clienttable) +{ + client_t *client = NULL; + cliententry_t *cliententries = NULL; + uint32_t client_count = 0; + int32_t i = 0; + + if (!clienttable) { + gf_log_callingfn ("client_t", GF_LOG_WARNING, "!clienttable"); + return; + } + + LOCK (&clienttable->lock); + { + client_count = clienttable->max_clients; + clienttable->max_clients = 0; + cliententries = clienttable->cliententries; + clienttable->cliententries = NULL; + } + UNLOCK (&clienttable->lock); + + if (cliententries != NULL) { + for (i = 0; i < client_count; i++) { + client = cliententries[i].client; + if (client != NULL) { + gf_client_unref (client); + } + } + + GF_FREE (cliententries); + LOCK_DESTROY (&clienttable->lock); + GF_FREE (clienttable); + } +} + +client_t * +gf_client_get (xlator_t *this, struct rpcsvc_auth_data *cred, char *client_uid) +{ + client_t *client = NULL; + cliententry_t *cliententry = NULL; + clienttable_t *clienttable = NULL; + unsigned int i = 0; + + if (this == NULL || client_uid == NULL) { + gf_log_callingfn ("client_t", GF_LOG_ERROR, "invalid argument"); + errno = EINVAL; + return NULL; + } + + gf_log (this->name, GF_LOG_INFO, "client_uid=%s", client_uid); + + clienttable = this->ctx->clienttable; + + LOCK (&clienttable->lock); + { + for (; i < clienttable->max_clients; i++) { + client = clienttable->cliententries[i].client; + if (client == NULL) + continue; + /* + * look for matching client_uid, _and_ + * if auth was used, matching auth flavour and data + */ + if (strcmp (client_uid, client->client_uid) == 0 && + (cred->flavour != AUTH_NONE && + (cred->flavour == client->auth.flavour && + (size_t) cred->datalen == client->auth.len && + memcmp (cred->authdata, + client->auth.data, + client->auth.len) == 0))) { +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) + __sync_add_and_fetch(&client->ref.bind, 1); +#else + LOCK (&client->ref.lock); + { + ++client->ref.bind; + } + UNLOCK (&client->ref.lock); +#endif + break; + } + } + if (client) { + gf_client_ref (client); + goto unlock; + } + client = GF_CALLOC (1, sizeof(client_t), gf_common_mt_client_t); + if (client == NULL) { + errno = ENOMEM; + goto unlock; + } + + client->this = this; + + LOCK_INIT (&client->scratch_ctx.lock); + LOCK_INIT (&client->ref.lock); + + client->client_uid = gf_strdup (client_uid); + if (client->client_uid == NULL) { + GF_FREE (client); + client = NULL; + errno = ENOMEM; + goto unlock; + } + client->scratch_ctx.count = GF_CLIENTCTX_INITIAL_SIZE; + client->scratch_ctx.ctx = + GF_CALLOC (GF_CLIENTCTX_INITIAL_SIZE, + sizeof (struct client_ctx), + gf_common_mt_client_ctx); + if (client->scratch_ctx.ctx == NULL) { + GF_FREE (client->client_uid); + GF_FREE (client); + client = NULL; + errno = ENOMEM; + goto unlock; + } + + /* no need to do these atomically here */ + client->ref.bind = client->ref.count = 1; + + client->auth.flavour = cred->flavour; + if (cred->flavour != AUTH_NONE) { + client->auth.data = + GF_CALLOC (1, cred->datalen, + gf_common_mt_client_t); + if (client->auth.data == NULL) { + GF_FREE (client->scratch_ctx.ctx); + GF_FREE (client->client_uid); + GF_FREE (client); + client = NULL; + errno = ENOMEM; + goto unlock; + } + memcpy (client->auth.data, cred->authdata, + cred->datalen); + client->auth.len = cred->datalen; + } + + client->tbl_index = clienttable->first_free; + cliententry = &clienttable->cliententries[client->tbl_index]; + cliententry->client = client; + clienttable->first_free = cliententry->next_free; + cliententry->next_free = GF_CLIENTENTRY_ALLOCATED; + gf_client_ref (client); + } +unlock: + UNLOCK (&clienttable->lock); + + return client; +} + +void +gf_client_put (client_t *client, gf_boolean_t *detached) +{ + gf_boolean_t unref = _gf_false; + int bind_ref; + + if (detached) + *detached = _gf_false; + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) + bind_ref = __sync_sub_and_fetch(&client->ref.bind, 1); +#else + LOCK (&client->ref.lock); + { + bind_ref = --client->ref.bind; + } + UNLOCK (&client->ref.lock); +#endif + if (bind_ref == 0) + unref = _gf_true; + + if (unref) { + gf_log (THIS->name, GF_LOG_INFO, "Shutting down connection %s", + client->client_uid); + if (detached) + *detached = _gf_true; + gf_client_unref (client); + } +} + + +client_t * +gf_client_ref (client_t *client) +{ + if (!client) { + gf_log_callingfn ("client_t", GF_LOG_ERROR, "null client"); + return NULL; + } + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) + __sync_add_and_fetch(&client->ref.count, 1); +#else + LOCK (&client->ref.lock); + { + ++client->ref.count; + } + UNLOCK (&client->ref.lock); +#endif + return client; +} + + +static void +client_destroy (client_t *client) +{ + clienttable_t *clienttable = NULL; + glusterfs_graph_t *gtrav = NULL; + xlator_t *xtrav = NULL; + + if (client == NULL){ + gf_log_callingfn ("xlator", GF_LOG_ERROR, "invalid argument"); + goto out; + } + + clienttable = client->this->ctx->clienttable; + + LOCK_DESTROY (&client->scratch_ctx.lock); + LOCK_DESTROY (&client->ref.lock); + + LOCK (&clienttable->lock); + { + clienttable->cliententries[client->tbl_index].client = NULL; + clienttable->cliententries[client->tbl_index].next_free = + clienttable->first_free; + clienttable->first_free = client->tbl_index; + } + UNLOCK (&clienttable->lock); + + list_for_each_entry (gtrav, &client->this->ctx->graphs, list) { + xtrav = gtrav->top; + while (xtrav != NULL) { + if (xtrav->cbks->client_destroy != NULL) + xtrav->cbks->client_destroy (xtrav, client); + xtrav = xtrav->next; + } + } + GF_FREE (client->auth.data); + GF_FREE (client->scratch_ctx.ctx); + GF_FREE (client->client_uid); + GF_FREE (client); +out: + return; +} + + +int +gf_client_disconnect (client_t *client) +{ + int ret = 0; + glusterfs_graph_t *gtrav = NULL; + xlator_t *xtrav = NULL; + + list_for_each_entry (gtrav, &client->this->ctx->graphs, list) { + xtrav = gtrav->top; + while (xtrav != NULL) { + if (xtrav->cbks->client_disconnect != NULL) + if (xtrav->cbks->client_disconnect (xtrav, client) != 0) + ret = -1; + xtrav = xtrav->next; + } + } + + return ret; +} + + +void +gf_client_unref (client_t *client) +{ + int refcount; + + if (!client) { + gf_log_callingfn ("client_t", GF_LOG_ERROR, "client is NULL"); + return; + } + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) + refcount = __sync_sub_and_fetch(&client->ref.count, 1); +#else + LOCK (&client->ref.lock); + { + refcount = --client->ref.count; + } + UNLOCK (&client->ref.lock); +#endif + if (refcount == 0) { + client_destroy (client); + } +} + + +static int +client_ctx_set_int (client_t *client, void *key, void *value) +{ + int index = 0; + int ret = 0; + int set_idx = -1; + + for (index = 0; index < client->scratch_ctx.count; index++) { + if (!client->scratch_ctx.ctx[index].ctx_key) { + if (set_idx == -1) + set_idx = index; + /* dont break, to check if key already exists + further on */ + } + if (client->scratch_ctx.ctx[index].ctx_key == key) { + set_idx = index; + break; + } + } + + if (set_idx == -1) { + ret = -1; + goto out; + } + + client->scratch_ctx.ctx[set_idx].ctx_key = key; + client->scratch_ctx.ctx[set_idx].ctx_value = value; + +out: + return ret; +} + + +int +client_ctx_set (client_t *client, void *key, void *value) +{ + int ret = 0; + + if (!client || !key) + return -1; + + LOCK (&client->scratch_ctx.lock); + { + ret = client_ctx_set_int (client, key, value); + } + UNLOCK (&client->scratch_ctx.lock); + + return ret; +} + + +static int +client_ctx_get_int (client_t *client, void *key, void **value) +{ + int index = 0; + int ret = 0; + + for (index = 0; index < client->scratch_ctx.count; index++) { + if (client->scratch_ctx.ctx[index].ctx_key == key) + break; + } + + if (index == client->scratch_ctx.count) { + ret = -1; + goto out; + } + + if (value) + *value = client->scratch_ctx.ctx[index].ctx_value; + +out: + return ret; +} + + +int +client_ctx_get (client_t *client, void *key, void **value) +{ + int ret = 0; + + if (!client || !key) + return -1; + + LOCK (&client->scratch_ctx.lock); + { + ret = client_ctx_get_int (client, key, value); + } + UNLOCK (&client->scratch_ctx.lock); + + return ret; +} + + +static int +client_ctx_del_int (client_t *client, void *key, void **value) +{ + int index = 0; + int ret = 0; + + for (index = 0; index < client->scratch_ctx.count; index++) { + if (client->scratch_ctx.ctx[index].ctx_key == key) + break; + } + + if (index == client->scratch_ctx.count) { + ret = -1; + goto out; + } + + if (value) + *value = client->scratch_ctx.ctx[index].ctx_value; + + client->scratch_ctx.ctx[index].ctx_key = 0; + client->scratch_ctx.ctx[index].ctx_value = 0; + +out: + return ret; +} + + +int +client_ctx_del (client_t *client, void *key, void **value) +{ + int ret = 0; + + if (!client || !key) + return -1; + + LOCK (&client->scratch_ctx.lock); + { + ret = client_ctx_del_int (client, key, value); + } + UNLOCK (&client->scratch_ctx.lock); + + return ret; +} + + +void +client_dump (client_t *client, char *prefix) +{ + char key[GF_DUMP_MAX_BUF_LEN]; + + if (!client) + return; + + memset(key, 0, sizeof key); + gf_proc_dump_write("refcount", "%d", client->ref.count); +} + + +void +cliententry_dump (cliententry_t *cliententry, char *prefix) +{ + if (!cliententry) + return; + + if (GF_CLIENTENTRY_ALLOCATED != cliententry->next_free) + return; + + if (cliententry->client) + client_dump(cliententry->client, prefix); +} + + +void +clienttable_dump (clienttable_t *clienttable, char *prefix) +{ + int i = 0; + int ret = -1; + char key[GF_DUMP_MAX_BUF_LEN] = {0}; + + if (!clienttable) + return; + + ret = TRY_LOCK (&clienttable->lock); + { + if (ret) { + gf_log ("client_t", GF_LOG_WARNING, + "Unable to acquire lock"); + return; + } + memset(key, 0, sizeof key); + gf_proc_dump_build_key(key, prefix, "maxclients"); + gf_proc_dump_write(key, "%d", clienttable->max_clients); + gf_proc_dump_build_key(key, prefix, "first_free"); + gf_proc_dump_write(key, "%d", clienttable->first_free); + for ( i = 0 ; i < clienttable->max_clients; i++) { + if (GF_CLIENTENTRY_ALLOCATED == + clienttable->cliententries[i].next_free) { + gf_proc_dump_build_key(key, prefix, + "cliententry[%d]", i); + gf_proc_dump_add_section(key); + cliententry_dump(&clienttable->cliententries[i], + key); + } + } + } + UNLOCK(&clienttable->lock); +} + + +void +client_ctx_dump (client_t *client, char *prefix) +{ +#if 0 /* TBD, FIXME */ + struct client_ctx *client_ctx = NULL; + xlator_t *xl = NULL; + int i = 0; + + if ((client == NULL) || (client->ctx == NULL)) { + goto out; + } + + LOCK (&client->ctx_lock); + if (client->ctx != NULL) { + client_ctx = GF_CALLOC (client->inode->table->xl->graph->ctx_count, + sizeof (*client_ctx), + gf_common_mt_client_ctx); + if (client_ctx == NULL) { + goto unlock; + } + + for (i = 0; i < client->inode->table->xl->graph->ctx_count; i++) { + client_ctx[i] = client->ctx[i]; + } + } +unlock: + UNLOCK (&client->ctx_lock); + + if (client_ctx == NULL) { + goto out; + } + + for (i = 0; i < client->inode->table->xl->graph->ctx_count; i++) { + if (client_ctx[i].xl_key) { + xl = (xlator_t *)(long)client_ctx[i].xl_key; + if (xl->dumpops && xl->dumpops->clientctx) + xl->dumpops->clientctx (xl, client); + } + } +out: + GF_FREE (client_ctx); +#endif +} + + +/* + * the following functions are here to preserve legacy behavior of the + * protocol/server xlator dump, but perhaps they should just be folded + * into the client dump instead? + */ +int +gf_client_dump_fdtables_to_dict (xlator_t *this, dict_t *dict) +{ + clienttable_t *clienttable = NULL; + int count = 0; + int ret = -1; +#ifdef NOTYET + client_t *client = NULL; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; +#endif + + GF_VALIDATE_OR_GOTO (THIS->name, this, out); + GF_VALIDATE_OR_GOTO (this->name, dict, out); + + clienttable = this->ctx->clienttable; + + if (!clienttable) + return -1; + +#ifdef NOTYET + ret = TRY_LOCK (&clienttable->lock); + { + if (ret) { + gf_log ("client_t", GF_LOG_WARNING, + "Unable to acquire lock"); + return -1; + } + for ( ; count < clienttable->max_clients; count++) { + if (GF_CLIENTENTRY_ALLOCATED != + clienttable->cliententries[count].next_free) + continue; + client = clienttable->cliententries[count].client; + memset(key, 0, sizeof key); + snprintf (key, sizeof key, "conn%d", count++); + fdtable_dump_to_dict (client->server_ctx.fdtable, + key, dict); + } + } + UNLOCK(&clienttable->lock); +#endif + + ret = dict_set_int32 (dict, "conncount", count); +out: + return ret; +} + +int +gf_client_dump_fdtables (xlator_t *this) +{ + client_t *client = NULL; + clienttable_t *clienttable = NULL; + int count = 1; + int ret = -1; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + + GF_VALIDATE_OR_GOTO (THIS->name, this, out); + + clienttable = this->ctx->clienttable; + + if (!clienttable) + return -1; + + ret = TRY_LOCK (&clienttable->lock); + { + if (ret) { + gf_log ("client_t", GF_LOG_WARNING, + "Unable to acquire lock"); + return -1; + } + + + for ( ; count < clienttable->max_clients; count++) { + if (GF_CLIENTENTRY_ALLOCATED != + clienttable->cliententries[count].next_free) + continue; + client = clienttable->cliententries[count].client; + memset(key, 0, sizeof key); + if (client->client_uid) { + gf_proc_dump_build_key (key, "conn", + "%d.id", count); + gf_proc_dump_write (key, "%s", + client->client_uid); + } + + gf_proc_dump_build_key (key, "conn", "%d.ref", + count); + gf_proc_dump_write (key, "%d", client->ref.count); + if (client->bound_xl) { + gf_proc_dump_build_key (key, "conn", + "%d.bound_xl", count); + gf_proc_dump_write (key, "%s", + client->bound_xl->name); + } + +#ifdef NOTYET + gf_proc_dump_build_key (key, "conn","%d.id", count); + fdtable_dump (client->server_ctx.fdtable, key); +#endif + } + } + + UNLOCK(&clienttable->lock); + + ret = 0; +out: + return ret; +} + + +int +gf_client_dump_inodes_to_dict (xlator_t *this, dict_t *dict) +{ + client_t *client = NULL; + clienttable_t *clienttable = NULL; + xlator_t *prev_bound_xl = NULL; + char key[32] = {0,}; + int count = 0; + int ret = -1; + + GF_VALIDATE_OR_GOTO (THIS->name, this, out); + GF_VALIDATE_OR_GOTO (this->name, dict, out); + + clienttable = this->ctx->clienttable; + + if (!clienttable) + return -1; + + ret = TRY_LOCK (&clienttable->lock); + { + if (ret) { + gf_log ("client_t", GF_LOG_WARNING, + "Unable to acquire lock"); + return -1; + } + for ( ; count < clienttable->max_clients; count++) { + if (GF_CLIENTENTRY_ALLOCATED != + clienttable->cliententries[count].next_free) + continue; + client = clienttable->cliententries[count].client; + memset(key, 0, sizeof key); + if (client->bound_xl && client->bound_xl->itable) { + /* Presently every brick contains only + * one bound_xl for all connections. + * This will lead to duplicating of + * the inode lists, if listing is + * done for every connection. This + * simple check prevents duplication + * in the present case. If need arises + * the check can be improved. + */ + if (client->bound_xl == prev_bound_xl) + continue; + prev_bound_xl = client->bound_xl; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "conn%d", count); + inode_table_dump_to_dict (client->bound_xl->itable, + key, dict); + } + } + } + UNLOCK(&clienttable->lock); + + ret = dict_set_int32 (dict, "conncount", count); + +out: + if (prev_bound_xl) + prev_bound_xl = NULL; + return ret; +} + +int +gf_client_dump_inodes (xlator_t *this) +{ + client_t *client = NULL; + clienttable_t *clienttable = NULL; + xlator_t *prev_bound_xl = NULL; + int count = 1; + int ret = -1; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + + GF_VALIDATE_OR_GOTO (THIS->name, this, out); + + clienttable = this->ctx->clienttable; + + if (!clienttable) + goto out; + + ret = TRY_LOCK (&clienttable->lock); + { + if (ret) { + gf_log ("client_t", GF_LOG_WARNING, + "Unable to acquire lock"); + goto out; + } + + for ( ; count < clienttable->max_clients; count++) { + if (GF_CLIENTENTRY_ALLOCATED != + clienttable->cliententries[count].next_free) + continue; + client = clienttable->cliententries[count].client; + memset(key, 0, sizeof key); + if (client->bound_xl && client->bound_xl->itable) { + /* Presently every brick contains only + * one bound_xl for all connections. + * This will lead to duplicating of + * the inode lists, if listing is + * done for every connection. This + * simple check prevents duplication + * in the present case. If need arises + * the check can be improved. + */ + if (client->bound_xl == prev_bound_xl) + continue; + prev_bound_xl = client->bound_xl; + + gf_proc_dump_build_key(key, "conn", + "%d.bound_xl.%s", count, + client->bound_xl->name); + inode_table_dump(client->bound_xl->itable,key); + } + } + } + UNLOCK(&clienttable->lock); + + ret = 0; +out: + return ret; +} + diff --git a/libglusterfs/src/client_t.h b/libglusterfs/src/client_t.h new file mode 100644 index 000000000..f7812f8f0 --- /dev/null +++ b/libglusterfs/src/client_t.h @@ -0,0 +1,135 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _CLIENT_T_H +#define _CLIENT_T_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "glusterfs.h" +#include "locking.h" /* for gf_lock_t, not included by glusterfs.h */ + +struct client_ctx { + void *ctx_key; + void *ctx_value; +}; + +typedef struct _client_t { + struct { + /* e.g. protocol/server stashes its ctx here */ + gf_lock_t lock; + unsigned short count; + struct client_ctx *ctx; + } scratch_ctx; + struct { + gf_lock_t lock; + volatile int bind; + volatile int count; + } ref; + xlator_t *bound_xl; + xlator_t *this; + int tbl_index; + char *client_uid; + struct { + int flavour; + size_t len; + char *data; + } auth; +} client_t; + +#define GF_CLIENTCTX_INITIAL_SIZE 8 + +struct client_table_entry { + client_t *client; + int next_free; +}; +typedef struct client_table_entry cliententry_t; + +struct clienttable { + unsigned int max_clients; + gf_lock_t lock; + cliententry_t *cliententries; + int first_free; +}; +typedef struct clienttable clienttable_t; + +#define GF_CLIENTTABLE_INITIAL_SIZE 32 + +/* Signifies no more entries in the client table. */ +#define GF_CLIENTTABLE_END -1 + +/* This is used to invalidate + * the next_free value in an cliententry that has been allocated + */ +#define GF_CLIENTENTRY_ALLOCATED -2 + +struct rpcsvc_auth_data; + +client_t * +gf_client_get (xlator_t *this, struct rpcsvc_auth_data *cred, char *client_uid); + +void +gf_client_put (client_t *client, gf_boolean_t *detached); + +clienttable_t * +gf_clienttable_alloc (void); + +void +gf_client_clienttable_destroy (clienttable_t *clienttable); + +client_t * +gf_client_ref (client_t *client); + +void +gf_client_unref (client_t *client); + +int +gf_client_dump_fdtable_to_dict (xlator_t *this, dict_t *dict); + +int +gf_client_dump_fdtable (xlator_t *this); + +int +gf_client_dump_inodes_to_dict (xlator_t *this, dict_t *dict); + +int +gf_client_dump_inodes (xlator_t *this); + +int +client_ctx_set (client_t *client, void *key, void *value); + +int +client_ctx_get (client_t *client, void *key, void **value); + +int +client_ctx_del (client_t *client, void *key, void **value); + +void +client_ctx_dump (client_t *client, char *prefix); + +int +gf_client_dump_fdtables_to_dict (xlator_t *this, dict_t *dict); + +int +gf_client_dump_fdtables (xlator_t *this); + +int +gf_client_dump_inodes_to_dict (xlator_t *this, dict_t *dict); + +int +gf_client_dump_inodes (xlator_t *this); + +int +gf_client_disconnect (client_t *client); + +#endif /* _CLIENT_T_H */ diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c index 59ac5386e..827475282 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -36,425 +27,577 @@ #include <time.h> #include <locale.h> #include <sys/socket.h> +#include <sys/wait.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> +#include <stdlib.h> + +#if defined GF_BSD_HOST_OS || defined GF_DARWIN_HOST_OS +#include <sys/sysctl.h> +#endif #include "logging.h" #include "common-utils.h" #include "revision.h" #include "glusterfs.h" #include "stack.h" +#include "globals.h" +#include "lkowner.h" +#include "syscall.h" +#include <ifaddrs.h> + +#ifndef AI_ADDRCONFIG +#define AI_ADDRCONFIG 0 +#endif /* AI_ADDRCONFIG */ 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; + 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; - } +void +md5_wrapper(const unsigned char *data, size_t len, char *md5) +{ + unsigned short i = 0; + unsigned short lim = MD5_DIGEST_LENGTH*2+1; + unsigned char scratch[MD5_DIGEST_LENGTH] = {0,}; + MD5(data, len, scratch); + for (; i < MD5_DIGEST_LENGTH; i++) + snprintf(md5 + i * 2, lim-i*2, "%02x", scratch[i]); +} - if (!*dnscache) { - *dnscache = CALLOC (1, sizeof (struct dnscache6)); - } +/* works similar to mkdir(1) -p. + */ +int +mkdir_p (char *path, mode_t mode, gf_boolean_t allow_symlinks) +{ + int i = 0; + int ret = -1; + char dir[PATH_MAX] = {0,}; + struct stat stbuf = {0,}; - cache = *dnscache; - if (cache->first && !cache->next) { - freeaddrinfo(cache->first); - cache->first = cache->next = NULL; - gf_log ("resolver", GF_LOG_TRACE, - "flushing DNS cache"); - } + strcpy (dir, path); + i = (dir[0] == '/')? 1: 0; + do { + if (path[i] != '/' && path[i] != '\0') + continue; + + dir[i] = '\0'; + ret = mkdir (dir, mode); + if (ret && errno != EEXIST) { + gf_log ("", GF_LOG_ERROR, "Failed due to reason %s", + strerror (errno)); + goto out; + } + + if (ret && errno == EEXIST && !allow_symlinks) { + ret = lstat (dir, &stbuf); + if (ret) + goto out; + + if (S_ISLNK (stbuf.st_mode)) { + ret = -1; + gf_log ("", GF_LOG_ERROR, "%s is a symlink", + dir); + goto out; + } + } + dir[i] = '/'; + + } while (path[i++] != '\0'); + + ret = stat (dir, &stbuf); + if (ret || !S_ISDIR (stbuf.st_mode)) { + ret = -1; + gf_log ("", GF_LOG_ERROR, "Failed to create directory, " + "possibly some of the components were not directories"); + goto out; + } + + ret = 0; +out: + + return ret; +} + +int +gf_lstat_dir (const char *path, struct stat *stbuf_in) +{ + int ret = -1; + struct stat stbuf = {0,}; + + if (path == NULL) { + errno = EINVAL; + goto out; + } + + ret = sys_lstat (path, &stbuf); + if (ret) + goto out; + + if (!S_ISDIR (stbuf.st_mode)) { + errno = ENOTDIR; + ret = -1; + goto out; + } + ret = 0; + +out: + if (!ret && stbuf_in) + *stbuf_in = stbuf; + + return ret; +} + +int +log_base2 (unsigned long x) +{ + int val = 0; + + while (x > 1) { + x /= 2; + val++; + } + + return val; +} + + +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_callingfn ("resolver", GF_LOG_WARNING, "hostname is NULL"); + return -1; + } - if (!cache->first) { - char *port_str = NULL; - gf_log ("resolver", GF_LOG_TRACE, - "DNS cache not present, freshly probing hostname: %s", - hostname); + if (!*dnscache) { + *dnscache = GF_CALLOC (1, sizeof (struct dnscache6), + gf_common_mt_dnscache6); + if (!*dnscache) + return -1; + } - memset(&hints, 0, sizeof(hints)); - hints.ai_family = family; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_ADDRCONFIG; + cache = *dnscache; + if (cache->first && !cache->next) { + freeaddrinfo(cache->first); + cache->first = cache->next = NULL; + gf_log ("resolver", GF_LOG_TRACE, + "flushing DNS cache"); + } - ret = asprintf (&port_str, "%d", port); + if (!cache->first) { + char *port_str = NULL; + gf_log ("resolver", GF_LOG_TRACE, + "DNS cache not present, freshly probing hostname: %s", + hostname); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = family; + hints.ai_socktype = SOCK_STREAM; +#ifndef __NetBSD__ + hints.ai_flags = AI_ADDRCONFIG; +#endif + + ret = gf_asprintf (&port_str, "%d", port); if (-1 == ret) { gf_log ("resolver", GF_LOG_ERROR, "asprintf failed"); return -1; } - 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 ((ret = getaddrinfo(hostname, port_str, &hints, &cache->first)) != 0) { + gf_log ("resolver", GF_LOG_ERROR, + "getaddrinfo failed (%s)", gai_strerror (ret)); - 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_TRACE, - "returning ip-%s (port-%s) for hostname: %s and port: %d", - host, service, hostname, port); - - *addr_info = cache->next; - } + GF_FREE (*dnscache); + *dnscache = NULL; + GF_FREE (port_str); + return -1; + } + GF_FREE (port_str); - 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_TRACE, - "next DNS query will return: ip-%s port-%s", host, service); - } + cache->next = cache->first; + } - return 0; + 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; + } + + if (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; + freeaddrinfo (cache->first); + cache->first = cache->next = NULL; + GF_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_fop_list[GF_FOP_FXATTROP] = "FXATTROP"; - gf_fop_list[GF_FOP_LOCK_NOTIFY] = "LOCK_NOTIFY"; - gf_fop_list[GF_FOP_LOCK_FNOTIFY]= "LOCK_FNOTIFY"; - gf_fop_list[GF_FOP_FSETXATTR] = "FSETXATTR"; - gf_fop_list[GF_FOP_FGETXATTR] = "FGETXATTR"; - gf_fop_list[GF_FOP_RCHECKSUM] = "RCHECKSUM"; - gf_fop_list[GF_FOP_SETATTR] = "SETATTR"; - gf_fop_list[GF_FOP_FSETATTR] = "FSETATTR"; - gf_fop_list[GF_FOP_READDIRP] = "READDIRP"; - - 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_mop_list[GF_MOP_LOG] = "LOG"; - gf_mop_list[GF_MOP_PING] = "PING"; - - 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; +struct xldump { + int lineno; + FILE *logfp; +}; + + +static int +nprintf (struct xldump *dump, const char *fmt, ...) +{ + va_list ap; + int ret = 0; + + + ret += fprintf (dump->logfp, "%3d: ", ++dump->lineno); + + va_start (ap, fmt); + ret += vfprintf (dump->logfp, fmt, ap); + va_end (ap); + + ret += fprintf (dump->logfp, "\n"); + + return ret; } -void -set_global_ctx_ptr (glusterfs_ctx_t *ctx) + +static int +xldump_options (dict_t *this, char *key, data_t *value, void *d) { - gf_global_ctx = ctx; + nprintf (d, " option %s %s", key, value->data); + return 0; } -/* - * Don't use this function other than in glusterfsd.c. libglusterfsclient does - * not set gf_global_ctx since there can be multiple glusterfs-contexts - * initialized in a single process. Instead access the context from ctx member - * of the xlator object. - */ -glusterfs_ctx_t * -get_global_ctx_ptr (void) +static void +xldump_subvolumes (xlator_t *this, void *d) { - return gf_global_ctx; + xlator_list_t *subv = NULL; + int len = 0; + char *subvstr = NULL; + + subv = this->children; + if (!this->children) + return; + + for (subv = this->children; subv; subv = subv->next) + len += (strlen (subv->xlator->name) + 1); + + subvstr = GF_CALLOC (1, len, gf_common_mt_strdup); + + len = 0; + for (subv = this->children; subv; subv= subv->next) + len += sprintf (subvstr + len, "%s%s", subv->xlator->name, + subv->next ? " " : ""); + + nprintf (d, " subvolumes %s", subvstr); + + GF_FREE (subvstr); } -void -gf_log_volume_file (FILE *specfp) + +static void +xldump (xlator_t *each, void *d) { - 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 (fgets (data, GF_UNIT_KB, specfp) != NULL){ - lcount++; - fprintf (gf_log_logfile, "%3d: %s", lcount, data); - } - fprintf (gf_log_logfile, - "\n+---------------------------------------" - "---------------------------------------+\n"); - fflush (gf_log_logfile); - fseek (specfp, 0L, SEEK_SET); + nprintf (d, "volume %s", each->name); + nprintf (d, " type %s", each->type); + dict_foreach (each->options, xldump_options, d); + + xldump_subvolumes (each, d); + + nprintf (d, "end-volume"); + nprintf (d, ""); } -static void + +void +gf_log_dump_graph (FILE *specfp, glusterfs_graph_t *graph) +{ + glusterfs_ctx_t *ctx; + struct xldump xld = {0, }; + + + ctx = THIS->ctx; + xld.logfp = ctx->log.gf_log_logfile; + + fprintf (ctx->log.gf_log_logfile, "Final graph:\n"); + fprintf (ctx->log.gf_log_logfile, + "+---------------------------------------" + "---------------------------------------+\n"); + + xlator_foreach_depth_first (graph->top, xldump, &xld); + + fprintf (ctx->log.gf_log_logfile, + "+---------------------------------------" + "---------------------------------------+\n"); + fflush (ctx->log.gf_log_logfile); +} + +static void gf_dump_config_flags (int fd) { int ret = 0; - /* TODO: 'ret' is not checked properly, add this later */ - ret = write (fd, "configuration details:\n", 23); + ret = write (fd, "configuration details:\n", 23); + if (ret == -1) + goto out; /* have argp */ #ifdef HAVE_ARGP - ret = write (fd, "argp 1\n", 7); + ret = write (fd, "argp 1\n", 7); + if (ret == -1) + goto out; #endif /* ifdef if found backtrace */ -#ifdef HAVE_BACKTRACE - ret = write (fd, "backtrace 1\n", 12); +#ifdef HAVE_BACKTRACE + ret = write (fd, "backtrace 1\n", 12); + if (ret == -1) + goto out; #endif /* Berkeley-DB version has cursor->get() */ -#ifdef HAVE_BDB_CURSOR_GET - ret = write (fd, "bdb->cursor->get 1\n", 19); +#ifdef HAVE_BDB_CURSOR_GET + ret = write (fd, "bdb->cursor->get 1\n", 19); + if (ret == -1) + goto out; #endif /* Define to 1 if you have the <db.h> header file. */ -#ifdef HAVE_DB_H - ret = write (fd, "db.h 1\n", 7); +#ifdef HAVE_DB_H + ret = write (fd, "db.h 1\n", 7); + if (ret == -1) + goto out; #endif /* Define to 1 if you have the <dlfcn.h> header file. */ -#ifdef HAVE_DLFCN_H - ret = write (fd, "dlfcn 1\n", 8); +#ifdef HAVE_DLFCN_H + ret = write (fd, "dlfcn 1\n", 8); + if (ret == -1) + goto out; #endif /* define if fdatasync exists */ -#ifdef HAVE_FDATASYNC - ret = write (fd, "fdatasync 1\n", 12); +#ifdef HAVE_FDATASYNC + ret = write (fd, "fdatasync 1\n", 12); + if (ret == -1) + goto out; #endif /* Define to 1 if you have the `pthread' library (-lpthread). */ -#ifdef HAVE_LIBPTHREAD - ret = write (fd, "libpthread 1\n", 13); +#ifdef HAVE_LIBPTHREAD + ret = write (fd, "libpthread 1\n", 13); + if (ret == -1) + goto out; #endif /* define if llistxattr exists */ -#ifdef HAVE_LLISTXATTR - ret = write (fd, "llistxattr 1\n", 13); +#ifdef HAVE_LLISTXATTR + ret = write (fd, "llistxattr 1\n", 13); + if (ret == -1) + goto out; #endif /* define if found setfsuid setfsgid */ -#ifdef HAVE_SET_FSID - ret = write (fd, "setfsid 1\n", 10); +#ifdef HAVE_SET_FSID + ret = write (fd, "setfsid 1\n", 10); + if (ret == -1) + goto out; #endif /* define if found spinlock */ -#ifdef HAVE_SPINLOCK - ret = write (fd, "spinlock 1\n", 11); +#ifdef HAVE_SPINLOCK + ret = write (fd, "spinlock 1\n", 11); + if (ret == -1) + goto out; #endif /* Define to 1 if you have the <sys/epoll.h> header file. */ -#ifdef HAVE_SYS_EPOLL_H - ret = write (fd, "epoll.h 1\n", 10); +#ifdef HAVE_SYS_EPOLL_H + ret = write (fd, "epoll.h 1\n", 10); + if (ret == -1) + goto out; #endif /* Define to 1 if you have the <sys/extattr.h> header file. */ -#ifdef HAVE_SYS_EXTATTR_H - ret = write (fd, "extattr.h 1\n", 12); +#ifdef HAVE_SYS_EXTATTR_H + ret = write (fd, "extattr.h 1\n", 12); + if (ret == -1) + goto out; #endif /* Define to 1 if you have the <sys/xattr.h> header file. */ -#ifdef HAVE_SYS_XATTR_H - ret = write (fd, "xattr.h 1\n", 10); +#ifdef HAVE_SYS_XATTR_H + ret = write (fd, "xattr.h 1\n", 10); + if (ret == -1) + goto out; #endif /* define if found st_atim.tv_nsec */ #ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC - ret = write (fd, "st_atim.tv_nsec 1\n", 18); + ret = write (fd, "st_atim.tv_nsec 1\n", 18); + if (ret == -1) + goto out; #endif /* define if found st_atimespec.tv_nsec */ #ifdef HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC - ret = write (fd, "st_atimespec.tv_nsec 1\n",23); + ret = write (fd, "st_atimespec.tv_nsec 1\n",23); + if (ret == -1) + goto out; #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); - ret = write (fd, msg, strlen (msg)); - } +#ifdef PACKAGE_STRING + { + char msg[128]; + sprintf (msg, "package-string: %s\n", PACKAGE_STRING); + ret = write (fd, msg, strlen (msg)); + if (ret == -1) + goto out; + } #endif - return; +out: + 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) +gf_print_trace (int32_t signum, glusterfs_ctx_t *ctx) { - extern FILE *gf_log_logfile; - struct tm *tm = NULL; char msg[1024] = {0,}; - char timestr[256] = {0,}; - time_t utime = 0; + char timestr[64] = {0,}; int ret = 0; int fd = 0; - fd = fileno (gf_log_logfile); - - /* Pending frames, (if any), list them in order */ - ret = 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]); - - ret = write (fd, msg, strlen (msg)); - trav = trav->next; - } - ret = write (fd, "\n", 1); - } + fd = fileno (ctx->log.gf_log_logfile); + + /* Now every gf_log call will just write to a buffer and when the + * buffer becomes full, its written to the log-file. Suppose the process + * crashes and prints the backtrace in the log-file, then the previous + * log information will still be in the buffer itself. So flush the + * contents of the buffer to the log file before printing the backtrace + * which helps in debugging. + */ + fflush (ctx->log.gf_log_logfile); + /* Pending frames, (if any), list them in order */ + ret = write (fd, "pending frames:\n", 16); + if (ret < 0) + goto out; - sprintf (msg, "patchset: %s\n", GLUSTERFS_REPOSITORY_REVISION); - ret = write (fd, msg, strlen (msg)); + { + 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) + sprintf (msg,"frame : type(%d) op(%s)\n", + tmp->root->type, + gf_fop_list[tmp->root->op]); + else + sprintf (msg,"frame : type(%d) op(%d)\n", + tmp->root->type, + tmp->root->op); + + ret = write (fd, msg, strlen (msg)); + if (ret < 0) + goto out; + + trav = trav->next; + } + ret = write (fd, "\n", 1); + if (ret < 0) + goto out; + } + + sprintf (msg, "patchset: %s\n", GLUSTERFS_REPOSITORY_REVISION); + ret = write (fd, msg, strlen (msg)); + if (ret < 0) + goto out; - sprintf (msg, "signal received: %d\n", signum); - ret = write (fd, msg, strlen (msg)); + sprintf (msg, "signal received: %d\n", signum); + ret = write (fd, msg, strlen (msg)); + if (ret < 0) + goto out; { - /* Dump the timestamp of the crash too, so the previous logs + /* Dump the timestamp of the crash too, so the previous logs can be related */ - utime = time (NULL); - tm = localtime (&utime); - strftime (timestr, 256, "%Y-%m-%d %H:%M:%S\n", tm); + gf_time_fmt (timestr, sizeof timestr, time (NULL), gf_timefmt_FT); ret = write (fd, "time of crash: ", 15); + if (ret < 0) + goto out; ret = write (fd, timestr, strlen (timestr)); + if (ret < 0) + goto out; } - gf_dump_config_flags (fd); + 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"); - ret = write (fd, msg, strlen (msg)); - } + /* Print 'backtrace' */ + { + void *array[200]; + size_t size; + + size = backtrace (array, 200); + backtrace_symbols_fd (&array[1], size-1, fd); + sprintf (msg, "---------\n"); + ret = write (fd, msg, strlen (msg)); + if (ret < 0) + goto out; + } #endif /* HAVE_BACKTRACE */ - - /* Send a signal to terminate the process */ - signal (signum, SIG_DFL); - raise (signum); + +out: + /* Send a signal to terminate the process */ + signal (signum, SIG_DFL); + raise (signum); } void @@ -466,963 +609,1009 @@ 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; - + 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) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); + return -1; + } + + _running = gf_strdup (str); + if (_running == NULL) + return -1; + + running = _running; + + while ((token = strsep (&running, delim)) != NULL) { + if (token[0] != '\0') + count++; + } + GF_FREE (_running); + + _running = gf_strdup (str); + if (_running == NULL) + return -1; + + running = _running; + + if ((token_list = GF_CALLOC (count, sizeof (char *), + gf_common_mt_char)) == NULL) { + GF_FREE (_running); + return -1; + } + + while ((token = strsep (&running, delim)) != NULL) { + if (token[0] == '\0') + continue; + + token_list[i] = gf_strdup (token); + if (token_list[i] == NULL) + goto free_exit; + i++; + } + + GF_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; + GF_FREE (_running); + for (j = 0; j < i; j++) + GF_FREE (token_list[j]); + + GF_FREE (token_list); + return -1; +} + +int +gf_strstr (const char *str, const char *delim, const char *match) +{ + char *tmp = NULL; + char *save_ptr = NULL; + char *tmp_str = NULL; + + int ret = 0; + + tmp_str = strdup (str); + + if (str == NULL || delim == NULL || match == NULL || tmp_str == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); + ret = -1; + goto out; + } + + + tmp = strtok_r (tmp_str, delim, &save_ptr); + + while (tmp) { + ret = strcmp (tmp, match); + + if (ret == 0) + break; + + tmp = strtok_r (NULL, delim, &save_ptr); + } + +out: + free (tmp_str); + + return ret; + } -int +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; + const char *vname = NULL; + + if (volume_name == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); + 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 +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; -} + unsigned long value = 0; + char *tail = NULL; + int old_errno = 0; + const char *s = NULL; + + if (str == NULL || n == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); + 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 (str == tail) + errno = EINVAL; + + 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) +int +gf_string2percent (const char *str, double *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; + double value = 0; + char *tail = NULL; + int old_errno = 0; + const char *s = NULL; + + if (str == NULL || n == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); + 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 = strtod (str, &tail); + if (str == tail) + errno = EINVAL; + + 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 +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; - } + long value = 0; + char *tail = NULL; + int old_errno = 0; + + if (str == NULL || n == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); + errno = EINVAL; + return -1; + } - if (tail[0] != '\0') - { - /* bala: invalid integer format */ - return -1; - } - - *n = value; - - return 0; + old_errno = errno; + errno = 0; + value = strtol (str, &tail, base); + if (str == tail) + errno = EINVAL; + + if (errno == ERANGE || errno == EINVAL) + return -1; + + if (errno == 0) + errno = old_errno; + + if (tail[0] != '\0') + return -1; + + *n = value; + + return 0; } -static int +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; + unsigned long value = 0; + char *tail = NULL; + int old_errno = 0; + const char *s = NULL; + + if (str == NULL || n == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); + 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 = strtoul (str, &tail, base); + if (str == tail) + errno = EINVAL; + + if (errno == ERANGE || errno == EINVAL) + return -1; + + if (errno == 0) + errno = old_errno; + + if (tail[0] != '\0') + return -1; + + *n = value; + + return 0; } -static int +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; + unsigned long value = 0; + char *tail = NULL; + int old_errno = 0; + const char *s = NULL; + + if (str == NULL || n == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); + 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 = strtoul (str, &tail, base); + if (str == tail) + errno = EINVAL; + + if (errno == ERANGE || errno == EINVAL) + return -1; + + if (errno == 0) + errno = old_errno; + + if (tail[0] != '\0') + return -1; + + *n = (unsigned int)value; + + return 0; } -static int +static int _gf_string2double (const char *str, double *n) { - double value = 0.0; - char *tail = NULL; - int old_errno = 0; - - if (str == NULL || n == NULL) { - errno = EINVAL; - return -1; - } - - old_errno = errno; - errno = 0; - value = strtod (str, &tail); - - if (errno == ERANGE || errno == EINVAL) { - return -1; - } - - if (errno == 0) { - errno = old_errno; - } - - if (tail[0] != '\0') { - return -1; - } - - *n = value; - - return 0; + double value = 0.0; + char *tail = NULL; + int old_errno = 0; + + if (str == NULL || n == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); + errno = EINVAL; + return -1; + } + + old_errno = errno; + errno = 0; + value = strtod (str, &tail); + if (str == tail) + errno = EINVAL; + + if (errno == ERANGE || errno == EINVAL) + return -1; + + if (errno == 0) + errno = old_errno; + + if (tail[0] != '\0') + return -1; + + *n = value; + + return 0; } -static int +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; + long long value = 0; + char *tail = NULL; + int old_errno = 0; + + if (str == NULL || n == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); + errno = EINVAL; + return -1; + } + + old_errno = errno; + errno = 0; + value = strtoll (str, &tail, base); + if (str == tail) + errno = EINVAL; + + if (errno == ERANGE || errno == EINVAL) + return -1; + + if (errno == 0) + errno = old_errno; + + if (tail[0] != '\0') + return -1; + + *n = value; + + return 0; } -static int +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; + unsigned long long value = 0; + char *tail = NULL; + int old_errno = 0; + const char *s = NULL; + + if (str == NULL || n == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); + 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 = strtoull (str, &tail, base); + if (str == tail) + errno = EINVAL; + + if (errno == ERANGE || errno == EINVAL) + return -1; + + if (errno == 0) + errno = old_errno; + + if (tail[0] != '\0') + return -1; + + *n = value; + + return 0; } -int +int gf_string2long (const char *str, long *n) { - return _gf_string2long (str, n, 0); + return _gf_string2long (str, n, 0); } -int +int gf_string2ulong (const char *str, unsigned long *n) { - return _gf_string2ulong (str, n, 0); + return _gf_string2ulong (str, n, 0); } -int +int gf_string2int (const char *str, int *n) { - return _gf_string2long (str, (long *) n, 0); + long l = 0; + int ret = 0; + + ret = _gf_string2long (str, &l, 0); + + *n = l; + return ret; } -int +int gf_string2uint (const char *str, unsigned int *n) { - return _gf_string2uint (str, n, 0); + return _gf_string2uint (str, n, 0); } int gf_string2double (const char *str, double *n) { - return _gf_string2double (str, n); + return _gf_string2double (str, n); } -int +int gf_string2longlong (const char *str, long long *n) { - return _gf_string2longlong (str, n, 0); + return _gf_string2longlong (str, n, 0); } -int +int gf_string2ulonglong (const char *str, unsigned long long *n) { - return _gf_string2ulonglong (str, n, 0); + return _gf_string2ulonglong (str, n, 0); } -int +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; + 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 +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; + 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 +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; + 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 +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; + 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 +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; + 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 +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; + 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 +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; + 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 +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; + 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 +int gf_string2ulong_base10 (const char *str, unsigned long *n) { - return _gf_string2ulong (str, n, 10); + return _gf_string2ulong (str, n, 10); } -int +int gf_string2uint_base10 (const char *str, unsigned int *n) { - return _gf_string2uint (str, n, 10); + return _gf_string2uint (str, n, 10); } -int +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; + 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 +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; + 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 +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; + 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 +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; + 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; +} + +char * +gf_uint64_2human_readable (uint64_t n) +{ + int ret = 0; + char *str = NULL; + + if (n >= GF_UNIT_PB) { + ret = gf_asprintf (&str, "%.1lfPB", ((double) n)/GF_UNIT_PB); + if (ret < 0) + goto err; + } else if (n >= GF_UNIT_TB) { + ret = gf_asprintf (&str, "%.1lfTB", ((double) n)/GF_UNIT_TB); + if (ret < 0) + goto err; + } else if (n >= GF_UNIT_GB) { + ret = gf_asprintf (&str, "%.1lfGB", ((double) n)/GF_UNIT_GB); + if (ret < 0) + goto err; + } else if (n >= GF_UNIT_MB) { + ret = gf_asprintf (&str, "%.1lfMB", ((double) n)/GF_UNIT_MB); + if (ret < 0) + goto err; + } else if (n >= GF_UNIT_KB) { + ret = gf_asprintf (&str, "%.1lfKB", ((double) n)/GF_UNIT_KB); + if (ret < 0) + goto err; + } else { + ret = gf_asprintf (&str, "%luBytes", n); + if (ret < 0) + goto err; + } + return str; +err: + return NULL; } -int +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; + double value = 0.0; + char *tail = NULL; + int old_errno = 0; + const char *s = NULL; + + if (str == NULL || n == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); + 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 = strtod (str, &tail); + if (str == tail) + errno = EINVAL; + + 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 + return -1; + } + + if ((UINT64_MAX - value) < 0) { + errno = ERANGE; + return -1; + } + + *n = (uint64_t) value; + + return 0; +} + +int +gf_string2percent_or_bytesize (const char *str, + uint64_t *n, + gf_boolean_t *is_percent) +{ + double value = 0ULL; + char *tail = NULL; + int old_errno = 0; + const char *s = NULL; + + if (str == NULL || n == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, + "argument invalid"); + 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 = strtod (str, &tail); + if (str == tail) + errno = EINVAL; + + 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 if (strcasecmp (tail, GF_UNIT_PERCENT_STRING) == 0) + *is_percent = _gf_true; + else + return -1; + } + + /* Error out if we cannot store the value in uint64 */ + if ((UINT64_MAX - value) < 0) { + errno = ERANGE; + return -1; + } + + *n = (uint64_t) value; + + return 0; } -int64_t +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; + 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 +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; + if (str == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); + 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 +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); + struct gf_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 +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); + struct gf_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); } - + static void compute_checksum (char *buf, size_t size, uint32_t *checksum) { @@ -1435,7 +1624,7 @@ compute_checksum (char *buf, size_t size, uint32_t *checksum) checksum_buf [0] = 0xba; checksum_buf [1] = 0xbe; checksum_buf [2] = 0xb0; - checksum_buf [3] = 0x0b; + checksum_buf [3] = 0x0b; } for (ret = 0; ret < (size - 4); ret += 4) { @@ -1448,14 +1637,14 @@ compute_checksum (char *buf, size_t size, uint32_t *checksum) for (ret = 0; ret <= (size % 4); ret++) { checksum_buf[ret] ^= (buf[(size - 4) + ret] << ret); } - + return; } #define GF_CHECKSUM_BUF_SIZE 1024 int -get_checksum_for_file (int fd, uint32_t *checksum) +get_checksum_for_file (int fd, uint32_t *checksum) { int ret = -1; char buf[GF_CHECKSUM_BUF_SIZE] = {0,}; @@ -1465,7 +1654,7 @@ get_checksum_for_file (int fd, uint32_t *checksum) do { ret = read (fd, &buf, GF_CHECKSUM_BUF_SIZE); if (ret > 0) - compute_checksum (buf, GF_CHECKSUM_BUF_SIZE, + compute_checksum (buf, GF_CHECKSUM_BUF_SIZE, checksum); } while (ret > 0); @@ -1474,3 +1663,1246 @@ get_checksum_for_file (int fd, uint32_t *checksum) return ret; } + + +int +get_checksum_for_path (char *path, uint32_t *checksum) +{ + int ret = -1; + int fd = -1; + + GF_ASSERT (path); + GF_ASSERT (checksum); + + fd = open (path, O_RDWR); + + if (fd == -1) { + gf_log (THIS->name, GF_LOG_ERROR, "Unable to open %s, errno: %d", + path, errno); + goto out; + } + + ret = get_checksum_for_file (fd, checksum); + +out: + if (fd != -1) + close (fd); + + return ret; +} + +char * +strtail (char *str, const char *pattern) +{ + int i = 0; + + for (i = 0; str[i] == pattern[i] && str[i]; i++); + + if (pattern[i] == '\0') + return str + i; + + return NULL; +} + +void +skipwhite (char **s) +{ + while (isspace (**s)) + (*s)++; +} + +char * +nwstrtail (char *str, char *pattern) +{ + for (;;) { + skipwhite (&str); + skipwhite (&pattern); + + if (*str != *pattern || !*str) + break; + + str++; + pattern++; + } + + return *pattern ? NULL : str; +} + +void +skipword (char **s) +{ + if (!*s) + return; + + skipwhite (s); + + while (!isspace(**s)) + (*s)++; +} + +char * +get_nth_word (const char *str, int n) +{ + char buf[4096] = {0}; + char *start = NULL; + char *word = NULL; + int i = 0; + int word_len = 0; + const char *end = NULL; + + if (!str) + goto out; + + snprintf (buf, sizeof (buf), "%s", str); + start = buf; + + for (i = 0; i < n-1; i++) + skipword (&start); + + skipwhite (&start); + end = strpbrk ((const char *)start, " \t\n\0"); + + if (!end) + goto out; + + word_len = abs (end - start); + + word = GF_CALLOC (1, word_len + 1, gf_common_mt_strdup); + if (!word) + goto out; + + strncpy (word, start, word_len); + *(word + word_len) = '\0'; + out: + return word; +} + +/* Syntax formed according to RFC 1912 (RFC 1123 & 952 are more restrictive) * + <hname> ::= <gen-name>*["."<gen-name>] * + <gen-name> ::= <let-or-digit> <[*[<let-or-digit-or-hyphen>]<let-or-digit>] */ +char +valid_host_name (char *address, int length) +{ + int i = 0; + int str_len = 0; + char ret = 1; + char *dup_addr = NULL; + char *temp_str = NULL; + char *save_ptr = NULL; + + if ((length > _POSIX_HOST_NAME_MAX) || (length < 1)) { + ret = 0; + goto out; + } + + dup_addr = gf_strdup (address); + if (!dup_addr) { + ret = 0; + goto out; + } + + if (!isalnum (dup_addr[length - 1]) && (dup_addr[length - 1] != '*')) { + ret = 0; + goto out; + } + + /* Check for consecutive dots, which is invalid in a hostname and is + * ignored by strtok() + */ + if (strstr (dup_addr, "..")) { + ret = 0; + goto out; + } + + /* gen-name */ + temp_str = strtok_r (dup_addr, ".", &save_ptr); + do { + str_len = strlen (temp_str); + + if (!isalnum (temp_str[0]) || + !isalnum (temp_str[str_len-1])) { + ret = 0; + goto out; + } + for (i = 1; i < str_len; i++) { + if (!isalnum (temp_str[i]) && (temp_str[i] != '-')) { + ret = 0; + goto out; + } + } + } while ((temp_str = strtok_r (NULL, ".", &save_ptr))); + +out: + GF_FREE (dup_addr); + return ret; +} + +/* Matches all ipv4 address, if wildcard_acc is true '*' wildcard pattern for* + subnets is considerd as valid strings as well */ +char +valid_ipv4_address (char *address, int length, gf_boolean_t wildcard_acc) +{ + int octets = 0; + int value = 0; + char *tmp = NULL, *ptr = NULL, *prev = NULL, *endptr = NULL; + char ret = 1; + int is_wildcard = 0; + + tmp = gf_strdup (address); + + /* + * To prevent cases where last character is '.' and which have + * consecutive dots like ".." as strtok ignore consecutive + * delimeters. + */ + if (length <= 0 || + (strstr (address, "..")) || + (!isdigit (tmp[length - 1]) && (tmp[length - 1] != '*'))) { + ret = 0; + goto out; + } + + prev = tmp; + prev = strtok_r (tmp, ".", &ptr); + + while (prev != NULL) { + octets++; + if (wildcard_acc && !strcmp (prev, "*")) { + is_wildcard = 1; + } else { + value = strtol (prev, &endptr, 10); + if ((value > 255) || (value < 0) || + (endptr != NULL && *endptr != '\0')) { + ret = 0; + goto out; + } + } + prev = strtok_r (NULL, ".", &ptr); + } + + if ((octets > 4) || (octets < 4 && !is_wildcard)) { + ret = 0; + } + +out: + GF_FREE (tmp); + return ret; +} + +char +valid_ipv6_address (char *address, int length, gf_boolean_t wildcard_acc) +{ + int hex_numbers = 0; + int value = 0; + int i = 0; + char *tmp = NULL, *ptr = NULL, *prev = NULL, *endptr = NULL; + char ret = 1; + int is_wildcard = 0; + int is_compressed = 0; + + tmp = gf_strdup (address); + + /* Check for compressed form */ + if (length <= 0 || tmp[length - 1] == ':') { + ret = 0; + goto out; + } + for (i = 0; i < (length - 1) ; i++) { + if (tmp[i] == ':' && tmp[i + 1] == ':') { + if (is_compressed == 0) + is_compressed = 1; + else { + ret = 0; + goto out; + } + } + } + + prev = strtok_r (tmp, ":", &ptr); + + while (prev != NULL) { + hex_numbers++; + if (wildcard_acc && !strcmp (prev, "*")) { + is_wildcard = 1; + } else { + value = strtol (prev, &endptr, 16); + if ((value > 0xffff) || (value < 0) + || (endptr != NULL && *endptr != '\0')) { + ret = 0; + goto out; + } + } + prev = strtok_r (NULL, ":", &ptr); + } + + if ((hex_numbers > 8) || (hex_numbers < 8 && !is_wildcard + && !is_compressed)) { + ret = 0; + } + +out: + GF_FREE (tmp); + return ret; +} + +char +valid_internet_address (char *address, gf_boolean_t wildcard_acc) +{ + char ret = 0; + int length = 0; + + if (address == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); + goto out; + } + + length = strlen (address); + if (length == 0) + goto out; + + if (valid_ipv4_address (address, length, wildcard_acc) + || valid_ipv6_address (address, length, wildcard_acc) + || valid_host_name (address, length)) + ret = 1; + +out: + return ret; +} + +/** + * gf_sock_union_equal_addr - check if two given gf_sock_unions have same addr + * + * @param a - first sock union + * @param b - second sock union + * @return _gf_true if a and b have same ipv{4,6} addr, _gf_false otherwise + */ +gf_boolean_t +gf_sock_union_equal_addr (union gf_sock_union *a, + union gf_sock_union *b) +{ + if (!a || !b) { + gf_log ("common-utils", GF_LOG_ERROR, "Invalid arguments" + " to gf_sock_union_equal_addr"); + return _gf_false; + } + + if (a->storage.ss_family != b->storage.ss_family) + return _gf_false; + + switch (a->storage.ss_family) { + case AF_INET: + if (a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr) + return _gf_true; + else + return _gf_false; + + case AF_INET6: + if (memcmp ((void *)(&a->sin6.sin6_addr), + (void *)(&b->sin6.sin6_addr), + sizeof (a->sin6.sin6_addr))) + return _gf_false; + else + return _gf_true; + + default: + gf_log ("common-utils", GF_LOG_DEBUG, + "Unsupported/invalid address family"); + break; + } + + return _gf_false; +} + +/*Thread safe conversion function*/ +char * +uuid_utoa (uuid_t uuid) +{ + char *uuid_buffer = glusterfs_uuid_buf_get(THIS->ctx); + uuid_unparse (uuid, uuid_buffer); + return uuid_buffer; +} + +/*Re-entrant conversion function*/ +char * +uuid_utoa_r (uuid_t uuid, char *dst) +{ + if(!dst) + return NULL; + uuid_unparse (uuid, dst); + return dst; +} + +/*Thread safe conversion function*/ +char * +lkowner_utoa (gf_lkowner_t *lkowner) +{ + char *lkowner_buffer = glusterfs_lkowner_buf_get(THIS->ctx); + lkowner_unparse (lkowner, lkowner_buffer, GF_LKOWNER_BUF_SIZE); + return lkowner_buffer; +} + +/*Re-entrant conversion function*/ +char * +lkowner_utoa_r (gf_lkowner_t *lkowner, char *dst, int len) +{ + if(!dst) + return NULL; + lkowner_unparse (lkowner, dst, len); + return dst; +} + +void* gf_array_elem (void *a, int index, size_t elem_size) +{ + uint8_t* ptr = a; + return (void*)(ptr + index * elem_size); +} + +void +gf_elem_swap (void *x, void *y, size_t l) { + uint8_t *a = x, *b = y, c; + while(l--) { + c = *a; + *a++ = *b; + *b++ = c; + } +} + +void +gf_array_insertionsort (void *A, int l, int r, size_t elem_size, + gf_cmp cmp) +{ + int i = l; + int N = r+1; + void *Temp = NULL; + int j = 0; + + for(i = l; i < N; i++) { + Temp = gf_array_elem (A, i, elem_size); + j = i - 1; + while((cmp (Temp, gf_array_elem (A, j, elem_size)) + < 0) && j>=0) { + gf_elem_swap (Temp, gf_array_elem (A, j, elem_size), + elem_size); + Temp = gf_array_elem (A, j, elem_size); + j = j-1; + } + } +} + +int +gf_is_str_int (const char *value) +{ + int flag = 0; + char *str = NULL; + char *fptr = NULL; + + GF_VALIDATE_OR_GOTO (THIS->name, value, out); + + str = gf_strdup (value); + if (!str) + goto out; + + fptr = str; + + while (*str) { + if (!isdigit(*str)) { + flag = 1; + goto out; + } + str++; + } + +out: + GF_FREE (fptr); + + return flag; +} +/* + * rounds up nr to power of two. If nr is already a power of two, just returns + * nr + */ + +inline int32_t +gf_roundup_power_of_two (int32_t nr) +{ + int32_t result = 1; + + if (nr < 0) { + gf_log ("common-utils", GF_LOG_WARNING, + "negative number passed"); + result = -1; + goto out; + } + + while (result < nr) + result *= 2; + +out: + return result; +} + +/* + * rounds up nr to next power of two. If nr is already a power of two, next + * power of two is returned. + */ + +inline int32_t +gf_roundup_next_power_of_two (int32_t nr) +{ + int32_t result = 1; + + if (nr < 0) { + gf_log ("common-utils", GF_LOG_WARNING, + "negative number passed"); + result = -1; + goto out; + } + + while (result <= nr) + result *= 2; + +out: + return result; +} + +int +validate_brick_name (char *brick) +{ + char *delimiter = NULL; + int ret = 0; + delimiter = strrchr (brick, ':'); + if (!delimiter || delimiter == brick + || *(delimiter+1) != '/') + ret = -1; + + return ret; +} + +char * +get_host_name (char *word, char **host) +{ + char *delimiter = NULL; + delimiter = strrchr (word, ':'); + if (delimiter) + *delimiter = '\0'; + else + return NULL; + *host = word; + return *host; +} + + +char * +get_path_name (char *word, char **path) +{ + char *delimiter = NULL; + delimiter = strchr (word, '/'); + if (!delimiter) + return NULL; + *path = delimiter; + return *path; +} + +void +gf_path_strip_trailing_slashes (char *path) +{ + int i = 0; + int len = 0; + + if (!path) + return; + + len = strlen (path); + for (i = len - 1; i > 0; i--) { + if (path[i] != '/') + break; + } + + if (i < (len -1)) + path [i+1] = '\0'; + + return; +} + +uint64_t +get_mem_size () +{ + uint64_t memsize = -1; + +#if defined GF_LINUX_HOST_OS || defined GF_SOLARIS_HOST_OS + + uint64_t page_size = 0; + uint64_t num_pages = 0; + + page_size = sysconf (_SC_PAGESIZE); + num_pages = sysconf (_SC_PHYS_PAGES); + + memsize = page_size * num_pages; +#endif + +#if defined GF_BSD_HOST_OS || defined GF_DARWIN_HOST_OS + + size_t len = sizeof(memsize); + int name [] = { CTL_HW, HW_PHYSMEM }; + + sysctl (name, 2, &memsize, &len, NULL, 0); +#endif + return memsize; +} + +/* Strips all whitespace characters in a string and returns length of new string + * on success + */ +int +gf_strip_whitespace (char *str, int len) +{ + int i = 0; + int new_len = 0; + char *new_str = NULL; + + GF_ASSERT (str); + + new_str = GF_CALLOC (1, len + 1, gf_common_mt_char); + if (new_str == NULL) + return -1; + + for (i = 0; i < len; i++) { + if (!isspace (str[i])) + new_str[new_len++] = str[i]; + } + new_str[new_len] = '\0'; + + if (new_len != len) { + memset (str, 0, len); + strncpy (str, new_str, new_len); + } + + GF_FREE (new_str); + return new_len; +} + +int +gf_canonicalize_path (char *path) +{ + int ret = -1; + int path_len = 0; + int dir_path_len = 0; + char *tmppath = NULL; + char *dir = NULL; + char *tmpstr = NULL; + + if (!path || *path != '/') + goto out; + + tmppath = gf_strdup (path); + if (!tmppath) + goto out; + + /* Strip the extra slashes and return */ + bzero (path, strlen(path)); + path[0] = '/'; + dir = strtok_r(tmppath, "/", &tmpstr); + + while (dir) { + dir_path_len = strlen(dir); + strncpy ((path + path_len + 1), dir, dir_path_len); + path_len += dir_path_len + 1; + dir = strtok_r (NULL, "/", &tmpstr); + if (dir) + strncpy ((path + path_len), "/", 1); + } + path[path_len] = '\0'; + ret = 0; + + out: + if (ret) + gf_log ("common-utils", GF_LOG_ERROR, + "Path manipulation failed"); + + GF_FREE(tmppath); + + return ret; +} + +static const char *__gf_timefmts[] = { + "%F %T", + "%Y/%m/%d-%T", + "%b %d %T", + "%F %H%M%S" +}; + +static const char *__gf_zerotimes[] = { + "0000-00-00 00:00:00", + "0000/00/00-00:00:00", + "xxx 00 00:00:00", + "0000-00-00 000000" +}; + +void +_gf_timestuff (gf_timefmts *fmt, const char ***fmts, const char ***zeros) +{ + *fmt = gf_timefmt_last; + *fmts = __gf_timefmts; + *zeros = __gf_zerotimes; +} + + +char * +generate_glusterfs_ctx_id (void) +{ + char tmp_str[1024] = {0,}; + char hostname[256] = {0,}; + struct timeval tv = {0,}; + char now_str[32]; + + if (gettimeofday (&tv, NULL) == -1) { + gf_log ("glusterfsd", GF_LOG_ERROR, + "gettimeofday: failed %s", + strerror (errno)); + } + + if (gethostname (hostname, 256) == -1) { + gf_log ("glusterfsd", GF_LOG_ERROR, + "gethostname: failed %s", + strerror (errno)); + } + + gf_time_fmt (now_str, sizeof now_str, tv.tv_sec, gf_timefmt_Ymd_T); + snprintf (tmp_str, sizeof tmp_str, "%s-%d-%s:%" +#ifdef GF_DARWIN_HOST_OS + PRId32, +#else + "ld", +#endif + hostname, getpid(), now_str, tv.tv_usec); + + return gf_strdup (tmp_str); +} + +char * +gf_get_reserved_ports () +{ + char *ports_info = NULL; +#if defined GF_LINUX_HOST_OS + int proc_fd = -1; + char *proc_file = "/proc/sys/net/ipv4/ip_local_reserved_ports"; + char buffer[4096] = {0,}; + int32_t ret = -1; + + proc_fd = open (proc_file, O_RDONLY); + if (proc_fd == -1) { + /* What should be done in this case? error out from here + * and thus stop the glusterfs process from starting or + * continue with older method of using any of the available + * port? For now 2nd option is considered. + */ + gf_log ("glusterfs", GF_LOG_WARNING, "could not open " + "the file /proc/sys/net/ipv4/ip_local_reserved_ports " + "for getting reserved ports info (%s)", + strerror (errno)); + goto out; + } + + ret = read (proc_fd, buffer, sizeof (buffer)); + if (ret < 0) { + gf_log ("glusterfs", GF_LOG_WARNING, "could not " + "read the file %s for getting reserved ports " + "info (%s)", proc_file, strerror (errno)); + goto out; + } + ports_info = gf_strdup (buffer); + +out: + if (proc_fd != -1) + close (proc_fd); +#endif /* GF_LINUX_HOST_OS */ + return ports_info; +} + +int +gf_process_reserved_ports (gf_boolean_t *ports) +{ + int ret = -1; +#if defined GF_LINUX_HOST_OS + char *ports_info = NULL; + char *tmp = NULL; + char *blocked_port = NULL; + + ports_info = gf_get_reserved_ports (); + if (!ports_info) { + gf_log ("glusterfs", GF_LOG_WARNING, "Not able to get reserved " + "ports, hence there is a possibility that glusterfs " + "may consume reserved port"); + goto out; + } + + blocked_port = strtok_r (ports_info, ",\n",&tmp); + + while (blocked_port) { + gf_ports_reserved (blocked_port, ports); + blocked_port = strtok_r (NULL, ",\n", &tmp); + } + + ret = 0; + +out: + GF_FREE (ports_info); +#endif /* GF_LINUX_HOST_OS */ + return ret; +} + +gf_boolean_t +gf_ports_reserved (char *blocked_port, gf_boolean_t *ports) +{ + gf_boolean_t result = _gf_false; + char *range_port = NULL; + int16_t tmp_port1, tmp_port2 = -1; + + if (strstr (blocked_port, "-") == NULL) { + /* get rid of the new line character*/ + if (blocked_port[strlen(blocked_port) -1] == '\n') + blocked_port[strlen(blocked_port) -1] = '\0'; + if (gf_string2int16 (blocked_port, &tmp_port1) == 0) { + if (tmp_port1 > (GF_CLIENT_PORT_CEILING - 1) + || tmp_port1 < 0) { + gf_log ("glusterfs-socket", GF_LOG_WARNING, + "invalid port %d", tmp_port1); + result = _gf_true; + goto out; + } else { + gf_log ("glusterfs", GF_LOG_DEBUG, + "blocking port %d", tmp_port1); + ports[tmp_port1] = _gf_true; + } + } else { + gf_log ("glusterfs-socket", GF_LOG_WARNING, "%s is " + "not a valid port identifier", blocked_port); + result = _gf_true; + goto out; + } + } else { + range_port = strtok (blocked_port, "-"); + if (!range_port){ + result = _gf_true; + goto out; + } + if (gf_string2int16 (range_port, &tmp_port1) == 0) { + if (tmp_port1 > (GF_CLIENT_PORT_CEILING - 1)) + tmp_port1 = GF_CLIENT_PORT_CEILING - 1; + if (tmp_port1 < 0) + tmp_port1 = 0; + } + range_port = strtok (NULL, "-"); + if (!range_port) { + result = _gf_true; + goto out; + } + /* get rid of the new line character*/ + if (range_port[strlen(range_port) -1] == '\n') + range_port[strlen(range_port) - 1] = '\0'; + if (gf_string2int16 (range_port, &tmp_port2) == 0) { + if (tmp_port2 > + (GF_CLIENT_PORT_CEILING - 1)) + tmp_port2 = GF_CLIENT_PORT_CEILING - 1; + if (tmp_port2 < 0) + tmp_port2 = 0; + } + gf_log ("glusterfs", GF_LOG_DEBUG, "lower: %d, higher: %d", + tmp_port1, tmp_port2); + for (; tmp_port1 <= tmp_port2; tmp_port1++) + ports[tmp_port1] = _gf_true; + } + +out: + return result; +} + +/* Takes in client ip{v4,v6} and returns associated hostname, if any + * Also, allocates memory for the hostname. + * Returns: 0 for success, -1 for failure + */ +int +gf_get_hostname_from_ip (char *client_ip, char **hostname) +{ + int ret = -1; + struct sockaddr *client_sockaddr = NULL; + struct sockaddr_in client_sock_in = {0}; + struct sockaddr_in6 client_sock_in6 = {0}; + char client_hostname[NI_MAXHOST] = {0}; + char *client_ip_copy = NULL; + char *tmp = NULL; + char *ip = NULL; + + /* if ipv4, reverse lookup the hostname to + * allow FQDN based rpc authentication + */ + if (valid_ipv4_address (client_ip, strlen (client_ip), 0) == _gf_false) { + /* most times, we get a.b.c.d:port form, so check that */ + client_ip_copy = gf_strdup (client_ip); + if (!client_ip_copy) + goto out; + + ip = strtok_r (client_ip_copy, ":", &tmp); + } else { + ip = client_ip; + } + + if (valid_ipv4_address (ip, strlen (ip), 0) == _gf_true) { + client_sockaddr = (struct sockaddr *)&client_sock_in; + client_sock_in.sin_family = AF_INET; + ret = inet_pton (AF_INET, ip, + (void *)&client_sock_in.sin_addr.s_addr); + + } else if (valid_ipv6_address (ip, strlen (ip), 0) == _gf_true) { + client_sockaddr = (struct sockaddr *) &client_sock_in6; + + client_sock_in6.sin6_family = AF_INET6; + ret = inet_pton (AF_INET6, ip, + (void *)&client_sock_in6.sin6_addr); + } else { + goto out; + } + + if (ret != 1) { + ret = -1; + goto out; + } + + ret = getnameinfo (client_sockaddr, + sizeof (*client_sockaddr), + client_hostname, sizeof (client_hostname), + NULL, 0, 0); + if (ret) { + gf_log ("common-utils", GF_LOG_ERROR, + "Could not lookup hostname of %s : %s", + client_ip, gai_strerror (ret)); + ret = -1; + goto out; + } + + *hostname = gf_strdup ((char *)client_hostname); + out: + if (client_ip_copy) + GF_FREE (client_ip_copy); + + return ret; +} + +gf_boolean_t +gf_interface_search (char *ip) +{ + int32_t ret = -1; + gf_boolean_t found = _gf_false; + struct ifaddrs *ifaddr, *ifa; + int family; + char host[NI_MAXHOST]; + xlator_t *this = NULL; + char *pct = NULL; + + this = THIS; + + ret = getifaddrs (&ifaddr); + + if (ret != 0) { + gf_log (this->name, GF_LOG_ERROR, "getifaddrs() failed: %s\n", + gai_strerror(ret)); + goto out; + } + + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr) { + /* + * This seemingly happens if an interface hasn't + * been bound to a particular protocol (seen with + * TUN devices). + */ + continue; + } + family = ifa->ifa_addr->sa_family; + + if (family != AF_INET && family != AF_INET6) + continue; + + ret = getnameinfo (ifa->ifa_addr, + (family == AF_INET) ? sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6), + host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); + + if (ret != 0) { + gf_log (this->name, GF_LOG_ERROR, + "getnameinfo() failed: %s\n", + gai_strerror(ret)); + goto out; + } + + /* + * Sometimes the address comes back as addr%eth0 or + * similar. Since % is an invalid character, we can + * strip it out with confidence that doing so won't + * harm anything. + */ + pct = index(host,'%'); + if (pct) { + *pct = '\0'; + } + + if (strncmp (ip, host, NI_MAXHOST) == 0) { + gf_log (this->name, GF_LOG_DEBUG, + "%s is local address at interface %s", + ip, ifa->ifa_name); + found = _gf_true; + goto out; + } + } +out: + if(ifaddr) + freeifaddrs (ifaddr); + return found; +} + +char * +get_ip_from_addrinfo (struct addrinfo *addr, char **ip) +{ + char buf[64]; + void *in_addr = NULL; + struct sockaddr_in *s4 = NULL; + struct sockaddr_in6 *s6 = NULL; + + switch (addr->ai_family) + { + case AF_INET: + s4 = (struct sockaddr_in *)addr->ai_addr; + in_addr = &s4->sin_addr; + break; + + case AF_INET6: + s6 = (struct sockaddr_in6 *)addr->ai_addr; + in_addr = &s6->sin6_addr; + break; + + default: + gf_log ("glusterd", GF_LOG_ERROR, "Invalid family"); + return NULL; + } + + if (!inet_ntop(addr->ai_family, in_addr, buf, sizeof(buf))) { + gf_log ("glusterd", GF_LOG_ERROR, "String conversion failed"); + return NULL; + } + + *ip = strdup (buf); + return *ip; +} + +gf_boolean_t +gf_is_loopback_localhost (const struct sockaddr *sa, char *hostname) +{ + GF_ASSERT (sa); + + gf_boolean_t is_local = _gf_false; + const struct in_addr *addr4 = NULL; + const struct in6_addr *addr6 = NULL; + uint8_t *ap = NULL; + struct in6_addr loopbackaddr6 = IN6ADDR_LOOPBACK_INIT; + + switch (sa->sa_family) { + case AF_INET: + addr4 = &(((struct sockaddr_in *)sa)->sin_addr); + ap = (uint8_t*)&addr4->s_addr; + if (ap[0] == 127) + is_local = _gf_true; + break; + + case AF_INET6: + addr6 = &(((struct sockaddr_in6 *)sa)->sin6_addr); + if (memcmp (addr6, &loopbackaddr6, + sizeof (loopbackaddr6)) == 0) + is_local = _gf_true; + break; + + default: + if (hostname) + gf_log ("glusterd", GF_LOG_ERROR, + "unknown address family %d for %s", + sa->sa_family, hostname); + break; + } + + return is_local; +} + +gf_boolean_t +gf_is_local_addr (char *hostname) +{ + int32_t ret = -1; + struct addrinfo *result = NULL; + struct addrinfo *res = NULL; + gf_boolean_t found = _gf_false; + char *ip = NULL; + xlator_t *this = NULL; + + this = THIS; + ret = getaddrinfo (hostname, NULL, NULL, &result); + + if (ret != 0) { + gf_log (this->name, GF_LOG_ERROR, "error in getaddrinfo: %s\n", + gai_strerror(ret)); + goto out; + } + + for (res = result; res != NULL; res = res->ai_next) { + gf_log (this->name, GF_LOG_DEBUG, "%s ", + get_ip_from_addrinfo (res, &ip)); + + found = gf_is_loopback_localhost (res->ai_addr, hostname) + || gf_interface_search (ip); + if (found) + goto out; + } + +out: + if (result) + freeaddrinfo (result); + + if (!found) + gf_log (this->name, GF_LOG_DEBUG, "%s is not local", hostname); + + return found; +} + +gf_boolean_t +gf_is_same_address (char *name1, char *name2) +{ + struct addrinfo *addr1 = NULL; + struct addrinfo *addr2 = NULL; + struct addrinfo *p = NULL; + struct addrinfo *q = NULL; + gf_boolean_t ret = _gf_false; + int gai_err = 0; + + gai_err = getaddrinfo(name1,NULL,NULL,&addr1); + if (gai_err != 0) { + gf_log (name1, GF_LOG_WARNING, + "error in getaddrinfo: %s\n", gai_strerror(gai_err)); + goto out; + } + + gai_err = getaddrinfo(name2,NULL,NULL,&addr2); + if (gai_err != 0) { + gf_log (name2, GF_LOG_WARNING, + "error in getaddrinfo: %s\n", gai_strerror(gai_err)); + goto out; + } + + for (p = addr1; p; p = p->ai_next) { + for (q = addr2; q; q = q->ai_next) { + if (p->ai_addrlen != q->ai_addrlen) { + continue; + } + if (memcmp(p->ai_addr,q->ai_addr,p->ai_addrlen)) { + continue; + } + ret = _gf_true; + goto out; + } + } + +out: + if (addr1) { + freeaddrinfo(addr1); + } + if (addr2) { + freeaddrinfo(addr2); + } + return ret; + +} + + +/* Sets log file path from user provided arguments */ +int +gf_set_log_file_path (cmd_args_t *cmd_args) +{ + int i = 0; + int j = 0; + int ret = 0; + char tmp_str[1024] = {0,}; + + if (!cmd_args) + goto done; + + if (cmd_args->mount_point) { + j = 0; + i = 0; + if (cmd_args->mount_point[0] == '/') + i = 1; + for (; i < strlen (cmd_args->mount_point); i++,j++) { + tmp_str[j] = cmd_args->mount_point[i]; + if (cmd_args->mount_point[i] == '/') + tmp_str[j] = '-'; + } + + ret = gf_asprintf (&cmd_args->log_file, + DEFAULT_LOG_FILE_DIRECTORY "/%s.log", + tmp_str); + if (ret > 0) + ret = 0; + goto done; + } + + if (cmd_args->volfile) { + j = 0; + i = 0; + if (cmd_args->volfile[0] == '/') + i = 1; + for (; i < strlen (cmd_args->volfile); i++,j++) { + tmp_str[j] = cmd_args->volfile[i]; + if (cmd_args->volfile[i] == '/') + tmp_str[j] = '-'; + } + ret = gf_asprintf (&cmd_args->log_file, + DEFAULT_LOG_FILE_DIRECTORY "/%s.log", + tmp_str); + if (ret > 0) + ret = 0; + goto done; + } + + if (cmd_args->volfile_server) { + + ret = gf_asprintf (&cmd_args->log_file, + DEFAULT_LOG_FILE_DIRECTORY "/%s-%s-%d.log", + cmd_args->volfile_server, + cmd_args->volfile_id, getpid()); + if (ret > 0) + ret = 0; + } +done: + return ret; +} + +int +gf_thread_create (pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg) +{ + sigset_t set, old; + int ret; + + sigemptyset (&set); + + sigfillset (&set); + sigdelset (&set, SIGSEGV); + sigdelset (&set, SIGBUS); + sigdelset (&set, SIGILL); + sigdelset (&set, SIGSYS); + sigdelset (&set, SIGFPE); + sigdelset (&set, SIGABRT); + + pthread_sigmask (SIG_BLOCK, &set, &old); + + ret = pthread_create (thread, attr, start_routine, arg); + + pthread_sigmask (SIG_SETMASK, &old, NULL); + + return ret; +} diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index 248efc83c..3c99a4212 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _COMMON_UTILS_H @@ -32,9 +23,10 @@ #include <string.h> #include <assert.h> #include <pthread.h> +#include <openssl/md5.h> #ifndef GF_BSD_HOST_OS #include <alloca.h> -#endif +#endif void trap (void); @@ -47,6 +39,8 @@ void trap (void); #include "glusterfs.h" #include "locking.h" #include "mem-pool.h" +#include "uuid.h" + #define min(a,b) ((a)<(b)?(a):(b)) @@ -67,78 +61,186 @@ void trap (void); #define GF_UNIT_TB_STRING "TB" #define GF_UNIT_PB_STRING "PB" +#define GF_UNIT_PERCENT_STRING "%" + +#define GEOREP "geo-replication" +#define GHADOOP "glusterfs-hadoop" + +#define GF_SELINUX_XATTR_KEY "security.selinux" + +#define WIPE(statp) do { typeof(*statp) z = {0,}; if (statp) *statp = z; } while (0) + +#define IS_EXT_FS(fs_name) \ + (!strcmp (fs_name, "ext2") || \ + !strcmp (fs_name, "ext3") || \ + !strcmp (fs_name, "ext4")) -#define ERR_ABORT(ptr) \ - if (ptr == NULL) { \ - abort (); \ - } +/* Defining this here as it is needed by glusterd for setting + * nfs port in volume status. + */ +#define GF_NFS3_PORT 2049 +#define GF_CLIENT_PORT_CEILING 1024 -enum _gf_boolean +enum _gf_boolean { - _gf_false = 0, + _gf_false = 0, _gf_true = 1 }; +/* + * we could have initialized these as +ve values and treated + * them as negative while comparing etc.. (which would have + * saved us with the pain of assigning values), but since we + * only have a couple of clients that use this feature, it's + * okay. + */ +enum _gf_client_pid +{ + GF_CLIENT_PID_MAX = 0, + GF_CLIENT_PID_GSYNCD = -1, + GF_CLIENT_PID_HADOOP = -2, + GF_CLIENT_PID_DEFRAG = -3, +}; + typedef enum _gf_boolean gf_boolean_t; +typedef enum _gf_client_pid gf_client_pid_t; +typedef int (*gf_cmp) (void *, void *); 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]; +void gf_log_dump_graph (FILE *specfp, glusterfs_graph_t *graph); +void gf_print_trace (int32_t signal, glusterfs_ctx_t *ctx); +int gf_set_log_file_path (cmd_args_t *cmd_args); #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); \ + gf_log_callingfn ((this ? (this->name) : \ + "(Govinda! Govinda!)"), \ + GF_LOG_WARNING, \ + "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_VALIDATE_OR_GOTO_WITH_ERROR(name, arg, label, error) do { \ - if (!arg) { \ - errno = error; \ - gf_log (name, GF_LOG_ERROR, \ - "invalid argument: " #arg); \ - goto label; \ - } \ - }while (0); - -#define GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO(name,arg,label) \ - do { \ - GF_VALIDATE_OR_GOTO (name, arg, label); \ - if ((arg[0]) != '/') { \ - errno = EINVAL; \ - gf_log (name, GF_LOG_ERROR, \ - "invalid argument: " #arg); \ - goto label; \ - } \ - } while (0); + } while (0) + +#define GF_VALIDATE_OR_GOTO(name,arg,label) do { \ + if (!arg) { \ + errno = EINVAL; \ + gf_log_callingfn (name, GF_LOG_ERROR, \ + "invalid argument: " #arg); \ + goto label; \ + } \ + } while (0) + +#define GF_VALIDATE_OR_GOTO_WITH_ERROR(name, arg, label, errno, error) do { \ + if (!arg) { \ + errno = error; \ + gf_log_callingfn (name, GF_LOG_ERROR, \ + "invalid argument: " #arg); \ + goto label; \ + } \ + }while (0) + +#define GF_ASSERT_AND_GOTO_WITH_ERROR(name, arg, label, errno, error) do { \ + if (!arg) { \ + GF_ASSERT (0); \ + errno = error; \ + goto label; \ + } \ + }while (0) + +#define GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO(name,arg,label) \ + do { \ + GF_VALIDATE_OR_GOTO (name, arg, label); \ + if ((arg[0]) != '/') { \ + errno = EINVAL; \ + gf_log_callingfn (name, GF_LOG_ERROR, \ + "invalid argument: " #arg); \ + goto label; \ + } \ + } while (0) + +#define GF_REMOVE_SLASH_FROM_PATH(path, string) \ + do { \ + int i = 0; \ + for (i = 1; i < strlen (path); i++) { \ + string[i-1] = path[i]; \ + if (string[i-1] == '/') \ + string[i-1] = '-'; \ + } \ + } while (0) + +#define GF_IF_INTERNAL_XATTR_GOTO(pattern, dict, op_errno, label) \ + do { \ + if (!dict) { \ + gf_log (this->name, GF_LOG_ERROR, \ + "setxattr dict is null"); \ + goto label; \ + } \ + if (dict_foreach_fnmatch (dict, pattern, \ + dict_null_foreach_fn, \ + NULL) > 0) { \ + op_errno = EPERM; \ + gf_log (this->name, GF_LOG_ERROR, \ + "attempt to set internal" \ + " xattr: %s: %s", pattern, \ + strerror (op_errno)); \ + goto label; \ + } \ + } while (0) + +#define GF_IF_NATIVE_XATTR_GOTO(pattern, key, op_errno, label) \ + do { \ + if (!key) { \ + gf_log (this->name, GF_LOG_ERROR, \ + "no key for removexattr"); \ + goto label; \ + } \ + if (!fnmatch (pattern, key, 0)) { \ + op_errno = EPERM; \ + gf_log (this->name, GF_LOG_ERROR, \ + "attempt to remove internal " \ + "xattr: %s: %s", key, \ + strerror (op_errno)); \ + goto label; \ + } \ + } while (0) + #define GF_FILE_CONTENT_REQUESTED(_xattr_req,_content_limit) \ (dict_get_uint64 (_xattr_req, "glusterfs.content", _content_limit) == 0) +#ifdef DEBUG +#define GF_ASSERT(x) assert (x); +#else +#define GF_ASSERT(x) \ + do { \ + if (!(x)) { \ + gf_log_callingfn ("", GF_LOG_ERROR, \ + "Assertion failed: " #x); \ + } \ + } while (0) +#endif + +#define GF_UUID_ASSERT(u) \ + if (uuid_is_null (u))\ + GF_ASSERT (!"uuid null"); + +union gf_sock_union { + struct sockaddr_storage storage; + struct sockaddr_in6 sin6; + struct sockaddr_in sin; + struct sockaddr sa; +}; + +#define GF_HIDDEN_PATH ".glusterfs" + static inline void iov_free (struct iovec *vector, int count) { @@ -147,7 +249,7 @@ iov_free (struct iovec *vector, int count) for (i = 0; i < count; i++) FREE (vector[i].iov_base); - FREE (vector); + GF_FREE (vector); } @@ -165,14 +267,14 @@ iov_length (const struct iovec *vector, int count) static inline struct iovec * -iov_dup (struct iovec *vector, int count) +iov_dup (const struct iovec *vector, int count) { int bytecount = 0; int i; struct iovec *newvec = NULL; bytecount = (count * sizeof (struct iovec)); - newvec = MALLOC (bytecount); + newvec = GF_MALLOC (bytecount, gf_common_mt_iovec); if (!newvec) return NULL; @@ -245,6 +347,65 @@ iov_unload (char *buf, const struct iovec *vector, int count) } +static inline size_t +iov_load (const struct iovec *vector, int count, char *buf, int size) +{ + size_t left = size; + size_t cp = 0; + int ret = 0; + int i = 0; + + while (left && i < count) { + cp = min (vector[i].iov_len, left); + if (vector[i].iov_base != buf + (size - left)) + memcpy (vector[i].iov_base, buf + (size - left), cp); + ret += cp; + left -= cp; + if (left) + i++; + } + + return ret; +} + + +static inline size_t +iov_copy (const struct iovec *dst, int dcnt, + const struct iovec *src, int scnt) +{ + size_t ret = 0; + size_t left = 0; + size_t min_i = 0; + int s_i = 0, s_ii = 0; + int d_i = 0, d_ii = 0; + + ret = min (iov_length (dst, dcnt), iov_length (src, scnt)); + left = ret; + + while (left) { + min_i = min (dst[d_i].iov_len - d_ii, src[s_i].iov_len - s_ii); + memcpy (dst[d_i].iov_base + d_ii, src[s_i].iov_base + s_ii, + min_i); + + d_ii += min_i; + if (d_ii == dst[d_i].iov_len) { + d_ii = 0; + d_i++; + } + + s_ii += min_i; + if (s_ii == src[s_i].iov_len) { + s_ii = 0; + s_i++; + } + + left -= min_i; + } + + return ret; +} + + static inline int mem_0filled (const char *buf, size_t size) { @@ -282,7 +443,7 @@ memdup (const void *ptr, size_t size) { void *newptr = NULL; - newptr = MALLOC (size); + newptr = GF_MALLOC (size, gf_common_mt_memdup); if (!newptr) return NULL; @@ -290,9 +451,55 @@ memdup (const void *ptr, size_t size) return newptr; } +typedef enum { + gf_timefmt_default = 0, + gf_timefmt_FT = 0, /* YYYY-MM-DD hh:mm:ss */ + gf_timefmt_Ymd_T, /* YYYY/MM-DD-hh:mm:ss */ + gf_timefmt_bdT, /* ddd DD hh:mm:ss */ + gf_timefmt_F_HMS, /* YYYY-MM-DD hhmmss */ + gf_timefmt_last +} gf_timefmts; + +static inline void +gf_time_fmt (char *dst, size_t sz_dst, time_t utime, unsigned int fmt) +{ + extern void _gf_timestuff (gf_timefmts *, const char ***, const char ***); + static gf_timefmts timefmt_last = (gf_timefmts) -1; + static const char **fmts; + static const char **zeros; + struct tm tm; + + if (timefmt_last == -1) + _gf_timestuff (&timefmt_last, &fmts, &zeros); + if (timefmt_last < fmt) fmt = gf_timefmt_default; + if (utime && gmtime_r (&utime, &tm) != NULL) { + strftime (dst, sz_dst, fmts[fmt], &tm); + } else { + strncpy (dst, "N/A", sz_dst); + } +} + +int +mkdir_p (char *path, mode_t mode, gf_boolean_t allow_symlinks); +/* + * rounds up nr to power of two. If nr is already a power of two, just returns + * nr + */ + +int +gf_lstat_dir (const char *path, struct stat *stbuf_in); + +int32_t gf_roundup_power_of_two (int32_t nr); + +/* + * rounds up nr to next power of two. If nr is already a power of two, next + * power of two is returned. + */ + +int32_t gf_roundup_next_power_of_two (int32_t nr); char *gf_trim (char *string); -int gf_strsplit (const char *str, const char *delim, +int gf_strsplit (const char *str, const char *delim, char ***tokens, int *token_count); int gf_volume_name_validate (const char *volume_name); @@ -313,6 +520,8 @@ 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_strstr (const char *str, const char *delim, const char *match); + 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); @@ -321,15 +530,65 @@ 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_string2percent_or_bytesize (const char *str, uint64_t *n, + gf_boolean_t *is_percent); int gf_string2boolean (const char *str, gf_boolean_t *b); -int gf_string2percent (const char *str, uint32_t *n); +int gf_string2percent (const char *str, double *n); int gf_string2time (const char *str, uint32_t *n); int gf_lockfd (int fd); int gf_unlockfd (int fd); int get_checksum_for_file (int fd, uint32_t *checksum); +int log_base2 (unsigned long x); + +int get_checksum_for_path (char *path, uint32_t *checksum); + +char *strtail (char *str, const char *pattern); +void skipwhite (char **s); +char *nwstrtail (char *str, char *pattern); +void skip_word (char **str); +/* returns a new string with nth word of given string. n>=1 */ +char *get_nth_word (const char *str, int n); + +char valid_host_name (char *address, int length); +char valid_ipv4_address (char *address, int length, gf_boolean_t wildcard_acc); +char valid_ipv6_address (char *address, int length, gf_boolean_t wildcard_acc); +char valid_internet_address (char *address, gf_boolean_t wildcard_acc); +char valid_ipv4_wildcard_check (char *address); +char valid_ipv6_wildcard_check (char *address); +char valid_wildcard_internet_address (char *address); +gf_boolean_t gf_sock_union_equal_addr (union gf_sock_union *a, + union gf_sock_union *b); + +char *uuid_utoa (uuid_t uuid); +char *uuid_utoa_r (uuid_t uuid, char *dst); +char *lkowner_utoa (gf_lkowner_t *lkowner); +char *lkowner_utoa_r (gf_lkowner_t *lkowner, char *dst, int len); + +void gf_array_insertionsort (void *a, int l, int r, size_t elem_size, + gf_cmp cmp); +int gf_is_str_int (const char *value); + +char *gf_uint64_2human_readable (uint64_t); +int validate_brick_name (char *brick); +char *get_host_name (char *word, char **host); +char *get_path_name (char *word, char **path); +void gf_path_strip_trailing_slashes (char *path); +uint64_t get_mem_size (); +int gf_strip_whitespace (char *str, int len); +int gf_canonicalize_path (char *path); +char *generate_glusterfs_ctx_id (void); +char *gf_get_reserved_ports(); +int gf_process_reserved_ports (gf_boolean_t ports[]); +gf_boolean_t gf_ports_reserved (char *blocked_port, gf_boolean_t *ports); +int gf_get_hostname_from_ip (char *client_ip, char **hostname); +gf_boolean_t gf_is_local_addr (char *hostname); +gf_boolean_t gf_is_same_address (char *host1, char *host2); +void md5_wrapper(const unsigned char *data, size_t len, char *md5); + +int gf_thread_create (pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg); #endif /* _COMMON_UTILS_H */ - diff --git a/libglusterfs/src/compat-errno.c b/libglusterfs/src/compat-errno.c index 63acb361a..fd5cc49ce 100644 --- a/libglusterfs/src/compat-errno.c +++ b/libglusterfs/src/compat-errno.c @@ -1,20 +1,11 @@ /* - Copyright (c) 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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -27,868 +18,870 @@ #include "compat-errno.h" -static int32_t gf_error_to_errno_array[1024]; +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 +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; +/* 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; +/* 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; +/* 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; +/* 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; +/* 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; +/* 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; +/* 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; +/* 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; +/* 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; +/* 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; +/* 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; +/* 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; +/* 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; +/* 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; +/* 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 */ +/* 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; + 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; +/* 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; +/* 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; +/* 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; +/* 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; +/* 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; + /* 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; +/* 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; +/* 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 ; + return ; } #endif /* GF_SOLARIS_HOST_OS */ #ifdef GF_DARWIN_HOST_OS -static void +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; + /* 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; - /* ENEEDAUTH 81 / * Need authenticator */ - gf_error_to_errno_array[GF_ERROR_CODE_NEEDAUTH] = ENEEDAUTH; - gf_errno_to_error_array[ENEEDAUTH] = GF_ERROR_CODE_NEEDAUTH; + /* 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; +/* 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; +/* 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; + +#ifdef EDOOFUS + /* 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; + /* 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; + /* 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; + /* 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; + /* 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; + /* 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; + /* 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; + /* 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; + /* 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; + /* 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; + /* 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; +/* 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; +/* 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; +/* 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 ; + return ; } #endif /* GF_DARWIN_HOST_OS */ #ifdef GF_BSD_HOST_OS -static void +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; + /* 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; - /* 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; + /* 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; - /* 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; + /* 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; - /* 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; + /* 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; - /* 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; + /* 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; - /* 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; + /* 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; - /* 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; + /* 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; - /* 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; + /* 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; - /* 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; + /* 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; - /* 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; + /* 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; - /* 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; + /* ECONNREFUSED 61 / * Connection refused */ + gf_error_to_errno_array[GF_ERROR_CODE_CONNREFUSED] = ECONNREFUSED; + gf_errno_to_error_array[ECONNREFUSED] = GF_ERROR_CODE_CONNREFUSED; - /* EAUTH 80 / * Authentication error */ - gf_error_to_errno_array[GF_ERROR_CODE_AUTH] = EAUTH; - gf_errno_to_error_array[EAUTH] = GF_ERROR_CODE_AUTH; + /* 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; - /* ENEEDAUTH 81 / * Need authenticator */ - gf_error_to_errno_array[GF_ERROR_CODE_NEEDAUTH] = ENEEDAUTH; - gf_errno_to_error_array[ENEEDAUTH] = GF_ERROR_CODE_NEEDAUTH; + /* 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; - /* EIDRM 82 / * Identifier removed */ - gf_error_to_errno_array[GF_ERROR_CODE_IDRM] = EIDRM; - gf_errno_to_error_array[EIDRM] = GF_ERROR_CODE_IDRM; + /* 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; - /* 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; + /* 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; - /* 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; + /* 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; - /* ECANCELED 85 / * Operation canceled */ - gf_error_to_errno_array[GF_ERROR_CODE_CANCELED] = ECANCELED; - gf_errno_to_error_array[ECANCELED] = GF_ERROR_CODE_CANCELED; + /* 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; - /* 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; + /* 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; - /* 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; + /* 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; - /* EBADMSG 89 / * Bad message */ - gf_error_to_errno_array[GF_ERROR_CODE_BADMSG] = EBADMSG; - gf_errno_to_error_array[EBADMSG] = GF_ERROR_CODE_BADMSG; + /* 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; - /* EMULTIHOP 90 / * Multihop attempted */ - gf_error_to_errno_array[GF_ERROR_CODE_MULTIHOP] = EMULTIHOP; - gf_errno_to_error_array[EMULTIHOP] = GF_ERROR_CODE_MULTIHOP; + /* 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; - /* 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; + /* 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; - /* EPROTO 92 / * Protocol error */ - gf_error_to_errno_array[GF_ERROR_CODE_PROTO] = EPROTO; - gf_errno_to_error_array[EPROTO] = GF_ERROR_CODE_PROTO; + /* 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; - return ; + /* 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; + +#ifdef EDOOFUS + /* 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 + + /* 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 +static void init_compat_errno_arrays () { - /* Things are fine. Everything should work seemlessly on GNU/Linux machines */ - return ; + /* Things are fine. Everything should work seemlessly on GNU/Linux machines */ + return ; } #endif /* GF_LINUX_HOST_OS */ @@ -896,43 +889,42 @@ init_compat_errno_arrays () 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; + 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 +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 (!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]; + if ((op_errno > GF_ERROR_CODE_SUCCESS) && (op_errno < GF_ERROR_CODE_UNKNOWN)) + return gf_errno_to_error_array[op_errno]; - return op_errno; + return op_errno; } -int32_t +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 (!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]; + if ((error > GF_ERROR_CODE_SUCCESS) && (error < GF_ERROR_CODE_UNKNOWN)) + return gf_error_to_errno_array[error]; - return error; + return error; } - diff --git a/libglusterfs/src/compat-errno.h b/libglusterfs/src/compat-errno.h index e1b2fec2a..65e52081d 100644 --- a/libglusterfs/src/compat-errno.h +++ b/libglusterfs/src/compat-errno.h @@ -1,20 +1,11 @@ /* - Copyright (c) 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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef __COMPAT_ERRNO_H__ @@ -199,9 +190,9 @@ /* Solaris */ -/* ENOTACTIVE 73 / * Facility is not active */ -#define GF_ERROR_CODE_NOTACTIVE 801 -/* ELOCKUNMAPPED 72 / * locked lock was unmapped */ +/* 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 */ @@ -231,8 +222,8 @@ #define EBADFD EBADRPC #endif /* EBADFD */ -/* These functions are defined for all the OS flags, but content will - * be different for each OS flag. +/* 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); diff --git a/libglusterfs/src/compat.c b/libglusterfs/src/compat.c index bad62b563..eb6d8d4b7 100644 --- a/libglusterfs/src/compat.c +++ b/libglusterfs/src/compat.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -35,404 +26,520 @@ #include "compat.h" #include "common-utils.h" +#include "iatt.h" +#include "inode.h" -#ifdef GF_DARWIN_HOST_OS +#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; +} -#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, -}; +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) + gf_log ("libglusterfs", GF_LOG_INFO, + "Couldn't read extended attribute for the file %d (%d)", + fd, errno); + if (errno == ENOENT) + errno = ENODATA; + return -1; + } + + return ret; +} +/* Solaris does not support xattr for symlinks and dev files. Since gfid and + other trusted attributes are stored as xattrs, we need to provide support for + them. A mapped regular file is stored in the /.glusterfs_xattr_inode of the export dir. + All xattr ops related to the special files are redirected to this map file. +*/ -int32_t -gf_darwin_compat_listxattr (int len, dict_t *dict, int size) +int +make_export_path (const char *real_path, char **path) { - 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; + int ret = -1; + char *tmp = NULL; + char *export_path = NULL; + char *dup = NULL; + char *ptr = NULL; + char *freeptr = NULL; + uuid_t gfid = {0, }; + + export_path = GF_CALLOC (1, sizeof (char) * PATH_MAX, 0); + if (!export_path) + goto out; + + dup = gf_strdup (real_path); + if (!dup) + goto out; + + freeptr = dup; + ret = solaris_getxattr ("/", GFID_XATTR_KEY, gfid, 16); + /* Return value of getxattr */ + if (ret == 16) { + if (__is_root_gfid (gfid)){ + strcat (export_path, "/"); + ret = 0; + goto done; + } + } + + do { + ptr = strtok_r (dup, "/", &tmp); + if (!ptr) + break; + strcat (export_path, dup); + ret = solaris_getxattr (export_path, GFID_XATTR_KEY, gfid, 16); + if (ret == 16) { + if (__is_root_gfid (gfid)) { + ret = 0; + goto done; + } + } + strcat (export_path, "/"); + dup = tmp; + } while (ptr); + + goto out; + +done: + if (!ret) { + *path = export_path; + } +out: + GF_FREE (freeptr); + if (ret && export_path) + GF_FREE (export_path); + + return ret; } - -int32_t -gf_darwin_compat_getxattr (const char *key, dict_t *dict) +int +solaris_xattr_resolve_path (const char *real_path, char **path) { - 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; + int ret = -1; + char *export_path = NULL; + char xattr_path[PATH_MAX] = {0, }; + struct stat lstatbuf = {0, }; + struct iatt stbuf = {0, }; + struct stat statbuf = {0, }; + + ret = lstat (real_path, &lstatbuf); + if (ret != 0 ) + return ret; + iatt_from_stat (&stbuf, &lstatbuf); + if (IA_ISREG(stbuf.ia_type) || IA_ISDIR(stbuf.ia_type)) + return -1; + + ret = make_export_path (real_path, &export_path); + if (!ret && export_path) { + strcat (export_path, "/"GF_SOLARIS_XATTR_DIR); + if (lstat (export_path, &statbuf)) { + ret = mkdir (export_path, 0777); + if (ret && (errno != EEXIST)) { + gf_log (THIS->name, GF_LOG_DEBUG, "mkdir failed," + " errno: %d", errno); + goto out; + } + } + + snprintf(xattr_path, PATH_MAX, "%s%s%lu", export_path, + "/", stbuf.ia_ino); + + ret = lstat (xattr_path, &statbuf); + + if (ret) { + ret = mknod (xattr_path, S_IFREG|O_WRONLY, 0); + if (ret && (errno != EEXIST)) { + gf_log (THIS->name, GF_LOG_WARNING,"Failed to create " + "mapped file %s, error %d", xattr_path, + errno); + goto out; + } + } + *path = gf_strdup (xattr_path); + } +out: + GF_FREE (export_path); + if (*path) + return 0; + else + return -1; } - -int32_t -gf_darwin_compat_setxattr (dict_t *dict) +int +solaris_setxattr(const char *path, const char* key, const char *value, + size_t size, int flags) { - data_t *data = NULL; + int attrfd = -1; + int ret = 0; + char *mapped_path = NULL; + + ret = solaris_xattr_resolve_path (path, &mapped_path); + if (!ret) { + attrfd = attropen (mapped_path, key, flags|O_CREAT|O_WRONLY, + 0777); + } else { + attrfd = attropen (path, key, flags|O_CREAT|O_WRONLY, 0777); + } + if (attrfd >= 0) { + ftruncate (attrfd, 0); + ret = write (attrfd, value, size); + close (attrfd); + ret = 0; + } else { + if (errno != ENOENT) + gf_log ("libglusterfs", GF_LOG_ERROR, + "Couldn't set extended attribute for %s (%d)", + path, errno); + ret = -1; + } + GF_FREE (mapped_path); + return ret; +} - 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; +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; + char *mapped_path = NULL; + int ret = -1; + + ret = solaris_xattr_resolve_path (path, &mapped_path); + if (!ret) { + attrdirfd = attropen (mapped_path, ".", O_RDONLY, 0); + } else { + 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 entry + null + 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); + len = -1; + goto out; + } + } else { + close (attrdirfd); + len = -1; + goto out; + } + close (attrdirfd); + } +out: + GF_FREE (mapped_path); + return len; } -#endif /* DARWIN */ +int +solaris_flistxattr(int fd, char *list, size_t size) +{ + int attrdirfd = -1; + ssize_t len = 0; + DIR *dirptr = NULL; + struct dirent *dent = NULL; + int newfd = -1; + + attrdirfd = openat (fd, ".", 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 entry + null + 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; +} -#ifdef GF_SOLARIS_HOST_OS -int -solaris_fsetxattr(int fd, - const char* key, - const char *value, - size_t size, - int flags) +int +solaris_removexattr(const char *path, const char* key) { - 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 ret = -1; + int attrfd = -1; + char *mapped_path = NULL; + + ret = solaris_xattr_resolve_path (path, &mapped_path); + if (!ret) { + attrfd = attropen (mapped_path, ".", O_RDONLY, 0); + } else { + attrfd = attropen (path, ".", O_RDONLY, 0); + } + if (attrfd >= 0) { + ret = unlinkat (attrfd, key, 0); + close (attrfd); + } else { + if (errno == ENOENT) + errno = ENODATA; + ret = -1; + } + + GF_FREE (mapped_path); + + return ret; } - -int -solaris_fgetxattr(int fd, - const char* key, - char *value, - size_t size) +int +solaris_getxattr(const char *path, + 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 attrfd = -1; + int ret = 0; + char *mapped_path = NULL; + + ret = solaris_xattr_resolve_path (path, &mapped_path); + if (!ret) { + attrfd = attropen (mapped_path, key, O_RDONLY, 0); + } else { + 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) + gf_log ("libglusterfs", GF_LOG_INFO, + "Couldn't read extended attribute for the file %s (%s)", + path, strerror (errno)); + if (errno == ENOENT) + errno = ENODATA; + ret = -1; + } + GF_FREE (mapped_path); + return ret; } -int -solaris_setxattr(const char *path, - const char* key, - const char *value, - size_t size, - int flags) +char* strsep(char** str, const char* delims) { - 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; + 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; } +/* Code comes from libiberty */ int -solaris_listxattr(const char *path, - char *list, - size_t size) +vasprintf (char **result, const char *format, va_list args) { - 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; + return gf_vasprintf(result, format, args); } - int -solaris_flistxattr(int fd, - char *list, - size_t size) +asprintf (char **buf, const char *fmt, ...) { - int attrdirfd = -1; - ssize_t len = 0; - DIR *dirptr = NULL; - struct dirent *dent = NULL; - int newfd = -1; - - attrdirfd = openat (fd, ".", 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 status; + va_list ap; + va_start (ap, fmt); + status = vasprintf (buf, fmt, ap); + va_end (ap); + return status; +} -int -solaris_removexattr(const char *path, - const char* key) +int solaris_unlink (const char *path) { - 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; + char *mapped_path = NULL; + struct stat stbuf = {0, }; + int ret = -1; + + ret = solaris_xattr_resolve_path (path, &mapped_path); + + + if (!ret && mapped_path) { + if (lstat(path, &stbuf)) { + gf_log (THIS->name, GF_LOG_WARNING, "Stat failed on mapped" + " file %s with error %d", mapped_path, errno); + goto out; + } + if (stbuf.st_nlink == 1) { + if(remove (mapped_path)) + gf_log (THIS->name, GF_LOG_WARNING, "Failed to remove mapped " + "file %s. Errno %d", mapped_path, errno); + } + + } + +out: + GF_FREE (mapped_path); + + return unlink (path); } -int -solaris_getxattr(const char *path, - const char* key, - char *value, - size_t size) +int +solaris_rename (const char *old_path, const char *new_path) { - 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; -} + char *mapped_path = NULL; + int ret = -1; + ret = solaris_xattr_resolve_path (new_path, &mapped_path); -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) + if (!ret && mapped_path) { + if (!remove (mapped_path)) + gf_log (THIS->name, GF_LOG_WARNING, "Failed to remove mapped " + "file %s. Errno %d", mapped_path, errno); + GF_FREE (mapped_path); + } + + return rename(old_path, new_path); + +} + +char * +mkdtemp (char *tempstring) { - 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; + char *new_string = NULL; + int ret = 0; + + new_string = mkstemp (tempstring); + if (!new_string) + goto out; + + ret = mkdir (new_string, 0700); + if (ret < 0) + new_string = NULL; + +out: + return new_string; } #endif /* GF_SOLARIS_HOST_OS */ #ifndef HAVE_STRNLEN -size_t -strnlen(const char *string, size_t maxlen) +size_t +strnlen(const char *string, size_t maxlen) { - int len = 0; - while ((len < maxlen) && string[len]) - len++; - return len; + 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 index 07ff30664..2bd982541 100644 --- a/libglusterfs/src/compat.h +++ b/libglusterfs/src/compat.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef __COMPAT_H__ @@ -41,11 +32,17 @@ #include <linux/limits.h> #include <sys/xattr.h> #include <endian.h> +#ifdef HAVE_FALLOC_H +#include <linux/falloc.h> +#else +#define FALLOC_FL_KEEP_SIZE 0x01 /* default is extend size */ +#define FALLOC_FL_PUNCH_HOLE 0x02 /* de-allocates range */ +#endif #ifndef HAVE_LLISTXATTR -/* This part is valid only incase of old glibc which doesn't support +/* This part is valid only incase of old glibc which doesn't support * 'llistxattr()' system calls. */ @@ -57,8 +54,8 @@ #endif /* HAVE_LLISTXATTR */ #endif /* GF_LINUX_HOST_OS */ -#ifdef GF_BSD_HOST_OS -/* In case of FreeBSD */ +#ifdef GF_BSD_HOST_OS +/* In case of FreeBSD and NetBSD */ #define UNIX_PATH_MAX 104 #include <sys/types.h> @@ -66,16 +63,21 @@ #include <sys/un.h> #include <sys/endian.h> #include <sys/extattr.h> +#ifdef HAVE_SYS_XATTR_H +#include <sys/xattr.h> +#endif /* HAVE_SYS_XATTR_H */ #include <limits.h> #include <libgen.h> +#ifndef XATTR_CREATE enum { ATTR_CREATE = 1, #define XATTR_CREATE ATTR_CREATE ATTR_REPLACE = 2 #define XATTR_REPLACE ATTR_REPLACE }; +#endif /* XATTR_CREATE */ #ifndef sighandler_t @@ -88,7 +90,7 @@ enum { #ifndef EUCLEAN #define EUCLEAN 0 -#endif +#endif #include <netinet/in.h> #ifndef s6_addr16 @@ -96,7 +98,7 @@ enum { #endif #ifndef s6_addr32 #define s6_addr32 __u6_addr.__u6_addr32 -#endif +#endif /* Posix dictates NAME_MAX to be used */ # ifndef NAME_MAX @@ -106,7 +108,7 @@ enum { # define NAME_MAX 255 # endif # endif - + #define F_GETLK64 F_GETLK #define F_SETLK64 F_SETLK #define F_SETLKW64 F_SETLKW @@ -146,10 +148,10 @@ enum { #include <netinet/in.h> #ifndef s6_addr16 #define s6_addr16 __u6_addr.__u6_addr16 -#endif +#endif #ifndef s6_addr32 #define s6_addr32 __u6_addr.__u6_addr32 -#endif +#endif /* Posix dictates NAME_MAX to be used */ # ifndef NAME_MAX @@ -164,6 +166,10 @@ enum { #define F_SETLK64 F_SETLK #define F_SETLKW64 F_SETLKW +#ifndef FTW_CONTINUE + #define FTW_CONTINUE 0 +#endif + 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); @@ -173,7 +179,7 @@ int32_t gf_darwin_compat_setxattr (dict_t *dict); #ifdef GF_SOLARIS_HOST_OS #define UNIX_PATH_MAX 108 -#define EUCLEAN 117 +#define EUCLEAN 117 #include <sys/un.h> #include <limits.h> @@ -185,8 +191,9 @@ int32_t gf_darwin_compat_setxattr (dict_t *dict); #ifndef lchmod #define lchmod chmod -#endif +#endif +#define lgetxattr(path, key, value, size) solaris_getxattr(path,key,value,size) enum { ATTR_CREATE = 1, #define XATTR_CREATE ATTR_CREATE @@ -203,10 +210,10 @@ enum { # ifndef NAME_MAX # ifdef MAXNAMLEN # define NAME_MAX MAXNAMLEN -# else +# else # define NAME_MAX 255 # endif -# endif +# endif #include <netinet/in.h> #ifndef s6_addr16 @@ -218,20 +225,73 @@ enum { #define lutimes(filename,times) utimes(filename,times) -int asprintf(char **string_ptr, const char *format, ...); +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +enum { + DT_UNKNOWN = 0, +# define DT_UNKNOWN DT_UNKNOWN + DT_FIFO = 1, +# define DT_FIFO DT_FIFO + DT_CHR = 2, +# define DT_CHR DT_CHR + DT_DIR = 4, +# define DT_DIR DT_DIR + DT_BLK = 6, +# define DT_BLK DT_BLK + DT_REG = 8, +# define DT_REG DT_REG + DT_LNK = 10, +# define DT_LNK DT_LNK + DT_SOCK = 12, +# define DT_SOCK DT_SOCK + DT_WHT = 14 +# define DT_WHT DT_WHT +}; + +#ifndef _PATH_MOUNTED + #define _PATH_MOUNTED "/etc/mtab" +#endif + +#ifndef O_ASYNC + #ifdef FASYNC + #define O_ASYNC FASYNC + #else + #define O_ASYNC 0 + #endif +#endif + +#ifndef FTW_CONTINUE + #define FTW_CONTINUE 0 +#endif + +int asprintf(char **string_ptr, const char *format, ...); + +int vasprintf (char **result, const char *format, va_list args); 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, +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, +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, +int solaris_fsetxattr(int fd, const char* key, const char *value, size_t size, int flags); int solaris_flistxattr(int fd, char *list, size_t size); +int solaris_rename (const char *oldpath, const char *newpath); + +int solaris_unlink (const char *pathname); + +char *mkdtemp (char *temp); + +#define GF_SOLARIS_XATTR_DIR ".glusterfs_xattr_inode" + +int solaris_xattr_resolve_path (const char *real_path, char **path); + #endif /* GF_SOLARIS_HOST_OS */ #ifndef HAVE_ARGP @@ -241,7 +301,7 @@ int solaris_flistxattr(int fd, char *list, size_t size); #endif /* HAVE_ARGP */ #ifndef HAVE_STRNLEN -size_t strnlen(const char *string, size_t maxlen); +size_t strnlen(const char *string, size_t maxlen); #endif /* STRNLEN */ #ifndef strdupa @@ -253,9 +313,9 @@ size_t strnlen(const char *string, size_t maxlen); char *__new = (char *) __builtin_alloca (__len); \ (char *) memcpy (__new, __old, __len); \ })) -#endif +#endif -#define ALIGN(x) (((x) + sizeof (uint64_t) - 1) & ~(sizeof (uint64_t) - 1)) +#define GF_DIR_ALIGN(x) (((x) + sizeof (uint64_t) - 1) & ~(sizeof (uint64_t) - 1)) #include <sys/types.h> #include <dirent.h> @@ -263,50 +323,35 @@ size_t strnlen(const char *string, size_t maxlen); static inline int32_t dirent_size (struct dirent *entry) { + int32_t size = -1; + #ifdef GF_BSD_HOST_OS - return ALIGN (24 /* FIX MEEEE!!! */ + entry->d_namlen); + size = GF_DIR_ALIGN (24 /* FIX MEEEE!!! */ + entry->d_namlen); #endif #ifdef GF_DARWIN_HOST_OS - return ALIGN (24 /* FIX MEEEE!!! */ + entry->d_namlen); + size = GF_DIR_ALIGN (24 /* FIX MEEEE!!! */ + entry->d_namlen); #endif #ifdef GF_LINUX_HOST_OS - return ALIGN (24 /* FIX MEEEE!!! */ + entry->d_reclen); + size = GF_DIR_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); + size = GF_DIR_ALIGN (24 /* FIX MEEEE!!! */ + entry->d_reclen); #endif - return -1; + return size; } +#ifdef THREAD_UNSAFE_BASENAME +char *basename_r(const char *); +#define basename(path) basename_r(path) +#endif /* THREAD_UNSAFE_BASENAME */ -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 THREAD_UNSAFE_DIRNAME +char *dirname_r(char *path); +#define dirname(path) dirname_r(path) +#endif /* THREAD_UNSAFE_DIRNAME */ +int gf_mkostemp (char *tmpl, int suffixlen, int flags); +#define mkostemp(tmpl, flags) gf_mkostemp(tmpl, 0, flags); #ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC /* Linux, Solaris, Cygwin */ @@ -333,4 +378,25 @@ gf_compat_listxattr (int len, dict_t *dict, int size) #define ST_CTIM_NSEC_SET(stbuf, val) do { } while (0); #endif +#ifndef IXDR_GET_LONG +#define IXDR_GET_LONG(buf) ((long)IXDR_GET_U_INT32(buf)) +#endif + +#ifndef IXDR_PUT_LONG +#define IXDR_PUT_LONG(buf, v) ((long)IXDR_PUT_INT32(buf, (long)(v))) +#endif + +#ifndef IXDR_GET_U_LONG +#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf)) +#endif + +#ifndef IXDR_PUT_U_LONG +#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG(buf, (long)(v)) +#endif + +#if defined(__GNUC__) && !defined(RELAX_POISONING) +/* Use run API, see run.h */ +#pragma GCC poison system popen +#endif + #endif /* __COMPAT_H__ */ diff --git a/libglusterfs/src/ctx.c b/libglusterfs/src/ctx.c new file mode 100644 index 000000000..0082601d4 --- /dev/null +++ b/libglusterfs/src/ctx.c @@ -0,0 +1,48 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif /* !_CONFIG_H */ + +#include <pthread.h> + +#include "glusterfs.h" + +glusterfs_ctx_t * +glusterfs_ctx_new () +{ + int ret = 0; + glusterfs_ctx_t *ctx = NULL; + + /* no GF_CALLOC here, gf_acct_mem_set_enable is not + yet decided at this point */ + ctx = calloc (1, sizeof (*ctx)); + if (!ctx) { + ret = -1; + goto out; + } + + INIT_LIST_HEAD (&ctx->graphs); + INIT_LIST_HEAD (&ctx->mempool_list); + + ctx->daemon_pipe[0] = -1; + ctx->daemon_pipe[1] = -1; + + ret = pthread_mutex_init (&ctx->lock, NULL); + if (ret) { + free (ctx); + ctx = NULL; + } +out: + return ctx; +} + diff --git a/libglusterfs/src/daemon.c b/libglusterfs/src/daemon.c new file mode 100644 index 000000000..348e3ad40 --- /dev/null +++ b/libglusterfs/src/daemon.c @@ -0,0 +1,66 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include "daemon.h" + +int +os_daemon_return (int nochdir, int noclose) +{ + pid_t pid = -1; + int ret = -1; + FILE *ptr = NULL; + + ret = fork(); + if (ret) + return ret; + + pid = setsid(); + + if (pid == -1) { + ret = -1; + goto out; + } + + if (!nochdir) + ret = chdir("/"); + + if (!noclose) { + ptr = freopen (DEVNULLPATH, "r", stdin); + if (!ptr) + goto out; + + ptr = freopen (DEVNULLPATH, "w", stdout); + if (!ptr) + goto out; + + ptr = freopen (DEVNULLPATH, "w", stderr); + if (!ptr) + goto out; + } + + ret = 0; +out: + return ret; +} + +int +os_daemon (int nochdir, int noclose) +{ + int ret = -1; + + ret = os_daemon_return (nochdir, noclose); + if (ret <= 0) + return ret; + + _exit (0); +} diff --git a/libglusterfs/src/daemon.h b/libglusterfs/src/daemon.h new file mode 100644 index 000000000..80836a326 --- /dev/null +++ b/libglusterfs/src/daemon.h @@ -0,0 +1,23 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _DAEMON_H +#define _DAEMON_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#define DEVNULLPATH "/dev/null" + +int os_daemon_return(int nochdir, int noclose); +int os_daemon(int nochdir, int noclose); +#endif /*_DAEMON_H */ diff --git a/libglusterfs/src/defaults.c b/libglusterfs/src/defaults.c index 89c010cd3..2ebb25150 100644 --- a/libglusterfs/src/defaults.c +++ b/libglusterfs/src/defaults.c @@ -1,28 +1,22 @@ /* - Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ /* libglusterfs/src/defaults.c: - This file contains functions, which are used to fill the 'fops' and 'mops' + This file contains functions, which are used to fill the 'fops', 'cbk' 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. + This function also implements *_resume () functions, which does same + operation as a fop(). + All the functions are plain enough to understand. */ @@ -33,1652 +27,1432 @@ #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, - struct stat *postparent) -{ - STACK_UNWIND (frame, - op_ret, - op_errno, - inode, - buf, - dict, - postparent); - return 0; +/* _CBK function section */ + +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 iatt *buf, dict_t *xdata, struct iatt *postparent) +{ + STACK_UNWIND_STRICT (lookup, frame, op_ret, op_errno, inode, buf, + xdata, postparent); + return 0; } int32_t -default_lookup (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - dict_t *xattr_req) +default_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *xdata) { - STACK_WIND (frame, - default_lookup_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->lookup, - loc, - xattr_req); - return 0; + STACK_UNWIND_STRICT (stat, frame, op_ret, op_errno, buf, xdata); + return 0; } int32_t -default_forget (xlator_t *this, - inode_t *inode) +default_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, + dict_t *xdata) { - return 0; + STACK_UNWIND_STRICT (truncate, frame, op_ret, op_errno, prebuf, + postbuf, xdata); + 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) +int32_t +default_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, + dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - buf); - return 0; + STACK_UNWIND_STRICT (ftruncate, frame, op_ret, op_errno, prebuf, + postbuf, xdata); + return 0; } int32_t -default_stat (call_frame_t *frame, - xlator_t *this, - loc_t *loc) +default_access_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_WIND (frame, - default_stat_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->stat, - loc); - return 0; + STACK_UNWIND_STRICT (access, frame, op_ret, op_errno, xdata); + 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) +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, + struct iatt *buf, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - buf); - return 0; + STACK_UNWIND_STRICT (readlink, frame, op_ret, op_errno, path, buf, + xdata); + return 0; } + int32_t -default_chmod (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - mode_t mode) +default_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) { - STACK_WIND (frame, - default_chmod_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->chmod, - loc, - mode); - return 0; + STACK_UNWIND_STRICT (mknod, frame, op_ret, op_errno, inode, + buf, preparent, postparent, xdata); + return 0; } +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 iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + STACK_UNWIND_STRICT (mkdir, frame, op_ret, op_errno, inode, + buf, preparent, postparent, xdata); + 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) +int32_t +default_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - buf); - return 0; + STACK_UNWIND_STRICT (unlink, frame, op_ret, op_errno, preparent, + postparent, xdata); + return 0; } int32_t -default_fchmod (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - mode_t mode) +default_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *preparent, + struct iatt *postparent, + dict_t *xdata) { - STACK_WIND (frame, - default_fchmod_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fchmod, - fd, - mode); - return 0; + STACK_UNWIND_STRICT (rmdir, frame, op_ret, op_errno, preparent, + postparent, xdata); + 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) + +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 iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - buf); - return 0; + STACK_UNWIND_STRICT (symlink, frame, op_ret, op_errno, inode, buf, + preparent, postparent, xdata); + return 0; } + int32_t -default_chown (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - uid_t uid, - gid_t gid) +default_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + struct iatt *preoldparent, struct iatt *postoldparent, + struct iatt *prenewparent, struct iatt *postnewparent, + dict_t *xdata) { - STACK_WIND (frame, - default_chown_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->chown, - loc, - uid, - gid); - return 0; + STACK_UNWIND_STRICT (rename, frame, op_ret, op_errno, buf, preoldparent, + postoldparent, prenewparent, postnewparent, xdata); + 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) + +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 iatt *buf, struct iatt *preparent, + struct iatt *postparent, + dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - buf); - return 0; + STACK_UNWIND_STRICT (link, frame, op_ret, op_errno, inode, buf, + preparent, postparent, xdata); + return 0; } + int32_t -default_fchown (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - uid_t uid, - gid_t gid) +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 iatt *buf, struct iatt *preparent, + struct iatt *postparent, + dict_t *xdata) { - STACK_WIND (frame, - default_fchown_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fchown, - fd, - uid, - gid); - return 0; + STACK_UNWIND_STRICT (create, frame, op_ret, op_errno, fd, inode, buf, + preparent, postparent, xdata); + 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 *prebuf, - struct stat *postbuf) -{ - STACK_UNWIND (frame, - op_ret, - op_errno, - prebuf, - postbuf); - return 0; +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, + dict_t *xdata) +{ + STACK_UNWIND_STRICT (open, frame, op_ret, op_errno, fd, xdata); + return 0; } int32_t -default_truncate (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - off_t offset) +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 iatt *stbuf, struct iobref *iobref, + dict_t *xdata) { - STACK_WIND (frame, - default_truncate_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->truncate, - loc, - offset); - return 0; + STACK_UNWIND_STRICT (readv, frame, op_ret, op_errno, vector, count, + stbuf, iobref, xdata); + 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 *prebuf, - struct stat *postbuf) -{ - STACK_UNWIND (frame, - op_ret, - op_errno, - prebuf, - postbuf); - return 0; + +int32_t +default_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, + dict_t *xdata) +{ + STACK_UNWIND_STRICT (writev, frame, op_ret, op_errno, prebuf, postbuf, xdata); + return 0; } + int32_t -default_ftruncate (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - off_t offset) +default_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_WIND (frame, - default_ftruncate_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->ftruncate, - fd, - offset); - return 0; + STACK_UNWIND_STRICT (flush, frame, op_ret, op_errno, xdata); + 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) +default_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, + dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - buf); - return 0; + STACK_UNWIND_STRICT (fsync, frame, op_ret, op_errno, prebuf, postbuf, + xdata); + return 0; } +int32_t +default_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *xdata) +{ + STACK_UNWIND_STRICT (fstat, frame, op_ret, op_errno, buf, xdata); + return 0; +} int32_t -default_utimens (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - struct timespec tv[2]) +default_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, + dict_t *xdata) { - STACK_WIND (frame, - default_utimens_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->utimens, - loc, - tv); - return 0; + STACK_UNWIND_STRICT (opendir, frame, op_ret, op_errno, fd, xdata); + 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) +int32_t +default_fsyncdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno); - return 0; + STACK_UNWIND_STRICT (fsyncdir, frame, op_ret, op_errno, xdata); + return 0; } int32_t -default_access (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t mask) +default_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct statvfs *buf, + dict_t *xdata) { - STACK_WIND (frame, - default_access_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->access, - loc, - mask); - return 0; + STACK_UNWIND_STRICT (statfs, frame, op_ret, op_errno, buf, xdata); + 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, - struct stat *buf) +int32_t +default_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - path, - buf); - return 0; + STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno, xdata); + return 0; } + int32_t -default_readlink (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - size_t size) +default_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_WIND (frame, - default_readlink_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readlink, - loc, - size); - return 0; + STACK_UNWIND_STRICT (fsetxattr, frame, op_ret, op_errno, xdata); + 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, - struct stat *preparent, - struct stat *postparent) -{ - STACK_UNWIND (frame, - op_ret, - op_errno, - inode, - buf, - preparent, - postparent); - return 0; + +int32_t +default_fgetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) +{ + STACK_UNWIND_STRICT (fgetxattr, frame, op_ret, op_errno, dict, xdata); + return 0; } + int32_t -default_mknod (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - mode_t mode, - dev_t rdev) +default_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) { - STACK_WIND (frame, - default_mknod_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->mknod, - loc, mode, rdev); - return 0; + STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict, xdata); + 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, - struct stat *preparent, - struct stat *postparent) -{ - STACK_UNWIND (frame, - op_ret, - op_errno, - inode, - buf, - preparent, - postparent); - 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, + dict_t *xdata) +{ + STACK_UNWIND_STRICT (xattrop, frame, op_ret, op_errno, dict, xdata); + return 0; } int32_t -default_mkdir (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - mode_t mode) +default_fxattrop_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) { - STACK_WIND (frame, - default_mkdir_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->mkdir, - loc, mode); - return 0; + STACK_UNWIND_STRICT (fxattrop, frame, op_ret, op_errno, dict, xdata); + 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, - struct stat *preparent, - struct stat *postparent) + +int32_t +default_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno, preparent, postparent); - return 0; + STACK_UNWIND_STRICT (removexattr, frame, op_ret, op_errno, xdata); + return 0; } + int32_t -default_unlink (call_frame_t *frame, - xlator_t *this, - loc_t *loc) +default_fremovexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_WIND (frame, - default_unlink_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->unlink, - loc); - return 0; + STACK_UNWIND_STRICT (fremovexattr, frame, op_ret, op_errno, xdata); + 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, - struct stat *preparent, - struct stat *postparent) -{ - STACK_UNWIND (frame, - op_ret, - op_errno, - preparent, - postparent); - return 0; +int32_t +default_lk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct gf_flock *lock, + dict_t *xdata) +{ + STACK_UNWIND_STRICT (lk, frame, op_ret, op_errno, lock, xdata); + return 0; } int32_t -default_rmdir (call_frame_t *frame, - xlator_t *this, - loc_t *loc) +default_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_WIND (frame, - default_rmdir_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rmdir, - loc); - return 0; + STACK_UNWIND_STRICT (inodelk, frame, op_ret, op_errno, xdata); + 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, - struct stat *preparent, - struct stat *postparent) +int32_t +default_finodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno, inode, buf, preparent, - postparent); - return 0; + STACK_UNWIND_STRICT (finodelk, frame, op_ret, op_errno, xdata); + return 0; } int32_t -default_symlink (call_frame_t *frame, - xlator_t *this, - const char *linkpath, - loc_t *loc) +default_entrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_WIND (frame, - default_symlink_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->symlink, - linkpath, loc); - return 0; + STACK_UNWIND_STRICT (entrylk, frame, op_ret, op_errno, xdata); + 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, - struct stat *preoldparent, - struct stat *postoldparent, - struct stat *prenewparent, - struct stat *postnewparent) +int32_t +default_fentrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno, buf, preoldparent, postoldparent, - prenewparent, postnewparent); - return 0; + STACK_UNWIND_STRICT (fentrylk, frame, op_ret, op_errno, xdata); + return 0; } + int32_t -default_rename (call_frame_t *frame, - xlator_t *this, - loc_t *oldloc, - loc_t *newloc) +default_rchecksum_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, uint32_t weak_checksum, + uint8_t *strong_checksum, + dict_t *xdata) { - STACK_WIND (frame, - default_rename_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rename, - oldloc, newloc); - return 0; + STACK_UNWIND_STRICT (rchecksum, frame, op_ret, op_errno, weak_checksum, + strong_checksum, xdata); + 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, - struct stat *preparent, - struct stat *postparent) +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, + dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno, inode, buf, preparent, - postparent); - return 0; + STACK_UNWIND_STRICT (readdir, frame, op_ret, op_errno, entries, xdata); + return 0; } + int32_t -default_link (call_frame_t *frame, - xlator_t *this, - loc_t *oldloc, - loc_t *newloc) +default_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, + dict_t *xdata) { - STACK_WIND (frame, - default_link_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->link, - oldloc, newloc); - return 0; + STACK_UNWIND_STRICT (readdirp, frame, op_ret, op_errno, entries, xdata); + 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, - struct stat *preparent, - struct stat *postparent) +int32_t +default_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *statpre, + struct iatt *statpost, + dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno, fd, inode, buf, preparent, - postparent); - return 0; + STACK_UNWIND_STRICT (setattr, frame, op_ret, op_errno, statpre, + statpost, xdata); + 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) +default_fsetattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *statpre, + struct iatt *statpost, + dict_t *xdata) { - STACK_WIND (frame, default_create_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->create, - loc, flags, mode, fd); - return 0; + STACK_UNWIND_STRICT (fsetattr, frame, op_ret, op_errno, statpre, + statpost, xdata); + 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) +int32_t +default_fallocate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *pre, + struct iatt *post, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - fd); + STACK_UNWIND_STRICT(fallocate, frame, op_ret, op_errno, pre, post, xdata); return 0; } int32_t -default_open (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t flags, fd_t *fd, - int32_t wbflags) +default_discard_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *pre, + struct iatt *post, dict_t *xdata) { - STACK_WIND (frame, - default_open_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->open, - loc, flags, fd, wbflags); + STACK_UNWIND_STRICT(discard, frame, op_ret, op_errno, pre, post, xdata); 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, - struct iobref *iobref) -{ - STACK_UNWIND (frame, - op_ret, - op_errno, - vector, - count, - stbuf, - iobref); - return 0; +int32_t +default_zerofill_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *pre, + struct iatt *post, dict_t *xdata) +{ + STACK_UNWIND_STRICT(zerofill, frame, op_ret, op_errno, pre, + post, xdata); + return 0; } + int32_t -default_readv (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - size_t size, - off_t offset) +default_getspec_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, char *spec_data) { - STACK_WIND (frame, - default_readv_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readv, - fd, - size, - offset); - return 0; + STACK_UNWIND_STRICT (getspec, frame, op_ret, op_errno, spec_data); + return 0; } +/* RESUME */ -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 *prebuf, - struct stat *postbuf) +int32_t +default_fgetxattr_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - prebuf, - postbuf); - return 0; + STACK_WIND (frame, default_fgetxattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fgetxattr, fd, name, xdata); + 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, - struct iobref *iobref) -{ - STACK_WIND (frame, - default_writev_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->writev, - fd, - vector, - count, - off, - iobref); - return 0; +default_fsetxattr_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, + dict_t *dict, int32_t flags, dict_t *xdata) +{ + STACK_WIND (frame, default_fsetxattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags, xdata); + 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) +int32_t +default_setxattr_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *dict, int32_t flags, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno); - return 0; + STACK_WIND (frame, default_setxattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->setxattr, loc, dict, flags, xdata); + return 0; } int32_t -default_flush (call_frame_t *frame, - xlator_t *this, - fd_t *fd) +default_statfs_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { - STACK_WIND (frame, - default_flush_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->flush, - fd); - return 0; + STACK_WIND (frame, default_statfs_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->statfs, loc, xdata); + return 0; } +int32_t +default_fsyncdir_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t flags, dict_t *xdata) +{ + STACK_WIND (frame, default_fsyncdir_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsyncdir, fd, flags, xdata); + 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, - struct stat *prebuf, - struct stat *postbuf) +int32_t +default_opendir_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + fd_t *fd, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - prebuf, - postbuf); - return 0; + STACK_WIND (frame, default_opendir_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->opendir, loc, fd, xdata); + return 0; } int32_t -default_fsync (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - int32_t flags) +default_fstat_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) { - STACK_WIND (frame, - default_fsync_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsync, - fd, - flags); - return 0; + STACK_WIND (frame, default_fstat_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fstat, fd, xdata); + 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) +int32_t +default_fsync_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t flags, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - buf); - return 0; + STACK_WIND (frame, default_fsync_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsync, fd, flags, xdata); + return 0; } int32_t -default_fstat (call_frame_t *frame, - xlator_t *this, - fd_t *fd) +default_flush_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) { - STACK_WIND (frame, - default_fstat_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fstat, - fd); - return 0; + STACK_WIND (frame, default_flush_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->flush, fd, xdata); + 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) +int32_t +default_writev_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iovec *vector, int32_t count, off_t off, + uint32_t flags, struct iobref *iobref, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - fd); - return 0; + STACK_WIND (frame, default_writev_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->writev, fd, vector, count, off, + flags, iobref, xdata); + return 0; } int32_t -default_opendir (call_frame_t *frame, - xlator_t *this, - loc_t *loc, fd_t *fd) +default_readv_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, + size_t size, off_t offset, uint32_t flags, dict_t *xdata) { - STACK_WIND (frame, - default_opendir_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->opendir, - loc, fd); - return 0; + STACK_WIND (frame, default_readv_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readv, fd, size, offset, flags, xdata); + 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) +int32_t +default_open_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t flags, fd_t *fd, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - entries, - count); - return 0; + STACK_WIND (frame, default_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, loc, flags, fd, xdata); + 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) +default_create_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t flags, mode_t mode, mode_t umask, fd_t *fd, + dict_t *xdata) { - STACK_WIND (frame, - default_getdents_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->getdents, - fd, - size, - offset, - flag); - return 0; + STACK_WIND (frame, default_create_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->create, loc, flags, mode, umask, + fd, xdata); + 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) +int32_t +default_link_resume (call_frame_t *frame, xlator_t *this, loc_t *oldloc, + loc_t *newloc, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno); - return 0; + STACK_WIND (frame, default_link_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->link, oldloc, newloc, xdata); + 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) +default_rename_resume (call_frame_t *frame, xlator_t *this, loc_t *oldloc, + loc_t *newloc, dict_t *xdata) { - STACK_WIND (frame, - default_setdents_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->setdents, - fd, - flags, - entries, - count); - return 0; + STACK_WIND (frame, default_rename_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->rename, oldloc, newloc, xdata); + 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) +int +default_symlink_resume (call_frame_t *frame, xlator_t *this, + const char *linkpath, loc_t *loc, mode_t umask, + dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno); - return 0; + STACK_WIND (frame, default_symlink_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->symlink, linkpath, loc, umask, + xdata); + return 0; } int32_t -default_fsyncdir (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - int32_t flags) +default_rmdir_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + int flags, dict_t *xdata) { - STACK_WIND (frame, - default_fsyncdir_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsyncdir, - fd, - flags); - return 0; + STACK_WIND (frame, default_rmdir_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->rmdir, loc, flags, xdata); + return 0; +} + +int32_t +default_unlink_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + int xflag, dict_t *xdata) +{ + STACK_WIND (frame, default_unlink_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->unlink, loc, xflag, xdata); + return 0; +} + +int +default_mkdir_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + mode_t mode, mode_t umask, dict_t *xdata) +{ + STACK_WIND (frame, default_mkdir_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->mkdir, loc, mode, umask, xdata); + 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) +int +default_mknod_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + mode_t mode, dev_t rdev, mode_t umask, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - buf); - return 0; + STACK_WIND (frame, default_mknod_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, umask, + xdata); + return 0; } int32_t -default_statfs (call_frame_t *frame, - xlator_t *this, - loc_t *loc) +default_readlink_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + size_t size, dict_t *xdata) { - STACK_WIND (frame, - default_statfs_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->statfs, - loc); - return 0; + STACK_WIND (frame, default_readlink_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readlink, loc, size, xdata); + 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) +int32_t +default_access_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + int32_t mask, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno); - return 0; + STACK_WIND (frame, default_access_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->access, loc, mask, xdata); + return 0; } int32_t -default_setxattr (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - dict_t *dict, - int32_t flags) +default_ftruncate_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, dict_t *xdata) { - STACK_WIND (frame, - default_setxattr_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->setxattr, - loc, - dict, - flags); - return 0; + STACK_WIND (frame, default_ftruncate_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->ftruncate, fd, offset, xdata); + return 0; } - -static int32_t -default_fsetxattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) +int32_t +default_getxattr_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno); - return 0; + STACK_WIND (frame, default_getxattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getxattr, loc, name, xdata); + return 0; } + int32_t -default_fsetxattr (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - dict_t *dict, - int32_t flags) +default_xattrop_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata) { - STACK_WIND (frame, - default_fsetxattr_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsetxattr, - fd, - dict, - flags); - return 0; + STACK_WIND (frame, default_xattrop_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->xattrop, loc, flags, dict, xdata); + return 0; } +int32_t +default_fxattrop_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, + gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata) +{ + STACK_WIND (frame, default_fxattrop_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fxattrop, fd, flags, dict, xdata); + return 0; +} -static int32_t -default_fgetxattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - dict_t *dict) +int32_t +default_removexattr_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - dict); - return 0; + STACK_WIND (frame, default_removexattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->removexattr, loc, name, xdata); + return 0; } +int32_t +default_fremovexattr_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name, dict_t *xdata) +{ + STACK_WIND (frame, default_fremovexattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fremovexattr, fd, name, xdata); + return 0; +} int32_t -default_fgetxattr (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - const char *name) +default_lk_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t cmd, struct gf_flock *lock, dict_t *xdata) { - STACK_WIND (frame, - default_fgetxattr_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fgetxattr, - fd, - name); - return 0; + STACK_WIND (frame, default_lk_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lk, fd, cmd, lock, xdata); + 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) + +int32_t +default_inodelk_resume (call_frame_t *frame, xlator_t *this, + const char *volume, loc_t *loc, int32_t cmd, + struct gf_flock *lock, + dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - dict); - return 0; + STACK_WIND (frame, default_inodelk_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->inodelk, + volume, loc, cmd, lock, xdata); + return 0; } int32_t -default_getxattr (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - const char *name) +default_finodelk_resume (call_frame_t *frame, xlator_t *this, + const char *volume, fd_t *fd, int32_t cmd, + struct gf_flock *lock, + dict_t *xdata) { - STACK_WIND (frame, - default_getxattr_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->getxattr, - loc, - name); - return 0; + STACK_WIND (frame, default_finodelk_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->finodelk, + volume, fd, cmd, lock, xdata); + 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) +default_entrylk_resume (call_frame_t *frame, xlator_t *this, + const char *volume, loc_t *loc, const char *basename, + entrylk_cmd cmd, entrylk_type type, + dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno, dict); - return 0; + STACK_WIND (frame, default_entrylk_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->entrylk, + volume, loc, basename, cmd, type, xdata); + return 0; } int32_t -default_xattrop (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - gf_xattrop_flags_t flags, - dict_t *dict) +default_fentrylk_resume (call_frame_t *frame, xlator_t *this, + const char *volume, fd_t *fd, const char *basename, + entrylk_cmd cmd, entrylk_type type, + dict_t *xdata) { - STACK_WIND (frame, - default_xattrop_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->xattrop, - loc, - flags, - dict); - return 0; + STACK_WIND (frame, default_fentrylk_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fentrylk, + volume, fd, basename, cmd, type, xdata); + 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) +default_rchecksum_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, int32_t len, + dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno, dict); - return 0; + STACK_WIND (frame, default_rchecksum_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->rchecksum, fd, offset, len, xdata); + return 0; } + int32_t -default_fxattrop (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - gf_xattrop_flags_t flags, - dict_t *dict) +default_readdir_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, + size_t size, off_t off, + dict_t *xdata) { - STACK_WIND (frame, - default_fxattrop_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fxattrop, - fd, - flags, - dict); - return 0; + STACK_WIND (frame, default_readdir_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readdir, fd, size, off, xdata); + 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) +int32_t +default_readdirp_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, + size_t size, off_t off, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno); - return 0; + STACK_WIND (frame, default_readdirp_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readdirp, fd, size, off, xdata); + return 0; } int32_t -default_removexattr (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - const char *name) +default_setattr_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + struct iatt *stbuf, int32_t valid, + dict_t *xdata) { - STACK_WIND (frame, - default_removexattr_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->removexattr, - loc, - name); - return 0; + STACK_WIND (frame, default_setattr_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->setattr, loc, stbuf, valid, xdata); + 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) +int32_t +default_truncate_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + off_t offset, + dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - lock); - return 0; + STACK_WIND (frame, default_truncate_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->truncate, loc, offset, xdata); + return 0; } int32_t -default_lk (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - int32_t cmd, - struct flock *lock) +default_stat_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata) { - STACK_WIND (frame, - default_lk_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->lk, - fd, - cmd, - lock); - return 0; + STACK_WIND (frame, default_stat_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->stat, loc, xdata); + return 0; } +int32_t +default_lookup_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata) +{ + STACK_WIND (frame, default_lookup_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lookup, loc, xdata); + 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) +int32_t +default_fsetattr_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iatt *stbuf, int32_t valid, + dict_t *xdata) +{ + STACK_WIND (frame, default_fsetattr_cbk, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fsetattr, fd, stbuf, valid, xdata); + return 0; +} +int32_t +default_fallocate_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t keep_size, off_t offset, size_t len, dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno); - return 0; + STACK_WIND(frame, default_fallocate_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fallocate, fd, keep_size, offset, len, + xdata); + return 0; } +int32_t +default_discard_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, size_t len, dict_t *xdata) +{ + STACK_WIND(frame, default_discard_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->discard, fd, offset, len, + xdata); + return 0; +} int32_t -default_inodelk (call_frame_t *frame, xlator_t *this, - const char *volume, loc_t *loc, int32_t cmd, - struct flock *lock) -{ - STACK_WIND (frame, - default_inodelk_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->inodelk, - volume, loc, cmd, lock); - return 0; +default_zerofill_resume(call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, size_t len, dict_t *xdata) +{ + STACK_WIND(frame, default_zerofill_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->zerofill, fd, offset, len, + xdata); + 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) +/* FOPS */ +int32_t +default_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name, dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fgetxattr, fd, name, xdata); + return 0; } +int32_t +default_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, + int32_t flags, dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags, + xdata); + return 0; +} int32_t -default_finodelk (call_frame_t *frame, xlator_t *this, - const char *volume, fd_t *fd, int32_t cmd, struct flock *lock) +default_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, + int32_t flags, dict_t *xdata) { - STACK_WIND (frame, - default_finodelk_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->finodelk, - volume, fd, cmd, lock); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->setxattr, loc, dict, flags, + xdata); + return 0; } +int32_t +default_statfs (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->statfs, loc, xdata); + 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) +int32_t +default_fsyncdir (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsyncdir, fd, flags, xdata); + return 0; +} +int32_t +default_opendir (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->opendir, loc, fd, xdata); + return 0; } int32_t -default_entrylk (call_frame_t *frame, xlator_t *this, - const char *volume, loc_t *loc, const char *basename, - entrylk_cmd cmd, entrylk_type type) +default_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) { - STACK_WIND (frame, default_entrylk_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->entrylk, - volume, loc, basename, cmd, type); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fstat, fd, xdata); + 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) +int32_t +default_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsync, fd, flags, xdata); + return 0; +} +int32_t +default_flush (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->flush, fd, xdata); + return 0; } int32_t -default_fentrylk (call_frame_t *frame, xlator_t *this, - const char *volume, fd_t *fd, const char *basename, - entrylk_cmd cmd, entrylk_type type) +default_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iovec *vector, int32_t count, off_t off, uint32_t flags, + struct iobref *iobref, dict_t *xdata) { - STACK_WIND (frame, default_fentrylk_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fentrylk, - volume, fd, basename, cmd, type); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->writev, fd, vector, count, + off, flags, iobref, xdata); + return 0; } +int32_t +default_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset, uint32_t flags, dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readv, fd, size, offset, + flags, xdata); + 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_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, + fd_t *fd, dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, loc, flags, fd, xdata); + return 0; } +int32_t +default_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, + mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->create, loc, flags, mode, + umask, fd, xdata); + return 0; +} int32_t -default_stats (call_frame_t *frame, - xlator_t *this, - int32_t flags) +default_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, + dict_t *xdata) { - STACK_WIND (frame, - default_stats_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->mops->stats, - flags); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->link, oldloc, newloc, xdata); + 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) +int32_t +default_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, + loc_t *newloc, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - spec_data); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->rename, oldloc, newloc, + xdata); + return 0; } +int +default_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, + loc_t *loc, mode_t umask, dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->symlink, linkpath, loc, + umask, xdata); + return 0; +} + int32_t -default_getspec (call_frame_t *frame, - xlator_t *this, - const char *key, - int32_t flags) +default_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags, + dict_t *xdata) { - STACK_WIND (frame, - default_getspec_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->mops->getspec, - key, flags); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->rmdir, loc, flags, xdata); + return 0; } +int32_t +default_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, + dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->unlink, loc, xflag, xdata); + return 0; +} -static int32_t -default_log_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno) +int +default_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, + mode_t umask, dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->mkdir, loc, mode, umask, + xdata); + return 0; } +int +default_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, + dev_t rdev, mode_t umask, dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, + umask, xdata); + return 0; +} + int32_t -default_log (call_frame_t *frame, - xlator_t *this, - const char *msg) +default_readlink (call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size, dict_t *xdata) { - STACK_WIND (frame, - default_log_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->mops->log, - msg); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readlink, loc, size, xdata); + 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) +int32_t +default_access (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t mask, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - file_checksum, - dir_checksum); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->access, loc, mask, xdata); + return 0; } +int32_t +default_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->ftruncate, fd, offset, xdata); + return 0; +} int32_t -default_checksum (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t flag) +default_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata) { - STACK_WIND (frame, - default_checksum_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->checksum, - loc, - flag); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getxattr, loc, name, xdata); + return 0; } -static int32_t -default_rchecksum_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - uint32_t weak_checksum, - uint8_t *strong_checksum) +int32_t +default_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc, + gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata) { - STACK_UNWIND (frame, - op_ret, - op_errno, - weak_checksum, - strong_checksum); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->xattrop, loc, flags, dict, + xdata); + return 0; } +int32_t +default_fxattrop (call_frame_t *frame, xlator_t *this, fd_t *fd, + gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fxattrop, fd, flags, dict, + xdata); + return 0; +} int32_t -default_rchecksum (call_frame_t *frame, - xlator_t *this, - fd_t *fd, off_t offset, - int32_t len) +default_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata) { - STACK_WIND (frame, - default_rchecksum_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rchecksum, - fd, offset, len); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->removexattr, loc, name, + xdata); + return 0; } +int32_t +default_fremovexattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name, dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fremovexattr, fd, name, + xdata); + 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) +default_lk (call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t cmd, struct gf_flock *lock, dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno, entries); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lk, fd, cmd, lock, xdata); + return 0; } int32_t -default_readdirp_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - gf_dirent_t *entries) +default_inodelk (call_frame_t *frame, xlator_t *this, + const char *volume, loc_t *loc, int32_t cmd, + struct gf_flock *lock, + dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno, entries); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->inodelk, volume, loc, cmd, + lock, xdata); + return 0; } int32_t -default_readdir (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - size_t size, - off_t off) +default_finodelk (call_frame_t *frame, xlator_t *this, + const char *volume, fd_t *fd, int32_t cmd, struct gf_flock *lock, + dict_t *xdata) { - STACK_WIND (frame, - default_readdir_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readdir, - fd, size, off); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->finodelk, volume, fd, cmd, + lock, xdata); + return 0; } +int32_t +default_entrylk (call_frame_t *frame, xlator_t *this, + const char *volume, loc_t *loc, const char *basename, + entrylk_cmd cmd, entrylk_type type, + dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->entrylk, volume, loc, + basename, cmd, type, xdata); + return 0; +} int32_t -default_readdirp (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - size_t size, - off_t off) +default_fentrylk (call_frame_t *frame, xlator_t *this, + const char *volume, fd_t *fd, const char *basename, + entrylk_cmd cmd, entrylk_type type, + dict_t *xdata) { - STACK_WIND (frame, - default_readdirp_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readdir, - fd, size, off); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fentrylk, volume, fd, + basename, cmd, type, xdata); + return 0; } int32_t -default_lock_notify_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) +default_rchecksum (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + int32_t len, + dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->rchecksum, fd, offset, len, + xdata); + return 0; } int32_t -default_lock_fnotify_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) +default_readdir (call_frame_t *frame, xlator_t *this, fd_t *fd, + size_t size, off_t off, + dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readdir, fd, size, off, + xdata); + return 0; } int32_t -default_lock_notify (call_frame_t *frame, xlator_t *this, - loc_t *loc, int32_t timeout) +default_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, + size_t size, off_t off, dict_t *xdata) { - STACK_WIND (frame, - default_lock_notify_cbk, - FIRST_CHILD (this), - FIRST_CHILD (this)->fops->lock_notify, - loc, timeout); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readdirp, fd, size, off, + xdata); + return 0; } +int32_t +default_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + struct iatt *stbuf, int32_t valid, + dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->setattr, loc, stbuf, valid, + xdata); + return 0; +} int32_t -default_lock_fnotify (call_frame_t *frame, xlator_t *this, - fd_t *fd, int32_t timeout) +default_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, + dict_t *xdata) { - STACK_WIND (frame, - default_lock_notify_cbk, - FIRST_CHILD (this), - FIRST_CHILD (this)->fops->lock_fnotify, - fd, timeout); - return 0; + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->truncate, loc, offset, xdata); + return 0; } +int32_t +default_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->stat, loc, xdata); + return 0; +} -/* notify */ -int -default_notify (xlator_t *this, int32_t event, void *data, ...) +int32_t +default_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata) { - switch (event) - { - case GF_EVENT_PARENT_UP: - { - xlator_list_t *list = this->children; - - while (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) { - if (parent->xlator->ready) - xlator_notify (parent->xlator, event, - this, NULL); - parent = parent->next; - } - } - } + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lookup, loc, xdata); + return 0; +} - return 0; +int32_t +default_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + struct iatt *stbuf, int32_t valid, + dict_t *xdata) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fsetattr, fd, stbuf, valid, + xdata); + return 0; } int32_t -default_releasedir (xlator_t *this, - fd_t *fd) +default_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, + int32_t keep_size, off_t offset, size_t len, dict_t *xdata) { + STACK_WIND_TAIL(frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fallocate, fd, keep_size, offset, + len, xdata); return 0; } int32_t -default_release (xlator_t *this, - fd_t *fd) +default_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, size_t len, dict_t *xdata) { + STACK_WIND_TAIL(frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->discard, fd, offset, len, + xdata); return 0; } int32_t -default_setattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct stat *statpre, - struct stat *statpost) +default_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, + off_t offset, size_t len, dict_t *xdata) { - STACK_UNWIND (frame, op_ret, op_errno, statpre, statpost); - return 0; + STACK_WIND_TAIL(frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->zerofill, fd, offset, len, + xdata); + return 0; } + int32_t -default_setattr (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - struct stat *stbuf, - int32_t valid) +default_forget (xlator_t *this, inode_t *inode) { - STACK_WIND (frame, - default_setattr_cbk, - FIRST_CHILD (this), - FIRST_CHILD (this)->fops->setattr, - loc, stbuf, valid); - return 0; + gf_log_callingfn (this->name, GF_LOG_WARNING, "xlator does not " + "implement forget_cbk"); + return 0; } + int32_t -default_fsetattr_cbk (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct stat *statpre, - struct stat *statpost) +default_releasedir (xlator_t *this, fd_t *fd) { - STACK_UNWIND (frame, op_ret, op_errno, statpre, statpost); - return 0; + gf_log_callingfn (this->name, GF_LOG_WARNING, "xlator does not " + "implement releasedir_cbk"); + return 0; } int32_t -default_fsetattr (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - struct stat *stbuf, - int32_t valid) +default_release (xlator_t *this, fd_t *fd) { - STACK_WIND (frame, - default_fsetattr_cbk, - FIRST_CHILD (this), - FIRST_CHILD (this)->fops->fsetattr, - fd, stbuf, valid); - return 0; + gf_log_callingfn (this->name, GF_LOG_WARNING, "xlator does not " + "implement release_cbk"); + return 0; +} + +/* End of FOP/_CBK/_RESUME section */ + + +/* Management operations */ + +int32_t +default_getspec (call_frame_t *frame, xlator_t *this, const char *key, + int32_t flags) +{ + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getspec, key, flags); + return 0; +} + +/* notify */ +int +default_notify (xlator_t *this, int32_t event, void *data, ...) +{ + switch (event) + { + case GF_EVENT_PARENT_UP: + case GF_EVENT_PARENT_DOWN: + { + xlator_list_t *list = this->children; + + while (list) { + xlator_notify (list->xlator, event, this); + list = list->next; + } + } + break; + case GF_EVENT_CHILD_CONNECTING: + case GF_EVENT_CHILD_MODIFIED: + case GF_EVENT_CHILD_DOWN: + case GF_EVENT_CHILD_UP: + case GF_EVENT_AUTH_FAILED: + { + xlator_list_t *parent = this->parents; + /* Handle case of CHILD_* & AUTH_FAILED event specially, send it to fuse */ + if (!parent && this->ctx && this->ctx->master) + xlator_notify (this->ctx->master, event, this->graph, NULL); + + while (parent) { + if (parent->xlator->init_succeeded) + xlator_notify (parent->xlator, event, + this, NULL); + parent = parent->next; + } + } + break; + default: + { + xlator_list_t *parent = this->parents; + while (parent) { + if (parent->xlator->init_succeeded) + xlator_notify (parent->xlator, event, + this, NULL); + parent = parent->next; + } + } + } + + return 0; +} + +int32_t +default_mem_acct_init (xlator_t *this) +{ + int ret = -1; + + ret = xlator_mem_acct_init (this, gf_common_mt_end); + + return ret; } diff --git a/libglusterfs/src/defaults.h b/libglusterfs/src/defaults.h index 6ef9cf571..0747027bc 100644 --- a/libglusterfs/src/defaults.h +++ b/libglusterfs/src/defaults.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ /* libglusterfs/src/defaults.h: @@ -31,293 +22,702 @@ #include "xlator.h" -/* Management Operations */ +int32_t default_notify (xlator_t *this, + int32_t event, + void *data, + ...); -int32_t default_stats (call_frame_t *frame, - xlator_t *this, - int32_t flags); +int32_t default_forget (xlator_t *this, inode_t *inode); -int32_t default_getspec (call_frame_t *frame, - xlator_t *this, - const char *key, - int32_t flag); +int32_t default_release (xlator_t *this, fd_t *fd); -int32_t -default_log (call_frame_t *frame, - xlator_t *this, - const char *msg); +int32_t default_releasedir (xlator_t *this, fd_t *fd); -int32_t default_checksum (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t flag); + +/* Management Operations */ + +int32_t default_getspec (call_frame_t *frame, + xlator_t *this, + const char *key, + int32_t flag); int32_t default_rchecksum (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, - int32_t len); + int32_t len, dict_t *xdata); /* FileSystem operations */ int32_t default_lookup (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - dict_t *xattr_req); + xlator_t *this, + loc_t *loc, + dict_t *xdata); int32_t default_stat (call_frame_t *frame, - xlator_t *this, - loc_t *loc); + xlator_t *this, + loc_t *loc, dict_t *xdata); 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); + xlator_t *this, + fd_t *fd, dict_t *xdata); int32_t default_truncate (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - off_t offset); + xlator_t *this, + loc_t *loc, + off_t offset, dict_t *xdata); 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]); + xlator_t *this, + fd_t *fd, + off_t offset, dict_t *xdata); int32_t default_access (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t mask); + xlator_t *this, + loc_t *loc, + int32_t mask, dict_t *xdata); int32_t default_readlink (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - size_t size); + xlator_t *this, + loc_t *loc, + size_t size, dict_t *xdata); -int32_t default_mknod (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - mode_t mode, - dev_t rdev); +int32_t default_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, + mode_t mode, dev_t rdev, mode_t umask, dict_t *xdata); -int32_t default_mkdir (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - mode_t mode); +int32_t default_mkdir (call_frame_t *frame, xlator_t *this, + loc_t *loc, mode_t mode, mode_t umask, dict_t *xdata); int32_t default_unlink (call_frame_t *frame, - xlator_t *this, - loc_t *loc); + xlator_t *this, + loc_t *loc, int xflag, dict_t *xdata); -int32_t default_rmdir (call_frame_t *frame, - xlator_t *this, - loc_t *loc); +int32_t default_rmdir (call_frame_t *frame, xlator_t *this, + loc_t *loc, int xflag, dict_t *xdata); -int32_t default_symlink (call_frame_t *frame, - xlator_t *this, - const char *linkpath, - loc_t *loc); +int32_t default_symlink (call_frame_t *frame, xlator_t *this, + const char *linkpath, loc_t *loc, mode_t umask, + dict_t *xdata); int32_t default_rename (call_frame_t *frame, - xlator_t *this, - loc_t *oldloc, - loc_t *newloc); + xlator_t *this, + loc_t *oldloc, + loc_t *newloc, dict_t *xdata); int32_t default_link (call_frame_t *frame, - xlator_t *this, - loc_t *oldloc, - loc_t *newloc); + xlator_t *this, + loc_t *oldloc, + loc_t *newloc, dict_t *xdata); -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_create (call_frame_t *frame, xlator_t *this, + loc_t *loc, int32_t flags, mode_t mode, + mode_t umask, fd_t *fd, dict_t *xdata); int32_t default_open (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t flags, fd_t *fd, - int32_t wbflags); + xlator_t *this, + loc_t *loc, + int32_t flags, fd_t *fd, + dict_t *xdata); int32_t default_readv (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - size_t size, - off_t offset); + xlator_t *this, + fd_t *fd, + size_t size, + off_t offset, + uint32_t flags, dict_t *xdata); int32_t default_writev (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - struct iovec *vector, - int32_t count, - off_t offset, - struct iobref *iobref); + xlator_t *this, + fd_t *fd, + struct iovec *vector, + int32_t count, + off_t offset, + uint32_t flags, + struct iobref *iobref, dict_t *xdata); int32_t default_flush (call_frame_t *frame, - xlator_t *this, - fd_t *fd); + xlator_t *this, + fd_t *fd, dict_t *xdata); int32_t default_fsync (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - int32_t datasync); + xlator_t *this, + fd_t *fd, + int32_t datasync, dict_t *xdata); 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); + xlator_t *this, + loc_t *loc, fd_t *fd, dict_t *xdata); int32_t default_fsyncdir (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - int32_t datasync); + xlator_t *this, + fd_t *fd, + int32_t datasync, dict_t *xdata); int32_t default_statfs (call_frame_t *frame, - xlator_t *this, - loc_t *loc); + xlator_t *this, + loc_t *loc, dict_t *xdata); int32_t default_setxattr (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - dict_t *dict, - int32_t flags); + xlator_t *this, + loc_t *loc, + dict_t *dict, + int32_t flags, dict_t *xdata); int32_t default_getxattr (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - const char *name); + xlator_t *this, + loc_t *loc, + const char *name, dict_t *xdata); int32_t default_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, - int32_t flags); + int32_t flags, dict_t *xdata); int32_t default_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, - const char *name); + const char *name, dict_t *xdata); int32_t default_removexattr (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - const char *name); + xlator_t *this, + loc_t *loc, + const char *name, dict_t *xdata); + +int32_t default_fremovexattr (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + const char *name, dict_t *xdata); int32_t default_lk (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - int32_t cmd, - struct flock *flock); + xlator_t *this, + fd_t *fd, + int32_t cmd, + struct gf_flock *flock, dict_t *xdata); int32_t default_inodelk (call_frame_t *frame, xlator_t *this, - const char *volume, loc_t *loc, int32_t cmd, - struct flock *flock); + const char *volume, loc_t *loc, int32_t cmd, + struct gf_flock *flock, dict_t *xdata); int32_t default_finodelk (call_frame_t *frame, xlator_t *this, - const char *volume, fd_t *fd, int32_t cmd, - struct flock *flock); + const char *volume, fd_t *fd, int32_t cmd, + struct gf_flock *flock, dict_t *xdata); int32_t default_entrylk (call_frame_t *frame, xlator_t *this, - const char *volume, loc_t *loc, const char *basename, - entrylk_cmd cmd, entrylk_type type); + const char *volume, loc_t *loc, const char *basename, + entrylk_cmd cmd, entrylk_type type, dict_t *xdata); int32_t default_fentrylk (call_frame_t *frame, xlator_t *this, - const char *volume, fd_t *fd, const char *basename, - entrylk_cmd cmd, entrylk_type type); + const char *volume, fd_t *fd, const char *basename, + entrylk_cmd cmd, entrylk_type type, dict_t *xdata); int32_t default_readdir (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - size_t size, off_t off); + xlator_t *this, + fd_t *fd, + size_t size, off_t off, dict_t *xdata); int32_t default_readdirp (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); + xlator_t *this, + fd_t *fd, + size_t size, off_t off, dict_t *xdata); int32_t default_xattrop (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - gf_xattrop_flags_t flags, - dict_t *dict); + xlator_t *this, + loc_t *loc, + gf_xattrop_flags_t flags, + dict_t *dict, dict_t *xdata); int32_t default_fxattrop (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + gf_xattrop_flags_t flags, + dict_t *dict, dict_t *xdata); + +int32_t default_setattr (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + struct iatt *stbuf, + int32_t valid, dict_t *xdata); + +int32_t default_fsetattr (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + struct iatt *stbuf, + int32_t valid, dict_t *xdata); + +int32_t default_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, - gf_xattrop_flags_t flags, - dict_t *dict); + int32_t keep_size, off_t offset, + size_t len, dict_t *xdata); -int32_t -default_lock_notify (call_frame_t *frame, xlator_t *this, - loc_t *loc, int32_t timeout); +int32_t default_discard(call_frame_t *frame, + xlator_t *this, + fd_t *fd, + off_t offset, + size_t len, dict_t *xdata); -int32_t -default_lock_fnotify (call_frame_t *frame, xlator_t *this, - fd_t *fd, int32_t timeout); +int32_t default_zerofill(call_frame_t *frame, + xlator_t *this, + fd_t *fd, + off_t offset, + size_t len, dict_t *xdata); -int32_t default_notify (xlator_t *this, - int32_t event, - void *data, - ...); +/* Resume */ +int32_t default_getspec_resume (call_frame_t *frame, + xlator_t *this, + const char *key, + int32_t flag); + +int32_t default_rchecksum_resume (call_frame_t *frame, + xlator_t *this, + fd_t *fd, off_t offset, + int32_t len, dict_t *xdata); -int32_t default_forget (xlator_t *this, - inode_t *inode); +/* FileSystem operations */ +int32_t default_lookup_resume (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + dict_t *xdata); -int32_t default_release (xlator_t *this, - fd_t *fd); +int32_t default_stat_resume (call_frame_t *frame, + xlator_t *this, + loc_t *loc, dict_t *xdata); -int32_t default_releasedir (xlator_t *this, - fd_t *fd); +int32_t default_fstat_resume (call_frame_t *frame, + xlator_t *this, + fd_t *fd, dict_t *xdata); -int32_t default_setattr (call_frame_t *frame, +int32_t default_truncate_resume (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + off_t offset, dict_t *xdata); + +int32_t default_ftruncate_resume (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + off_t offset, dict_t *xdata); + +int32_t default_access_resume (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + int32_t mask, dict_t *xdata); + +int32_t default_readlink_resume (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + size_t size, dict_t *xdata); + +int32_t default_mknod_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + mode_t mode, dev_t rdev, mode_t umask, + dict_t *xdata); + +int32_t default_mkdir_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + mode_t mode, mode_t umask, dict_t *xdata); + +int32_t default_unlink_resume (call_frame_t *frame, + xlator_t *this, + loc_t *loc, int xflag, dict_t *xdata); + +int32_t default_rmdir_resume (call_frame_t *frame, xlator_t *this, + loc_t *loc, int xflag, dict_t *xdata); + +int32_t default_symlink_resume (call_frame_t *frame, xlator_t *this, + const char *linkpath, loc_t *loc, mode_t umask, + dict_t *xdata); + +int32_t default_rename_resume (call_frame_t *frame, + xlator_t *this, + loc_t *oldloc, + loc_t *newloc, dict_t *xdata); + +int32_t default_link_resume (call_frame_t *frame, + xlator_t *this, + loc_t *oldloc, + loc_t *newloc, dict_t *xdata); + +int32_t default_create_resume (call_frame_t *frame, xlator_t *this, + loc_t *loc, int32_t flags, mode_t mode, + mode_t umask, fd_t *fd, dict_t *xdata); + +int32_t default_open_resume (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + int32_t flags, fd_t *fd, dict_t *xdata); + +int32_t default_readv_resume (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + size_t size, + off_t offset, uint32_t flags, dict_t *xdata); + +int32_t default_writev_resume (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + struct iovec *vector, + int32_t count, + off_t offset, uint32_t flags, + struct iobref *iobref, dict_t *xdata); + +int32_t default_flush_resume (call_frame_t *frame, + xlator_t *this, + fd_t *fd, dict_t *xdata); + +int32_t default_fsync_resume (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t datasync, dict_t *xdata); + +int32_t default_opendir_resume (call_frame_t *frame, + xlator_t *this, + loc_t *loc, fd_t *fd, dict_t *xdata); + +int32_t default_fsyncdir_resume (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t datasync, dict_t *xdata); + +int32_t default_statfs_resume (call_frame_t *frame, + xlator_t *this, + loc_t *loc, dict_t *xdata); + +int32_t default_setxattr_resume (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + dict_t *dict, + int32_t flags, dict_t *xdata); + +int32_t default_getxattr_resume (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + const char *name, dict_t *xdata); + +int32_t default_fsetxattr_resume (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + dict_t *dict, + int32_t flags, dict_t *xdata); + +int32_t default_fgetxattr_resume (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + const char *name, dict_t *xdata); + +int32_t default_removexattr_resume (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + const char *name, dict_t *xdata); + +int32_t default_fremovexattr_resume (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + const char *name, dict_t *xdata); + +int32_t default_lk_resume (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t cmd, + struct gf_flock *flock, dict_t *xdata); + +int32_t default_inodelk_resume (call_frame_t *frame, xlator_t *this, + const char *volume, loc_t *loc, int32_t cmd, + struct gf_flock *flock, dict_t *xdata); + +int32_t default_finodelk_resume (call_frame_t *frame, xlator_t *this, + const char *volume, fd_t *fd, int32_t cmd, + struct gf_flock *flock, dict_t *xdata); + +int32_t default_entrylk_resume (call_frame_t *frame, xlator_t *this, + const char *volume, loc_t *loc, const char *basename, + entrylk_cmd cmd, entrylk_type type, dict_t *xdata); + +int32_t default_fentrylk_resume (call_frame_t *frame, xlator_t *this, + const char *volume, fd_t *fd, const char *basename, + entrylk_cmd cmd, entrylk_type type, dict_t *xdata); + +int32_t default_readdir_resume (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + size_t size, off_t off, dict_t *xdata); + +int32_t default_readdirp_resume (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + size_t size, off_t off, dict_t *xdata); + +int32_t default_xattrop_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - struct stat *stbuf, - int32_t valid); + gf_xattrop_flags_t flags, + dict_t *dict, dict_t *xdata); -int32_t default_fsetattr (call_frame_t *frame, +int32_t default_fxattrop_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, - struct stat *stbuf, - int32_t valid); + gf_xattrop_flags_t flags, + dict_t *dict, dict_t *xdata); +int32_t default_rchecksum_resume (call_frame_t *frame, + xlator_t *this, + fd_t *fd, off_t offset, + int32_t len, dict_t *xdata); + +int32_t default_setattr_resume (call_frame_t *frame, + xlator_t *this, + loc_t *loc, + struct iatt *stbuf, + int32_t valid, dict_t *xdata); + +int32_t default_fsetattr_resume (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + struct iatt *stbuf, + int32_t valid, dict_t *xdata); + +int32_t default_fallocate_resume(call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t keep_size, off_t offset, + size_t len, dict_t *xdata); + +int32_t default_discard_resume(call_frame_t *frame, + xlator_t *this, + fd_t *fd, + off_t offset, + size_t len, dict_t *xdata); + +int32_t default_zerofill_resume(call_frame_t *frame, + xlator_t *this, + fd_t *fd, + off_t offset, + size_t len, dict_t *xdata); + + +/* _cbk */ + +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 iatt *buf, dict_t *xdata, struct iatt *postparent); + +int32_t +default_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, dict_t *xdata); + + +int32_t +default_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +int32_t +default_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +int32_t +default_access_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +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, + struct iatt *buf, dict_t *xdata); + + +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 iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +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 iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int32_t +default_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +int32_t +default_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + + +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 iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + + +int32_t +default_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + struct iatt *preoldparent, struct iatt *postoldparent, + struct iatt *prenewparent, struct iatt *postnewparent, dict_t *xdata); + + +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 iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + + +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 iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); + +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, dict_t *xdata); + +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 iatt *stbuf, struct iobref *iobref, dict_t *xdata); + + +int32_t +default_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + + +int32_t +default_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + + + +int32_t +default_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + +int32_t +default_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, dict_t *xdata); + +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, dict_t *xdata); + +int32_t +default_fsyncdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +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, dict_t *xdata); + + +int32_t +default_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + + +int32_t +default_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + + + +int32_t +default_fgetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata); + + +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, dict_t *xdata); + +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, dict_t *xdata); + +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, dict_t *xdata); + + +int32_t +default_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_fremovexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_lk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct gf_flock *lock, dict_t *xdata); + +int32_t +default_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + + +int32_t +default_finodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_entrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int32_t +default_fentrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + + +int32_t +default_rchecksum_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, uint32_t weak_checksum, + uint8_t *strong_checksum, dict_t *xdata); + + +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, dict_t *xdata); + + +int32_t +default_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, dict_t *xdata); + +int32_t +default_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *statpre, + struct iatt *statpost, dict_t *xdata); + +int32_t +default_fsetattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *statpre, + struct iatt *statpost, dict_t *xdata); + +int32_t default_fallocate_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *pre, + struct iatt *post, dict_t *xdata); + +int32_t default_discard_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *pre, + struct iatt *post, dict_t *xdata); + +int32_t default_zerofill_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *pre, + struct iatt *post, dict_t *xdata); + +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); + +int32_t +default_mem_acct_init (xlator_t *this); #endif /* _DEFAULTS_H */ diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c index fd1be7318..3b7ddce5e 100644 --- a/libglusterfs/src/dict.c +++ b/libglusterfs/src/dict.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include <unistd.h> @@ -22,6 +13,8 @@ #include <stdlib.h> #include <stdio.h> #include <inttypes.h> +#include <limits.h> +#include <fnmatch.h> #ifndef _CONFIG_H #define _CONFIG_H @@ -35,842 +28,663 @@ #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; -} +#include "globals.h" data_t * get_new_data () { - data_t *data = NULL; + 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; - } + data = mem_get0 (THIS->ctx->dict_data_pool); + if (!data) { + return NULL; + } - LOCK_INIT (&data->lock); - return data; + LOCK_INIT (&data->lock); + return data; } dict_t * get_new_dict_full (int size_hint) { - dict_t *dict = CALLOC (1, sizeof (dict_t)); + dict_t *dict = mem_get0 (THIS->ctx->dict_pool); - 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) { + return NULL; + } - if (!dict->members) { - gf_log ("dict", GF_LOG_CRITICAL, - "calloc () returned NULL"); - return NULL; - } + dict->hash_size = size_hint; + if (size_hint == 1) { + /* + * This is the only case we ever see currently. If we ever + * need to support resizing the hash table, the resize function + * will have to take into account the possibility that + * "members" is not separately allocated (i.e. don't just call + * realloc() blindly. + */ + dict->members = &dict->members_internal; + } + else { + /* + * We actually need to allocate space for size_hint *pointers* + * but we actually allocate space for one *structure*. Since + * a data_pair_t consists of five pointers, we're wasting four + * pointers' worth for N=1, and will overrun what we allocated + * for N>5. If anybody ever starts using size_hint, we'll need + * to fix this. + */ + GF_ASSERT (size_hint <= + (sizeof(data_pair_t) / sizeof(data_pair_t *))); + dict->members = mem_get0 (THIS->ctx->dict_pair_pool); + if (!dict->members) { + mem_put (dict); + return NULL; + } + } - LOCK_INIT (&dict->lock); + LOCK_INIT (&dict->lock); - return dict; + return dict; } dict_t * get_new_dict (void) { - return get_new_dict_full (1); + 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; + dict_t *dict = NULL; + + dict = get_new_dict_full(1); + + if (dict) + dict_ref (dict); + + return dict; } -int32_t +int32_t is_data_equal (data_t *one, - data_t *two) + data_t *two) { - if (!one || !two || !one->data || !two->data) - return 1; + if (!one || !two || !one->data || !two->data) { + gf_log_callingfn ("dict", GF_LOG_ERROR, + "input arguments are provided " + "with value data_t as NULL"); + return -1; + } - if (one == two) - return 1; + if (one == two) + return 1; - if (one->len != two->len) - return 0; + if (one->len != two->len) + return 0; - if (one->data == two->data) - return 1; + if (one->data == two->data) + return 1; - if (memcmp (one->data, two->data, one->len) == 0) - return 1; + if (memcmp (one->data, two->data, one->len) == 0) + return 1; - return 0; + return 0; } void data_destroy (data_t *data) { - if (data) { - LOCK_DESTROY (&data->lock); + if (data) { + LOCK_DESTROY (&data->lock); - if (!data->is_static) { - if (data->data) - FREE (data->data); - if (data->vec) - FREE (data->vec); - } + if (!data->is_static) { + if (data->data) { + if (data->is_stdalloc) + free (data->data); + else + GF_FREE (data->data); + } + } - data->len = 0xbabababa; - if (!data->is_const) - FREE (data); - } + data->len = 0xbabababa; + if (!data->is_const) + mem_put (data); + } } data_t * data_copy (data_t *old) { - if (!old) { - gf_log ("dict", GF_LOG_CRITICAL, - "@old is NULL"); - return NULL; - } + if (!old) { + gf_log_callingfn ("dict", GF_LOG_WARNING, + "old is NULL"); + return NULL; + } - data_t *newdata = (data_t *) CALLOC (1, sizeof (*newdata)); + data_t *newdata = mem_get0 (THIS->ctx->dict_data_pool); + if (!newdata) { + return NULL; + } - if (!newdata) { - gf_log ("dict", GF_LOG_CRITICAL, - "@newdata - NULL returned by CALLOC"); - return NULL; - } + if (old) { + newdata->len = old->len; + if (old->data) { + newdata->data = memdup (old->data, old->len); + if (!newdata->data) + goto err_out; + } + } - 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; - } - } + LOCK_INIT (&newdata->lock); + return newdata; + +err_out: - return newdata; + FREE (newdata->data); + mem_put (newdata); + + return NULL; } 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; - } + if (!this || !key) { + gf_log_callingfn ("dict", GF_LOG_WARNING, + "!this || !key (%s)", 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; + 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; } +int32_t +dict_lookup (dict_t *this, char *key, data_t **data) +{ + if (!this || !key || !data) { + gf_log_callingfn ("dict", GF_LOG_WARNING, + "!this || !key || !data"); + return -1; + } + + data_pair_t *tmp = NULL; + LOCK (&this->lock); + { + tmp = _dict_lookup (this, key); + } + UNLOCK (&this->lock); + + if (!tmp) + return -1; + + *data = tmp->value; + return 0; +} 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; +_dict_set (dict_t *this, char *key, data_t *value, gf_boolean_t replace) +{ + int hashval; + data_pair_t *pair; + char key_free = 0; + int tmp = 0; int ret = 0; - if (!key) { - ret = asprintf (&key, "ref:%p", value); + if (!key) { + ret = gf_asprintf (&key, "ref:%p", value); if (-1 == ret) { - gf_log ("dict", GF_LOG_ERROR, "asprintf failed"); + gf_log ("dict", GF_LOG_WARNING, "asprintf failed %s", key); return -1; } - key_free = 1; - } + 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; - } + tmp = SuperFastHash (key, strlen (key)); + hashval = (tmp % this->hash_size); + + /* Search for a existing key if 'replace' is asked for */ + if (replace) { + 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) + GF_FREE (key); + /* Indicates duplicate key */ + return 0; + } + } - 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; - } + if (this->free_pair_in_use) { + pair = mem_get0 (THIS->ctx->dict_pair_pool); + if (!pair) { + if (key_free) + GF_FREE (key); + return -1; + } + } + else { + pair = &this->free_pair; + this->free_pair_in_use = _gf_true; + } + + if (key_free) { + /* It's ours. Use it. */ + pair->key = key; + key_free = 0; + } + else { + pair->key = (char *) GF_CALLOC (1, strlen (key) + 1, + gf_common_mt_char); + if (!pair->key) { + if (pair == &this->free_pair) { + this->free_pair_in_use = _gf_false; + } + else { + mem_put (pair); + } + 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++; - 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; + if (key_free) + GF_FREE (key); + return 0; } int32_t dict_set (dict_t *this, - char *key, - data_t *value) + char *key, + data_t *value) { - int32_t ret; + int32_t ret; - if (!this || !value) { - gf_log ("dict", GF_LOG_CRITICAL, - "@this=%p @value=%p", this, value); - return -1; - } + if (!this || !value) { + gf_log_callingfn ("dict", GF_LOG_WARNING, + "!this || !value for key=%s", key); + return -1; + } - LOCK (&this->lock); + LOCK (&this->lock); - ret = _dict_set (this, key, value); + ret = _dict_set (this, key, value, 1); - UNLOCK (&this->lock); + UNLOCK (&this->lock); - return ret; + return ret; } -data_t * -dict_get (dict_t *this, - char *key) +int32_t +dict_add (dict_t *this, char *key, data_t *value) { - data_pair_t *pair; + int32_t ret; - if (!this || !key) { - gf_log ("dict", GF_LOG_DEBUG, - "@this=%p @key=%p", this, key); - return NULL; - } + if (!this || !value) { + gf_log_callingfn ("dict", GF_LOG_WARNING, + "!this || !value for key=%s", key); + return -1; + } - LOCK (&this->lock); + LOCK (&this->lock); - pair = _dict_lookup (this, key); + ret = _dict_set (this, key, value, 0); - UNLOCK (&this->lock); + UNLOCK (&this->lock); - if (pair) - return pair->value; - - return NULL; + return ret; } -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) +data_t * +dict_get (dict_t *this, char *key) { - if (!this) { - gf_log ("dict", GF_LOG_DEBUG, - "@this=%p", this); - return; - } + data_pair_t *pair; - data_pair_t *pair = this->members_list; - data_pair_t *prev = this->members_list; - - LOCK_DESTROY (&this->lock); + if (!this || !key) { + gf_log_callingfn ("dict", GF_LOG_INFO, + "!this || key=%s", (key) ? key : "()"); + return NULL; + } - while (prev) { - pair = pair->next; - data_unref (prev->value); - FREE (prev->key); - FREE (prev); - prev = pair; - } + LOCK (&this->lock); - FREE (this->members); + pair = _dict_lookup (this, key); - if (this->extra_free) - FREE (this->extra_free); + UNLOCK (&this->lock); - if (!this->is_static) - FREE (this); + if (pair) + return pair->value; - return; + return NULL; } void -dict_unref (dict_t *this) +dict_del (dict_t *this, char *key) { - 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); -} + if (!this || !key) { + gf_log_callingfn ("dict", GF_LOG_WARNING, + "!this || key=%s", key); + return; + } -dict_t * -dict_ref (dict_t *this) -{ - if (!this) { - gf_log ("dict", GF_LOG_DEBUG, - "@this=%p", this); - return NULL; - } + LOCK (&this->lock); - 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; + + GF_FREE (pair->key); + if (pair == &this->free_pair) { + this->free_pair_in_use = _gf_false; + } + else { + mem_put (pair); + } + this->count--; + break; + } - this->refcount++; + prev = pair; + pair = pair->hash_next; + } - UNLOCK (&this->lock); + UNLOCK (&this->lock); - return this; + return; } void -data_unref (data_t *this) +dict_destroy (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; + if (!this) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "dict is NULL"); + return; + } - UNLOCK (&this->lock); + data_pair_t *pair = this->members_list; + data_pair_t *prev = this->members_list; - if (!ref) - data_destroy (this); -} + LOCK_DESTROY (&this->lock); -data_t * -data_ref (data_t *this) -{ - if (!this) { - gf_log ("dict", GF_LOG_DEBUG, - "@this=%p", this); - return NULL; - } + while (prev) { + pair = pair->next; + data_unref (prev->value); + GF_FREE (prev->key); + if (prev != &this->free_pair) { + mem_put (prev); + } + prev = pair; + } - LOCK (&this->lock); + if (this->members != &this->members_internal) { + mem_put (this->members); + } - this->refcount++; + GF_FREE (this->extra_free); + free (this->extra_stdfree); - UNLOCK (&this->lock); + if (!this->is_static) + mem_put (this); - return this; + return; } -/* - Serialization format: - ---- - Count:8 - Key_len:8:Value_len:8 - Key - Value - . - . - . -*/ - -int32_t -dict_serialized_length_old (dict_t *this) +void +dict_unref (dict_t *this) { + int32_t ref; - if (!this) { - gf_log ("dict", GF_LOG_DEBUG, - "@this=%p", this); - return -1; - } + if (!this) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "dict is NULL"); + return; + } - 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--; - } + LOCK (&this->lock); - return len; -} + this->refcount--; + ref = this->refcount; -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; - } + UNLOCK (&this->lock); - 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); + if (!ref) + dict_destroy (this); } - dict_t * -dict_unserialize_old (char *buf, int32_t size, dict_t **fill) +dict_ref (dict_t *this) { - 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; - } + if (!this) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "dict is NULL"); + return NULL; + } - 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); - } + LOCK (&this->lock); - goto ret; + this->refcount++; -err: - FREE (*fill); - *fill = NULL; + UNLOCK (&this->lock); -ret: - return *fill; + return this; } - -int32_t -dict_iovec_len (dict_t *this) +void +data_unref (data_t *this) { - if (!this) { - gf_log ("dict", GF_LOG_CRITICAL, - "@this=%p", this); - return -1; - } + int32_t ref; - int32_t len = 0; - data_pair_t *pair = this->members_list; + if (!this) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "dict is NULL"); + return; + } - len++; /* initial header */ - while (pair) { - len++; /* pair header */ - len++; /* key */ + LOCK (&this->lock); - if (pair->value->vec) - len += pair->value->len; - else - len++; - pair = pair->next; - } + this->refcount--; + ref = this->refcount; - return len; + UNLOCK (&this->lock); + + if (!ref) + data_destroy (this); } -int32_t -dict_to_iovec (dict_t *this, - struct iovec *vec, - int32_t count) +data_t * +data_ref (data_t *this) { - 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; + if (!this) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "dict is NULL"); + return NULL; + } - for (i=0; i<pair->value->len; i++) { - vallen += pair->value->vec[i].iov_len; - } - } else { - vallen = pair->value->len; - } + LOCK (&this->lock); - 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++; - } + this->refcount++; - pair = pair->next; - } + UNLOCK (&this->lock); - return 0; + return this; } data_t * int_to_data (int64_t value) { int ret = 0; - data_t *data = get_new_data (); + data_t *data = get_new_data (); - if (!data) { - gf_log ("dict", GF_LOG_CRITICAL, - "@data - NULL returned by CALLOC"); - return NULL; - } + if (!data) { + return NULL; + } - ret = asprintf (&data->data, "%"PRId64, value); + ret = gf_asprintf (&data->data, "%"PRId64, value); if (-1 == ret) { - gf_log ("dict", GF_LOG_ERROR, "asprintf failed"); + gf_log ("dict", GF_LOG_DEBUG, "asprintf failed"); return NULL; } - data->len = strlen (data->data) + 1; + data->len = strlen (data->data) + 1; - return data; + return data; } data_t * data_from_int64 (int64_t value) { int ret = 0; - data_t *data = get_new_data (); + data_t *data = get_new_data (); - if (!data) { - gf_log ("dict", GF_LOG_CRITICAL, - "@data - NULL returned by CALLOC"); - return NULL; - } - ret = asprintf (&data->data, "%"PRId64, value); + if (!data) { + return NULL; + } + ret = gf_asprintf (&data->data, "%"PRId64, value); if (-1 == ret) { - gf_log ("dict", GF_LOG_ERROR, "asprintf failed"); + gf_log ("dict", GF_LOG_DEBUG, "asprintf failed"); return NULL; } - data->len = strlen (data->data) + 1; + data->len = strlen (data->data) + 1; - return data; + return data; } data_t * data_from_int32 (int32_t value) { int ret = 0; - data_t *data = get_new_data (); + data_t *data = get_new_data (); - if (!data) { - gf_log ("dict", GF_LOG_CRITICAL, - "@data - NULL returned by CALLOC"); - return NULL; - } - ret = asprintf (&data->data, "%"PRId32, value); + if (!data) { + return NULL; + } + ret = gf_asprintf (&data->data, "%"PRId32, value); if (-1 == ret) { - gf_log ("dict", GF_LOG_ERROR, "asprintf failed"); + gf_log ("dict", GF_LOG_DEBUG, "asprintf failed"); return NULL; } - data->len = strlen (data->data) + 1; + data->len = strlen (data->data) + 1; - return data; + return data; } data_t * data_from_int16 (int16_t value) { int ret = 0; - data_t *data = get_new_data (); + data_t *data = get_new_data (); - if (!data) { - gf_log ("dict", GF_LOG_CRITICAL, - "@data - NULL returned by CALLOC"); - return NULL; - } - ret = asprintf (&data->data, "%"PRId16, value); + if (!data) { + return NULL; + } + ret = gf_asprintf (&data->data, "%"PRId16, value); if (-1 == ret) { - gf_log ("dict", GF_LOG_ERROR, "asprintf failed"); + gf_log ("dict", GF_LOG_DEBUG, "asprintf failed"); return NULL; } - data->len = strlen (data->data) + 1; + data->len = strlen (data->data) + 1; - return data; + return data; } data_t * data_from_int8 (int8_t value) { int ret = 0; - data_t *data = get_new_data (); + data_t *data = get_new_data (); - if (!data) { - gf_log ("dict", GF_LOG_CRITICAL, - "@data - NULL returned by CALLOC"); - return NULL; - } - ret = asprintf (&data->data, "%d", value); + if (!data) { + return NULL; + } + ret = gf_asprintf (&data->data, "%d", value); if (-1 == ret) { - gf_log ("dict", GF_LOG_ERROR, "asprintf failed"); + gf_log ("dict", GF_LOG_DEBUG, "asprintf failed"); return NULL; } - data->len = strlen (data->data) + 1; + data->len = strlen (data->data) + 1; - return data; + return data; } data_t * data_from_uint64 (uint64_t value) { int ret = 0; - data_t *data = get_new_data (); + data_t *data = get_new_data (); - if (!data) { - gf_log ("dict", GF_LOG_CRITICAL, - "@data - NULL returned by CALLOC"); - return NULL; - } - ret = asprintf (&data->data, "%"PRIu64, value); + if (!data) { + return NULL; + } + ret = gf_asprintf (&data->data, "%"PRIu64, value); if (-1 == ret) { - gf_log ("dict", GF_LOG_ERROR, "asprintf failed"); + gf_log ("dict", GF_LOG_DEBUG, "asprintf failed"); return NULL; } - data->len = strlen (data->data) + 1; + data->len = strlen (data->data) + 1; - return data; + return data; } static data_t * data_from_double (double value) { - data_t *data = NULL; - int ret = 0; + data_t *data = NULL; + int ret = 0; - data = get_new_data (); + data = get_new_data (); - if (!data) { - gf_log ("dict", GF_LOG_CRITICAL, - "@data - NULL returned by CALLOC"); - return NULL; - } + if (!data) { + return NULL; + } - ret = asprintf (&data->data, "%f", value); - if (ret == -1) { - gf_log ("dict", GF_LOG_CRITICAL, - "@data - allocation failed by ASPRINTF"); - return NULL; - } - data->len = strlen (data->data) + 1; + ret = gf_asprintf (&data->data, "%f", value); + if (ret == -1) { + return NULL; + } + data->len = strlen (data->data) + 1; - return data; + return data; } @@ -878,22 +692,20 @@ data_t * data_from_uint32 (uint32_t value) { int ret = 0; - data_t *data = get_new_data (); + data_t *data = get_new_data (); - if (!data) { - gf_log ("dict", GF_LOG_CRITICAL, - "@data - NULL returned by CALLOC"); - return NULL; - } - ret = asprintf (&data->data, "%"PRIu32, value); + if (!data) { + return NULL; + } + ret = gf_asprintf (&data->data, "%"PRIu32, value); if (-1 == ret) { - gf_log ("dict", GF_LOG_ERROR, "asprintf failed"); + gf_log ("dict", GF_LOG_DEBUG, "asprintf failed"); return NULL; } - data->len = strlen (data->data) + 1; + data->len = strlen (data->data) + 1; - return data; + return data; } @@ -901,44 +713,38 @@ data_t * data_from_uint16 (uint16_t value) { int ret = 0; - data_t *data = get_new_data (); + data_t *data = get_new_data (); - if (!data) { - gf_log ("dict", GF_LOG_CRITICAL, - "@data - NULL returned by CALLOC"); - return NULL; - } - ret = asprintf (&data->data, "%"PRIu16, value); + if (!data) { + return NULL; + } + ret = gf_asprintf (&data->data, "%"PRIu16, value); if (-1 == ret) { - gf_log ("dict", GF_LOG_ERROR, "asprintf failed"); return NULL; } - data->len = strlen (data->data) + 1; + data->len = strlen (data->data) + 1; - return data; + return data; } data_t * data_from_ptr (void *value) { - if (!value) { - gf_log ("dict", GF_LOG_CRITICAL, - "@value=%p", value); - return NULL; - } + if (!value) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "value is NULL"); + return NULL; + } - data_t *data = get_new_data (); + data_t *data = get_new_data (); - if (!data) { - gf_log ("dict", GF_LOG_CRITICAL, - "@data - NULL returned by CALLOC"); - return NULL; - } + if (!data) { + return NULL; + } - data->data = value; - return data; + data->data = value; + return data; } data_t * @@ -947,292 +753,517 @@ 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; - } + if (!value) { + gf_log ("dict", GF_LOG_CRITICAL, + "@value=%p", value); + return NULL; + } */ - data_t *data = get_new_data (); + data_t *data = get_new_data (); - if (!data) { - gf_log ("dict", GF_LOG_CRITICAL, - "@data - NULL returned by CALLOC"); - return NULL; - } + if (!data) { + return NULL; + } - data->is_static = 1; - data->data = value; + data->is_static = 1; + data->data = value; - return data; + 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 (!value) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "value is NULL"); + 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; + if (!data) { + return NULL; + } + data->len = strlen (value) + 1; - data->data = value; - data->is_static = 1; + data->data = value; + data->is_static = 1; - return data; + return data; } data_t * data_from_dynstr (char *value) { - if (!value) { - gf_log ("dict", GF_LOG_CRITICAL, - "@value=%p", value); - return NULL; - } + if (!value) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "value is NULL"); + return NULL; + } - data_t *data = get_new_data (); + data_t *data = get_new_data (); - data->len = strlen (value) + 1; - data->data = value; + data->len = strlen (value) + 1; + data->data = value; - return data; + return data; +} + +data_t * +data_from_dynmstr (char *value) +{ + if (!value) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "value is NULL"); + return NULL; + } + + data_t *data = get_new_data (); + + data->len = strlen (value) + 1; + data->data = value; + data->is_stdalloc = 1; + + return data; } data_t * data_from_dynptr (void *value, int32_t len) { - data_t *data = get_new_data (); + data_t *data = get_new_data (); + + if (!data) + return NULL; - data->len = len; - data->data = value; + data->len = len; + data->data = value; - return data; + 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; - } + if (!value) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "value is NULL"); + return NULL; + } + + data_t *data = get_new_data (); - data_t *data = get_new_data (); + if (!data) + return NULL; - data->is_static = 1; - data->len = len; - data->data = value; + data->is_static = 1; + data->len = len; + data->data = value; - return data; + return data; } int64_t data_to_int64 (data_t *data) { - if (!data) - return -1; + if (!data) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "data is NULL"); + return -1; + } + + char *str = alloca (data->len + 1); + if (!str) + 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); + 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; + if (!data) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "data is NULL"); + return -1; + } - char *str = alloca (data->len + 1); - ERR_ABORT (str); - memcpy (str, data->data, data->len); - str[data->len] = '\0'; + char *str = alloca (data->len + 1); + if (!str) + return -1; - return strtoul (str, NULL, 0); + 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; + int16_t value = 0; + + if (!data) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "data is NULL"); + return -1; + } + + char *str = alloca (data->len + 1); + if (!str) + return -1; + + memcpy (str, data->data, data->len); + str[data->len] = '\0'; - char *str = alloca (data->len + 1); - ERR_ABORT (str); - memcpy (str, data->data, data->len); - str[data->len] = '\0'; + errno = 0; + value = strtol (str, NULL, 0); - return strtol (str, NULL, 0); + if ((value > SHRT_MAX) || (value < SHRT_MIN)) { + errno = ERANGE; + gf_log_callingfn ("dict", GF_LOG_WARNING, + "Error in data conversion: " + "detected overflow"); + return -1; + } + + return (int16_t)value; } int8_t data_to_int8 (data_t *data) { - if (!data) - return -1; + int8_t value = 0; + + if (!data) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "data is NULL"); + return -1; + } - char *str = alloca (data->len + 1); - ERR_ABORT (str); - memcpy (str, data->data, data->len); - str[data->len] = '\0'; + char *str = alloca (data->len + 1); + if (!str) + return -1; - return (int8_t)strtol (str, NULL, 0); + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + errno = 0; + value = strtol (str, NULL, 0); + + if ((value > SCHAR_MAX) || (value < SCHAR_MIN)) { + errno = ERANGE; + gf_log_callingfn ("dict", GF_LOG_WARNING, + "Error in data conversion: " + "detected overflow"); + return -1; + } + + return (int8_t)value; } 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'; + if (!data) + return -1; + char *str = alloca (data->len + 1); + if (!str) + return -1; + + memcpy (str, data->data, data->len); + str[data->len] = '\0'; - return strtoll (str, NULL, 0); + return strtoll (str, NULL, 0); } uint32_t data_to_uint32 (data_t *data) { - if (!data) - return -1; + if (!data) + return -1; + + char *str = alloca (data->len + 1); + if (!str) + return -1; - char *str = alloca (data->len + 1); - ERR_ABORT (str); - memcpy (str, data->data, data->len); - str[data->len] = '\0'; + memcpy (str, data->data, data->len); + str[data->len] = '\0'; - return strtol (str, NULL, 0); + return strtol (str, NULL, 0); } uint16_t data_to_uint16 (data_t *data) { - if (!data) + uint16_t value = 0; + + if (!data) + return -1; + + char *str = alloca (data->len + 1); + if (!str) + return -1; + + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + errno = 0; + value = strtol (str, NULL, 0); + + if ((USHRT_MAX - value) < 0) { + errno = ERANGE; + gf_log_callingfn ("dict", GF_LOG_WARNING, + "Error in data conversion: " + "overflow detected"); return -1; + } + + return (uint16_t)value; +} + +uint8_t +data_to_uint8 (data_t *data) +{ + uint32_t value = 0; + + if (!data) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "data is NULL"); + return -1; + } - char *str = alloca (data->len + 1); - ERR_ABORT (str); - memcpy (str, data->data, data->len); - str[data->len] = '\0'; + char *str = alloca (data->len + 1); + if (!str) + return -1; - return strtol (str, NULL, 0); + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + errno = 0; + value = strtol (str, NULL, 0); + + if ((UCHAR_MAX - value) < 0) { + errno = ERANGE; + gf_log_callingfn ("dict", GF_LOG_WARNING, + "data conversion overflow detected (%s)", + strerror(errno)); + return -1; + } + + return (uint8_t) value; } char * data_to_str (data_t *data) { - if (!data) { - gf_log ("dict", GF_LOG_CRITICAL, - "@data=%p", data); - return NULL; - } - return data->data; + if (!data) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "data is NULL"); + return NULL; + } + return data->data; } void * data_to_ptr (data_t *data) { - if (!data) { - return NULL; - } - return data->data; + if (!data) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "data is NULL"); + 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; + if (!data) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "data is NULL"); + return NULL; + } + return data->data; } -void +int +dict_null_foreach_fn (dict_t *d, char *k, + data_t *v, void *tmp) +{ + return 0; +} + +int 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; - } + int (*fn)(dict_t *this, + char *key, + data_t *value, + void *data), + void *data) +{ + if (!dict) { + gf_log_callingfn ("dict", GF_LOG_WARNING, + "dict is NULL"); + return -1; + } - data_pair_t *pairs = dict->members_list; + int ret = -1; + data_pair_t *pairs = NULL; + data_pair_t *next = NULL; - while (pairs) { - fn (dict, pairs->key, pairs->value, data); - pairs = pairs->next; - } + pairs = dict->members_list; + while (pairs) { + next = pairs->next; + ret = fn (dict, pairs->key, pairs->value, data); + if (ret == -1) + return -1; + pairs = next; + } + + return 0; } +/* return values: + -1 = failure, + 0 = no matches found, + +n = n number of matches +*/ +int +dict_foreach_fnmatch (dict_t *dict, char *pattern, + int (*fn)(dict_t *this, + char *key, + data_t *value, + void *data), + void *data) +{ + if (!dict) { + gf_log_callingfn ("dict", GF_LOG_WARNING, + "dict is NULL"); + return 0; + } + + int ret = -1; + int count = 0; + data_pair_t *pairs = NULL; + data_pair_t *next = NULL; + + pairs = dict->members_list; + while (pairs) { + next = pairs->next; + if (!fnmatch (pattern, pairs->key, 0)) { + ret = fn (dict, pairs->key, pairs->value, data); + if (ret == -1) + return -1; + count++; + } + pairs = next; + } + + return count; +} + + +/** + * dict_keys_join - pack the keys of the dictionary in a buffer. + * + * @value : buffer in which the keys will be packed (can be NULL) + * @size : size of the buffer which is sent (can be 0, in which case buffer + * is not packed but only length is returned) + * @dict : dictionary of which all the keys will be packed + * @filter_fn : keys matched in filter_fn() is counted. + * + * @return : @length of string after joining keys. + * + */ + +int +dict_keys_join (void *value, int size, dict_t *dict, + int (*filter_fn)(char *k)) +{ + int len = 0; + data_pair_t *pairs = NULL; + data_pair_t *next = NULL; + + pairs = dict->members_list; + while (pairs) { + next = pairs->next; + + if (filter_fn && filter_fn (pairs->key)){ + pairs = next; + continue; + } + + if (value && (size > len)) + strncpy (value + len, pairs->key, size - len); + + len += (strlen (pairs->key) + 1); + + pairs = next; + } + + return len; +} -static void +static int _copy (dict_t *unused, char *key, data_t *value, void *newdict) { - dict_set ((dict_t *)newdict, key, (value)); + return dict_set ((dict_t *)newdict, key, (value)); +} + +static int +_remove (dict_t *dict, + char *key, + data_t *value, + void *unused) +{ + dict_del ((dict_t *)dict, key); + return 0; } dict_t * dict_copy (dict_t *dict, - dict_t *new) + dict_t *new) { - if (!dict) { - gf_log ("dict", GF_LOG_CRITICAL, - "@data=%p", dict); - return NULL; - } + if (!dict) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "dict is NULL"); + return NULL; + } - if (!new) - new = get_new_dict_full (dict->hash_size); + if (!new) + new = get_new_dict_full (dict->hash_size); - dict_foreach (dict, _copy, new); + dict_foreach (dict, _copy, new); - return new; + return new; +} + +int +dict_reset (dict_t *dict) +{ + int32_t ret = -1; + if (!dict) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "dict is NULL"); + goto out; + } + dict_foreach (dict, _remove, NULL); + ret = 0; +out: + return ret; } dict_t * dict_copy_with_ref (dict_t *dict, - dict_t *new) + dict_t *new) { - dict_t *local_new = NULL; + dict_t *local_new = NULL; - GF_VALIDATE_OR_GOTO("dict", dict, fail); + 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; - } + if (new == NULL) { + local_new = dict_new (); + GF_VALIDATE_OR_GOTO("dict", local_new, fail); + new = local_new; + } - dict_foreach (dict, _copy, new); + dict_foreach (dict, _copy, new); fail: - return new; + return new; } /* @@ -1241,7 +1272,7 @@ fail: /** * Common cleaned up interface: - * + * * Return value: 0 success * -val error, val = errno */ @@ -1250,506 +1281,508 @@ fail: static int dict_get_with_ref (dict_t *this, char *key, data_t **data) { - data_pair_t * pair = NULL; - int ret = -ENOENT; + data_pair_t * pair = NULL; + int ret = -ENOENT; - if (!this || !key || !data) { - ret = -EINVAL; - goto err; - } + if (!this || !key || !data) { + gf_log_callingfn ("dict", GF_LOG_WARNING, + "dict OR key (%s) is NULL", key); + ret = -EINVAL; + goto err; + } - LOCK (&this->lock); - { - pair = _dict_lookup (this, key); - } - UNLOCK (&this->lock); + LOCK (&this->lock); + { + pair = _dict_lookup (this, key); + } + UNLOCK (&this->lock); - if (pair) { - ret = 0; - *data = data_ref (pair->value); - } + if (pair) { + ret = 0; + *data = data_ref (pair->value); + } -err: - return ret; +err: + return ret; } static int _data_to_ptr (data_t *data, void **val) { - int ret = 0; + int ret = 0; - if (!data) { - ret = -EINVAL; - goto err; - } + if (!data) { + ret = -EINVAL; + goto err; + } - *val = data->data; + *val = data->data; err: - return ret; + return ret; } static int _data_to_int8 (data_t *data, int8_t *val) { - int ret = 0; - char * str = NULL; + int ret = 0; + char * str = NULL; - if (!data || !val) { - ret = -EINVAL; - goto err; - } + 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'; + 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; + errno = 0; + *val = strtol (str, NULL, 0); + if (errno != 0) + ret = -errno; err: - return ret; + return ret; } static int _data_to_int16 (data_t *data, int16_t *val) { - int ret = 0; - char * str = NULL; + int ret = 0; + char * str = NULL; - if (!data || !val) { - ret = -EINVAL; - goto err; - } + 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'; + 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; + errno = 0; + *val = strtol (str, NULL, 0); + if (errno != 0) + ret = -errno; err: - return ret; + return ret; } static int _data_to_int32 (data_t *data, int32_t *val) { - int ret = 0; - char * str = NULL; + int ret = 0; + char * str = NULL; - if (!data || !val) { - ret = -EINVAL; - goto err; - } + 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'; + 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; + errno = 0; + *val = strtol (str, NULL, 0); + if (errno != 0) + ret = -errno; err: - return ret; + return ret; } static int _data_to_int64 (data_t *data, int64_t *val) { - int ret = 0; - char * str = NULL; + int ret = 0; + char * str = NULL; - if (!data || !val) { - ret = -EINVAL; - goto err; - } + 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'; + 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; + errno = 0; + *val = strtoll (str, NULL, 0); + if (errno != 0) + ret = -errno; err: - return ret; + return ret; } static int _data_to_uint16 (data_t *data, uint16_t *val) { - int ret = 0; - char * str = NULL; + int ret = 0; + char * str = NULL; - if (!data || !val) { - ret = -EINVAL; - goto err; - } + 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'; + 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; + errno = 0; + *val = strtoul (str, NULL, 0); + if (errno != 0) + ret = -errno; err: - return ret; + return ret; } static int _data_to_uint32 (data_t *data, uint32_t *val) { - int ret = 0; - char * str = NULL; + int ret = 0; + char * str = NULL; - if (!data || !val) { - ret = -EINVAL; - goto err; - } + 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'; + 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; + errno = 0; + *val = strtoul (str, NULL, 0); + if (errno != 0) + ret = -errno; err: - return ret; + return ret; } static int _data_to_uint64 (data_t *data, uint64_t *val) { - int ret = 0; - char * str = NULL; + int ret = 0; + char * str = NULL; - if (!data || !val) { - ret = -EINVAL; - goto err; - } + 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'; + 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; + errno = 0; + *val = strtoull (str, NULL, 0); + if (errno != 0) + ret = -errno; err: - return ret; + return ret; } static int _data_to_double (data_t *data, double *val) { - int ret = 0; - char * str = NULL; + int ret = 0; + char * str = NULL; - if (!data || !val) { - ret = -EINVAL; - goto err; - } + 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'; + str = alloca (data->len + 1); + if (!str) { + ret = -ENOMEM; + goto err; + } + memcpy (str, data->data, data->len); + str[data->len] = '\0'; - errno = 0; - *val = strtod (str, NULL); - if (errno != 0) - ret = -errno; + errno = 0; + *val = strtod (str, NULL); + if (errno != 0) + ret = -errno; err: - return ret; + return ret; } int dict_get_int8 (dict_t *this, char *key, int8_t *val) { - data_t * data = NULL; - int ret = 0; + data_t * data = NULL; + int ret = 0; - if (!this || !key || !val) { - ret = -EINVAL; - goto err; - } + if (!this || !key || !val) { + ret = -EINVAL; + goto err; + } - ret = dict_get_with_ref (this, key, &data); - if (ret != 0) { - goto err; - } + ret = dict_get_with_ref (this, key, &data); + if (ret != 0) { + goto err; + } + + ret = _data_to_int8 (data, val); - ret = _data_to_int8 (data, val); - err: - if (data) - data_unref (data); - return ret; + 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_t * data = NULL; + int ret = 0; - data = data_from_int8 (val); - if (!data) { - ret = -EINVAL; - goto err; - } + data = data_from_int8 (val); + if (!data) { + ret = -EINVAL; + goto err; + } - ret = dict_set (this, key, data); + ret = dict_set (this, key, data); err: - return ret; + return ret; } int dict_get_int16 (dict_t *this, char *key, int16_t *val) { - data_t * data = NULL; - int ret = 0; + data_t * data = NULL; + int ret = 0; - if (!this || !key || !val) { - ret = -EINVAL; - goto err; - } + if (!this || !key || !val) { + ret = -EINVAL; + goto err; + } - ret = dict_get_with_ref (this, key, &data); - if (ret != 0) { - goto err; - } + ret = dict_get_with_ref (this, key, &data); + if (ret != 0) { + goto err; + } + + ret = _data_to_int16 (data, val); - ret = _data_to_int16 (data, val); - err: - if (data) - data_unref (data); - return ret; + 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_t * data = NULL; + int ret = 0; - data = data_from_int16 (val); - if (!data) { - ret = -EINVAL; - goto err; - } + data = data_from_int16 (val); + if (!data) { + ret = -EINVAL; + goto err; + } - ret = dict_set (this, key, data); + ret = dict_set (this, key, data); err: - return ret; + return ret; } int dict_get_int32 (dict_t *this, char *key, int32_t *val) { - data_t * data = NULL; - int ret = 0; + data_t * data = NULL; + int ret = 0; - if (!this || !key || !val) { - ret = -EINVAL; - goto err; - } + if (!this || !key || !val) { + ret = -EINVAL; + goto err; + } - ret = dict_get_with_ref (this, key, &data); - if (ret != 0) { - goto err; - } + ret = dict_get_with_ref (this, key, &data); + if (ret != 0) { + goto err; + } + + ret = _data_to_int32 (data, val); - ret = _data_to_int32 (data, val); - err: - if (data) - data_unref (data); - return ret; + 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_t * data = NULL; + int ret = 0; - data = data_from_int32 (val); - if (!data) { - ret = -EINVAL; - goto err; - } + data = data_from_int32 (val); + if (!data) { + ret = -EINVAL; + goto err; + } - ret = dict_set (this, key, data); + ret = dict_set (this, key, data); err: - return ret; + return ret; } int dict_get_int64 (dict_t *this, char *key, int64_t *val) { - data_t * data = NULL; - int ret = 0; + data_t * data = NULL; + int ret = 0; - if (!this || !key || !val) { - ret = -EINVAL; - goto err; - } + if (!this || !key || !val) { + ret = -EINVAL; + goto err; + } - ret = dict_get_with_ref (this, key, &data); - if (ret != 0) { - goto err; - } + ret = dict_get_with_ref (this, key, &data); + if (ret != 0) { + goto err; + } + + ret = _data_to_int64 (data, val); - ret = _data_to_int64 (data, val); - err: - if (data) - data_unref (data); - return ret; + 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_t * data = NULL; + int ret = 0; - data = data_from_int64 (val); - if (!data) { - ret = -EINVAL; - goto err; - } + data = data_from_int64 (val); + if (!data) { + ret = -EINVAL; + goto err; + } - ret = dict_set (this, key, data); + ret = dict_set (this, key, data); err: - return ret; + return ret; } int dict_get_uint16 (dict_t *this, char *key, uint16_t *val) { - data_t * data = NULL; - int ret = 0; + data_t * data = NULL; + int ret = 0; - if (!this || !key || !val) { - ret = -EINVAL; - goto err; - } + if (!this || !key || !val) { + ret = -EINVAL; + goto err; + } - ret = dict_get_with_ref (this, key, &data); - if (ret != 0) { - goto err; - } + ret = dict_get_with_ref (this, key, &data); + if (ret != 0) { + goto err; + } + + ret = _data_to_uint16 (data, val); - ret = _data_to_uint16 (data, val); - err: - if (data) - data_unref (data); - return ret; + 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_t * data = NULL; + int ret = 0; - data = data_from_uint16 (val); - if (!data) { - ret = -EINVAL; - goto err; - } + data = data_from_uint16 (val); + if (!data) { + ret = -EINVAL; + goto err; + } - ret = dict_set (this, key, data); + ret = dict_set (this, key, data); err: - return ret; + return ret; } int dict_get_uint32 (dict_t *this, char *key, uint32_t *val) { - data_t * data = NULL; - int ret = 0; + data_t * data = NULL; + int ret = 0; - if (!this || !key || !val) { - ret = -EINVAL; - goto err; - } + if (!this || !key || !val) { + ret = -EINVAL; + goto err; + } - ret = dict_get_with_ref (this, key, &data); - if (ret != 0) { - goto err; - } + ret = dict_get_with_ref (this, key, &data); + if (ret != 0) { + goto err; + } + + ret = _data_to_uint32 (data, val); - ret = _data_to_uint32 (data, val); - err: - if (data) - data_unref (data); - return ret; + if (data) + data_unref (data); + return ret; } @@ -1757,336 +1790,448 @@ err: int dict_set_uint32 (dict_t *this, char *key, uint32_t val) { - data_t * data = NULL; - int ret = 0; + data_t * data = NULL; + int ret = 0; - data = data_from_uint32 (val); - if (!data) { - ret = -EINVAL; - goto err; - } + data = data_from_uint32 (val); + if (!data) { + ret = -EINVAL; + goto err; + } - ret = dict_set (this, key, data); + ret = dict_set (this, key, data); err: - return ret; + return ret; } int dict_get_uint64 (dict_t *this, char *key, uint64_t *val) { - data_t * data = NULL; - int ret = 0; + data_t * data = NULL; + int ret = 0; - if (!this || !key || !val) { - ret = -EINVAL; - goto err; - } + if (!this || !key || !val) { + ret = -EINVAL; + goto err; + } - ret = dict_get_with_ref (this, key, &data); - if (ret != 0) { - goto err; - } + ret = dict_get_with_ref (this, key, &data); + if (ret != 0) { + goto err; + } + + ret = _data_to_uint64 (data, val); - ret = _data_to_uint64 (data, val); - err: - if (data) - data_unref (data); - return ret; + 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_t * data = NULL; + int ret = 0; - data = data_from_uint64 (val); - if (!data) { - ret = -EINVAL; - goto err; - } + data = data_from_uint64 (val); + if (!data) { + ret = -EINVAL; + goto err; + } - ret = dict_set (this, key, data); + ret = dict_set (this, key, data); err: - return ret; + return ret; } int dict_get_double (dict_t *this, char *key, double *val) { - data_t *data = NULL; - int ret = 0; + data_t *data = NULL; + int ret = 0; - if (!this || !key || !val) { - ret = -EINVAL; - goto err; - } + if (!this || !key || !val) { + ret = -EINVAL; + goto err; + } - ret = dict_get_with_ref (this, key, &data); - if (ret != 0) { - goto err; - } + ret = dict_get_with_ref (this, key, &data); + if (ret != 0) { + goto err; + } + + ret = _data_to_double (data, val); - ret = _data_to_double (data, val); - err: - if (data) - data_unref (data); - return ret; + if (data) + data_unref (data); + return ret; } int dict_set_double (dict_t *this, char *key, double val) { - data_t * data = NULL; - int ret = 0; + data_t * data = NULL; + int ret = 0; - data = data_from_double (val); - if (!data) { - ret = -EINVAL; - goto err; - } + data = data_from_double (val); + if (!data) { + ret = -EINVAL; + goto err; + } - ret = dict_set (this, key, data); + ret = dict_set (this, key, data); err: - return ret; + return ret; } int dict_set_static_ptr (dict_t *this, char *key, void *ptr) { - data_t * data = NULL; - int ret = 0; + data_t * data = NULL; + int ret = 0; - data = data_from_static_ptr (ptr); - if (!data) { - ret = -EINVAL; - goto err; - } + data = data_from_static_ptr (ptr); + if (!data) { + ret = -EINVAL; + goto err; + } - ret = dict_set (this, key, data); + ret = dict_set (this, key, data); err: - return ret; + return ret; } int dict_set_dynptr (dict_t *this, char *key, void *ptr, size_t len) { - data_t * data = NULL; - int ret = 0; + data_t * data = NULL; + int ret = 0; - data = data_from_dynptr (ptr, len); - if (!data) { - ret = -EINVAL; - goto err; - } + data = data_from_dynptr (ptr, len); + if (!data) { + ret = -EINVAL; + goto err; + } - ret = dict_set (this, key, data); + ret = dict_set (this, key, data); err: - return ret; + return ret; } int dict_get_ptr (dict_t *this, char *key, void **ptr) { - data_t * data = NULL; - int ret = 0; + data_t * data = NULL; + int ret = 0; - if (!this || !key || !ptr) { - ret = -EINVAL; - goto err; - } + if (!this || !key || !ptr) { + ret = -EINVAL; + goto err; + } - ret = dict_get_with_ref (this, key, &data); - if (ret != 0) { - 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; - } + ret = _data_to_ptr (data, ptr); + if (ret != 0) { + goto err; + } -err: - if (data) - data_unref (data); +err: + if (data) + data_unref (data); - return ret; + return ret; +} + +int +dict_get_ptr_and_len (dict_t *this, char *key, void **ptr, int *len) +{ + 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; + } + + *len = data->len; + + 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_t * data = NULL; + int ret = 0; - data = data_from_ptr (ptr); - if (!data) { - ret = -EINVAL; - goto err; - } + data = data_from_ptr (ptr); + if (!data) { + ret = -EINVAL; + goto err; + } - ret = dict_set (this, key, data); + ret = dict_set (this, key, data); err: - return ret; + return ret; } int dict_get_str (dict_t *this, char *key, char **str) { - data_t * data = NULL; - int ret = -EINVAL; + data_t * data = NULL; + int ret = -EINVAL; - if (!this || !key || !str) { - goto err; - } + if (!this || !key || !str) { + goto err; + } - ret = dict_get_with_ref (this, key, &data); - if (ret < 0) { - goto err; - } + ret = dict_get_with_ref (this, key, &data); + if (ret < 0) { + goto err; + } - if (!data || !data->data) { - goto err; - } - *str = data->data; + if (!data || !data->data) { + goto err; + } + *str = data->data; -err: - if (data) - data_unref (data); +err: + if (data) + data_unref (data); - return ret; + return ret; } int dict_set_str (dict_t *this, char *key, char *str) { - data_t * data = NULL; - int ret = 0; + data_t * data = NULL; + int ret = 0; - data = str_to_data (str); - if (!data) { - ret = -EINVAL; - goto err; - } + data = str_to_data (str); + if (!data) { + ret = -EINVAL; + goto err; + } - ret = dict_set (this, key, data); + ret = dict_set (this, key, data); err: - return ret; + return ret; } int dict_set_dynstr (dict_t *this, char *key, char *str) { - data_t * data = NULL; - int ret = 0; + data_t * data = NULL; + int ret = 0; - data = data_from_dynstr (str); - if (!data) { - ret = -EINVAL; - goto err; - } + data = data_from_dynstr (str); + if (!data) { + ret = -EINVAL; + goto err; + } + + ret = dict_set (this, key, data); + +err: + return ret; +} + +/* + for malloced strings we should do a free instead of GF_FREE +*/ +int +dict_set_dynmstr (dict_t *this, char *key, char *str) +{ + data_t * data = NULL; + int ret = 0; + + data = data_from_dynmstr (str); + if (!data) { + ret = -EINVAL; + goto err; + } - ret = dict_set (this, key, data); + ret = dict_set (this, key, data); err: - return ret; + return ret; } int dict_get_bin (dict_t *this, char *key, void **bin) { - data_t * data = NULL; - int ret = -EINVAL; + data_t * data = NULL; + int ret = -EINVAL; - if (!this || !key || !bin) { - goto err; - } + if (!this || !key || !bin) { + goto err; + } - ret = dict_get_with_ref (this, key, &data); - if (ret < 0) { - goto err; - } + ret = dict_get_with_ref (this, key, &data); + if (ret < 0) { + goto err; + } - if (!data || !data->data) { - goto err; - } - *bin = data->data; + if (!data || !data->data) { + goto err; + } + *bin = data->data; -err: - if (data) - data_unref (data); +err: + if (data) + data_unref (data); - return ret; + return ret; } int dict_set_bin (dict_t *this, char *key, void *ptr, size_t size) { - data_t * data = NULL; - int ret = 0; + data_t * data = NULL; + int ret = 0; - if (!ptr || (size < 0)) { - ret = -EINVAL; - goto err; - } + if (!ptr || (size < 0)) { + ret = -EINVAL; + goto err; + } - data = bin_to_data (ptr, size); - if (!data) { - 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; + data->data = ptr; + data->len = size; + data->is_static = 0; - ret = dict_set (this, key, data); + ret = dict_set (this, key, data); err: - return ret; + return ret; } int dict_set_static_bin (dict_t *this, char *key, void *ptr, size_t size) { - data_t * data = NULL; - int ret = 0; + data_t * data = NULL; + int ret = 0; - if (!ptr || (size < 0)) { - ret = -EINVAL; - goto err; - } + if (!ptr || (size < 0)) { + ret = -EINVAL; + goto err; + } - data = bin_to_data (ptr, size); - if (!data) { - 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; +} + + +/** + * dict_get_str_boolean - get a boolean value based on string representation. + * + * @this : dictionary + * @key : dictionary key queried + * @default_val : default value if key not found + * + * @return : @default_val if key not found + * : boolean interpretation of @this[@key] if it makes sense + * (ie., "on", "true", "enable" ...) + * : -1 if error occurs or @this[@key] doesn't make sens as + * boolean + * + * So if you query a boolean option, then via @default_val you can choose + * between following patterns: + * + * - fall back to _gf_false if @key is not set [@default_val = 0] + * - fall back to _gf_true if @key is not set [@default_val = 1] + * - regard as failure if @key is not set [@default_val = -1] + * - handle specially (not as error) if @key is not set + * [@default_val = anything else] + */ - data->data = ptr; - data->len = size; - data->is_static = 1; +int +dict_get_str_boolean (dict_t *this, char *key, int default_val) +{ + data_t *data = NULL; + gf_boolean_t boo = _gf_false; + int ret = 0; + + ret = dict_get_with_ref (this, key, &data); + if (ret < 0) { + if (ret == -ENOENT) + ret = default_val; + else + ret = -1; + goto err; + } + + GF_ASSERT (data); + + if (!data->data) { + ret = -1; + goto err; + } + + ret = gf_string2boolean (data->data, &boo); + if (ret == -1) + goto err; - ret = dict_set (this, key, data); + ret = boo; err: - return ret; + if (data) + data_unref (data); + + return ret; } + /** * Serialization format: * -------- -------- -------- ----------- ------------- @@ -2111,81 +2256,67 @@ err: int _dict_serialized_length (dict_t *this) { - int ret = -EINVAL; - int count = 0; - int len = 0; - int i = 0; - data_pair_t * pair = NULL; + int ret = -EINVAL; + int count = 0; + int len = 0; + data_pair_t * pair = NULL; - len = DICT_HDR_LEN; - count = this->count; + len = DICT_HDR_LEN; + count = this->count; - if (count < 0) { - gf_log ("dict", GF_LOG_ERROR, "count (%d) < 0!", count); - goto out; - } + if (count < 0) { + gf_log ("dict", GF_LOG_ERROR, "count (%d) < 0!", count); + goto out; + } - pair = this->members_list; + pair = this->members_list; - while (count) { - if (!pair) { - gf_log ("dict", GF_LOG_ERROR, - "less than count data pairs found!"); - goto out; - } + 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; + 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; - } + if (!pair->key) { + gf_log ("dict", GF_LOG_ERROR, "pair->key is null!"); + goto out; + } - len += strlen (pair->key) + 1 /* for '\0' */; + 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) { + 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; - } + if (pair->value->len < 0) { + gf_log ("dict", GF_LOG_ERROR, + "value->len (%d) < 0", + pair->value->len); + goto out; + } - pair = pair->next; - count--; - } - - ret = len; + len += pair->value->len; + + pair = pair->next; + count--; + } + + ret = len; out: - return ret; + return ret; } /** - * _dict_serialize - serialize a dictionary into a buffer. This procedure has + * _dict_serialize - serialize a dictionary into a buffer. This procedure has * to be called with this->lock held. * * @this: dict to serialize - * @buf: buffer to serialize into. This must be + * @buf: buffer to serialize into. This must be * atleast dict_serialized_length (this) large * * @return: success: 0 @@ -2195,74 +2326,80 @@ out: 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 (!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; - } + int ret = -1; + data_pair_t * pair = NULL; + int32_t count = 0; + int32_t keylen = 0; + int32_t vallen = 0; + int32_t netword = 0; - *(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 (!buf) { + gf_log ("dict", GF_LOG_ERROR, + "buf is null!"); + 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; + count = this->count; + if (count < 0) { + gf_log ("dict", GF_LOG_ERROR, "count (%d) < 0!", count); + goto out; + } - if (!pair->value) { - gf_log ("dict", GF_LOG_ERROR, - "pair->value is null!"); - goto out; - } + netword = hton32 (count); + memcpy (buf, &netword, sizeof(netword)); + buf += DICT_HDR_LEN; + pair = this->members_list; - vallen = pair->value->len; - *(int32_t *) buf = hton32 (vallen); - buf += DICT_DATA_HDR_VAL_LEN; + while (count) { + if (!pair) { + gf_log ("dict", GF_LOG_ERROR, + "less than count data pairs found!"); + goto out; + } - memcpy (buf, pair->key, keylen); - buf += keylen; - *buf++ = '\0'; + if (!pair->key) { + gf_log ("dict", GF_LOG_ERROR, + "pair->key is null!"); + goto out; + } - 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; + keylen = strlen (pair->key); + netword = hton32 (keylen); + memcpy (buf, &netword, sizeof(netword)); + buf += DICT_DATA_HDR_KEY_LEN; - pair = pair->next; - count--; - } + if (!pair->value) { + gf_log ("dict", GF_LOG_ERROR, + "pair->value is null!"); + goto out; + } + + vallen = pair->value->len; + netword = hton32 (vallen); + memcpy (buf, &netword, sizeof(netword)); + 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; - ret = 0; + pair = pair->next; + count--; + } + + ret = 0; out: - return ret; + return ret; } @@ -2277,13 +2414,13 @@ out: int dict_serialized_length (dict_t *this) { - int ret = -EINVAL; + int ret = -EINVAL; + + if (!this) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "dict is null!"); + goto out; + } - if (!this) { - gf_log ("dict", GF_LOG_ERROR, "this is null!"); - goto out; - } - LOCK (&this->lock); { ret = _dict_serialized_length (this); @@ -2291,14 +2428,14 @@ dict_serialized_length (dict_t *this) UNLOCK (&this->lock); out: - return ret; + return ret; } /** * dict_serialize - serialize a dictionary into a buffer * * @this: dict to serialize - * @buf: buffer to serialize into. This must be + * @buf: buffer to serialize into. This must be * atleast dict_serialized_length (this) large * * @return: success: 0 @@ -2308,18 +2445,12 @@ out: int dict_serialize (dict_t *this, char *buf) { - int ret = -1; - - 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; - } + int ret = -1; + + if (!this || !buf) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "dict is null!"); + goto out; + } LOCK (&this->lock); { @@ -2327,7 +2458,7 @@ dict_serialize (dict_t *this, char *buf) } UNLOCK (&this->lock); out: - return ret; + return ret; } @@ -2337,7 +2468,7 @@ out: * @buf: buf containing serialized dict * @size: size of the @buf * @fill: dict to fill in - * + * * @return: success: 0 * failure: -errno */ @@ -2345,103 +2476,120 @@ out: 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; + 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; + int32_t hostord = 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; - } + buf = orig_buf; - if (!*fill) { - gf_log ("dict", GF_LOG_ERROR, - "*fill is null!"); - goto out; - } + if (!buf) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "buf is null!"); + goto out; + } - if ((buf + DICT_HDR_LEN) > (orig_buf + size)) { - gf_log ("dict", GF_LOG_ERROR, - "undersized buffer passsed"); - goto out; - } + if (size == 0) { + gf_log_callingfn ("dict", GF_LOG_ERROR, + "size is 0!"); + goto out; + } - count = ntoh32 (*(int32_t *) buf); - buf += DICT_HDR_LEN; + if (!fill) { + gf_log_callingfn ("dict", GF_LOG_ERROR, + "fill is null!"); + goto out; + } - if (count < 0) { - gf_log ("dict", GF_LOG_ERROR, - "count (%d) <= 0", count); - goto out; - } + if (!*fill) { + gf_log_callingfn ("dict", GF_LOG_ERROR, + "*fill is null!"); + goto out; + } - /* count will be set by the dict_set's below */ - (*fill)->count = 0; + if ((buf + DICT_HDR_LEN) > (orig_buf + size)) { + gf_log_callingfn ("dict", GF_LOG_ERROR, + "undersized buffer passed. " + "available (%lu) < required (%lu)", + (long)(orig_buf + size), + (long)(buf + DICT_HDR_LEN)); + goto out; + } - 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; + memcpy (&hostord, buf, sizeof(hostord)); + count = ntoh32 (hostord); + buf += DICT_HDR_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 (count < 0) { + gf_log ("dict", GF_LOG_ERROR, + "count (%d) <= 0", count); + goto out; + } - 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; + /* 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_callingfn ("dict", GF_LOG_ERROR, + "undersized buffer passed. " + "available (%lu) < required (%lu)", + (long)(orig_buf + size), + (long)(buf + DICT_DATA_HDR_KEY_LEN)); + goto out; + } + memcpy (&hostord, buf, sizeof(hostord)); + keylen = ntoh32 (hostord); + buf += DICT_DATA_HDR_KEY_LEN; + + if ((buf + DICT_DATA_HDR_VAL_LEN) > (orig_buf + size)) { + gf_log_callingfn ("dict", GF_LOG_ERROR, + "undersized buffer passed. " + "available (%lu) < required (%lu)", + (long)(orig_buf + size), + (long)(buf + DICT_DATA_HDR_VAL_LEN)); + goto out; + } + memcpy (&hostord, buf, sizeof(hostord)); + vallen = ntoh32 (hostord); + buf += DICT_DATA_HDR_VAL_LEN; + + if ((buf + keylen) > (orig_buf + size)) { + gf_log_callingfn ("dict", GF_LOG_ERROR, + "undersized buffer passed. " + "available (%lu) < required (%lu)", + (long)(orig_buf + size), + (long)(buf + keylen)); + goto out; + } + key = buf; + buf += keylen + 1; /* for '\0' */ + + if ((buf + vallen) > (orig_buf + size)) { + gf_log_callingfn ("dict", GF_LOG_ERROR, + "undersized buffer passed. " + "available (%lu) < required (%lu)", + (long)(orig_buf + size), + (long)(buf + vallen)); + goto out; + } + value = get_new_data (); + value->len = vallen; + value->data = memdup (buf, vallen); + value->is_static = 0; + buf += vallen; - dict_set (*fill, key, value); - } + dict_add (*fill, key, value); + } - ret = 0; + ret = 0; out: - return ret; + return ret; } @@ -2450,47 +2598,41 @@ out: * * @this: dict to serialize * @buf: pointer to pointer to character. The allocated buffer is stored in - * this pointer. The buffer has to be freed by the caller. + * this pointer. The buffer has to be freed by the caller. * * @return: success: 0 * failure: -errno */ int32_t -dict_allocate_and_serialize (dict_t *this, char **buf, size_t *length) +dict_allocate_and_serialize (dict_t *this, char **buf, u_int *length) { - int ret = -EINVAL; - ssize_t len = 0; + int ret = -EINVAL; + ssize_t len = 0; + + if (!this || !buf) { + gf_log_callingfn ("dict", GF_LOG_DEBUG, + "dict OR buf is NULL"); + goto out; + } - if (!this) { - gf_log ("dict", GF_LOG_DEBUG, - "NULL passed as this pointer"); - goto out; - } - if (!buf) { - gf_log ("dict", GF_LOG_DEBUG, - "NULL passed as buf"); - goto out; - } - LOCK (&this->lock); - { + { len = _dict_serialized_length (this); if (len < 0) { ret = len; goto unlock; } - *buf = CALLOC (1, len); + *buf = GF_CALLOC (1, len, gf_common_mt_char); if (*buf == NULL) { ret = -ENOMEM; - gf_log ("dict", GF_LOG_ERROR, "out of memory"); goto unlock; } ret = _dict_serialize (this, *buf); if (ret < 0) { - FREE (*buf); + GF_FREE (*buf); *buf = NULL; goto unlock; } @@ -2502,5 +2644,138 @@ dict_allocate_and_serialize (dict_t *this, char **buf, size_t *length) unlock: UNLOCK (&this->lock); out: - return ret; + return ret; +} + +/** + * _dict_serialize_value_with_delim: serialize the values in the dictionary + * into a buffer separated by delimiter (except the last) + * + * @this : dictionary to serialize + * @buf : the buffer to store the serialized data + * @serz_len : the length of the serialized data (excluding the last delimiter) + * @delimiter : the delimiter to separate the values + * + * @return : 0 -> success + * : -errno -> faliure + */ +int +_dict_serialize_value_with_delim (dict_t *this, char *buf, int32_t *serz_len, + char delimiter) +{ + int ret = -1; + int32_t count = 0; + int32_t vallen = 0; + int32_t total_len = 0; + data_pair_t *pair = NULL; + + 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; + } + + 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 || !pair->value) { + gf_log ("dict", GF_LOG_ERROR, + "key or value is null"); + goto out; + } + + if (!pair->value->data) { + gf_log ("dict", GF_LOG_ERROR, + "null value found in dict"); + goto out; + } + + vallen = pair->value->len - 1; // length includes \0 + memcpy (buf, pair->value->data, vallen); + buf += vallen; + *buf++ = delimiter; + + total_len += (vallen + 1); + + pair = pair->next; + count--; + } + + *--buf = '\0'; // remove the last delimiter + total_len--; // adjust the length + ret = 0; + + if (serz_len) + *serz_len = total_len; + + out: + return ret; +} + +int +dict_serialize_value_with_delim (dict_t *this, char *buf, int32_t *serz_len, + char delimiter) +{ + int ret = -1; + + if (!this || !buf) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "dict is null!"); + goto out; + } + + LOCK (&this->lock); + { + ret = _dict_serialize_value_with_delim (this, buf, serz_len, delimiter); + } + UNLOCK (&this->lock); +out: + return ret; +} + +void +dict_dump (dict_t *this) +{ + int ret = 0; + int dumplen = 0; + data_pair_t *trav = NULL; + char dump[64*1024]; /* This is debug only, hence + performance should not matter */ + + if (!this) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "dict NULL"); + goto out; + } + + dump[0] = '\0'; /* the array is not initialized to '\0' */ + + /* There is a possibility of issues if data is binary, ignore it + for now as debugging is more important */ + for (trav = this->members_list; trav; trav = trav->next) { + ret = snprintf (&dump[dumplen], ((64*1024) - dumplen - 1), + "(%s:%s)", trav->key, trav->value->data); + if ((ret == -1) || !ret) + break; + + dumplen += ret; + /* snprintf doesn't append a trailing '\0', add it here */ + dump[dumplen] = '\0'; + } + + if (dumplen) + gf_log_callingfn ("dict", GF_LOG_INFO, + "dict=%p (%s)", this, dump); + +out: + return; } diff --git a/libglusterfs/src/dict.h b/libglusterfs/src/dict.h index e2d87166a..9b41b5a7d 100644 --- a/libglusterfs/src/dict.h +++ b/libglusterfs/src/dict.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _DICT_H @@ -35,60 +26,102 @@ typedef struct _data data_t; typedef struct _dict dict_t; typedef struct _data_pair data_pair_t; + +#define GF_PROTOCOL_DICT_SERIALIZE(this,from_dict,to,len,ope,labl) do { \ + int ret = 0; \ + \ + if (!from_dict) \ + break; \ + \ + ret = dict_allocate_and_serialize (from_dict, to, &len);\ + if (ret < 0) { \ + gf_log (this->name, GF_LOG_WARNING, \ + "failed to get serialized dict (%s)", \ + (#from_dict)); \ + ope = EINVAL; \ + goto labl; \ + } \ + } while (0) + + +#define GF_PROTOCOL_DICT_UNSERIALIZE(xl,to,buff,len,ret,ope,labl) do { \ + if (!len) \ + break; \ + to = dict_new(); \ + GF_VALIDATE_OR_GOTO (xl->name, to, labl); \ + \ + ret = dict_unserialize (buff, len, &to); \ + if (ret < 0) { \ + gf_log (xl->name, GF_LOG_WARNING, \ + "failed to unserialize dictionary (%s)", \ + (#to)); \ + \ + ope = EINVAL; \ + goto labl; \ + } \ + \ + } while (0) + 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; + unsigned char is_static:1; + unsigned char is_const:1; + unsigned char is_stdalloc:1; + int32_t len; + 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 _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; + 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; + char *extra_stdfree; + gf_lock_t lock; + data_pair_t *members_internal; + data_pair_t free_pair; + gf_boolean_t free_pair_in_use; }; int32_t is_data_equal (data_t *one, data_t *two); void data_destroy (data_t *data); +/* function to set a key/value pair (overwrite existing if matches the key */ int32_t dict_set (dict_t *this, char *key, data_t *value); +/* function to set a new key/value pair (without checking for duplicate) */ +int32_t dict_add (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); +int dict_reset (dict_t *dict); 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_allocate_and_serialize (dict_t *this, char **buf, size_t *length); +int32_t dict_allocate_and_serialize (dict_t *this, char **buf, u_int *length); -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); -/* +int32_t dict_lookup (dict_t *this, char *key, data_t **data); +/* TODO: provide converts for differnt byte sizes, signedness, and void * */ data_t *int_to_data (int64_t value); @@ -107,6 +140,7 @@ 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); +uint8_t data_to_uint8 (data_t *data); data_t *data_from_ptr (void *value); data_t *data_from_static_ptr (void *value); @@ -125,25 +159,36 @@ void *data_to_bin (data_t *data); void *data_to_ptr (data_t *data); data_t *get_new_data (); +data_t * data_copy (data_t *old); dict_t *get_new_dict_full (int size_hint); dict_t *get_new_dict (); -data_pair_t *get_new_data_pair (); +int dict_foreach (dict_t *this, + int (*fn)(dict_t *this, + char *key, + data_t *value, + void *data), + void *data); + +int dict_foreach_fnmatch (dict_t *dict, char *pattern, + int (*fn)(dict_t *this, + char *key, + data_t *value, + void *data), + void *data); -void dict_foreach (dict_t *this, - void (*fn)(dict_t *this, - char *key, - data_t *value, - void *data), - void *data); +int dict_null_foreach_fn (dict_t *d, char *k, + data_t *v, void *tmp); -dict_t *dict_copy (dict_t *this, - dict_t *new); +dict_t *dict_copy (dict_t *this, dict_t *new); +int dict_keys_join (void *value, int size, dict_t *dict, + int (*filter_fn)(char *key)); /* CLEANED UP FUNCTIONS DECLARATIONS */ GF_MUST_CHECK dict_t *dict_new (void); -dict_t *dict_copy_with_ref (dict_t *this, - dict_t *new); +dict_t *dict_copy_with_ref (dict_t *this, dict_t *new); + +GF_MUST_CHECK int dict_reset (dict_t *dict); 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); @@ -171,6 +216,7 @@ GF_MUST_CHECK int dict_set_double (dict_t *this, char *key, double 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_get_ptr_and_len (dict_t *this, char *key, void **ptr, int *len); 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); @@ -179,7 +225,13 @@ 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_dynmstr (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); +GF_MUST_CHECK int dict_get_str_boolean (dict_t *this, char *key, int default_val); +GF_MUST_CHECK int dict_serialize_value_with_delim (dict_t *this, char *buf, int32_t *serz_len, + char delimiter); + +void dict_dump (dict_t *dict); #endif diff --git a/libglusterfs/src/event-epoll.c b/libglusterfs/src/event-epoll.c new file mode 100644 index 000000000..06b323624 --- /dev/null +++ b/libglusterfs/src/event-epoll.c @@ -0,0 +1,463 @@ +/* + Copyright (c) 2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#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" +#include "common-utils.h" + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + + +#ifdef HAVE_SYS_EPOLL_H +#include <sys/epoll.h> + + +static int +__event_getindex (struct event_pool *event_pool, int fd, int idx) +{ + int ret = -1; + int i = 0; + + GF_VALIDATE_OR_GOTO ("event", event_pool, out); + + 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; + } + } + +out: + return ret; +} + + +static struct event_pool * +event_pool_new_epoll (int count) +{ + struct event_pool *event_pool = NULL; + int epfd = -1; + + event_pool = GF_CALLOC (1, sizeof (*event_pool), + gf_common_mt_event_pool); + + if (!event_pool) + goto out; + + event_pool->count = count; + event_pool->reg = GF_CALLOC (event_pool->count, + sizeof (*event_pool->reg), + gf_common_mt_reg); + + if (!event_pool->reg) { + GF_FREE (event_pool); + event_pool = NULL; + goto out; + } + + epfd = epoll_create (count); + + if (epfd == -1) { + gf_log ("epoll", GF_LOG_ERROR, "epoll fd creation failed (%s)", + strerror (errno)); + GF_FREE (event_pool->reg); + GF_FREE (event_pool); + event_pool = NULL; + goto out; + } + + event_pool->fd = epfd; + + event_pool->count = count; + + pthread_mutex_init (&event_pool->mutex, NULL); + pthread_cond_init (&event_pool->cond, NULL); + +out: + 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; + + + GF_VALIDATE_OR_GOTO ("event", event_pool, out); + + pthread_mutex_lock (&event_pool->mutex); + { + if (event_pool->count == event_pool->used) { + event_pool->count *= 2; + + event_pool->reg = GF_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_out); + 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); + +out: + 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; + + GF_VALIDATE_OR_GOTO ("event", event_pool, out); + + 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); + +out: + 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; + + + GF_VALIDATE_OR_GOTO ("event", event_pool, out); + + 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_out); + 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); + +out: + 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; + + 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; + + GF_VALIDATE_OR_GOTO ("event", event_pool, out); + + 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) { + GF_FREE (event_pool->evcache); + + event_pool->evcache = events = NULL; + + event_pool->evcache_size = + event_pool->used + 256; + + events = GF_CALLOC (event_pool->evcache_size, + sizeof (struct epoll_event), + gf_common_mt_epoll_event); + if (!events) + break; + + 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 || !events[i].events) + continue; + + ret = event_dispatch_epoll_handler (event_pool, + events, i); + } + } + +out: + return ret; +} + + +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 diff --git a/libglusterfs/src/event-history.c b/libglusterfs/src/event-history.c new file mode 100644 index 000000000..82baa521a --- /dev/null +++ b/libglusterfs/src/event-history.c @@ -0,0 +1,83 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include "event-history.h" + +eh_t * +eh_new (size_t buffer_size, gf_boolean_t use_buffer_once, + void (*destroy_buffer_data) (void *data)) +{ + eh_t *history = NULL; + buffer_t *buffer = NULL; + + history = GF_CALLOC (1, sizeof (eh_t), gf_common_mt_eh_t); + if (!history) { + gf_log ("", GF_LOG_ERROR, "allocating history failed."); + goto out; + } + + buffer = cb_buffer_new (buffer_size, use_buffer_once, + destroy_buffer_data); + if (!buffer) { + gf_log ("", GF_LOG_ERROR, "allocating circular buffer failed"); + GF_FREE (history); + history = NULL; + } + + history->buffer = buffer; + + pthread_mutex_init (&history->lock, NULL); +out: + return history; +} + +void +eh_dump (eh_t *history, void *data, + int (dump_fn) (circular_buffer_t *buffer, void *data)) +{ + if (!history) { + gf_log ("", GF_LOG_DEBUG, "history is NULL"); + goto out; + } + + cb_buffer_dump (history->buffer, data, dump_fn); + +out: + return; +} + +int +eh_save_history (eh_t *history, void *data) +{ + int ret = -1; + + ret = cb_add_entry_buffer (history->buffer, data); + + return ret; +} + +int +eh_destroy (eh_t *history) +{ + if (!history) { + gf_log ("", GF_LOG_INFO, "history for the xlator is " + "NULL"); + return -1; + } + + cb_buffer_destroy (history->buffer); + history->buffer = NULL; + + pthread_mutex_destroy (&history->lock); + + GF_FREE (history); + + return 0; +} diff --git a/libglusterfs/src/event-history.h b/libglusterfs/src/event-history.h new file mode 100644 index 000000000..b64f63b5e --- /dev/null +++ b/libglusterfs/src/event-history.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _EH_H +#define _EH_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "mem-types.h" +#include "circ-buff.h" + +struct event_hist +{ + buffer_t *buffer; + pthread_mutex_t lock; +}; + +typedef struct event_hist eh_t; + +void +eh_dump (eh_t *event , void *data, + int (fn) (circular_buffer_t *buffer, void *data)); + +eh_t * +eh_new (size_t buffer_size, gf_boolean_t use_buffer_once, + void (*destroy_data) (void *data)); + +int +eh_save_history (eh_t *history, void *string); + +int +eh_destroy (eh_t *history); + +#endif /* _EH_H */ diff --git a/libglusterfs/src/event-poll.c b/libglusterfs/src/event-poll.c new file mode 100644 index 000000000..7f7f560d0 --- /dev/null +++ b/libglusterfs/src/event-poll.c @@ -0,0 +1,451 @@ +/* + Copyright (c) 2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#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" +#include "common-utils.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; + + GF_VALIDATE_OR_GOTO ("event", event_pool, out); + + 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; + } + } + +out: + return ret; +} + + +static struct event_pool * +event_pool_new_poll (int count) +{ + struct event_pool *event_pool = NULL; + int ret = -1; + + event_pool = GF_CALLOC (1, sizeof (*event_pool), + gf_common_mt_event_pool); + + if (!event_pool) + return NULL; + + event_pool->count = count; + event_pool->reg = GF_CALLOC (event_pool->count, + sizeof (*event_pool->reg), + gf_common_mt_reg); + + if (!event_pool->reg) { + GF_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)); + GF_FREE (event_pool->reg); + GF_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; + + GF_FREE (event_pool->reg); + GF_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; + + GF_FREE (event_pool->reg); + GF_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; + + GF_FREE (event_pool->reg); + GF_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; + + GF_VALIDATE_OR_GOTO ("event", event_pool, out); + + pthread_mutex_lock (&event_pool->mutex); + { + if (event_pool->count == event_pool->used) + { + event_pool->count += 256; + + event_pool->reg = GF_REALLOC (event_pool->reg, + event_pool->count * + sizeof (*event_pool->reg)); + if (!event_pool->reg) + goto unlock; + } + + 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_out); + break; + } + + event_pool->changed = 1; + + } +unlock: + pthread_mutex_unlock (&event_pool->mutex); + +out: + return idx; +} + + +static int +event_unregister_poll (struct event_pool *event_pool, int fd, int idx_hint) +{ + int idx = -1; + + GF_VALIDATE_OR_GOTO ("event", event_pool, out); + + 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); + +out: + 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; + + GF_VALIDATE_OR_GOTO ("event", event_pool, out); + + 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); + +out: + 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; + + 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) { + GF_FREE (event_pool->evcache); + + event_pool->evcache = ufds = NULL; + + event_pool->evcache_size = event_pool->used; + + ufds = GF_CALLOC (sizeof (struct pollfd), + event_pool->evcache_size, + gf_common_mt_pollfd); + if (!ufds) + goto unlock; + 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; + + GF_VALIDATE_OR_GOTO ("event", event_pool, out); + + 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); + } + } + +out: + return -1; +} + + +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 +}; diff --git a/libglusterfs/src/event.c b/libglusterfs/src/event.c index e53002e5a..0197e7948 100644 --- a/libglusterfs/src/event.c +++ b/libglusterfs/src/event.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2009 Z RESEARCH, Inc. <http://www.zresearch.com> - This file is part of GlusterFS. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include <sys/poll.h> @@ -28,951 +19,99 @@ #include "logging.h" #include "event.h" #include "mem-pool.h" - +#include "common-utils.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_out); - 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_out); - 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_out); - 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; + struct event_pool *event_pool = NULL; + extern struct event_ops event_ops_poll; #ifdef HAVE_SYS_EPOLL_H - event_pool = event_ops_epoll.new (count); + extern struct event_ops event_ops_epoll; + + 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"); - } + if (event_pool) { + event_pool->ops = &event_ops_epoll; + } else { + gf_log ("event", GF_LOG_WARNING, + "falling back to poll based event handling"); + } #endif - if (!event_pool) { - event_pool = event_ops_poll.new (count); + if (!event_pool) { + event_pool = event_ops_poll.new (count); - if (event_pool) - event_pool->ops = &event_ops_poll; - } + if (event_pool) + event_pool->ops = &event_ops_poll; + } - return event_pool; + 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) + event_handler_t handler, + void *data, int poll_in, int poll_out) { - int ret = -1; + int ret = -1; + + GF_VALIDATE_OR_GOTO ("event", event_pool, out); - 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; + ret = event_pool->ops->event_register (event_pool, fd, handler, data, + poll_in, poll_out); +out: + return ret; } int event_unregister (struct event_pool *event_pool, int fd, int idx) { - int ret = -1; + 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); + GF_VALIDATE_OR_GOTO ("event", event_pool, out); - return ret; + ret = event_pool->ops->event_unregister (event_pool, fd, idx); + +out: + return ret; } int event_select_on (struct event_pool *event_pool, int fd, int idx_hint, - int poll_in, int poll_out) + int poll_in, int poll_out) { - int ret = -1; + int ret = -1; + + GF_VALIDATE_OR_GOTO ("event", event_pool, out); - 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; + ret = event_pool->ops->event_select_on (event_pool, fd, idx_hint, + poll_in, poll_out); +out: + return ret; } int event_dispatch (struct event_pool *event_pool) { - int ret = -1; + int ret = -1; + + GF_VALIDATE_OR_GOTO ("event", event_pool, out); - if (event_pool == NULL) { - gf_log ("event", GF_LOG_ERROR, "invalid argument"); - return -1; - } - - ret = event_pool->ops->event_dispatch (event_pool); + ret = event_pool->ops->event_dispatch (event_pool); - return ret; +out: + return ret; } diff --git a/libglusterfs/src/event.h b/libglusterfs/src/event.h index 19565e5ed..7ed182492 100644 --- a/libglusterfs/src/event.h +++ b/libglusterfs/src/event.h @@ -1,20 +1,11 @@ /* - Copyright (c) 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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _EVENT_H_ @@ -30,52 +21,51 @@ struct event_pool; struct event_ops; struct event_data { - int fd; - int idx; -} __attribute__ ((__packed__)); + int fd; + int idx; +} __attribute__ ((__packed__, __may_alias__)); 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; + struct event_ops *ops; - int fd; - int breaker[2]; + int fd; + int breaker[2]; - int count; - struct { - int fd; - int events; - void *data; - event_handler_t handler; - } *reg; + int count; + struct { + int fd; + int events; + void *data; + event_handler_t handler; + } *reg; - int used; - int idx_cache; - int changed; + int used; + int changed; - pthread_mutex_t mutex; - pthread_cond_t cond; + pthread_mutex_t mutex; + pthread_cond_t cond; - void *evcache; - int evcache_size; + void *evcache; + int evcache_size; }; struct event_ops { - struct event_pool * (*new) (int count); + 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_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_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_unregister) (struct event_pool *event_pool, int fd, int idx); - int (*event_dispatch) (struct event_pool *event_pool); + int (*event_dispatch) (struct event_pool *event_pool); }; struct event_pool * event_pool_new (int count); diff --git a/libglusterfs/src/fd-lk.c b/libglusterfs/src/fd-lk.c new file mode 100644 index 000000000..caf2bb38e --- /dev/null +++ b/libglusterfs/src/fd-lk.c @@ -0,0 +1,490 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include "fd-lk.h" +#include "common-utils.h" + + +int32_t +_fd_lk_delete_lock (fd_lk_ctx_node_t *lock) +{ + int32_t ret = -1; + + GF_VALIDATE_OR_GOTO ("fd-lk", lock, out); + + list_del_init (&lock->next); + + ret = 0; +out: + return ret; +} + +int32_t +_fd_lk_destroy_lock (fd_lk_ctx_node_t *lock) +{ + int32_t ret = -1; + + GF_VALIDATE_OR_GOTO ("fd-lk", lock, out); + + GF_FREE (lock); + + ret = 0; +out: + return ret; +} + +int +_fd_lk_destroy_lock_list (fd_lk_ctx_t *lk_ctx) +{ + int ret = -1; + fd_lk_ctx_node_t *lk = NULL; + fd_lk_ctx_node_t *tmp = NULL; + + GF_VALIDATE_OR_GOTO ("fd-lk", lk_ctx, out); + + list_for_each_entry_safe (lk, tmp, &lk_ctx->lk_list, next) { + _fd_lk_delete_lock (lk); + _fd_lk_destroy_lock (lk); + } + ret = 0; +out: + return ret; +} + +int +fd_lk_ctx_unref (fd_lk_ctx_t *lk_ctx) +{ + int ref = -1; + + GF_VALIDATE_OR_GOTO ("fd-lk", lk_ctx, err); + + LOCK (&lk_ctx->lock); + { + ref = --lk_ctx->ref; + if (ref < 0) + GF_ASSERT (!ref); + if (ref == 0) + _fd_lk_destroy_lock_list (lk_ctx); + } + UNLOCK (&lk_ctx->lock); + + if (ref == 0) { + LOCK_DESTROY (&lk_ctx->lock); + GF_FREE (lk_ctx); + } + + return 0; +err: + return -1; +} + +fd_lk_ctx_t * +_fd_lk_ctx_ref (fd_lk_ctx_t *lk_ctx) +{ + if (!lk_ctx) { + gf_log_callingfn ("fd", GF_LOG_WARNING, + "invalid argument"); + return NULL; + } + + ++lk_ctx->ref; + + return lk_ctx; +} + +fd_lk_ctx_t * +fd_lk_ctx_ref (fd_lk_ctx_t *lk_ctx) +{ + fd_lk_ctx_t *new_lk_ctx = NULL; + + if (!lk_ctx) { + gf_log_callingfn ("fd", GF_LOG_WARNING, + "invalid argument"); + return NULL; + } + + LOCK (&lk_ctx->lock); + { + new_lk_ctx = _fd_lk_ctx_ref (lk_ctx); + } + UNLOCK (&lk_ctx->lock); + + return new_lk_ctx; +} + +fd_lk_ctx_t * +fd_lk_ctx_try_ref (fd_lk_ctx_t *lk_ctx) +{ + int ret = -1; + fd_lk_ctx_t *new_lk_ctx = NULL; + + if (!lk_ctx) { + goto out; + } + + ret = TRY_LOCK (&lk_ctx->lock); + if (ret) + goto out; + + new_lk_ctx = _fd_lk_ctx_ref (lk_ctx); + UNLOCK (&lk_ctx->lock); + +out: + return new_lk_ctx; +} + +fd_lk_ctx_t * +fd_lk_ctx_create () +{ + fd_lk_ctx_t *fd_lk_ctx = NULL; + + fd_lk_ctx = GF_CALLOC (1, sizeof (fd_lk_ctx_t), + gf_common_mt_fd_lk_ctx_t); + if (!fd_lk_ctx) + goto out; + + INIT_LIST_HEAD (&fd_lk_ctx->lk_list); + + LOCK_INIT (&fd_lk_ctx->lock); + + fd_lk_ctx = fd_lk_ctx_ref (fd_lk_ctx); +out: + return fd_lk_ctx; +} + +int +_fd_lk_insert_lock (fd_lk_ctx_t *lk_ctx, + fd_lk_ctx_node_t *lock) +{ + list_add_tail (&lock->next, &lk_ctx->lk_list); + return 0; +} + +static off_t +_fd_lk_get_lock_len (off_t start, off_t end) +{ + if (end == LLONG_MAX) + return 0; + else + return (end - start + 1); +} + +fd_lk_ctx_node_t * +fd_lk_ctx_node_new (int32_t cmd, struct gf_flock *flock) +{ + fd_lk_ctx_node_t *new_lock = NULL; + + /* TODO: get from mem-pool */ + new_lock = GF_CALLOC (1, sizeof (fd_lk_ctx_node_t), + gf_common_mt_fd_lk_ctx_node_t); + if (!new_lock) + goto out; + + new_lock->cmd = cmd; + + if (flock) { + new_lock->fl_type = flock->l_type; + new_lock->fl_start = flock->l_start; + + if (flock->l_len == 0) + new_lock->fl_end = LLONG_MAX; + else + new_lock->fl_end = flock->l_start + flock->l_len - 1; + + memcpy (&new_lock->user_flock, flock, + sizeof (struct gf_flock)); + } + + INIT_LIST_HEAD (&new_lock->next); +out: + return new_lock; +} + +int32_t +_fd_lk_delete_unlck_locks (fd_lk_ctx_t *lk_ctx) +{ + int32_t ret = -1; + fd_lk_ctx_node_t *tmp = NULL; + fd_lk_ctx_node_t *lk = NULL; + + GF_VALIDATE_OR_GOTO ("fd-lk", lk_ctx, out); + + list_for_each_entry_safe (lk, tmp, &lk_ctx->lk_list, next) { + if (lk->fl_type == F_UNLCK) { + _fd_lk_delete_lock (lk); + _fd_lk_destroy_lock (lk); + } + } +out: + return ret; +} + +int +fd_lk_overlap (fd_lk_ctx_node_t *l1, + fd_lk_ctx_node_t *l2) +{ + if (l1->fl_end >= l2->fl_start && + l2->fl_end >= l1->fl_start) + return 1; + + return 0; +} + +fd_lk_ctx_node_t * +_fd_lk_add_locks (fd_lk_ctx_node_t *l1, + fd_lk_ctx_node_t *l2) +{ + fd_lk_ctx_node_t *sum = NULL; + + sum = fd_lk_ctx_node_new (0, NULL); + if (!sum) + goto out; + + sum->fl_start = min (l1->fl_start, l2->fl_start); + sum->fl_end = max (l1->fl_end, l2->fl_end); + + sum->user_flock.l_start = sum->fl_start; + sum->user_flock.l_len = _fd_lk_get_lock_len (sum->fl_start, + sum->fl_end); +out: + return sum; +} + +/* Subtract two locks */ +struct _values { + fd_lk_ctx_node_t *locks[3]; +}; + +int32_t +_fd_lk_sub_locks (struct _values *v, + fd_lk_ctx_node_t *big, + fd_lk_ctx_node_t *small) +{ + int32_t ret = -1; + + if ((big->fl_start == small->fl_start) && + (big->fl_end == small->fl_end)) { + /* both edges coincide with big */ + v->locks[0] = fd_lk_ctx_node_new (small->cmd, NULL); + if (!v->locks[0]) + goto out; + + memcpy (v->locks[0], big, sizeof (fd_lk_ctx_node_t)); + + v->locks[0]->fl_type = small->fl_type; + v->locks[0]->user_flock.l_type = small->fl_type; + } else if ((small->fl_start > big->fl_start) && + (small->fl_end < big->fl_end)) { + /* small lock is completely inside big lock, + break it down into 3 different locks. */ + v->locks[0] = fd_lk_ctx_node_new (big->cmd, NULL); + if (!v->locks[0]) + goto out; + + v->locks[1] = fd_lk_ctx_node_new (small->cmd, NULL); + if (!v->locks[1]) + goto out; + + v->locks[2] = fd_lk_ctx_node_new (big->cmd, NULL); + if (!v->locks[2]) + goto out; + + memcpy (v->locks[0], big, sizeof (fd_lk_ctx_node_t)); + v->locks[0]->fl_end = small->fl_start - 1; + v->locks[0]->user_flock.l_len = + _fd_lk_get_lock_len (v->locks[0]->fl_start, + v->locks[0]->fl_end); + + memcpy (v->locks[1], small, sizeof (fd_lk_ctx_node_t)); + + memcpy (v->locks[2], big, sizeof (fd_lk_ctx_node_t)); + v->locks[2]->fl_start = small->fl_end + 1; + v->locks[2]->user_flock.l_len = + _fd_lk_get_lock_len (v->locks[2]->fl_start, + v->locks[2]->fl_end); + } else if (small->fl_start == big->fl_start) { + /* One of the ends co-incide, break the + locks into two seperate parts */ + v->locks[0] = fd_lk_ctx_node_new (small->cmd, NULL); + if (!v->locks[0]) + goto out; + + v->locks[1] = fd_lk_ctx_node_new (big->cmd, NULL); + if (!v->locks[1]) + goto out; + + memcpy (v->locks[0], small, sizeof (fd_lk_ctx_node_t)); + + memcpy (v->locks[1], big, sizeof (fd_lk_ctx_node_t)); + v->locks[1]->fl_start = small->fl_end + 1; + v->locks[1]->user_flock.l_start = small->fl_end + 1; + } else if (small->fl_end == big->fl_end) { + /* One of the ends co-incide, break the + locks into two seperate parts */ + v->locks[0] = fd_lk_ctx_node_new (small->cmd, NULL); + if (!v->locks[0]) + goto out; + + v->locks[1] = fd_lk_ctx_node_new (big->cmd, NULL); + if (!v->locks[1]) + goto out; + + memcpy (v->locks[0], big, sizeof (fd_lk_ctx_node_t)); + v->locks[0]->fl_end = small->fl_start - 1; + v->locks[0]->user_flock.l_len = + _fd_lk_get_lock_len (v->locks[0]->fl_start, + v->locks[0]->fl_end); + + memcpy (v->locks[1], small, sizeof (fd_lk_ctx_node_t)); + } else { + /* We should never come to this case */ + GF_ASSERT (!"Invalid case"); + } + ret = 0; +out: + return ret; +} + +static void +_fd_lk_insert_and_merge (fd_lk_ctx_t *lk_ctx, + fd_lk_ctx_node_t *lock) +{ + int32_t ret = -1; + int32_t i = 0; + fd_lk_ctx_node_t *entry = NULL; + fd_lk_ctx_node_t *t = NULL; + fd_lk_ctx_node_t *sum = NULL; + struct _values v = {.locks = {0, 0, 0 }}; + + list_for_each_entry_safe (entry, t, &lk_ctx->lk_list, next) { + if (!fd_lk_overlap (entry, lock)) + continue; + + if (entry->fl_type == lock->fl_type) { + sum = _fd_lk_add_locks (entry, lock); + if (!sum) + return; + sum->fl_type = entry->fl_type; + sum->user_flock.l_type = entry->fl_type; + _fd_lk_delete_lock (entry); + _fd_lk_destroy_lock (entry); + _fd_lk_destroy_lock (lock); + _fd_lk_insert_and_merge (lk_ctx, sum); + return; + } else { + sum = _fd_lk_add_locks (entry, lock); + sum->fl_type = lock->fl_type; + sum->user_flock.l_type = lock->fl_type; + ret = _fd_lk_sub_locks (&v, sum, lock); + if (ret) + return; + _fd_lk_delete_lock (entry); + _fd_lk_destroy_lock (entry); + + _fd_lk_delete_lock (lock); + _fd_lk_destroy_lock (lock); + + _fd_lk_destroy_lock (sum); + + for (i = 0; i < 3; i++) { + if (!v.locks[i]) + continue; + + INIT_LIST_HEAD (&v.locks[i]->next); + _fd_lk_insert_and_merge (lk_ctx, v.locks[i]); + } + _fd_lk_delete_unlck_locks (lk_ctx); + return; + } + } + + /* no conflicts, so just insert */ + if (lock->fl_type != F_UNLCK) { + _fd_lk_insert_lock (lk_ctx, lock); + } else { + _fd_lk_destroy_lock (lock); + } +} + +static void +print_lock_list (fd_lk_ctx_t *lk_ctx) +{ + fd_lk_ctx_node_t *lk = NULL; + + gf_log ("fd-lk", GF_LOG_DEBUG, "lock list:"); + + list_for_each_entry (lk, &lk_ctx->lk_list, next) + gf_log ("fd-lk", GF_LOG_DEBUG, "owner = %s, " + "cmd = %s fl_type = %s, fs_start = %"PRId64", " + "fs_end = %"PRId64", user_flock: l_type = %s, " + "l_start = %"PRId64", l_len = %"PRId64", ", + lkowner_utoa (&lk->user_flock.l_owner), + get_lk_cmd (lk->cmd), get_lk_type (lk->fl_type), + lk->fl_start, lk->fl_end, + get_lk_type (lk->user_flock.l_type), + lk->user_flock.l_start, + lk->user_flock.l_len); +} + +int +fd_lk_insert_and_merge (fd_t *fd, int32_t cmd, + struct gf_flock *flock) +{ + int32_t ret = -1; + fd_lk_ctx_t *lk_ctx = NULL; + fd_lk_ctx_node_t *lk = NULL; + + GF_VALIDATE_OR_GOTO ("fd-lk", fd, out); + GF_VALIDATE_OR_GOTO ("fd-lk", flock, out); + + lk_ctx = fd_lk_ctx_ref (fd->lk_ctx); + lk = fd_lk_ctx_node_new (cmd, flock); + + gf_log ("fd-lk", GF_LOG_DEBUG, + "new lock requrest: owner = %s, fl_type = %s, " + "fs_start = %"PRId64", fs_end = %"PRId64", " + "user_flock: l_type = %s, l_start = %"PRId64", " + "l_len = %"PRId64, lkowner_utoa (&flock->l_owner), + get_lk_type (lk->fl_type), lk->fl_start, + lk->fl_end, get_lk_type (lk->user_flock.l_type), + lk->user_flock.l_start, + lk->user_flock.l_len); + + LOCK (&lk_ctx->lock); + { + _fd_lk_insert_and_merge (lk_ctx, lk); + print_lock_list (lk_ctx); + } + UNLOCK (&lk_ctx->lock); + + fd_lk_ctx_unref (lk_ctx); + + ret = 0; +out: + return ret; +} + + +gf_boolean_t +fd_lk_ctx_empty (fd_lk_ctx_t *lk_ctx) +{ + gf_boolean_t verdict = _gf_true; + + if (!lk_ctx) + return _gf_true; + + LOCK (&lk_ctx->lock); + { + verdict = list_empty (&lk_ctx->lk_list); + } + UNLOCK (&lk_ctx->lock); + + return verdict; +} diff --git a/libglusterfs/src/fd-lk.h b/libglusterfs/src/fd-lk.h new file mode 100644 index 000000000..1d2ff794c --- /dev/null +++ b/libglusterfs/src/fd-lk.h @@ -0,0 +1,70 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _FD_LK_H +#define _FD_LK_H + +#include "fd.h" +#include "locking.h" +#include "list.h" +#include "logging.h" +#include "mem-pool.h" +#include "mem-types.h" +#include "glusterfs.h" +#include "common-utils.h" + +#define get_lk_type(type) \ + type == F_UNLCK ? "F_UNLCK" : (type == F_RDLCK ? "F_RDLCK" : "F_WRLCK") + +#define get_lk_cmd(cmd) \ + cmd == F_SETLKW ? "F_SETLKW" : (cmd == F_SETLK ? "F_SETLK" : "F_GETLK") + +struct _fd; + +struct fd_lk_ctx { + struct list_head lk_list; + int ref; + gf_lock_t lock; +}; +typedef struct fd_lk_ctx fd_lk_ctx_t; + +struct fd_lk_ctx_node { + int32_t cmd; + struct gf_flock user_flock; + off_t fl_start; + off_t fl_end; + short fl_type; + struct list_head next; +}; +typedef struct fd_lk_ctx_node fd_lk_ctx_node_t; + +fd_lk_ctx_t * +_fd_lk_ctx_ref (fd_lk_ctx_t *lk_ctx); + +fd_lk_ctx_t * +fd_lk_ctx_ref (fd_lk_ctx_t *lk_ctx); + +fd_lk_ctx_t * +fd_lk_ctx_try_ref (fd_lk_ctx_t *lk_ctx); + +fd_lk_ctx_t * +fd_lk_ctx_create (); + +int +fd_lk_insert_and_merge (struct _fd *lk_ctx, int32_t cmd, + struct gf_flock *flock); + +int +fd_lk_ctx_unref (fd_lk_ctx_t *lk_ctx); + +gf_boolean_t +fd_lk_ctx_empty (fd_lk_ctx_t *lk_ctx); + +#endif /* _FD_LK_H */ diff --git a/libglusterfs/src/fd.c b/libglusterfs/src/fd.c index 5b2d32bff..36cc4d056 100644 --- a/libglusterfs/src/fd.c +++ b/libglusterfs/src/fd.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include "fd.h" @@ -30,33 +21,12 @@ #endif -static uint32_t +static int 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 = 1; - - if (nr < 0) { - gf_log ("server-protocol/fd", - GF_LOG_ERROR, - "Negative number passed"); - return -1; - } - - while (result <= nr) - result *= 2; - return result; -} +fd_t * +__fd_ref (fd_t *fd); static int gf_fd_chain_fd_entries (fdentry_t *entries, uint32_t startidx, @@ -64,8 +34,10 @@ gf_fd_chain_fd_entries (fdentry_t *entries, uint32_t startidx, { uint32_t i = 0; - if (!entries) + if (!entries) { + gf_log_callingfn ("fd", GF_LOG_WARNING, "!entries"); return -1; + } /* Chain only till the second to last entry because we want to * ensure that the last entry has GF_FDTABLE_END. @@ -80,33 +52,38 @@ gf_fd_chain_fd_entries (fdentry_t *entries, uint32_t startidx, } -static uint32_t +static int gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr) { - fdentry_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 (fdentry_t)); - nr = gf_roundup_power_of_two (nr + 1); - nr *= (1024 / sizeof (fdentry_t)); - - oldfds = fdtable->fdentries; - oldmax_fds = fdtable->max_fds; - - fdtable->fdentries = CALLOC (nr, sizeof (fdentry_t)); - ERR_ABORT (fdtable->fdentries); - fdtable->max_fds = nr; - - if (oldfds) { - uint32_t cpy = oldmax_fds * sizeof (fdentry_t); - memcpy (fdtable->fdentries, oldfds, cpy); - } + fdentry_t *oldfds = NULL; + uint32_t oldmax_fds = -1; + int ret = -1; + + if (fdtable == NULL || nr < 0) { + gf_log_callingfn ("fd", GF_LOG_ERROR, "invalid argument"); + ret = EINVAL; + goto out; + } + + nr /= (1024 / sizeof (fdentry_t)); + nr = gf_roundup_next_power_of_two (nr + 1); + nr *= (1024 / sizeof (fdentry_t)); + + oldfds = fdtable->fdentries; + oldmax_fds = fdtable->max_fds; + + fdtable->fdentries = GF_CALLOC (nr, sizeof (fdentry_t), + gf_common_mt_fdentry_t); + if (!fdtable->fdentries) { + ret = ENOMEM; + goto out; + } + fdtable->max_fds = nr; + + if (oldfds) { + uint32_t cpy = oldmax_fds * sizeof (fdentry_t); + memcpy (fdtable->fdentries, oldfds, cpy); + } gf_fd_chain_fd_entries (fdtable->fdentries, oldmax_fds, fdtable->max_fds); @@ -116,41 +93,47 @@ gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr) * using the expanded table. */ fdtable->first_free = oldmax_fds; - FREE (oldfds); - return 0; + GF_FREE (oldfds); + ret = 0; +out: + return ret; } + fdtable_t * -gf_fd_fdtable_alloc (void) +gf_fd_fdtable_alloc (void) { - fdtable_t *fdtable = NULL; + fdtable_t *fdtable = NULL; - fdtable = CALLOC (1, sizeof (*fdtable)); - if (!fdtable) - return NULL; + fdtable = GF_CALLOC (1, sizeof (*fdtable), gf_common_mt_fdtable_t); + if (!fdtable) + return NULL; - pthread_mutex_init (&fdtable->lock, NULL); + pthread_mutex_init (&fdtable->lock, NULL); - pthread_mutex_lock (&fdtable->lock); - { - gf_fd_fdtable_expand (fdtable, 0); - } - pthread_mutex_unlock (&fdtable->lock); + pthread_mutex_lock (&fdtable->lock); + { + gf_fd_fdtable_expand (fdtable, 0); + } + pthread_mutex_unlock (&fdtable->lock); - return fdtable; + return fdtable; } -fdentry_t * + +static fdentry_t * __gf_fd_fdtable_get_all_fds (fdtable_t *fdtable, uint32_t *count) { fdentry_t *fdentries = NULL; if (count == NULL) { + gf_log_callingfn ("fd", GF_LOG_WARNING, "!count"); goto out; } fdentries = fdtable->fdentries; - fdtable->fdentries = calloc (fdtable->max_fds, sizeof (fdentry_t)); + fdtable->fdentries = GF_CALLOC (fdtable->max_fds, sizeof (fdentry_t), + gf_common_mt_fdentry_t); gf_fd_chain_fd_entries (fdtable->fdentries, 0, fdtable->max_fds); *count = fdtable->max_fds; @@ -158,10 +141,12 @@ out: return fdentries; } + fdentry_t * gf_fd_fdtable_get_all_fds (fdtable_t *fdtable, uint32_t *count) { fdentry_t *entries = NULL; + if (fdtable) { pthread_mutex_lock (&fdtable->lock); { @@ -173,26 +158,76 @@ gf_fd_fdtable_get_all_fds (fdtable_t *fdtable, uint32_t *count) return entries; } -void + +static fdentry_t * +__gf_fd_fdtable_copy_all_fds (fdtable_t *fdtable, uint32_t *count) +{ + fdentry_t *fdentries = NULL; + int i = 0; + + if (count == NULL) { + gf_log_callingfn ("fd", GF_LOG_WARNING, "!count"); + goto out; + } + + fdentries = GF_CALLOC (fdtable->max_fds, sizeof (fdentry_t), + gf_common_mt_fdentry_t); + if (fdentries == NULL) { + goto out; + } + + *count = fdtable->max_fds; + + for (i = 0; i < fdtable->max_fds; i++) { + if (fdtable->fdentries[i].fd != NULL) { + fdentries[i].fd = fd_ref (fdtable->fdentries[i].fd); + } + } + +out: + return fdentries; +} + + +fdentry_t * +gf_fd_fdtable_copy_all_fds (fdtable_t *fdtable, uint32_t *count) +{ + fdentry_t *entries = NULL; + + if (fdtable) { + pthread_mutex_lock (&fdtable->lock); + { + entries = __gf_fd_fdtable_copy_all_fds (fdtable, count); + } + pthread_mutex_unlock (&fdtable->lock); + } + + return entries; +} + + +void gf_fd_fdtable_destroy (fdtable_t *fdtable) { struct list_head list = {0, }; fd_t *fd = NULL; fdentry_t *fdentries = NULL; uint32_t fd_count = 0; - int32_t i = 0; + int32_t i = 0; INIT_LIST_HEAD (&list); - if (!fdtable) + if (!fdtable) { + gf_log_callingfn ("fd", GF_LOG_WARNING, "!fdtable"); return; + } - pthread_mutex_lock (&fdtable->lock); - { + pthread_mutex_lock (&fdtable->lock); + { fdentries = __gf_fd_fdtable_get_all_fds (fdtable, &fd_count); - FREE (fdtable->fdentries); - } - pthread_mutex_unlock (&fdtable->lock); + GF_FREE (fdtable->fdentries); + } + pthread_mutex_unlock (&fdtable->lock); if (fdentries != NULL) { for (i = 0; i < fd_count; i++) { @@ -202,53 +237,53 @@ gf_fd_fdtable_destroy (fdtable_t *fdtable) } } - FREE (fdentries); - pthread_mutex_destroy (&fdtable->lock); - FREE (fdtable); - } + GF_FREE (fdentries); + pthread_mutex_destroy (&fdtable->lock); + GF_FREE (fdtable); + } } -int32_t + +int gf_fd_unused_get (fdtable_t *fdtable, fd_t *fdptr) { - int32_t fd = -1; + int32_t fd = -1; fdentry_t *fde = NULL; - int error; + int error; int alloc_attempts = 0; - - if (fdtable == NULL || fdptr == NULL) - { - gf_log ("fd", GF_LOG_ERROR, "invalid argument"); - return EINVAL; - } - - pthread_mutex_lock (&fdtable->lock); - { -fd_alloc_try_again: + + if (fdtable == NULL || fdptr == NULL) { + gf_log_callingfn ("fd", GF_LOG_ERROR, "invalid argument"); + return EINVAL; + } + + pthread_mutex_lock (&fdtable->lock); + { + fd_alloc_try_again: if (fdtable->first_free != GF_FDTABLE_END) { fde = &fdtable->fdentries[fdtable->first_free]; fd = fdtable->first_free; fdtable->first_free = fde->next_free; fde->next_free = GF_FDENTRY_ALLOCATED; fde->fd = fdptr; - } else { + } else { /* If this is true, there is something * seriously wrong with our data structures. */ if (alloc_attempts >= 2) { - gf_log ("server-protocol.c", GF_LOG_ERROR, - "Multiple attempts to expand fd table" + gf_log ("fd", GF_LOG_ERROR, + "multiple attempts to expand fd table" " have failed."); goto out; } 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)); + if (error) { + gf_log ("fd", GF_LOG_ERROR, + "Cannot expand fdtable: %s", + strerror (error)); goto out; - } + } ++alloc_attempts; /* At this point, the table stands expanded * with the first_free referring to the first @@ -257,41 +292,43 @@ fd_alloc_try_again: * above logic should just work. */ goto fd_alloc_try_again; - } - } + } + } out: - pthread_mutex_unlock (&fdtable->lock); + pthread_mutex_unlock (&fdtable->lock); - return fd; + return fd; } -inline void +inline void gf_fd_put (fdtable_t *fdtable, int32_t fd) { - fd_t *fdptr = NULL; + fd_t *fdptr = NULL; fdentry_t *fde = 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); - { + if (fd == -2) + /* anonymous fd */ + return; + + if (fdtable == NULL || fd < 0) { + gf_log_callingfn ("fd", GF_LOG_ERROR, "invalid argument"); + return; + } + + if (!(fd < fdtable->max_fds)) { + gf_log_callingfn ("fd", GF_LOG_ERROR, "invalid argument"); + return; + } + + pthread_mutex_lock (&fdtable->lock); + { fde = &fdtable->fdentries[fd]; /* If the entry is not allocated, put operation must return * without doing anything. * This has the potential of masking out any bugs in a user of * fd that ends up calling gf_fd_put twice for the same fd or - * for an unallocated fd, but thats a price we have to pay for + * for an unallocated fd, but it is a price we have to pay for * ensuring sanity of our fd-table. */ if (fde->next_free != GF_FDENTRY_ALLOCATED) @@ -300,150 +337,213 @@ gf_fd_put (fdtable_t *fdtable, int32_t fd) fde->fd = NULL; fde->next_free = fdtable->first_free; fdtable->first_free = fd; - } + } +unlock_out: + pthread_mutex_unlock (&fdtable->lock); + + if (fdptr) { + fd_unref (fdptr); + } +} + + +inline void +gf_fdptr_put (fdtable_t *fdtable, fd_t *fd) +{ + fdentry_t *fde = NULL; + int32_t i = 0; + + if ((fdtable == NULL) || (fd == NULL)) { + gf_log_callingfn ("fd", GF_LOG_ERROR, "invalid argument"); + return; + } + + pthread_mutex_lock (&fdtable->lock); + { + for (i = 0; i < fdtable->max_fds; i++) { + if (fdtable->fdentries[i].fd == fd) { + fde = &fdtable->fdentries[i]; + break; + } + } + + if (fde == NULL) { + gf_log_callingfn ("fd", GF_LOG_WARNING, + "fd (%p) is not present in fdtable", fd); + goto unlock_out; + } + + /* If the entry is not allocated, put operation must return + * without doing anything. + * This has the potential of masking out any bugs in a user of + * fd that ends up calling gf_fd_put twice for the same fd or + * for an unallocated fd, but it is a price we have to pay for + * ensuring sanity of our fd-table. + */ + if (fde->next_free != GF_FDENTRY_ALLOCATED) + goto unlock_out; + fde->fd = NULL; + fde->next_free = fdtable->first_free; + fdtable->first_free = i; + } unlock_out: - pthread_mutex_unlock (&fdtable->lock); + pthread_mutex_unlock (&fdtable->lock); - if (fdptr) { - fd_unref (fdptr); - } + if ((fd != NULL) && (fde != NULL)) { + fd_unref (fd); + } } 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->fdentries[fd].fd; - if (fdptr) { - fd_ref (fdptr); - } - } - pthread_mutex_unlock (&fdtable->lock); - - return fdptr; + fd_t *fdptr = NULL; + + if (fdtable == NULL || fd < 0) { + gf_log_callingfn ("fd", GF_LOG_ERROR, "invalid argument"); + errno = EINVAL; + return NULL; + } + + if (!(fd < fdtable->max_fds)) { + gf_log_callingfn ("fd", GF_LOG_ERROR, "invalid argument"); + errno = EINVAL; + return NULL; + } + + pthread_mutex_lock (&fdtable->lock); + { + fdptr = fdtable->fdentries[fd].fd; + if (fdptr) { + fd_ref (fdptr); + } + } + pthread_mutex_unlock (&fdtable->lock); + + return fdptr; } + fd_t * -_fd_ref (fd_t *fd) +__fd_ref (fd_t *fd) { - ++fd->refcount; - - return fd; + ++fd->refcount; + + return fd; } + fd_t * fd_ref (fd_t *fd) { - fd_t *refed_fd = NULL; + fd_t *refed_fd = NULL; - if (!fd) { - gf_log ("fd", GF_LOG_ERROR, "@fd=%p", fd); - return NULL; - } + if (!fd) { + gf_log_callingfn ("fd", GF_LOG_ERROR, "null fd"); + return NULL; + } + + LOCK (&fd->inode->lock); + refed_fd = __fd_ref (fd); + UNLOCK (&fd->inode->lock); - LOCK (&fd->inode->lock); - refed_fd = _fd_ref (fd); - UNLOCK (&fd->inode->lock); - - return refed_fd; + return refed_fd; } + fd_t * -_fd_unref (fd_t *fd) +__fd_unref (fd_t *fd) { - assert (fd->refcount); + GF_ASSERT (fd->refcount); + + --fd->refcount; - --fd->refcount; + if (fd->refcount == 0) { + list_del_init (&fd->inode_list); + } - if (fd->refcount == 0){ - list_del_init (&fd->inode_list); - } - - return fd; + return fd; } + static void fd_destroy (fd_t *fd) { xlator_t *xl = NULL; - int i = 0; + int i = 0; + xlator_t *old_THIS = NULL; if (fd == NULL){ - gf_log ("xlator", GF_LOG_ERROR, "invalid arugument"); + gf_log_callingfn ("xlator", GF_LOG_ERROR, "invalid argument"); goto out; } - + if (fd->inode == NULL){ - gf_log ("xlator", GF_LOG_ERROR, "fd->inode is NULL"); + gf_log_callingfn ("xlator", GF_LOG_ERROR, "fd->inode is NULL"); goto out; } - if (!fd->_ctx) - goto out; - - if (S_ISDIR (fd->inode->st_mode)) { - 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); - } - } + if (!fd->_ctx) + goto out; + + if (IA_ISDIR (fd->inode->ia_type)) { + for (i = 0; i < fd->xl_count; i++) { + if (fd->_ctx[i].key) { + xl = fd->_ctx[i].xl_key; + old_THIS = THIS; + THIS = xl; + if (xl->cbks->releasedir) + xl->cbks->releasedir (xl, fd); + THIS = old_THIS; + } + } } else { - 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); - } - } - } - + for (i = 0; i < fd->xl_count; i++) { + if (fd->_ctx[i].key) { + xl = fd->_ctx[i].xl_key; + old_THIS = THIS; + THIS = xl; + if (xl->cbks->release) + xl->cbks->release (xl, fd); + THIS = old_THIS; + } + } + } + LOCK_DESTROY (&fd->lock); - FREE (fd->_ctx); + GF_FREE (fd->_ctx); + LOCK (&fd->inode->lock); + { + fd->inode->fd_count--; + } + UNLOCK (&fd->inode->lock); inode_unref (fd->inode); fd->inode = (inode_t *)0xaaaaaaaa; - FREE (fd); - + fd_lk_ctx_unref (fd->lk_ctx); + mem_put (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"); + gf_log_callingfn ("fd", GF_LOG_ERROR, "fd is NULL"); return; } - + LOCK (&fd->inode->lock); { - _fd_unref (fd); + __fd_unref (fd); refcount = fd->refcount; } UNLOCK (&fd->inode->lock); - + if (refcount == 0) { fd_destroy (fd); } @@ -451,129 +551,336 @@ fd_unref (fd_t *fd) return ; } + fd_t * -fd_bind (fd_t *fd) +__fd_bind (fd_t *fd) { - inode_t *inode = fd->inode; + list_del_init (&fd->inode_list); + list_add (&fd->inode_list, &fd->inode->fd_list); + fd->inode->fd_count++; - if (!fd) { - gf_log ("fd.c", GF_LOG_ERROR, "fd is NULL"); + return fd; +} + + +fd_t * +fd_bind (fd_t *fd) +{ + if (!fd || !fd->inode) { + gf_log_callingfn ("fd", GF_LOG_ERROR, "!fd || !fd->inode"); return NULL; } - LOCK (&inode->lock); + LOCK (&fd->inode->lock); { - list_add (&fd->inode_list, &inode->fd_list); + fd = __fd_bind (fd); } - UNLOCK (&inode->lock); - + UNLOCK (&fd->inode->lock); + return fd; } -fd_t * -fd_create (inode_t *inode, pid_t pid) + +static fd_t * +__fd_create (inode_t *inode, uint64_t pid) { fd_t *fd = NULL; - + if (inode == NULL) { - gf_log ("fd", GF_LOG_ERROR, "invalid argument"); + gf_log_callingfn ("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 = mem_get0 (inode->table->fd_mem_pool); + if (!fd) + goto out; + + fd->xl_count = inode->table->xl->graph->xl_count + 1; + + fd->_ctx = GF_CALLOC (1, (sizeof (struct _fd_ctx) * fd->xl_count), + gf_common_mt_fd_ctx); + if (!fd->_ctx) + goto free_fd; + + fd->lk_ctx = fd_lk_ctx_create (); + if (!fd->lk_ctx) + goto free_fd_ctx; + fd->inode = inode_ref (inode); fd->pid = pid; INIT_LIST_HEAD (&fd->inode_list); - + LOCK_INIT (&fd->lock); +out: + return fd; + +free_fd_ctx: + GF_FREE (fd->_ctx); +free_fd: + mem_put (fd); + + return NULL; +} + + +fd_t * +fd_create (inode_t *inode, pid_t pid) +{ + fd_t *fd = NULL; + + fd = __fd_create (inode, (uint64_t)pid); + if (!fd) + goto out; + + fd = fd_ref (fd); + +out: + return fd; +} + +fd_t * +fd_create_uint64 (inode_t *inode, uint64_t pid) +{ + fd_t *fd = NULL; + + fd = __fd_create (inode, pid); + if (!fd) + goto out; + + fd = fd_ref (fd); + +out: + return fd; +} + + +static fd_t * +__fd_lookup (inode_t *inode, uint64_t pid) +{ + fd_t *iter_fd = NULL; + fd_t *fd = NULL; + + if (list_empty (&inode->fd_list)) + return NULL; + + + list_for_each_entry (iter_fd, &inode->fd_list, inode_list) { + if (iter_fd->anonymous) + /* If someone was interested in getting an + anonymous fd (or was OK getting an anonymous fd), + they can as well call fd_anonymous() directly */ + continue; + + if (!pid || iter_fd->pid == pid) { + fd = __fd_ref (iter_fd); + break; + } + } + + return fd; +} + + +fd_t * +fd_lookup (inode_t *inode, pid_t pid) +{ + fd_t *fd = NULL; + + if (!inode) { + gf_log_callingfn ("fd", GF_LOG_WARNING, "!inode"); + return NULL; + } LOCK (&inode->lock); - fd = _fd_ref (fd); + { + fd = __fd_lookup (inode, (uint64_t)pid); + } UNLOCK (&inode->lock); return fd; } fd_t * -fd_lookup (inode_t *inode, pid_t pid) +fd_lookup_uint64 (inode_t *inode, uint64_t pid) { fd_t *fd = NULL; - fd_t *iter_fd = NULL; + + if (!inode) { + gf_log_callingfn ("fd", GF_LOG_WARNING, "!inode"); + return 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; - } - } + fd = __fd_lookup (inode, pid); + } + UNLOCK (&inode->lock); + + return fd; +} + +static fd_t * +__fd_lookup_anonymous (inode_t *inode) +{ + fd_t *iter_fd = NULL; + fd_t *fd = NULL; + + if (list_empty (&inode->fd_list)) + return NULL; + + list_for_each_entry (iter_fd, &inode->fd_list, inode_list) { + if (iter_fd->anonymous) { + fd = __fd_ref (iter_fd); + break; } } + + return fd; +} + +static fd_t * +__fd_anonymous (inode_t *inode) +{ + fd_t *fd = NULL; + + fd = __fd_lookup_anonymous (inode); + + /* if (fd); then we already have increased the refcount in + __fd_lookup_anonymous(), so no need of one more fd_ref(). + if (!fd); then both create and bind wont bump up the ref + count, so we have to call fd_ref() after bind. */ + if (!fd) { + fd = __fd_create (inode, 0); + + if (!fd) + return NULL; + + fd->anonymous = _gf_true; + + __fd_bind (fd); + + __fd_ref (fd); + } + + return fd; +} + + +fd_t * +fd_anonymous (inode_t *inode) +{ + fd_t *fd = NULL; + + LOCK (&inode->lock); + { + fd = __fd_anonymous (inode); + } + UNLOCK (&inode->lock); + + return fd; +} + +fd_t* +fd_lookup_anonymous (inode_t *inode) +{ + fd_t *fd = NULL; + + if (!inode) { + gf_log_callingfn ("fd", GF_LOG_WARNING, "!inode"); + return NULL; + } + + LOCK (&inode->lock); + { + fd = __fd_lookup_anonymous (inode); + } UNLOCK (&inode->lock); - return fd; } +gf_boolean_t +fd_is_anonymous (fd_t *fd) +{ + return (fd && fd->anonymous); +} + + uint8_t fd_list_empty (inode_t *inode) { - uint8_t empty = 0; + 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; - int ret = 0; - int set_idx = -1; + int index = 0, new_xl_count = 0; + int ret = 0; + int set_idx = -1; + void *begin = NULL; + size_t diff = 0; + struct _fd_ctx *tmp = NULL; if (!fd || !xlator) return -1; - - for (index = 0; index < xlator->ctx->xl_count; index++) { + + for (index = 0; index < fd->xl_count; index++) { if (!fd->_ctx[index].key) { if (set_idx == -1) set_idx = index; /* dont break, to check if key already exists further on */ } - if (fd->_ctx[index].key == (uint64_t)(long) xlator) { + if (fd->_ctx[index].xl_key == xlator) { set_idx = index; break; } } - + if (set_idx == -1) { - ret = -1; - goto out; + set_idx = fd->xl_count; + + new_xl_count = fd->xl_count + xlator->graph->xl_count; + + tmp = GF_REALLOC (fd->_ctx, + (sizeof (struct _fd_ctx) + * new_xl_count)); + if (tmp == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, + "realloc of fd->_ctx for fd " + "(ptr: %p) failed, cannot set the key" + , fd); + ret = -1; + goto out; + } + + fd->_ctx = tmp; + + begin = fd->_ctx; + begin += (fd->xl_count * sizeof (struct _fd_ctx)); + + diff = (new_xl_count - fd->xl_count ) + * sizeof (struct _fd_ctx); + + memset (begin, 0, diff); + + fd->xl_count = new_xl_count; } - - fd->_ctx[set_idx].key = (uint64_t)(long) xlator; - fd->_ctx[set_idx].value = value; + + fd->_ctx[set_idx].xl_key = xlator; + fd->_ctx[set_idx].value1 = value; out: - return ret; + return ret; } @@ -582,9 +889,11 @@ fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value) { int ret = 0; - if (!fd || !xlator) + if (!fd || !xlator) { + gf_log_callingfn ("", GF_LOG_WARNING, "%p %p", fd, xlator); return -1; - + } + LOCK (&fd->lock); { ret = __fd_ctx_set (fd, xlator, value); @@ -595,40 +904,40 @@ fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value) } -int +int __fd_ctx_get (fd_t *fd, xlator_t *xlator, uint64_t *value) { - int index = 0; + int index = 0; int ret = 0; - if (!fd || !xlator) - return -1; - - for (index = 0; index < xlator->ctx->xl_count; index++) { - if (fd->_ctx[index].key == (uint64_t)(long)xlator) + if (!fd || !xlator) + return -1; + + for (index = 0; index < fd->xl_count; index++) { + if (fd->_ctx[index].xl_key == xlator) break; } - - if (index == xlator->ctx->xl_count) { + + if (index == fd->xl_count) { ret = -1; goto out; } - if (value) - *value = fd->_ctx[index].value; - + if (value) + *value = fd->_ctx[index].value1; + out: - return ret; + return ret; } -int +int fd_ctx_get (fd_t *fd, xlator_t *xlator, uint64_t *value) { int ret = 0; - if (!fd || !xlator) - return -1; + if (!fd || !xlator) + return -1; LOCK (&fd->lock); { @@ -640,44 +949,44 @@ fd_ctx_get (fd_t *fd, xlator_t *xlator, uint64_t *value) } -int +int __fd_ctx_del (fd_t *fd, xlator_t *xlator, uint64_t *value) { - int index = 0; + int index = 0; int ret = 0; - if (!fd || !xlator) - return -1; - - for (index = 0; index < xlator->ctx->xl_count; index++) { - if (fd->_ctx[index].key == (uint64_t)(long)xlator) + if (!fd || !xlator) + return -1; + + for (index = 0; index < fd->xl_count; index++) { + if (fd->_ctx[index].xl_key == xlator) break; } - - if (index == xlator->ctx->xl_count) { + + if (index == fd->xl_count) { ret = -1; goto out; } - - if (value) - *value = fd->_ctx[index].value; - + + if (value) + *value = fd->_ctx[index].value1; + fd->_ctx[index].key = 0; - fd->_ctx[index].value = 0; + fd->_ctx[index].value1 = 0; out: - return ret; + return ret; } -int +int fd_ctx_del (fd_t *fd, xlator_t *xlator, uint64_t *value) { int ret = 0; - if (!fd || !xlator) - return -1; - + if (!fd || !xlator) + return -1; + LOCK (&fd->lock); { ret = __fd_ctx_del (fd, xlator, value); @@ -695,18 +1004,18 @@ fd_dump (fd_t *fd, char *prefix) if (!fd) return; - + memset(key, 0, sizeof(key)); - gf_proc_dump_build_key(key, prefix, "pid"); - gf_proc_dump_write(key, "%d", fd->pid); - gf_proc_dump_build_key(key, prefix, "refcount"); - gf_proc_dump_write(key, "%d", fd->refcount); - gf_proc_dump_build_key(key, prefix, "flags"); - gf_proc_dump_write(key, "%d", fd->flags); + gf_proc_dump_write("pid", "%llu", fd->pid); + gf_proc_dump_write("refcount", "%d", fd->refcount); + gf_proc_dump_write("flags", "%d", fd->flags); + if (fd->inode) { - gf_proc_dump_build_key(key, prefix, "inode"); - gf_proc_dump_write(key, "%ld", fd->inode->ino); + gf_proc_dump_build_key (key, "inode", NULL); + gf_proc_dump_add_section(key); + inode_dump (fd->inode, key); } + } @@ -719,10 +1028,11 @@ fdentry_dump (fdentry_t *fdentry, char *prefix) if (GF_FDENTRY_ALLOCATED != fdentry->next_free) return; - if (fdentry->fd) + if (fdentry->fd) fd_dump(fdentry->fd, prefix); } + void fdtable_dump (fdtable_t *fdtable, char *prefix) { @@ -732,13 +1042,11 @@ fdtable_dump (fdtable_t *fdtable, char *prefix) if (!fdtable) return; - - ret = pthread_mutex_trylock (&fdtable->lock); - if (ret) { - gf_log ("fd", GF_LOG_WARNING, "Unable to acquire lock"); - return; - } + ret = pthread_mutex_trylock (&fdtable->lock); + + if (ret) + goto out; memset(key, 0, sizeof(key)); gf_proc_dump_build_key(key, prefix, "refcount"); @@ -749,8 +1057,8 @@ fdtable_dump (fdtable_t *fdtable, char *prefix) gf_proc_dump_write(key, "%d", fdtable->first_free); for ( i = 0 ; i < fdtable->max_fds; i++) { - if (GF_FDENTRY_ALLOCATED == - fdtable->fdentries[i].next_free) { + if (GF_FDENTRY_ALLOCATED == + fdtable->fdentries[i].next_free) { gf_proc_dump_build_key(key, prefix, "fdentry[%d]", i); gf_proc_dump_add_section(key); fdentry_dump(&fdtable->fdentries[i], key); @@ -758,5 +1066,150 @@ fdtable_dump (fdtable_t *fdtable, char *prefix) } pthread_mutex_unlock(&fdtable->lock); + +out: + if (ret != 0) + gf_proc_dump_write ("Unable to dump the fdtable", + "(Lock acquistion failed) %p", fdtable); + return; } + +void +fd_ctx_dump (fd_t *fd, char *prefix) +{ + struct _fd_ctx *fd_ctx = NULL; + xlator_t *xl = NULL; + int i = 0; + + + if ((fd == NULL) || (fd->_ctx == NULL)) { + goto out; + } + + LOCK (&fd->lock); + { + if (fd->_ctx != NULL) { + fd_ctx = GF_CALLOC (fd->xl_count, sizeof (*fd_ctx), + gf_common_mt_fd_ctx); + if (fd_ctx == NULL) { + goto unlock; + } + + for (i = 0; i < fd->xl_count; i++) { + fd_ctx[i] = fd->_ctx[i]; + } + } + } +unlock: + UNLOCK (&fd->lock); + + if (fd_ctx == NULL) { + goto out; + } + + for (i = 0; i < fd->xl_count; i++) { + if (fd_ctx[i].xl_key) { + xl = (xlator_t *)(long)fd_ctx[i].xl_key; + if (xl->dumpops && xl->dumpops->fdctx) + xl->dumpops->fdctx (xl, fd); + } + } + +out: + GF_FREE (fd_ctx); + + return; +} + +void +fdentry_dump_to_dict (fdentry_t *fdentry, char *prefix, dict_t *dict, + int *openfds) +{ + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + int ret = -1; + + if (!fdentry) + return; + if (!dict) + return; + + if (GF_FDENTRY_ALLOCATED != fdentry->next_free) + return; + + if (fdentry->fd) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.pid", prefix); + ret = dict_set_int32 (dict, key, fdentry->fd->pid); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.refcount", prefix); + ret = dict_set_int32 (dict, key, fdentry->fd->refcount); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.flags", prefix); + ret = dict_set_int32 (dict, key, fdentry->fd->flags); + + (*openfds)++; + } + return; +} + +void +fdtable_dump_to_dict (fdtable_t *fdtable, char *prefix, dict_t *dict) +{ + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + int i = 0; + int openfds = 0; + int ret = -1; + + if (!fdtable) + return; + if (!dict) + return; + + ret = pthread_mutex_trylock (&fdtable->lock); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.fdtable.refcount", prefix); + ret = dict_set_int32 (dict, key, fdtable->refcount); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.fdtable.maxfds", prefix); + ret = dict_set_uint32 (dict, key, fdtable->max_fds); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.fdtable.firstfree", prefix); + ret = dict_set_int32 (dict, key, fdtable->first_free); + if (ret) + goto out; + + for (i = 0; i < fdtable->max_fds; i++) { + if (GF_FDENTRY_ALLOCATED == + fdtable->fdentries[i].next_free) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.fdtable.fdentry%d", + prefix, i); + fdentry_dump_to_dict (&fdtable->fdentries[i], key, + dict, &openfds); + } + } + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.fdtable.openfds", prefix); + ret = dict_set_int32 (dict, key, openfds); + +out: + pthread_mutex_unlock (&fdtable->lock); + return; +} diff --git a/libglusterfs/src/fd.h b/libglusterfs/src/fd.h index 6b0571351..c1b9157d8 100644 --- a/libglusterfs/src/fd.h +++ b/libglusterfs/src/fd.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _FD_H @@ -30,37 +21,49 @@ #include <unistd.h> #include "glusterfs.h" #include "locking.h" +#include "fd-lk.h" +#include "common-utils.h" + +#define GF_ANON_FD_NO -2 struct _inode; struct _dict; +struct fd_lk_ctx; + struct _fd_ctx { - uint64_t key; - uint64_t value; + union { + uint64_t key; + void *xl_key; + }; + union { + uint64_t value1; + void *ptr1; + }; }; -/* If this structure changes, please have mercy on the booster maintainer - * and update the fd_t struct in booster/src/booster-fd.h. - * See the comment there to know why. - */ struct _fd { - pid_t pid; + uint64_t pid; int32_t flags; int32_t refcount; - uint64_t flush_unique; struct list_head inode_list; struct _inode *inode; gf_lock_t lock; /* used ONLY for manipulating 'struct _fd_ctx' array (_ctx).*/ struct _fd_ctx *_ctx; + int xl_count; /* Number of xl referred in this fd */ + struct fd_lk_ctx *lk_ctx; + gf_boolean_t anonymous; /* geo-rep anonymous fd */ }; typedef struct _fd fd_t; + struct fd_table_entry { fd_t *fd; int next_free; }; typedef struct fd_table_entry fdentry_t; + struct _fdtable { int refcount; uint32_t max_fds; @@ -70,6 +73,7 @@ struct _fdtable { }; typedef struct _fdtable fdtable_t; + /* Signifies no more entries in the fd table. */ #define GF_FDTABLE_END -1 @@ -81,58 +85,105 @@ typedef struct _fdtable fdtable_t; #include "logging.h" #include "xlator.h" -inline void + +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 + +int gf_fd_unused_get (fdtable_t *fdtable, fd_t *fdptr); + fdentry_t * gf_fd_fdtable_get_all_fds (fdtable_t *fdtable, uint32_t *count); -void + +void gf_fd_fdtable_destroy (fdtable_t *fdtable); + +fd_t * +__fd_ref (fd_t *fd); + + 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_create_uint64 (struct _inode *inode, uint64_t pid); + +fd_t * fd_lookup (struct _inode *inode, pid_t pid); +fd_t * +fd_lookup_uint64 (struct _inode *inode, uint64_t pid); + +fd_t* +fd_lookup_anonymous (inode_t *inode); + +fd_t * +fd_anonymous (inode_t *inode); + + +gf_boolean_t +fd_is_anonymous (fd_t *fd); + + 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 + +int fd_ctx_get (fd_t *fd, xlator_t *xlator, uint64_t *value); -int + +int fd_ctx_del (fd_t *fd, xlator_t *xlator, uint64_t *value); int +__fd_ctx_del (fd_t *fd, xlator_t *xlator, uint64_t *value); + + +int __fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value); -int + +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); + +void +fd_ctx_dump (fd_t *fd, char *prefix); + +fdentry_t * +gf_fd_fdtable_copy_all_fds (fdtable_t *fdtable, uint32_t *count); + + +void +gf_fdptr_put (fdtable_t *fdtable, fd_t *fd); #endif /* _FD_H */ diff --git a/libglusterfs/src/gf-dirent.c b/libglusterfs/src/gf-dirent.c index 546c2f82b..bb028c967 100644 --- a/libglusterfs/src/gf-dirent.c +++ b/libglusterfs/src/gf-dirent.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ @@ -29,54 +20,35 @@ #include <stdint.h> #include "compat.h" #include "xlator.h" -#include "byte-order.h" -#include "protocol.h" - - -struct gf_dirent_nb { - uint64_t d_ino; - uint64_t d_off; - uint32_t d_len; - uint32_t d_type; - struct gf_stat d_stat; - 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; + gf_dirent_t *gf_dirent = NULL; - /* TODO: use mem-pool */ - gf_dirent = CALLOC (gf_dirent_size (name), 1); - if (!gf_dirent) - return NULL; + /* TODO: use mem-pool */ + gf_dirent = GF_CALLOC (gf_dirent_size (name), 1, + gf_common_mt_gf_dirent_t); + if (!gf_dirent) + return NULL; - INIT_LIST_HEAD (&gf_dirent->list); - strcpy (gf_dirent->d_name, name); + 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); + gf_dirent->d_off = 0; + gf_dirent->d_ino = -1; + gf_dirent->d_type = 0; + gf_dirent->d_len = strlen (name); - return gf_dirent; + return gf_dirent; } void gf_dirent_free (gf_dirent_t *entries) { - gf_dirent_t *entry = NULL; - gf_dirent_t *tmp = NULL; + gf_dirent_t *entry = NULL; + gf_dirent_t *tmp = NULL; if (!entries) return; @@ -84,87 +56,37 @@ gf_dirent_free (gf_dirent_t *entries) if (list_empty (&entries->list)) return; - 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); + list_for_each_entry_safe (entry, tmp, &entries->list, list) { + if (entry->dict) + dict_unref (entry->dict); + if (entry->inode) + inode_unref (entry->inode); - 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); - - gf_stat_from_stat (&entry_nb->d_stat, &entry->d_stat); - - strcpy (entry_nb->d_name, entry->d_name); - } - size += entry_size; - } - - return size; + list_del (&entry->list); + GF_FREE (entry); + } } - +/* TODO: Currently, with this function, we will be breaking the + policy of 1-1 mapping of kernel nlookup refs with our inode_t's + nlookup count. + Need more thoughts before finalizing this function +*/ int -gf_dirent_unserialize (gf_dirent_t *entries, const char *buf, size_t buf_size) +gf_link_inodes_from_dirent (xlator_t *this, inode_t *parent, + gf_dirent_t *entries) { - 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); - - gf_stat_to_stat (&entry_nb->d_stat, &entry->d_stat); - - 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; + gf_dirent_t *entry = NULL; + inode_t *link_inode = NULL; + + list_for_each_entry (entry, &entries->list, list) { + if (entry->inode) { + link_inode = inode_link (entry->inode, parent, + entry->d_name, &entry->d_stat); + inode_lookup (link_inode); + inode_unref (link_inode); + } + } + + return 0; } diff --git a/libglusterfs/src/gf-dirent.h b/libglusterfs/src/gf-dirent.h index baf08a58b..588d522db 100644 --- a/libglusterfs/src/gf-dirent.h +++ b/libglusterfs/src/gf-dirent.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ @@ -26,13 +17,16 @@ #include "config.h" #endif +#include "iatt.h" +#include "inode.h" + #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 iatt buf; }; @@ -48,14 +42,17 @@ struct _gf_dirent_t { uint64_t d_off; uint32_t d_len; uint32_t d_type; - struct stat d_stat; - char d_name[0]; + struct iatt d_stat; + dict_t *dict; + inode_t *inode; + char d_name[]; }; +#define DT_ISDIR(mode) (mode == DT_DIR) 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); +int gf_link_inodes_from_dirent (xlator_t *this, inode_t *parent, + gf_dirent_t *entries); #endif /* _GF_DIRENT_H */ diff --git a/libglusterfs/src/gidcache.c b/libglusterfs/src/gidcache.c new file mode 100644 index 000000000..c5bdda925 --- /dev/null +++ b/libglusterfs/src/gidcache.c @@ -0,0 +1,192 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include "gidcache.h" +#include "mem-pool.h" + +/* + * We treat this as a very simple set-associative LRU cache, with entries aged + * out after a configurable interval. Hardly rocket science, but lots of + * details to worry about. + */ +#define BUCKET_START(p,n) ((p) + ((n) * AUX_GID_CACHE_ASSOC)) + +/* + * Initialize the cache. + */ +int gid_cache_init(gid_cache_t *cache, uint32_t timeout) +{ + if (!cache) + return -1; + + LOCK_INIT(&cache->gc_lock); + cache->gc_max_age = timeout; + cache->gc_nbuckets = AUX_GID_CACHE_BUCKETS; + memset(cache->gc_cache, 0, sizeof(gid_list_t) * AUX_GID_CACHE_SIZE); + + return 0; +} + +/* + * Reconfigure the cache timeout. + */ +int gid_cache_reconf(gid_cache_t *cache, uint32_t timeout) +{ + if (!cache) + return -1; + + LOCK(&cache->gc_lock); + cache->gc_max_age = timeout; + UNLOCK(&cache->gc_lock); + + return 0; +} + +/* + * Look up an ID in the cache. If found, return the actual cache entry to avoid + * an additional allocation and memory copy. The caller should copy the data and + * release (unlock) the cache as soon as possible. + */ +const gid_list_t *gid_cache_lookup(gid_cache_t *cache, uint64_t id) +{ + int bucket; + int i; + time_t now; + const gid_list_t *agl; + + LOCK(&cache->gc_lock); + now = time(NULL); + bucket = id % cache->gc_nbuckets; + agl = BUCKET_START(cache->gc_cache, bucket); + for (i = 0; i < AUX_GID_CACHE_ASSOC; i++, agl++) { + if (!agl->gl_list) + continue; + if (agl->gl_id != id) + continue; + + /* + * We don't put new entries in the cache when expiration=0, but + * there might be entries still in there if expiration was + * changed very recently. Writing the check this way ensures + * that they're not used. + */ + if (now < agl->gl_deadline) { + return agl; + } + + /* + * We're not going to find any more UID matches, and reaping + * is handled further down to maintain LRU order. + */ + break; + } + UNLOCK(&cache->gc_lock); + return NULL; +} + +/* + * Release an entry found via lookup. + */ +void gid_cache_release(gid_cache_t *cache, const gid_list_t *agl) +{ + UNLOCK(&cache->gc_lock); +} + +/* + * Add a new list entry to the cache. If an entry for this ID already exists, + * update it. + */ +int gid_cache_add(gid_cache_t *cache, gid_list_t *gl) +{ + gid_list_t *agl; + int bucket; + int i; + time_t now; + + if (!gl || !gl->gl_list) + return -1; + + if (!cache->gc_max_age) + return 0; + + LOCK(&cache->gc_lock); + now = time(NULL); + + /* + * Scan for the first free entry or one that matches this id. The id + * check is added to address a bug where the cache might contain an + * expired entry for this id. Since lookup occurs in LRU order and + * does not reclaim entries, it will always return failure on discovery + * of an expired entry. This leads to duplicate entries being added, + * which still do not satisfy lookups until the expired entry (and + * everything before it) is reclaimed. + * + * We address this through reuse of an entry already allocated to this + * id, whether expired or not, since we have obviously already received + * more recent data. The entry is repopulated with the new data and a new + * deadline and is pushed forward to reside as the last populated entry in + * the bucket. + */ + bucket = gl->gl_id % cache->gc_nbuckets; + agl = BUCKET_START(cache->gc_cache, bucket); + for (i = 0; i < AUX_GID_CACHE_ASSOC; ++i, ++agl) { + if (agl->gl_id == gl->gl_id) + break; + if (!agl->gl_list) + break; + } + + /* + * The way we allocate free entries naturally places the newest + * ones at the highest indices, so evicting the lowest makes + * sense, but that also means we can't just replace it with the + * one that caused the eviction. That would cause us to thrash + * the first entry while others remain idle. Therefore, we + * need to slide the other entries down and add the new one at + * the end just as if the *last* slot had been free. + * + * Deadline expiration is also handled here, since the oldest + * expired entry will be in the first position. This does mean + * the bucket can stay full of expired entries if we're idle + * but, if the small amount of extra memory or scan time before + * we decide to evict someone ever become issues, we could + * easily add a reaper thread. + */ + + if (i >= AUX_GID_CACHE_ASSOC) { + /* cache full, evict the first (LRU) entry */ + i = 0; + agl = BUCKET_START(cache->gc_cache, bucket); + GF_FREE(agl->gl_list); + } else if (agl->gl_list) { + /* evict the old entry we plan to reuse */ + GF_FREE(agl->gl_list); + } + + /* + * If we have evicted an entry, slide the subsequent populated entries + * back and populate the last entry. + */ + for (; i < AUX_GID_CACHE_ASSOC - 1; i++) { + if (!agl[1].gl_list) + break; + agl[0] = agl[1]; + agl++; + } + + agl->gl_id = gl->gl_id; + agl->gl_count = gl->gl_count; + agl->gl_list = gl->gl_list; + agl->gl_deadline = now + cache->gc_max_age; + + UNLOCK(&cache->gc_lock); + + return 1; +} diff --git a/libglusterfs/src/gidcache.h b/libglusterfs/src/gidcache.h new file mode 100644 index 000000000..9379f8e8b --- /dev/null +++ b/libglusterfs/src/gidcache.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __GIDCACHE_H__ +#define __GIDCACHE_H__ + +#include "glusterfs.h" +#include "locking.h" + +/* + * TBD: make the cache size tunable + * + * The current size represents a pretty trivial amount of memory, and should + * provide good hit rates even for quite busy systems. If we ever want to + * support really large cache sizes, we'll need to do dynamic allocation + * instead of just defining an array within a private structure. It doesn't make + * a whole lot of sense to change the associativity, because it won't improve + * hit rates all that much and will increase the maintenance cost as we have + * to scan more entries with every lookup/update. + */ + +#define AUX_GID_CACHE_ASSOC 4 +#define AUX_GID_CACHE_BUCKETS 256 +#define AUX_GID_CACHE_SIZE (AUX_GID_CACHE_ASSOC * AUX_GID_CACHE_BUCKETS) + +typedef struct { + uint64_t gl_id; + int gl_count; + gid_t *gl_list; + time_t gl_deadline; +} gid_list_t; + +typedef struct { + gf_lock_t gc_lock; + uint32_t gc_max_age; + unsigned int gc_nbuckets; + gid_list_t gc_cache[AUX_GID_CACHE_SIZE]; +} gid_cache_t; + +int gid_cache_init(gid_cache_t *, uint32_t); +int gid_cache_reconf(gid_cache_t *, uint32_t); +const gid_list_t *gid_cache_lookup(gid_cache_t *, uint64_t); +void gid_cache_release(gid_cache_t *, const gid_list_t *); +int gid_cache_add(gid_cache_t *, gid_list_t *); + +#endif /* __GIDCACHE_H__ */ diff --git a/libglusterfs/src/globals.c b/libglusterfs/src/globals.c index ae7fdcd61..259c5c885 100644 --- a/libglusterfs/src/globals.c +++ b/libglusterfs/src/globals.c @@ -1,20 +1,11 @@ /* - Copyright (c) 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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -24,54 +15,78 @@ #include <pthread.h> -#include "globals.h" #include "glusterfs.h" +#include "globals.h" #include "xlator.h" - - -/* CTX */ -static glusterfs_ctx_t *glusterfs_ctx; - - -int -glusterfs_ctx_init () -{ - int ret = 0; - - if (glusterfs_ctx) - goto out; - - glusterfs_ctx = CALLOC (1, sizeof (*glusterfs_ctx)); - if (!glusterfs_ctx) { - ret = -1; - goto out; - } - - ret = pthread_mutex_init (&glusterfs_ctx->lock, NULL); - -out: - return ret; -} - - -glusterfs_ctx_t * -glusterfs_ctx_get () -{ - return glusterfs_ctx; - -} - - +#include "mem-pool.h" +#include "syncop.h" + +const char *gf_fop_list[GF_FOP_MAXVALUE] = { + [GF_FOP_NULL] = "NULL", + [GF_FOP_STAT] = "STAT", + [GF_FOP_READLINK] = "READLINK", + [GF_FOP_MKNOD] = "MKNOD", + [GF_FOP_MKDIR] = "MKDIR", + [GF_FOP_UNLINK] = "UNLINK", + [GF_FOP_RMDIR] = "RMDIR", + [GF_FOP_SYMLINK] = "SYMLINK", + [GF_FOP_RENAME] = "RENAME", + [GF_FOP_LINK] = "LINK", + [GF_FOP_TRUNCATE] = "TRUNCATE", + [GF_FOP_OPEN] = "OPEN", + [GF_FOP_READ] = "READ", + [GF_FOP_WRITE] = "WRITE", + [GF_FOP_STATFS] = "STATFS", + [GF_FOP_FLUSH] = "FLUSH", + [GF_FOP_FSYNC] = "FSYNC", + [GF_FOP_SETXATTR] = "SETXATTR", + [GF_FOP_GETXATTR] = "GETXATTR", + [GF_FOP_REMOVEXATTR] = "REMOVEXATTR", + [GF_FOP_OPENDIR] = "OPENDIR", + [GF_FOP_FSYNCDIR] = "FSYNCDIR", + [GF_FOP_ACCESS] = "ACCESS", + [GF_FOP_CREATE] = "CREATE", + [GF_FOP_FTRUNCATE] = "FTRUNCATE", + [GF_FOP_FSTAT] = "FSTAT", + [GF_FOP_LK] = "LK", + [GF_FOP_LOOKUP] = "LOOKUP", + [GF_FOP_READDIR] = "READDIR", + [GF_FOP_INODELK] = "INODELK", + [GF_FOP_FINODELK] = "FINODELK", + [GF_FOP_ENTRYLK] = "ENTRYLK", + [GF_FOP_FENTRYLK] = "FENTRYLK", + [GF_FOP_XATTROP] = "XATTROP", + [GF_FOP_FXATTROP] = "FXATTROP", + [GF_FOP_FSETXATTR] = "FSETXATTR", + [GF_FOP_FGETXATTR] = "FGETXATTR", + [GF_FOP_RCHECKSUM] = "RCHECKSUM", + [GF_FOP_SETATTR] = "SETATTR", + [GF_FOP_FSETATTR] = "FSETATTR", + [GF_FOP_READDIRP] = "READDIRP", + [GF_FOP_GETSPEC] = "GETSPEC", + [GF_FOP_FORGET] = "FORGET", + [GF_FOP_RELEASE] = "RELEASE", + [GF_FOP_RELEASEDIR] = "RELEASEDIR", + [GF_FOP_FREMOVEXATTR]= "FREMOVEXATTR", + [GF_FOP_FALLOCATE] = "FALLOCATE", + [GF_FOP_DISCARD] = "DISCARD", + [GF_FOP_ZEROFILL] = "ZEROFILL", +}; /* THIS */ xlator_t global_xlator; static pthread_key_t this_xlator_key; +static pthread_key_t synctask_key; +static pthread_key_t uuid_buf_key; +static char global_uuid_buf[GF_UUID_BUF_SIZE]; +static pthread_key_t lkowner_buf_key; +static char global_lkowner_buf[GF_LKOWNER_BUF_SIZE]; + void glusterfs_this_destroy (void *ptr) { - if (ptr) - FREE (ptr); + FREE (ptr); } @@ -82,12 +97,15 @@ glusterfs_this_init () ret = pthread_key_create (&this_xlator_key, glusterfs_this_destroy); if (ret != 0) { + gf_log ("", GF_LOG_WARNING, "failed to create the pthread key"); return ret; } global_xlator.name = "glusterfs"; global_xlator.type = "global"; + INIT_LIST_HEAD (&global_xlator.volume_options); + return ret; } @@ -148,78 +166,196 @@ glusterfs_this_set (xlator_t *this) return 0; } +/* SYNCOPCTX */ +static pthread_key_t syncopctx_key; + +static void +syncopctx_key_destroy (void *ptr) +{ + struct syncopctx *opctx = ptr; -/* IS_CENTRAL_LOG */ + if (opctx) { + if (opctx->groups) + GF_FREE (opctx->groups); -static pthread_key_t central_log_flag_key; + GF_FREE (opctx); + } -void -glusterfs_central_log_flag_destroy (void *ptr) + return; +} + +void * +syncopctx_getctx () +{ + void *opctx = NULL; + + opctx = pthread_getspecific (syncopctx_key); + + return opctx; +} + +int +syncopctx_setctx (void *ctx) +{ + int ret = 0; + + ret = pthread_setspecific (syncopctx_key, ctx); + + return ret; +} + +static int +syncopctx_init (void) { - if (ptr) - FREE (ptr); + int ret; + + ret = pthread_key_create (&syncopctx_key, syncopctx_key_destroy); + + return ret; } +/* SYNCTASK */ int -glusterfs_central_log_flag_init () +synctask_init () { - int ret = 0; + int ret = 0; - ret = pthread_key_create (¢ral_log_flag_key, - glusterfs_central_log_flag_destroy); + ret = pthread_key_create (&synctask_key, NULL); + + return ret; +} + +void * +synctask_get () +{ + void *synctask = NULL; + + synctask = pthread_getspecific (synctask_key); + + return synctask; +} - if (ret != 0) { - return ret; - } - pthread_setspecific (central_log_flag_key, (void *) 0); +int +synctask_set (void *synctask) +{ + int ret = 0; + + pthread_setspecific (synctask_key, synctask); return ret; } +//UUID_BUFFER void -glusterfs_central_log_flag_set () +glusterfs_uuid_buf_destroy (void *ptr) { - pthread_setspecific (central_log_flag_key, (void *) 1); + FREE (ptr); } +int +glusterfs_uuid_buf_init () +{ + int ret = 0; + + ret = pthread_key_create (&uuid_buf_key, + glusterfs_uuid_buf_destroy); + return ret; +} -long -glusterfs_central_log_flag_get () +char * +glusterfs_uuid_buf_get () { - long flag = 0; + char *buf; + int ret = 0; - flag = (long) pthread_getspecific (central_log_flag_key); - - return flag; + buf = pthread_getspecific (uuid_buf_key); + if(!buf) { + buf = MALLOC (GF_UUID_BUF_SIZE); + ret = pthread_setspecific (uuid_buf_key, (void *) buf); + if (ret) + buf = global_uuid_buf; + } + return buf; } +/* LKOWNER_BUFFER */ void -glusterfs_central_log_flag_unset () +glusterfs_lkowner_buf_destroy (void *ptr) { - pthread_setspecific (central_log_flag_key, (void *) 0); + FREE (ptr); } +int +glusterfs_lkowner_buf_init () +{ + int ret = 0; + + ret = pthread_key_create (&lkowner_buf_key, + glusterfs_lkowner_buf_destroy); + return ret; +} + +char * +glusterfs_lkowner_buf_get () +{ + char *buf; + int ret = 0; + + buf = pthread_getspecific (lkowner_buf_key); + if(!buf) { + buf = MALLOC (GF_LKOWNER_BUF_SIZE); + ret = pthread_setspecific (lkowner_buf_key, (void *) buf); + if (ret) + buf = global_lkowner_buf; + } + return buf; +} int -glusterfs_globals_init () +glusterfs_globals_init (glusterfs_ctx_t *ctx) { int ret = 0; - ret = glusterfs_ctx_init (); - if (ret) - goto out; + gf_log_globals_init (ctx); ret = glusterfs_this_init (); - if (ret) + if (ret) { + gf_log ("", GF_LOG_CRITICAL, + "ERROR: glusterfs-translator init failed"); goto out; + } + + ret = glusterfs_uuid_buf_init (); + if(ret) { + gf_log ("", GF_LOG_CRITICAL, + "ERROR: glusterfs uuid buffer init failed"); + goto out; + } - ret = glusterfs_central_log_flag_init (); - if (ret) + ret = glusterfs_lkowner_buf_init (); + if(ret) { + gf_log ("", GF_LOG_CRITICAL, + "ERROR: glusterfs lkowner buffer init failed"); goto out; + } + + ret = synctask_init (); + if (ret) { + gf_log ("", GF_LOG_CRITICAL, + "ERROR: glusterfs synctask init failed"); + goto out; + } + + ret = syncopctx_init (); + if (ret) { + gf_log ("", GF_LOG_CRITICAL, + "ERROR: glusterfs syncopctx init failed"); + goto out; + } out: return ret; } diff --git a/libglusterfs/src/globals.h b/libglusterfs/src/globals.h index 2f284ca9b..3085db21c 100644 --- a/libglusterfs/src/globals.h +++ b/libglusterfs/src/globals.h @@ -1,32 +1,38 @@ /* - Copyright (c) 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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _GLOBALS_H #define _GLOBALS_H -#include "glusterfs.h" -#include "xlator.h" - -/* CTX */ -#define CTX (glusterfs_ctx_get()) +#define GF_DEFAULT_BASE_PORT 24007 + +#define GD_OP_VERSION_KEY "operating-version" +#define GD_MIN_OP_VERSION_KEY "minimum-operating-version" +#define GD_MAX_OP_VERSION_KEY "maximum-operating-version" + +/* Gluster versions - OP-VERSION mapping + * + * 3.3.0 - 1 + * 3.4.0 - 2 + * 3.next (3.5?) - 3 + * + * TODO: Change above comment once gluster version is finalised + * TODO: Finalize the op-version ranges + */ +#define GD_OP_VERSION_MIN 1 /* MIN is the fresh start op-version, mostly + should not change */ +#define GD_OP_VERSION_MAX 3 /* MAX VERSION is the maximum count in VME table, + should keep changing with introduction of newer + versions */ -glusterfs_ctx_t *glusterfs_ctx_get (); +#include "xlator.h" /* THIS */ #define THIS (*__glusterfs_this_location()) @@ -35,12 +41,22 @@ xlator_t **__glusterfs_this_location (); xlator_t *glusterfs_this_get (); int glusterfs_this_set (xlator_t *); -void glusterfs_central_log_flag_set (); -long glusterfs_central_log_flag_get (); -void glusterfs_central_log_flag_unset (); +/* syncopctx */ +void *syncopctx_getctx (); +int syncopctx_setctx (void *ctx); + +/* task */ +void *synctask_get (); +int synctask_set (void *); +/* uuid_buf */ +char *glusterfs_uuid_buf_get(); +/* lkowner_buf */ +char *glusterfs_lkowner_buf_get(); /* init */ -int glusterfs_globals_init (void); +int glusterfs_globals_init (glusterfs_ctx_t *ctx); + +extern const char *gf_fop_list[]; #endif /* !_GLOBALS_H */ diff --git a/libglusterfs/src/glusterfs-acl.h b/libglusterfs/src/glusterfs-acl.h new file mode 100644 index 000000000..b7de1cdb4 --- /dev/null +++ b/libglusterfs/src/glusterfs-acl.h @@ -0,0 +1,81 @@ +/* + Copyright (c) 2008-2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _GLUSTERFS_ACL_H +#define _GLUSTERFS_ACL_H + +#include <stdint.h> +#include <sys/types.h> /* For uid_t */ + +#include "locking.h" /* For gf_lock_t in struct posix_acl_conf */ + +#define ACL_PROGRAM 100227 +#define ACLV3_VERSION 3 + +#define POSIX_ACL_MINIMAL_ACE_COUNT 3 + +#define POSIX_ACL_READ (0x04) +#define POSIX_ACL_WRITE (0x02) +#define POSIX_ACL_EXECUTE (0x01) + +#define POSIX_ACL_UNDEFINED_TAG (0x00) +#define POSIX_ACL_USER_OBJ (0x01) +#define POSIX_ACL_USER (0x02) +#define POSIX_ACL_GROUP_OBJ (0x04) +#define POSIX_ACL_GROUP (0x08) +#define POSIX_ACL_MASK (0x10) +#define POSIX_ACL_OTHER (0x20) + +#define POSIX_ACL_UNDEFINED_ID (-1) + +#define POSIX_ACL_VERSION (0x02) + +#define POSIX_ACL_ACCESS_XATTR "system.posix_acl_access" +#define POSIX_ACL_DEFAULT_XATTR "system.posix_acl_default" + +struct posix_acl_xattr_entry { + uint16_t tag; + uint16_t perm; + uint32_t id; +}; + +struct posix_acl_xattr_header { + uint32_t version; + struct posix_acl_xattr_entry entries[]; +}; + +struct posix_ace { + uint16_t tag; + uint16_t perm; + uint32_t id; +}; + + +struct posix_acl { + int refcnt; + int count; + struct posix_ace entries[]; +}; + +struct posix_acl_ctx { + uid_t uid; + gid_t gid; + mode_t perm; + struct posix_acl *acl_access; + struct posix_acl *acl_default; +}; + +struct posix_acl_conf { + gf_lock_t acl_lock; + uid_t super_uid; + struct posix_acl *minimal_acl; +}; + +#endif /* _GLUSTERFS_ACL_H */ diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index bea33f81a..2f1e12ee7 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _GLUSTERFS_H @@ -41,16 +32,23 @@ #include <arpa/inet.h> #include <sys/poll.h> #include <pthread.h> +#include <limits.h> /* For PATH_MAX */ #include "list.h" #include "logging.h" +#include "lkowner.h" #define GF_YES 1 #define GF_NO 0 #ifndef O_LARGEFILE /* savannah bug #20053, patch for compiling on darwin */ -#define O_LARGEFILE 0 +#define O_LARGEFILE 0100000 /* from bits/fcntl.h */ +#endif + +#ifndef O_FMODE_EXEC +/* redhat bug 843080, added from linux/fs.h */ +#define O_FMODE_EXEC 040 //0x20 #endif #ifndef O_DIRECT @@ -63,227 +61,434 @@ #define O_DIRECTORY 0 #endif +#ifndef EBADFD +/* Mac OS X does not have EBADFD */ +#define EBADFD EBADF +#endif + +#ifndef FNM_EXTMATCH +#define FNM_EXTMATCH 0 +#endif + +#define GLUSTERD_MAX_SNAP_NAME 256 +#define ZR_MOUNTPOINT_OPT "mountpoint" +#define ZR_ATTR_TIMEOUT_OPT "attribute-timeout" +#define ZR_ENTRY_TIMEOUT_OPT "entry-timeout" +#define ZR_NEGATIVE_TIMEOUT_OPT "negative-timeout" +#define ZR_DIRECT_IO_OPT "direct-io-mode" +#define ZR_STRICT_VOLFILE_CHECK "strict-volfile-check" +#define ZR_DUMP_FUSE "dump-fuse" +#define ZR_FUSE_MOUNTOPTS "fuse-mountopts" + +#define GF_XATTR_CLRLK_CMD "glusterfs.clrlk" +#define GF_XATTR_PATHINFO_KEY "trusted.glusterfs.pathinfo" +#define GF_XATTR_NODE_UUID_KEY "trusted.glusterfs.node-uuid" +#define GF_XATTR_VOL_ID_KEY "trusted.glusterfs.volume-id" +#define GF_XATTR_LOCKINFO_KEY "trusted.glusterfs.lockinfo" +#define GF_XATTR_GET_REAL_FILENAME_KEY "user.glusterfs.get_real_filename:" + +#define GF_READDIR_SKIP_DIRS "readdir-filter-directories" + +#define BD_XATTR_KEY "user.glusterfs" + +#define XATTR_IS_PATHINFO(x) (strncmp (x, GF_XATTR_PATHINFO_KEY, \ + strlen (GF_XATTR_PATHINFO_KEY)) == 0) +#define XATTR_IS_NODE_UUID(x) (strncmp (x, GF_XATTR_NODE_UUID_KEY, \ + strlen (GF_XATTR_NODE_UUID_KEY)) == 0) +#define XATTR_IS_LOCKINFO(x) (strncmp (x, GF_XATTR_LOCKINFO_KEY, \ + strlen (GF_XATTR_LOCKINFO_KEY)) == 0) + +#define XATTR_IS_BD(x) (strncmp (x, BD_XATTR_KEY, strlen (BD_XATTR_KEY)) == 0) + +#define GF_XATTR_LINKINFO_KEY "trusted.distribute.linkinfo" +#define GFID_XATTR_KEY "trusted.gfid" +#define VIRTUAL_GFID_XATTR_KEY_STR "glusterfs.gfid.string" +#define VIRTUAL_GFID_XATTR_KEY "glusterfs.gfid" +#define UUID_CANONICAL_FORM_LEN 36 + +#define GLUSTERFS_INTERNAL_FOP_KEY "glusterfs-internal-fop" + #define ZR_FILE_CONTENT_STR "glusterfs.file." #define ZR_FILE_CONTENT_STRLEN 15 +#define GLUSTERFS_WRITE_IS_APPEND "glusterfs.write-is-append" #define GLUSTERFS_OPEN_FD_COUNT "glusterfs.open-fd-count" +#define GLUSTERFS_INODELK_COUNT "glusterfs.inodelk-count" +#define GLUSTERFS_ENTRYLK_COUNT "glusterfs.entrylk-count" +#define GLUSTERFS_POSIXLK_COUNT "glusterfs.posixlk-count" +#define GLUSTERFS_PARENT_ENTRYLK "glusterfs.parent-entrylk" +#define GLUSTERFS_INODELK_DOM_COUNT "glusterfs.inodelk-dom-count" +#define QUOTA_SIZE_KEY "trusted.glusterfs.quota.size" +#define GFID_TO_PATH_KEY "glusterfs.gfid2path" +#define GF_XATTR_STIME_PATTERN "trusted.glusterfs.*.stime" + +/* Index xlator related */ +#define GF_XATTROP_INDEX_GFID "glusterfs.xattrop_index_gfid" +#define GF_BASE_INDICES_HOLDER_GFID "glusterfs.base_indicies_holder_gfid" + +#define GF_GFIDLESS_LOOKUP "gfidless-lookup" +/* replace-brick and pump related internal xattrs */ +#define RB_PUMP_CMD_START "glusterfs.pump.start" +#define RB_PUMP_CMD_PAUSE "glusterfs.pump.pause" +#define RB_PUMP_CMD_COMMIT "glusterfs.pump.commit" +#define RB_PUMP_CMD_ABORT "glusterfs.pump.abort" +#define RB_PUMP_CMD_STATUS "glusterfs.pump.status" + +#define GLUSTERFS_RDMA_INLINE_THRESHOLD (2048) +#define GLUSTERFS_RDMA_MAX_HEADER_SIZE (228) /* (sizeof (rdma_header_t) \ + + RDMA_MAX_SEGMENTS \ + * sizeof (rdma_read_chunk_t)) + */ + +#define GLUSTERFS_RPC_REPLY_SIZE 24 #define ZR_FILE_CONTENT_REQUEST(key) (!strncmp(key, ZR_FILE_CONTENT_STR, \ - ZR_FILE_CONTENT_STRLEN)) + ZR_FILE_CONTENT_STRLEN)) -/* TODO: Should we use PATH-MAX? On some systems it may save space */ -#define ZR_PATH_MAX 4096 +#define DEFAULT_VAR_RUN_DIRECTORY DATADIR "/run/gluster" +#define GF_REPLICATE_TRASH_DIR ".landfill" +/* GlusterFS's maximum supported Auxilary GIDs */ +/* TODO: Keeping it to 200, so that we can fit in 2KB buffer for auth data + * in RPC server code, if there is ever need for having more aux-gids, then + * we have to add aux-gid in payload of actors */ +#define GF_MAX_AUX_GROUPS 65536 + +#define GF_UUID_BUF_SIZE 50 + +#define GF_REBALANCE_TID_KEY "rebalance-id" +#define GF_REMOVE_BRICK_TID_KEY "remove-brick-id" +#define GF_REPLACE_BRICK_TID_KEY "replace-brick-id" + +#define UUID_CANONICAL_FORM_LEN 36 + +/* Adding this here instead of any glusterd*.h files as it is also required by + * cli + */ +#define DEFAULT_GLUSTERD_SOCKFILE DATADIR "/run/glusterd.socket" /* 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_NULL = 0, + GF_FOP_STAT, + GF_FOP_READLINK, + GF_FOP_MKNOD, GF_FOP_MKDIR, GF_FOP_UNLINK, - GF_FOP_RMDIR, /* 5 */ + GF_FOP_RMDIR, 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_STATFS, GF_FOP_FLUSH, - GF_FOP_FSYNC, + GF_FOP_FSYNC, /* 15 */ GF_FOP_SETXATTR, GF_FOP_GETXATTR, - GF_FOP_REMOVEXATTR,/* 20 */ + GF_FOP_REMOVEXATTR, GF_FOP_OPENDIR, - GF_FOP_GETDENTS, GF_FOP_FSYNCDIR, GF_FOP_ACCESS, - GF_FOP_CREATE, /* 25 */ + GF_FOP_CREATE, GF_FOP_FTRUNCATE, - GF_FOP_FSTAT, + GF_FOP_FSTAT, /* 25 */ 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_INODELK, GF_FOP_FINODELK, - GF_FOP_ENTRYLK, - GF_FOP_FENTRYLK, - GF_FOP_CHECKSUM, - GF_FOP_XATTROP, /* 40 */ + GF_FOP_ENTRYLK, + GF_FOP_FENTRYLK, + GF_FOP_XATTROP, GF_FOP_FXATTROP, - GF_FOP_LOCK_NOTIFY, - GF_FOP_LOCK_FNOTIFY, GF_FOP_FGETXATTR, - GF_FOP_FSETXATTR, /* 45 */ + GF_FOP_FSETXATTR, GF_FOP_RCHECKSUM, GF_FOP_SETATTR, GF_FOP_FSETATTR, GF_FOP_READDIRP, + GF_FOP_FORGET, + GF_FOP_RELEASE, + GF_FOP_RELEASEDIR, + GF_FOP_GETSPEC, + GF_FOP_FREMOVEXATTR, + GF_FOP_FALLOCATE, + GF_FOP_DISCARD, + GF_FOP_ZEROFILL, 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_LOG, - 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; + GF_MGMT_NULL = 0, + GF_MGMT_MAXVALUE, +} glusterfs_mgmt_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; + GF_OP_TYPE_NULL = 0, + GF_OP_TYPE_FOP, + GF_OP_TYPE_MGMT, + GF_OP_TYPE_MAX, +} gf_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, + GF_LK_RESLK_LCK, + GF_LK_RESLK_LCKW, + GF_LK_RESLK_UNLCK, + GF_LK_GETLK_FD, } glusterfs_lk_cmds_t; + typedef enum { GF_LK_F_RDLCK = 0, GF_LK_F_WRLCK, - GF_LK_F_UNLCK + GF_LK_F_UNLCK, + GF_LK_EOL, } glusterfs_lk_types_t; typedef enum { - GF_LOCK_POSIX, + F_RESLK_LCK = 200, + F_RESLK_LCKW, + F_RESLK_UNLCK, + F_GETLK_FD, +} glusterfs_lk_recovery_cmds_t; + +typedef enum { + GF_LOCK_POSIX, GF_LOCK_INTERNAL } gf_lk_domain_t; + typedef enum { - ENTRYLK_LOCK, - ENTRYLK_UNLOCK, - ENTRYLK_LOCK_NB + ENTRYLK_LOCK, + ENTRYLK_UNLOCK, + ENTRYLK_LOCK_NB } entrylk_cmd; + typedef enum { - ENTRYLK_RDLCK, - ENTRYLK_WRLCK + 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_ADD_ARRAY, + GF_XATTROP_ADD_ARRAY64, + GF_XATTROP_OR_ARRAY, + GF_XATTROP_AND_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 */ +/* key value which quick read uses to get small files in lookup cbk */ +#define GF_CONTENT_KEY "glusterfs.content" struct _xlator_cmdline_option { - struct list_head cmd_args; - char *volume; - char *key; - char *value; + struct list_head cmd_args; + char *volume; + char *key; + char *value; }; typedef struct _xlator_cmdline_option xlator_cmdline_option_t; +struct _server_cmdline { + struct list_head list; + char *volfile_server; +}; +typedef struct _server_cmdline server_cmdline_t; + +#define GF_OPTION_ENABLE _gf_true +#define GF_OPTION_DISABLE _gf_false +#define GF_OPTION_DEFERRED 2 + struct _cmd_args { - /* basic options */ - char *volfile_server; - char *volume_file; - char *log_server; - gf_loglevel_t log_level; - char *log_file; + /* basic options */ + char *volfile_server; + server_cmdline_t *curr_server; + /* List of backup volfile servers, including original */ + struct list_head volfile_servers; + char *volfile; + char *log_server; + gf_loglevel_t log_level; + char *log_file; int32_t max_connect_attempts; - /* advanced options */ - uint32_t volfile_server_port; - char *volfile_server_transport; + /* advanced options */ + uint32_t volfile_server_port; + char *volfile_server_transport; uint32_t log_server_port; - 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; + char *pid_file; + char *sock_file; + int no_daemon_mode; + char *run_id; + int debug_mode; + int read_only; + int acl; + int selinux; + int enable_ino32; + int worm; + int mac_compat; + int fopen_keep_cache; + int gid_timeout; + int aux_gfid_mount; + struct list_head xlator_options; /* list of xlator_option_t */ + + /* fuse options */ + int fuse_direct_io_mode; + char *use_readdirp; int volfile_check; - double fuse_entry_timeout; - double 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; + double fuse_entry_timeout; + double fuse_negative_timeout; + double fuse_attribute_timeout; + char *volume_name; + int fuse_nodev; + int fuse_nosuid; + char *dump_fuse; + pid_t client_pid; + int client_pid_set; + unsigned uid_map_root; + int background_qlen; + int congestion_threshold; + char *fuse_mountopts; + + /* key args */ + char *mount_point; + char *volfile_id; + + /* required for portmap */ + int brick_port; + char *brick_name; + int brick_port2; }; 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; - void *iobuf_pool; - pthread_mutex_t lock; - int xl_count; - uint32_t volfile_checksum; - size_t page_size; + +struct _glusterfs_graph { + struct list_head list; + char graph_uuid[128]; + struct timeval dob; + void *first; + void *top; /* selected by -n */ + int xl_count; + int id; /* Used in logging */ + int used; /* Should be set when fuse gets + first CHILD_UP */ + uint32_t volfile_checksum; }; +typedef struct _glusterfs_graph glusterfs_graph_t; + +typedef int32_t (*glusterfsd_mgmt_event_notify_fn_t) (int32_t event, void *data, + ...); +struct _glusterfs_ctx { + cmd_args_t cmd_args; + char *process_uuid; + FILE *pidfp; + char fin; + void *timer; + void *ib; + struct call_pool *pool; + void *event_pool; + void *iobuf_pool; + pthread_mutex_t lock; + size_t page_size; + struct list_head graphs; /* double linked list of graphs - one per volfile parse */ + glusterfs_graph_t *active; /* the latest graph in use */ + void *master; /* fuse, or libglusterfsclient (however, not protocol/server) */ + void *mgmt; /* xlator implementing MOPs for centralized logging, volfile server */ + void *listener; /* listener of the commands from glusterd */ + unsigned char measure_latency; /* toggle switch for latency measurement */ + pthread_t sigwaiter; + struct mem_pool *stub_mem_pool; + unsigned char cleanup_started; + int graph_id; /* Incremented per graph, value should + indicate how many times the graph has + got changed */ + pid_t mnt_pid; /* pid of the mount agent */ + int process_mode; /*mode in which process is runninng*/ + struct syncenv *env; /* The env pointer to the synctasks */ + + struct list_head mempool_list; /* used to keep a global list of + mempools, used to log details of + mempool in statedump */ + char *statedump_path; + + struct mem_pool *dict_pool; + struct mem_pool *dict_pair_pool; + struct mem_pool *dict_data_pool; + + glusterfsd_mgmt_event_notify_fn_t notify; /* Used for xlators to make + call to fsd-mgmt */ + gf_log_handle_t log; /* all logging related variables */ + + int mem_acct_enable; + + int daemon_pipe[2]; + + struct client_disconnect *client_disconnect; + struct clienttable *clienttable; +}; typedef struct _glusterfs_ctx glusterfs_ctx_t; +glusterfs_ctx_t *glusterfs_ctx_new (void); + 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, - GF_EVENT_VOLFILE_MODIFIED, + 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_CHILD_MODIFIED, + GF_EVENT_TRANSPORT_CLEANUP, + GF_EVENT_TRANSPORT_CONNECTED, + GF_EVENT_VOLFILE_MODIFIED, + GF_EVENT_GRAPH_NEW, + GF_EVENT_TRANSLATOR_INFO, + GF_EVENT_TRANSLATOR_OP, + GF_EVENT_AUTH_FAILED, + GF_EVENT_VOLUME_DEFRAG, + GF_EVENT_PARENT_DOWN, + GF_EVENT_VOLUME_BARRIER_OP, + GF_EVENT_MAXVAL, } glusterfs_event_t; +struct gf_flock { + short l_type; + short l_whence; + off_t l_start; + off_t l_len; + pid_t l_pid; + gf_lkowner_t l_owner; +}; + #define GF_MUST_CHECK __attribute__((warn_unused_result)) +/* + * Some macros (e.g. ALLOC_OR_GOTO) set variables in function scope, but the + * calling function might not only declare the variable to keep the macro happy + * and not use it otherwise. In such cases, the following can be used to + * suppress the "set but not used" warning that would otherwise occur. + */ +#define GF_UNUSED __attribute__((unused)) + +int glusterfs_graph_prepare (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx); +int glusterfs_graph_destroy (glusterfs_graph_t *graph); +int glusterfs_graph_activate (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx); +glusterfs_graph_t *glusterfs_graph_construct (FILE *fp); +glusterfs_graph_t *glusterfs_graph_new (); +int glusterfs_graph_reconfigure (glusterfs_graph_t *oldgraph, + glusterfs_graph_t *newgraph); #endif /* _GLUSTERFS_H */ diff --git a/libglusterfs/src/graph-print.c b/libglusterfs/src/graph-print.c new file mode 100644 index 000000000..d860d63b3 --- /dev/null +++ b/libglusterfs/src/graph-print.c @@ -0,0 +1,200 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <sys/uio.h> + +#include "common-utils.h" +#include "xlator.h" +#include "graph-utils.h" + + + +struct gf_printer { + ssize_t (*write) (struct gf_printer *gp, char *buf, size_t len); + void *priv; + int len; +}; + +static ssize_t +gp_write_file (struct gf_printer *gp, char *buf, size_t len) +{ + FILE *f = gp->priv; + + if (fwrite (buf, len, 1, f) != 1) { + gf_log ("graph-print", GF_LOG_ERROR, "fwrite failed (%s)", + strerror (errno)); + + return -1; + } + + return len; +} + +static ssize_t +gp_write_buf (struct gf_printer *gp, char *buf, size_t len) +{ + struct iovec *iov = gp->priv; + + if (iov->iov_len < len) { + gf_log ("graph-print", GF_LOG_ERROR, "buffer full"); + + return -1; + } + + memcpy (iov->iov_base, buf, len); + iov->iov_base += len; + iov->iov_len -= len; + + return len; +} + +static int +gpprintf (struct gf_printer *gp, const char *format, ...) +{ + va_list arg; + char *str = NULL; + int ret = 0; + + va_start (arg, format); + ret = gf_vasprintf (&str, format, arg); + va_end (arg); + + if (ret < 0) + return ret; + + ret = gp->write (gp, str, ret); + + GF_FREE (str); + + return ret; +} + +#define GPPRINTF(gp, fmt, ...) do { \ + ret = gpprintf (gp, fmt, ## __VA_ARGS__); \ + if (ret == -1) \ + goto out; \ + else \ + gp->len += ret; \ + } while (0) + +static int +_print_volume_options (dict_t *d, char *k, data_t *v, + void *tmp) +{ + struct gf_printer *gp = tmp; + int ret = 0; + GPPRINTF (gp, " option %s %s\n", k, v->data); + return 0; +out: + /* means, it is a failure */ + return -1; +} + +static int +glusterfs_graph_print (struct gf_printer *gp, glusterfs_graph_t *graph) +{ + xlator_t *trav = NULL; + xlator_list_t *xch = NULL; + int ret = 0; + ssize_t len = 0; + + if (!graph->first) + return 0; + + for (trav = graph->first; trav->next; trav = trav->next); + for (; trav; trav = trav->prev) { + GPPRINTF (gp, "volume %s\n type %s\n", trav->name, + trav->type); + + ret = dict_foreach (trav->options, _print_volume_options, gp); + if (ret) + goto out; + + if (trav->children) { + GPPRINTF (gp, " subvolumes"); + + for (xch = trav->children; xch; xch = xch->next) + GPPRINTF (gp, " %s", xch->xlator->name); + + GPPRINTF (gp, "\n"); + } + + GPPRINTF (gp, "end-volume\n"); + if (trav != graph->first) + GPPRINTF (gp, "\n"); + } + +out: + len = gp->len; + if (ret == -1) { + gf_log ("graph-print", GF_LOG_ERROR, "printing failed"); + + return -1; + } + + return len; + +#undef GPPRINTF +} + +int +glusterfs_graph_print_file (FILE *file, glusterfs_graph_t *graph) +{ + struct gf_printer gp = { .write = gp_write_file, + .priv = file + }; + + return glusterfs_graph_print (&gp, graph); +} + +char * +glusterfs_graph_print_buf (glusterfs_graph_t *graph) +{ + FILE *f = NULL; + struct iovec iov = {0,}; + int len = 0; + char *buf = NULL; + struct gf_printer gp = { .write = gp_write_buf, + .priv = &iov + }; + + f = fopen ("/dev/null", "a"); + if (!f) { + gf_log ("graph-print", GF_LOG_ERROR, + "cannot open /dev/null (%s)", strerror (errno)); + + return NULL; + } + len = glusterfs_graph_print_file (f, graph); + fclose (f); + if (len == -1) + return NULL; + + buf = GF_CALLOC (1, len + 1, gf_common_mt_graph_buf); + if (!buf) { + return NULL; + } + iov.iov_base = buf; + iov.iov_len = len; + + len = glusterfs_graph_print (&gp, graph); + if (len == -1) { + GF_FREE (buf); + + return NULL; + } + + return buf; +} diff --git a/libglusterfs/src/graph-utils.h b/libglusterfs/src/graph-utils.h new file mode 100644 index 000000000..207664fdb --- /dev/null +++ b/libglusterfs/src/graph-utils.h @@ -0,0 +1,20 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _GRAPH_H_ +#define _GRAPH_H_ + +int glusterfs_graph_print_file (FILE *file, glusterfs_graph_t *graph); + +char *glusterfs_graph_print_buf (glusterfs_graph_t *graph); + +int glusterfs_xlator_link (xlator_t *pxl, xlator_t *cxl); +void glusterfs_graph_set_first (glusterfs_graph_t *graph, xlator_t *xl); +#endif diff --git a/libglusterfs/src/graph.c b/libglusterfs/src/graph.c new file mode 100644 index 000000000..e76df1ca5 --- /dev/null +++ b/libglusterfs/src/graph.c @@ -0,0 +1,751 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#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" + + +#if 0 +static void +_gf_dump_details (int argc, char **argv) +{ + extern FILE *gf_log_logfile; + int i = 0; + char timestr[64]; + time_t utime = 0; + pid_t mypid = 0; + struct utsname uname_buf = {{0, }, }; + int uname_ret = -1; + + mypid = getpid (); + uname_ret = uname (&uname_buf); + + utime = time (NULL); + gf_time_fmt (timestr, sizeof timestr, utime, gf_timefmt_FT); + fprintf (gf_log_logfile, + "========================================" + "========================================\n"); + fprintf (gf_log_logfile, "Version : %s %s built on %s %s\n", + PACKAGE_NAME, PACKAGE_VERSION, __DATE__, __TIME__); + fprintf (gf_log_logfile, "git: %s\n", + GLUSTERFS_REPOSITORY_REVISION); + fprintf (gf_log_logfile, "Starting Time: %s\n", timestr); + fprintf (gf_log_logfile, "Command line : "); + for (i = 0; i < argc; i++) { + fprintf (gf_log_logfile, "%s ", argv[i]); + } + + fprintf (gf_log_logfile, "\nPID : %d\n", mypid); + + if (uname_ret == 0) { + fprintf (gf_log_logfile, "System name : %s\n", + uname_buf.sysname); + fprintf (gf_log_logfile, "Nodename : %s\n", + uname_buf.nodename); + fprintf (gf_log_logfile, "Kernel Release : %s\n", + uname_buf.release); + fprintf (gf_log_logfile, "Hardware Identifier: %s\n", + uname_buf.machine); + } + + + fprintf (gf_log_logfile, "\n"); + fflush (gf_log_logfile); +} +#endif + + + +int +glusterfs_xlator_link (xlator_t *pxl, xlator_t *cxl) +{ + xlator_list_t *xlchild = NULL; + xlator_list_t *xlparent = NULL; + xlator_list_t **tmp = NULL; + + xlparent = (void *) GF_CALLOC (1, sizeof (*xlparent), + gf_common_mt_xlator_list_t); + if (!xlparent) + return -1; + + xlchild = (void *) GF_CALLOC (1, sizeof (*xlchild), + gf_common_mt_xlator_list_t); + if (!xlchild) { + GF_FREE (xlparent); + + return -1; + } + + xlparent->xlator = pxl; + for (tmp = &cxl->parents; *tmp; tmp = &(*tmp)->next); + *tmp = xlparent; + + xlchild->xlator = cxl; + for (tmp = &pxl->children; *tmp; tmp = &(*tmp)->next); + *tmp = xlchild; + + return 0; +} + + +void +glusterfs_graph_set_first (glusterfs_graph_t *graph, xlator_t *xl) +{ + xl->next = graph->first; + if (graph->first) + ((xlator_t *)graph->first)->prev = xl; + graph->first = xl; + + graph->xl_count++; +} + + +int +glusterfs_graph_insert (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx, + const char *type, const char *name, + gf_boolean_t autoload) +{ + xlator_t *ixl = NULL; + + if (!ctx->master) { + gf_log ("glusterfs", GF_LOG_ERROR, + "volume \"%s\" can be added from command line only " + "on client side", type); + + return -1; + } + + ixl = GF_CALLOC (1, sizeof (*ixl), gf_common_mt_xlator_t); + if (!ixl) + return -1; + + ixl->ctx = ctx; + ixl->graph = graph; + ixl->options = get_new_dict (); + if (!ixl->options) + goto err; + + ixl->name = gf_strdup (name); + if (!ixl->name) + goto err; + + ixl->is_autoloaded = autoload; + + if (xlator_set_type (ixl, type) == -1) { + gf_log ("glusterfs", GF_LOG_ERROR, + "%s (%s) initialization failed", + name, type); + return -1; + } + + if (glusterfs_xlator_link (ixl, graph->top) == -1) + goto err; + glusterfs_graph_set_first (graph, ixl); + graph->top = ixl; + + return 0; +err: + xlator_destroy (ixl); + return -1; +} + +int +glusterfs_graph_acl (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) +{ + int ret = 0; + cmd_args_t *cmd_args = NULL; + + cmd_args = &ctx->cmd_args; + + if (!cmd_args->acl) + return 0; + + ret = glusterfs_graph_insert (graph, ctx, "system/posix-acl", + "posix-acl-autoload", 1); + return ret; +} + +int +glusterfs_graph_worm (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) +{ + int ret = 0; + cmd_args_t *cmd_args = NULL; + + cmd_args = &ctx->cmd_args; + + if (!cmd_args->worm) + return 0; + + ret = glusterfs_graph_insert (graph, ctx, "features/worm", + "worm-autoload", 1); + return ret; +} + +int +glusterfs_graph_mac_compat (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) +{ + int ret = 0; + cmd_args_t *cmd_args = NULL; + + cmd_args = &ctx->cmd_args; + + if (cmd_args->mac_compat == GF_OPTION_DISABLE) + return 0; + + ret = glusterfs_graph_insert (graph, ctx, "features/mac-compat", + "mac-compat-autoload", 1); + + return ret; +} + +int +glusterfs_graph_gfid_access (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) +{ + int ret = 0; + cmd_args_t *cmd_args = NULL; + + cmd_args = &ctx->cmd_args; + + if (!cmd_args->aux_gfid_mount) + return 0; + + ret = glusterfs_graph_insert (graph, ctx, "features/gfid-access", + "gfid-access-autoload", 1); + return ret; +} + +static void +gf_add_cmdline_options (glusterfs_graph_t *graph, cmd_args_t *cmd_args) +{ + int ret = 0; + xlator_t *trav = NULL; + xlator_cmdline_option_t *cmd_option = NULL; + + trav = graph->first; + + while (trav) { + list_for_each_entry (cmd_option, + &cmd_args->xlator_options, cmd_args) { + if (!fnmatch (cmd_option->volume, + trav->name, FNM_NOESCAPE)) { + ret = dict_set_str (trav->options, + cmd_option->key, + cmd_option->value); + if (ret == 0) { + gf_log (trav->name, GF_LOG_INFO, + "adding option '%s' for " + "volume '%s' with value '%s'", + cmd_option->key, trav->name, + cmd_option->value); + } else { + gf_log (trav->name, GF_LOG_WARNING, + "adding option '%s' for " + "volume '%s' failed: %s", + cmd_option->key, trav->name, + strerror (-ret)); + } + } + } + trav = trav->next; + } +} + + +int +glusterfs_graph_validate_options (glusterfs_graph_t *graph) +{ + xlator_t *trav = NULL; + int ret = -1; + char *errstr = NULL; + + trav = graph->first; + + while (trav) { + if (list_empty (&trav->volume_options)) + continue; + + ret = xlator_options_validate (trav, trav->options, &errstr); + if (ret) { + gf_log (trav->name, GF_LOG_ERROR, + "validation failed: %s", errstr); + return ret; + } + trav = trav->next; + } + + return 0; +} + + +int +glusterfs_graph_init (glusterfs_graph_t *graph) +{ + xlator_t *trav = NULL; + int ret = -1; + + trav = graph->first; + + while (trav) { + ret = xlator_init (trav); + if (ret) { + gf_log (trav->name, GF_LOG_ERROR, + "initializing translator failed"); + return ret; + } + trav = trav->next; + } + + return 0; +} + + +static int +_log_if_unknown_option (dict_t *dict, char *key, data_t *value, void *data) +{ + volume_option_t *found = NULL; + xlator_t *xl = NULL; + + xl = data; + + found = xlator_volume_option_get (xl, key); + + if (!found) { + gf_log (xl->name, GF_LOG_WARNING, + "option '%s' is not recognized", key); + } + + return 0; +} + + +static void +_xlator_check_unknown_options (xlator_t *xl, void *data) +{ + dict_foreach (xl->options, _log_if_unknown_option, xl); +} + + +int +glusterfs_graph_unknown_options (glusterfs_graph_t *graph) +{ + xlator_foreach (graph->first, _xlator_check_unknown_options, NULL); + return 0; +} + + +void +fill_uuid (char *uuid, int size) +{ + char hostname[256] = {0,}; + struct timeval tv = {0,}; + char now_str[64]; + + if (gettimeofday (&tv, NULL) == -1) { + gf_log ("graph", GF_LOG_ERROR, + "gettimeofday: failed %s", + strerror (errno)); + } + + if (gethostname (hostname, 256) == -1) { + gf_log ("graph", GF_LOG_ERROR, + "gethostname: failed %s", + strerror (errno)); + } + + gf_time_fmt (now_str, sizeof now_str, tv.tv_sec, gf_timefmt_Ymd_T); + snprintf (uuid, size, "%s-%d-%s:%"GF_PRI_SUSECONDS, + hostname, getpid(), now_str, tv.tv_usec); + + return; +} + + +int +glusterfs_graph_settop (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) +{ + const char *volume_name = NULL; + xlator_t *trav = NULL; + + volume_name = ctx->cmd_args.volume_name; + + if (!volume_name) { + graph->top = graph->first; + return 0; + } + + for (trav = graph->first; trav; trav = trav->next) { + if (strcmp (trav->name, volume_name) == 0) { + graph->top = trav; + return 0; + } + } + + return -1; +} + + +int +glusterfs_graph_parent_up (glusterfs_graph_t *graph) +{ + xlator_t *trav = NULL; + int ret = -1; + + trav = graph->first; + + while (trav) { + if (!xlator_has_parent (trav)) { + ret = xlator_notify (trav, GF_EVENT_PARENT_UP, trav); + } + + if (ret) + break; + + trav = trav->next; + } + + return ret; +} + + +int +glusterfs_graph_prepare (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) +{ + xlator_t *trav = NULL; + int ret = 0; + + /* XXX: CHECKSUM */ + + /* XXX: attach to -n volname */ + ret = glusterfs_graph_settop (graph, ctx); + if (ret) { + gf_log ("graph", GF_LOG_ERROR, "glusterfs graph settop failed"); + return -1; + } + + /* XXX: WORM VOLUME */ + ret = glusterfs_graph_worm (graph, ctx); + if (ret) { + gf_log ("graph", GF_LOG_ERROR, "glusterfs graph worm failed"); + return -1; + } + ret = glusterfs_graph_acl (graph, ctx); + if (ret) { + gf_log ("graph", GF_LOG_ERROR, "glusterfs graph ACL failed"); + return -1; + } + + /* XXX: MAC COMPAT */ + ret = glusterfs_graph_mac_compat (graph, ctx); + if (ret) { + gf_log ("graph", GF_LOG_ERROR, "glusterfs graph mac compat failed"); + return -1; + } + + /* XXX: gfid-access */ + ret = glusterfs_graph_gfid_access (graph, ctx); + if (ret) { + gf_log ("graph", GF_LOG_ERROR, + "glusterfs graph 'gfid-access' failed"); + return -1; + } + + /* XXX: this->ctx setting */ + for (trav = graph->first; trav; trav = trav->next) { + trav->ctx = ctx; + } + + /* XXX: DOB setting */ + gettimeofday (&graph->dob, NULL); + + fill_uuid (graph->graph_uuid, 128); + + graph->id = ctx->graph_id++; + + /* XXX: --xlator-option additions */ + gf_add_cmdline_options (graph, &ctx->cmd_args); + + + return 0; +} + + +int +glusterfs_graph_activate (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) +{ + int ret = 0; + + /* XXX: all xlator options validation */ + ret = glusterfs_graph_validate_options (graph); + if (ret) { + gf_log ("graph", GF_LOG_ERROR, "validate options failed"); + return ret; + } + + /* XXX: perform init () */ + ret = glusterfs_graph_init (graph); + if (ret) { + gf_log ("graph", GF_LOG_ERROR, "init failed"); + return ret; + } + + ret = glusterfs_graph_unknown_options (graph); + if (ret) { + gf_log ("graph", GF_LOG_ERROR, "unknown options failed"); + return ret; + } + + /* XXX: log full graph (_gf_dump_details) */ + + list_add (&graph->list, &ctx->graphs); + ctx->active = graph; + + /* XXX: attach to master and set active pointer */ + if (ctx->master) { + ret = xlator_notify (ctx->master, GF_EVENT_GRAPH_NEW, graph); + if (ret) { + gf_log ("graph", GF_LOG_ERROR, + "graph new notification failed"); + return ret; + } + ((xlator_t *)ctx->master)->next = graph->top; + } + + /* XXX: perform parent up */ + ret = glusterfs_graph_parent_up (graph); + if (ret) { + gf_log ("graph", GF_LOG_ERROR, "parent up notification failed"); + return ret; + } + + return 0; +} + + +int +xlator_equal_rec (xlator_t *xl1, xlator_t *xl2) +{ + xlator_list_t *trav1 = NULL; + xlator_list_t *trav2 = NULL; + int ret = 0; + + if (xl1 == NULL || xl2 == NULL) { + gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); + return -1; + } + + trav1 = xl1->children; + trav2 = xl2->children; + + while (trav1 && trav2) { + ret = xlator_equal_rec (trav1->xlator, trav2->xlator); + if (ret) { + gf_log ("glusterfsd-mgmt", GF_LOG_DEBUG, + "xlators children not equal"); + goto out; + } + + trav1 = trav1->next; + trav2 = trav2->next; + } + + if (trav1 || trav2) { + ret = -1; + goto out; + } + + if (strcmp (xl1->name, xl2->name)) { + ret = -1; + goto out; + } + + /* type could have changed even if xlator names match, + e.g cluster/distrubte and cluster/nufa share the same + xlator name + */ + if (strcmp (xl1->type, xl2->type)) { + ret = -1; + goto out; + } +out : + return ret; +} + + +gf_boolean_t +is_graph_topology_equal (glusterfs_graph_t *graph1, glusterfs_graph_t *graph2) +{ + xlator_t *trav1 = NULL; + xlator_t *trav2 = NULL; + gf_boolean_t ret = _gf_true; + + trav1 = graph1->first; + trav2 = graph2->first; + + ret = xlator_equal_rec (trav1, trav2); + + if (ret) { + gf_log ("glusterfsd-mgmt", GF_LOG_DEBUG, + "graphs are not equal"); + ret = _gf_false; + goto out; + } + + ret = _gf_true; + gf_log ("glusterfsd-mgmt", GF_LOG_DEBUG, + "graphs are equal"); + +out: + return ret; +} + + +/* Function has 3types of return value 0, -ve , 1 + * return 0 =======> reconfiguration of options has succeeded + * return 1 =======> the graph has to be reconstructed and all the xlators should be inited + * return -1(or -ve) =======> Some Internal Error occurred during the operation + */ +int +glusterfs_volfile_reconfigure (int oldvollen, FILE *newvolfile_fp, + glusterfs_ctx_t *ctx, const char *oldvolfile) +{ + glusterfs_graph_t *oldvolfile_graph = NULL; + glusterfs_graph_t *newvolfile_graph = NULL; + FILE *oldvolfile_fp = NULL; + gf_boolean_t active_graph_found = _gf_true; + + int ret = -1; + + if (!oldvollen) { + ret = 1; // Has to call INIT for the whole graph + goto out; + } + + if (!ctx) { + gf_log ("glusterfsd-mgmt", GF_LOG_ERROR, + "ctx is NULL"); + goto out; + } + + oldvolfile_graph = ctx->active; + if (!oldvolfile_graph) { + active_graph_found = _gf_false; + gf_log ("glusterfsd-mgmt", GF_LOG_ERROR, + "glusterfs_ctx->active is NULL"); + + oldvolfile_fp = tmpfile (); + if (!oldvolfile_fp) { + gf_log ("glusterfsd-mgmt", GF_LOG_ERROR, "Unable to " + "create temporary volfile: (%s)", + strerror (errno)); + goto out; + } + + fwrite (oldvolfile, oldvollen, 1, oldvolfile_fp); + fflush (oldvolfile_fp); + if (ferror (oldvolfile_fp)) { + goto out; + } + + oldvolfile_graph = glusterfs_graph_construct (oldvolfile_fp); + if (!oldvolfile_graph) + goto out; + } + + newvolfile_graph = glusterfs_graph_construct (newvolfile_fp); + if (!newvolfile_graph) { + goto out; + } + + if (!is_graph_topology_equal (oldvolfile_graph, + newvolfile_graph)) { + + ret = 1; + gf_log ("glusterfsd-mgmt", GF_LOG_DEBUG, + "Graph topology not equal(should call INIT)"); + goto out; + } + + gf_log ("glusterfsd-mgmt", GF_LOG_DEBUG, + "Only options have changed in the new " + "graph"); + + /* */ + ret = glusterfs_graph_reconfigure (oldvolfile_graph, + newvolfile_graph); + if (ret) { + gf_log ("glusterfsd-mgmt", GF_LOG_DEBUG, + "Could not reconfigure new options in old graph"); + goto out; + } + + ret = 0; +out: + if (oldvolfile_fp) + fclose (oldvolfile_fp); + + /* Do not simply destroy the old graph here. If the oldgraph + is constructed here in this function itself instead of getting + it from ctx->active (which happens only of ctx->active is NULL), + then destroy the old graph. If some i/o is still happening in + the old graph and the old graph is obtained from ctx->active, + then destroying the graph will cause problems. + */ + if (!active_graph_found && oldvolfile_graph) + glusterfs_graph_destroy (oldvolfile_graph); + if (newvolfile_graph) + glusterfs_graph_destroy (newvolfile_graph); + + return ret; +} + + +int +glusterfs_graph_reconfigure (glusterfs_graph_t *oldgraph, + glusterfs_graph_t *newgraph) +{ + xlator_t *old_xl = NULL; + xlator_t *new_xl = NULL; + + GF_ASSERT (oldgraph); + GF_ASSERT (newgraph); + + old_xl = oldgraph->first; + while (old_xl->is_autoloaded) { + old_xl = old_xl->children->xlator; + } + + new_xl = newgraph->first; + while (new_xl->is_autoloaded) { + new_xl = new_xl->children->xlator; + } + + return xlator_tree_reconfigure (old_xl, new_xl); +} + +int +glusterfs_graph_destroy (glusterfs_graph_t *graph) +{ + xlator_tree_free (graph->first); + + if (graph) { + list_del_init (&graph->list); + GF_FREE (graph); + } + + return 0; +} diff --git a/libglusterfs/src/graph.l b/libglusterfs/src/graph.l new file mode 100644 index 000000000..e4eba9cbe --- /dev/null +++ b/libglusterfs/src/graph.l @@ -0,0 +1,79 @@ +/* + Copyright (c) 2006-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +%x STRING +%option yylineno +%option noinput +%{ + +#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 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; + if (!text) { + text = GF_CALLOC (1, new_size, + gf_common_mt_char); + } else { + text = GF_REALLOC (text, new_size); + } + if (!text) { + gf_log ("parser", GF_LOG_ERROR, + "out of memory"); + return; + } + text_asize = new_size; + } + memcpy(text + text_size, str, size); + text_size += size; + text[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 VOLUME_BEGIN; +{TYPE} return TYPE; +{END}[-]{VOLUME} return VOLUME_END; +{SUB}{VOLUME}[Ss] return SUBVOLUME; +{OPTION} return OPTION; +\" BEGIN(STRING); +<STRING>{ + [^\n\"\\]* { append_string (yytext, yyleng); } + \\. { append_string (yytext + 1, yyleng - 1); } + \" { + if (0) { + yyunput (0, NULL); + } + BEGIN (INITIAL); + graphyylval = text; + return STRING_TOK; + } +} +[^ \t\r\n\"\\]+ { graphyylval = gf_strdup (yytext) ; return ID; } +[ \t\r\n]+ ; +%% diff --git a/libglusterfs/src/graph.y b/libglusterfs/src/graph.y new file mode 100644 index 000000000..a220abeb9 --- /dev/null +++ b/libglusterfs/src/graph.y @@ -0,0 +1,620 @@ +/* + Copyright (c) 2006-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +%token VOLUME_BEGIN VOLUME_END OPTION NEWLINE SUBVOLUME ID WHITESPACE COMMENT TYPE STRING_TOK + +%{ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <pthread.h> + +#define RELAX_POISONING + +#include "xlator.h" +#include "graph-utils.h" +#include "logging.h" + +static int new_volume (char *name); +static int volume_type (char *type); +static int volume_option (char *key, char *value); +static int volume_sub (char *sub); +static int volume_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 (8 * GF_UNIT_KB) + +int graphyyerror (const char *); +int graphyylex (); +%} + + +%% +VOLUMES: VOLUME | VOLUMES VOLUME; + +VOLUME: VOLUME_HEADER VOLUME_DATA VOLUME_FOOTER; +VOLUME_HEADER: VOLUME_BEGIN WORD {if (new_volume ($2) == -1) { YYABORT; }}; +VOLUME_FOOTER: VOLUME_END {if (volume_end () == -1) { YYABORT; }}; + +VOLUME_DATA: TYPE_LINE OPTIONS_LINE SUBVOLUME_LINE OPTIONS_LINE | + TYPE_LINE SUBVOLUME_LINE OPTIONS_LINE | + TYPE_LINE OPTIONS_LINE SUBVOLUME_LINE | + TYPE_LINE SUBVOLUME_LINE | + TYPE_LINE OPTIONS_LINE | + OPTIONS_LINE SUBVOLUME_LINE OPTIONS_LINE | /* error case */ + OPTIONS_LINE; /* error case */ + +TYPE_LINE: TYPE WORD {if (volume_type ($2) == -1) { YYABORT; }} | TYPE { type_error(); YYABORT; }; + +SUBVOLUME_LINE: SUBVOLUME WORDS | SUBVOLUME { sub_error (); YYABORT; }; + +OPTIONS_LINE: OPTION_LINE | OPTIONS_LINE OPTION_LINE; + +OPTION_LINE: OPTION WORD WORD {if (volume_option ($2, $3) == -1) { YYABORT; }} | + OPTION WORD { option_error (); YYABORT; } | + OPTION { option_error (); YYABORT; }; + +WORDS: WORD {if (volume_sub ($1) == -1) {YYABORT; }} | WORDS WORD { if (volume_sub ($2) == -1) { YYABORT; }}; +WORD: ID | STRING_TOK ; +%% + +xlator_t *curr; +glusterfs_graph_t *construct; + + +static void +type_error (void) +{ + extern int graphyylineno; + + gf_log ("parser", GF_LOG_ERROR, + "Volume %s, before line %d: Please specify volume type", + curr->name, graphyylineno); + return; +} + + +static void +sub_error (void) +{ + extern int graphyylineno; + + gf_log ("parser", GF_LOG_ERROR, + "Volume %s, before line %d: Please specify subvolumes", + curr->name, graphyylineno); + return; +} + + +static void +option_error (void) +{ + extern int graphyylineno; + + gf_log ("parser", GF_LOG_ERROR, + "Volume %s, before line %d: Please specify " + "option <key> <value>", + curr->name, graphyylineno); + return; +} + + +static int +new_volume (char *name) +{ + extern int graphyylineno; + xlator_t *trav = NULL; + int ret = 0; + + if (!name) { + gf_log ("parser", GF_LOG_DEBUG, + "Invalid argument name: '%s'", name); + ret = -1; + goto out; + } + + if (curr) { + gf_log ("parser", GF_LOG_ERROR, + "new volume (%s) defintion in line %d unexpected", + name, graphyylineno); + ret = -1; + goto out; + } + + curr = (void *) GF_CALLOC (1, sizeof (*curr), + gf_common_mt_xlator_t); + + if (!curr) { + gf_log ("parser", GF_LOG_ERROR, "Out of memory"); + ret = -1; + goto out; + } + + trav = construct->first; + + while (trav) { + if (!strcmp (name, trav->name)) { + gf_log ("parser", GF_LOG_ERROR, + "Line %d: volume '%s' defined again", + graphyylineno, name); + ret = -1; + goto out; + } + trav = trav->next; + } + + curr->name = gf_strdup (name); + if (!curr->name) { + GF_FREE (curr); + ret = -1; + goto out; + } + + curr->options = get_new_dict (); + + if (!curr->options) { + GF_FREE (curr->name); + GF_FREE (curr); + ret = -1; + goto out; + } + + curr->next = construct->first; + if (curr->next) + curr->next->prev = curr; + + curr->graph = construct; + + construct->first = curr; + + construct->xl_count++; + + gf_log ("parser", GF_LOG_TRACE, "New node for '%s'", name); + +out: + GF_FREE (name); + + return ret; +} + + +static int +volume_type (char *type) +{ + extern int graphyylineno; + int32_t ret = 0; + + if (!type) { + gf_log ("parser", GF_LOG_DEBUG, "Invalid argument type"); + ret = -1; + goto out; + } + + ret = xlator_set_type (curr, type); + if (ret) { + gf_log ("parser", GF_LOG_ERROR, + "Volume '%s', line %d: type '%s' is not valid or " + "not found on this machine", + curr->name, graphyylineno, type); + ret = -1; + goto out; + } + + gf_log ("parser", GF_LOG_TRACE, "Type:%s:%s", curr->name, type); + +out: + GF_FREE (type); + + return 0; +} + + +static int +volume_option (char *key, char *value) +{ + extern int graphyylineno; + int ret = 0; + char *set_value = NULL; + + if (!key || !value){ + gf_log ("parser", GF_LOG_ERROR, "Invalid argument"); + ret = -1; + goto out; + } + + set_value = gf_strdup (value); + ret = dict_set_dynstr (curr->options, key, set_value); + + if (ret == 1) { + gf_log ("parser", GF_LOG_ERROR, + "Volume '%s', line %d: duplicate entry " + "('option %s') present", + curr->name, graphyylineno, key); + ret = -1; + goto out; + } + + gf_log ("parser", GF_LOG_TRACE, "Option:%s:%s:%s", + curr->name, key, value); + +out: + GF_FREE (key); + GF_FREE (value); + + return 0; +} + + +static int +volume_sub (char *sub) +{ + extern int graphyylineno; + xlator_t *trav = NULL; + int ret = 0; + + if (!sub) { + gf_log ("parser", GF_LOG_ERROR, "Invalid subvolumes argument"); + ret = -1; + goto out; + } + + trav = construct->first; + + while (trav) { + if (!strcmp (sub, trav->name)) + break; + trav = trav->next; + } + + if (!trav) { + gf_log ("parser", GF_LOG_ERROR, + "Volume '%s', line %d: subvolume '%s' is not defined " + "prior to usage", + curr->name, graphyylineno, sub); + ret = -1; + goto out; + } + + if (trav == curr) { + gf_log ("parser", GF_LOG_ERROR, + "Volume '%s', line %d: has '%s' itself as subvolume", + curr->name, graphyylineno, sub); + ret = -1; + goto out; + } + + ret = glusterfs_xlator_link (curr, trav); + if (ret) { + gf_log ("parser", GF_LOG_ERROR, "Out of memory"); + ret = -1; + goto out; + } + + gf_log ("parser", GF_LOG_TRACE, "child:%s->%s", curr->name, sub); + +out: + GF_FREE (sub); + + return 0; +} + + +static int +volume_end (void) +{ + if (!curr->fops) { + gf_log ("parser", GF_LOG_ERROR, + "\"type\" not specified for volume %s", curr->name); + return -1; + } + gf_log ("parser", GF_LOG_TRACE, "end:%s", curr->name); + + curr = NULL; + return 0; +} + + +int +graphyywrap () +{ + return 1; +} + + +int +graphyyerror (const char *str) +{ + extern char *graphyytext; + extern int graphyylineno; + + if (curr && curr->name && graphyytext) { + if (!strcmp (graphyytext, "volume")) { + gf_log ("parser", GF_LOG_ERROR, + "'end-volume' not defined for volume '%s'", + curr->name); + } else if (!strcmp (graphyytext, "type")) { + gf_log ("parser", GF_LOG_ERROR, + "line %d: duplicate 'type' defined for " + "volume '%s'", + graphyylineno, curr->name); + } else if (!strcmp (graphyytext, "subvolumes")) { + gf_log ("parser", GF_LOG_ERROR, + "line %d: duplicate 'subvolumes' defined for " + "volume '%s'", + graphyylineno, curr->name); + } else if (curr) { + gf_log ("parser", GF_LOG_ERROR, + "syntax error: line %d (volume '%s'): \"%s\"" + "\nallowed tokens are 'volume', 'type', " + "'subvolumes', 'option', 'end-volume'()", + graphyylineno, curr->name, + graphyytext); + } else { + gf_log ("parser", GF_LOG_ERROR, + "syntax error: line %d (just after volume " + "'%s'): \"%s\"\n(%s)", + graphyylineno, curr->name, + graphyytext, + "allowed tokens are 'volume', 'type', " + "'subvolumes', 'option', 'end-volume'"); + } + } else { + gf_log ("parser", GF_LOG_ERROR, + "syntax error in line %d: \"%s\" \n" + "(allowed tokens are 'volume', 'type', " + "'subvolumes', 'option', 'end-volume')\n", + graphyylineno, graphyytext); + } + + return -1; +} + + +static int +execute_cmd (char *cmd, char **result, size_t size) +{ + FILE *fpp = NULL; + int i = 0; + int status = 0; + int character = 0; + char *buf = *result; + + fpp = popen (cmd, "r"); + if (!fpp) { + gf_log ("parser", GF_LOG_ERROR, "%s: failed to popen", cmd); + return -1; + } + + while ((character = fgetc (fpp)) != EOF) { + if (i == size) { + size *= 2; + buf = *result = GF_REALLOC (*result, size); + } + + buf[i++] = character; + } + + if (i > 0) { + i--; + buf[i] = '\0'; + } + + status = pclose (fpp); + if (status == -1 || !WIFEXITED (status) || + ((WEXITSTATUS (status)) != 0)) { + i = -1; + buf[0] = '\0'; + } + + return i; +} + + +static int +preprocess (FILE *srcfp, FILE *dstfp) +{ + int ret = 0; + int i = 0; + char *cmd = NULL; + char *result = NULL; + size_t cmd_buf_size = GF_CMD_BUFFER_LEN; + char escaped = 0; + char in_backtick = 0; + int line = 1; + int column = 0; + int character = 0; + + + fseek (srcfp, 0L, SEEK_SET); + fseek (dstfp, 0L, SEEK_SET); + + cmd = GF_CALLOC (cmd_buf_size, 1, + gf_common_mt_char); + if (cmd == NULL) { + gf_log ("parser", GF_LOG_ERROR, "Out of memory"); + return -1; + } + + result = GF_CALLOC (cmd_buf_size * 2, 1, + gf_common_mt_char); + if (result == NULL) { + GF_FREE (cmd); + gf_log ("parser", GF_LOG_ERROR, "Out of memory"); + return -1; + } + + while ((character = fgetc (srcfp)) != EOF) { + if ((character == '`') && !escaped) { + if (in_backtick) { + cmd[i] = '\0'; + result[0] = '\0'; + + ret = execute_cmd (cmd, &result, + 2 * cmd_buf_size); + if (ret < 0) { + ret = -1; + goto out; + } + fwrite (result, ret, 1, dstfp); + } else { + i = 0; + cmd[i] = '\0'; + } + + in_backtick = !in_backtick; + } else { + if (in_backtick) { + if (i == cmd_buf_size) { + cmd_buf_size *= 2; + cmd = GF_REALLOC (cmd, cmd_buf_size); + if (cmd == NULL) { + GF_FREE (result); + return -1; + } + + result = GF_REALLOC (result, + 2 * cmd_buf_size); + if (result == NULL) { + GF_FREE (cmd); + return -1; + } + } + + cmd[i++] = character; + } else { + fputc (character, dstfp); + } + } + + if (character == '\\') { + escaped = !escaped; + } else { + escaped = 0; + } + + if (character == '\n') { + line++; + column = 0; + } else { + column++; + } + } + + if (in_backtick) { + gf_log ("parser", GF_LOG_ERROR, + "Unterminated backtick in volume specfication file at line (%d), column (%d).", + line, column); + ret = -1; + } + +out: + fseek (srcfp, 0L, SEEK_SET); + fseek (dstfp, 0L, SEEK_SET); + + GF_FREE (cmd); + GF_FREE (result); + + return ret; +} + + +extern FILE *graphyyin; + +glusterfs_graph_t * +glusterfs_graph_new () +{ + glusterfs_graph_t *graph = NULL; + + graph = GF_CALLOC (1, sizeof (*graph), + gf_common_mt_glusterfs_graph_t); + if (!graph) + return NULL; + + INIT_LIST_HEAD (&graph->list); + + gettimeofday (&graph->dob, NULL); + + return graph; +} + + +glusterfs_graph_t * +glusterfs_graph_construct (FILE *fp) +{ + int ret = 0; + int tmp_fd = -1; + glusterfs_graph_t *graph = NULL; + FILE *tmp_file = NULL; + char template[PATH_MAX] = {0}; + static pthread_mutex_t graph_mutex = PTHREAD_MUTEX_INITIALIZER; + + graph = glusterfs_graph_new (); + if (!graph) + goto err; + + strcpy (template, "/tmp/tmp.XXXXXX"); + tmp_fd = mkstemp (template); + if (-1 == tmp_fd) + goto err; + + ret = unlink (template); + if (ret < 0) { + gf_log ("parser", GF_LOG_WARNING, "Unable to delete file: %s", + template); + } + + tmp_file = fdopen (tmp_fd, "w+b"); + if (!tmp_file) + goto err; + + ret = preprocess (fp, tmp_file); + if (ret < 0) { + gf_log ("parser", GF_LOG_ERROR, "parsing of backticks failed"); + goto err; + } + + pthread_mutex_lock (&graph_mutex); + { + graphyyin = tmp_file; + construct = graph; + ret = yyparse (); + construct = NULL; + } + pthread_mutex_unlock (&graph_mutex); + + if (ret == 1) { + gf_log ("parser", GF_LOG_DEBUG, + "parsing of volfile failed, please review it " + "once more"); + goto err; + } + + fclose (tmp_file); + return graph; +err: + if (tmp_file) { + fclose (tmp_file); + } else { + gf_log ("parser", GF_LOG_ERROR, "cannot create temporary file"); + if (-1 != tmp_fd) + close (tmp_fd); + } + + glusterfs_graph_destroy (graph); + return NULL; +} + diff --git a/libglusterfs/src/hashfn.c b/libglusterfs/src/hashfn.c index cf0e72a9f..f79165b22 100644 --- a/libglusterfs/src/hashfn.c +++ b/libglusterfs/src/hashfn.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include <stdint.h> @@ -31,7 +22,7 @@ #define DM_DELTA 0x9E3779B9 #define DM_FULLROUNDS 10 /* 32 is overkill, 16 is strong crypto */ -#define DM_PARTROUNDS 6 /* 6 gets complete mixing */ +#define DM_PARTROUNDS 6 /* 6 gets complete mixing */ uint32_t @@ -52,48 +43,48 @@ ReallySimpleHash (char *path, int len) /* 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; - - 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; + uint32_t hash = len, tmp; + int32_t rem; + + if (len <= 1 || data == NULL) return 1; + + 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; } @@ -102,95 +93,95 @@ uint32_t SuperFastHash (const char * data, int32_t len) { static int dm_round (int rounds, uint32_t *array, uint32_t *h0, uint32_t *h1) { - uint32_t sum = 0; - int n = 0; - uint32_t b0 = 0; - uint32_t b1 = 0; - - b0 = *h0; - b1 = *h1; - - n = rounds; - - do { - sum += DM_DELTA; - b0 += ((b1 << 4) + array[0]) - ^ (b1 + sum) - ^ ((b1 >> 5) + array[1]); - b1 += ((b0 << 4) + array[2]) - ^ (b0 + sum) - ^ ((b0 >> 5) + array[3]); - } while (--n); - - *h0 += b0; - *h1 += b1; - - return 0; + uint32_t sum = 0; + int n = 0; + uint32_t b0 = 0; + uint32_t b1 = 0; + + b0 = *h0; + b1 = *h1; + + n = rounds; + + do { + sum += DM_DELTA; + b0 += ((b1 << 4) + array[0]) + ^ (b1 + sum) + ^ ((b1 >> 5) + array[1]); + b1 += ((b0 << 4) + array[2]) + ^ (b0 + sum) + ^ ((b0 >> 5) + array[3]); + } while (--n); + + *h0 += b0; + *h1 += b1; + + return 0; } uint32_t __pad (int len) { - uint32_t pad = 0; + uint32_t pad = 0; - pad = (uint32_t) len | ((uint32_t) len << 8); - pad |= pad << 16; + pad = (uint32_t) len | ((uint32_t) len << 8); + pad |= pad << 16; - return pad; + return pad; } uint32_t gf_dm_hashfn (const char *msg, int len) { - uint32_t h0 = 0x9464a485; - uint32_t h1 = 0x542e1a94; - uint32_t array[4]; - uint32_t pad = 0; - int i = 0; - int j = 0; - int full_quads = 0; - int full_words = 0; - int full_bytes = 0; - uint32_t *intmsg = NULL; - int word = 0; - - - intmsg = (uint32_t *) msg; - pad = __pad (len); - - full_bytes = len; - full_words = len / 4; - full_quads = len / 16; - - for (i = 0; i < full_quads; i++) { - for (j = 0; j < 4; j++) { - word = *intmsg; - array[j] = word; - intmsg++; - full_words--; - full_bytes -= 4; - } - dm_round (DM_PARTROUNDS, &array[0], &h0, &h1); - } - - for (j = 0; j < 4; j++) { - if (full_words) { - word = *intmsg; - array[j] = word; - intmsg++; - full_words--; - full_bytes -= 4; - } else { - array[j] = pad; - while (full_bytes) { - array[j] <<= 8; - array[j] |= msg[len - full_bytes]; - full_bytes--; - } - } - } - dm_round (DM_FULLROUNDS, &array[0], &h0, &h1); - - return h0 ^ h1; + uint32_t h0 = 0x9464a485; + uint32_t h1 = 0x542e1a94; + uint32_t array[4]; + uint32_t pad = 0; + int i = 0; + int j = 0; + int full_quads = 0; + int full_words = 0; + int full_bytes = 0; + uint32_t *intmsg = NULL; + int word = 0; + + + intmsg = (uint32_t *) msg; + pad = __pad (len); + + full_bytes = len; + full_words = len / 4; + full_quads = len / 16; + + for (i = 0; i < full_quads; i++) { + for (j = 0; j < 4; j++) { + word = *intmsg; + array[j] = word; + intmsg++; + full_words--; + full_bytes -= 4; + } + dm_round (DM_PARTROUNDS, &array[0], &h0, &h1); + } + + for (j = 0; j < 4; j++) { + if (full_words) { + word = *intmsg; + array[j] = word; + intmsg++; + full_words--; + full_bytes -= 4; + } else { + array[j] = pad; + while (full_bytes) { + array[j] <<= 8; + array[j] |= msg[len - full_bytes]; + full_bytes--; + } + } + } + dm_round (DM_FULLROUNDS, &array[0], &h0, &h1); + + return h0 ^ h1; } diff --git a/libglusterfs/src/hashfn.h b/libglusterfs/src/hashfn.h index b8adcc6cc..06ae37e79 100644 --- a/libglusterfs/src/hashfn.h +++ b/libglusterfs/src/hashfn.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com> - This file is part of GlusterFS. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef __HASHFN_H__ @@ -32,6 +23,5 @@ uint32_t SuperFastHash (const char * data, int32_t len); uint32_t gf_dm_hashfn (const char *msg, int len); -uint32_t -ReallySimpleHash (char *path, int len); +uint32_t ReallySimpleHash (char *path, int len); #endif /* __HASHFN_H__ */ diff --git a/libglusterfs/src/iatt.h b/libglusterfs/src/iatt.h new file mode 100644 index 000000000..60ae59047 --- /dev/null +++ b/libglusterfs/src/iatt.h @@ -0,0 +1,331 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + + +#ifndef _IATT_H +#define _IATT_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> +#include <sys/stat.h> /* for iatt <--> stat conversions */ +#include <unistd.h> + +#include "compat.h" +#include "uuid.h" + +typedef enum { + IA_INVAL = 0, + IA_IFREG, + IA_IFDIR, + IA_IFLNK, + IA_IFBLK, + IA_IFCHR, + IA_IFIFO, + IA_IFSOCK +} ia_type_t; + + +typedef struct { + uint8_t suid:1; + uint8_t sgid:1; + uint8_t sticky:1; + struct { + uint8_t read:1; + uint8_t write:1; + uint8_t exec:1; + } owner, group, other; +} ia_prot_t; + + +struct iatt { + uint64_t ia_ino; /* inode number */ + uuid_t ia_gfid; + uint64_t ia_dev; /* backing device ID */ + ia_type_t ia_type; /* type of file */ + ia_prot_t ia_prot; /* protection */ + uint32_t ia_nlink; /* Link count */ + uint32_t ia_uid; /* user ID of owner */ + uint32_t ia_gid; /* group ID of owner */ + uint64_t ia_rdev; /* device ID (if special file) */ + uint64_t ia_size; /* file size in bytes */ + uint32_t ia_blksize; /* blocksize for filesystem I/O */ + uint64_t ia_blocks; /* number of 512B blocks allocated */ + uint32_t ia_atime; /* last access time */ + uint32_t ia_atime_nsec; + uint32_t ia_mtime; /* last modification time */ + uint32_t ia_mtime_nsec; + uint32_t ia_ctime; /* last status change time */ + uint32_t ia_ctime_nsec; +}; + + +#define IA_ISREG(t) (t == IA_IFREG) +#define IA_ISDIR(t) (t == IA_IFDIR) +#define IA_ISLNK(t) (t == IA_IFLNK) +#define IA_ISBLK(t) (t == IA_IFBLK) +#define IA_ISCHR(t) (t == IA_IFCHR) +#define IA_ISFIFO(t) (t == IA_IFIFO) +#define IA_ISSOCK(t) (t == IA_IFSOCK) + +#define IA_PROT_RUSR(prot) ((prot).owner.read == 1) +#define IA_PROT_WUSR(prot) ((prot).owner.write == 1) +#define IA_PROT_XUSR(prot) ((prot).owner.exec == 1) + +#define IA_PROT_RGRP(prot) ((prot).group.read == 1) +#define IA_PROT_WGRP(prot) ((prot).group.write == 1) +#define IA_PROT_XGRP(prot) ((prot).group.exec == 1) + +#define IA_PROT_ROTH(prot) ((prot).other.read == 1) +#define IA_PROT_WOTH(prot) ((prot).other.write == 1) +#define IA_PROT_XOTH(prot) ((prot).other.exec == 1) + +#define IA_PROT_SUID(prot) ((prot).suid == 1) +#define IA_PROT_SGID(prot) ((prot).sgid == 1) +#define IA_PROT_STCKY(prot) ((prot).sticky == 1) + +#define IA_FILE_OR_DIR(t) (IA_ISREG(t) || IA_ISDIR(t)) + +static inline uint32_t +ia_major (uint64_t ia_dev) +{ + return (uint32_t) (ia_dev >> 32); +} + + +static inline uint32_t +ia_minor (uint64_t ia_dev) +{ + return (uint32_t) (ia_dev & 0xffffffff); +} + + +static inline uint64_t +ia_makedev (uint32_t ia_maj, uint32_t ia_min) +{ + return ((((uint64_t) ia_maj) << 32) | ia_min); +} + + +static inline ia_prot_t +ia_prot_from_st_mode (mode_t mode) +{ + ia_prot_t ia_prot = {0, }; + + if (mode & S_ISUID) + ia_prot.suid = 1; + if (mode & S_ISGID) + ia_prot.sgid = 1; + if (mode & S_ISVTX) + ia_prot.sticky = 1; + + if (mode & S_IRUSR) + ia_prot.owner.read = 1; + if (mode & S_IWUSR) + ia_prot.owner.write = 1; + if (mode & S_IXUSR) + ia_prot.owner.exec = 1; + + if (mode & S_IRGRP) + ia_prot.group.read = 1; + if (mode & S_IWGRP) + ia_prot.group.write = 1; + if (mode & S_IXGRP) + ia_prot.group.exec = 1; + + if (mode & S_IROTH) + ia_prot.other.read = 1; + if (mode & S_IWOTH) + ia_prot.other.write = 1; + if (mode & S_IXOTH) + ia_prot.other.exec = 1; + + return ia_prot; +} + + +static inline ia_type_t +ia_type_from_st_mode (mode_t mode) +{ + ia_type_t type = IA_INVAL; + + if (S_ISREG (mode)) + type = IA_IFREG; + if (S_ISDIR (mode)) + type = IA_IFDIR; + if (S_ISLNK (mode)) + type = IA_IFLNK; + if (S_ISBLK (mode)) + type = IA_IFBLK; + if (S_ISCHR (mode)) + type = IA_IFCHR; + if (S_ISFIFO (mode)) + type = IA_IFIFO; + if (S_ISSOCK (mode)) + type = IA_IFSOCK; + + return type; +} + + +static inline mode_t +st_mode_from_ia (ia_prot_t prot, ia_type_t type) +{ + mode_t st_mode = 0; + uint32_t type_bit = 0; + uint32_t prot_bit = 0; + + switch (type) { + case IA_IFREG: + type_bit = S_IFREG; + break; + case IA_IFDIR: + type_bit = S_IFDIR; + break; + case IA_IFLNK: + type_bit = S_IFLNK; + break; + case IA_IFBLK: + type_bit = S_IFBLK; + break; + case IA_IFCHR: + type_bit = S_IFCHR; + break; + case IA_IFIFO: + type_bit = S_IFIFO; + break; + case IA_IFSOCK: + type_bit = S_IFSOCK; + break; + case IA_INVAL: + break; + } + + if (prot.suid) + prot_bit |= S_ISUID; + if (prot.sgid) + prot_bit |= S_ISGID; + if (prot.sticky) + prot_bit |= S_ISVTX; + + if (prot.owner.read) + prot_bit |= S_IRUSR; + if (prot.owner.write) + prot_bit |= S_IWUSR; + if (prot.owner.exec) + prot_bit |= S_IXUSR; + + if (prot.group.read) + prot_bit |= S_IRGRP; + if (prot.group.write) + prot_bit |= S_IWGRP; + if (prot.group.exec) + prot_bit |= S_IXGRP; + + if (prot.other.read) + prot_bit |= S_IROTH; + if (prot.other.write) + prot_bit |= S_IWOTH; + if (prot.other.exec) + prot_bit |= S_IXOTH; + + st_mode = (type_bit | prot_bit); + + return st_mode; +} + + +static inline int +iatt_from_stat (struct iatt *iatt, struct stat *stat) +{ + iatt->ia_dev = stat->st_dev; + iatt->ia_ino = stat->st_ino; + + iatt->ia_type = ia_type_from_st_mode (stat->st_mode); + iatt->ia_prot = ia_prot_from_st_mode (stat->st_mode); + + iatt->ia_nlink = stat->st_nlink; + iatt->ia_uid = stat->st_uid; + iatt->ia_gid = stat->st_gid; + + iatt->ia_rdev = ia_makedev (major (stat->st_rdev), + minor (stat->st_rdev)); + + iatt->ia_size = stat->st_size; + iatt->ia_blksize = stat->st_blksize; + iatt->ia_blocks = stat->st_blocks; + + /* There is a possibility that the backend FS (like XFS) can + allocate blocks beyond EOF for better performance reasons, which + results in 'st_blocks' with higher values than what is consumed by + the file descriptor. This would break few logic inside GlusterFS, + like quota behavior etc, thus we need the exact number of blocks + which are consumed by the file to the higher layers inside GlusterFS. + Currently, this logic won't work for sparse files (ie, file with + holes) + */ + { + uint64_t maxblocks; + + maxblocks = (iatt->ia_size + 511) / 512; + + if (iatt->ia_blocks > maxblocks) + iatt->ia_blocks = maxblocks; + } + + iatt->ia_atime = stat->st_atime; + iatt->ia_atime_nsec = ST_ATIM_NSEC (stat); + + iatt->ia_mtime = stat->st_mtime; + iatt->ia_mtime_nsec = ST_MTIM_NSEC (stat); + + iatt->ia_ctime = stat->st_ctime; + iatt->ia_ctime_nsec = ST_CTIM_NSEC (stat); + + return 0; +} + + +static inline int +iatt_to_stat (struct iatt *iatt, struct stat *stat) +{ + stat->st_dev = iatt->ia_dev; + stat->st_ino = iatt->ia_ino; + + stat->st_mode = st_mode_from_ia (iatt->ia_prot, iatt->ia_type); + + stat->st_nlink = iatt->ia_nlink; + stat->st_uid = iatt->ia_uid; + stat->st_gid = iatt->ia_gid; + + stat->st_rdev = makedev (ia_major (iatt->ia_rdev), + ia_minor (iatt->ia_rdev)); + + stat->st_size = iatt->ia_size; + stat->st_blksize = iatt->ia_blksize; + stat->st_blocks = iatt->ia_blocks; + + stat->st_atime = iatt->ia_atime; + ST_ATIM_NSEC_SET (stat, iatt->ia_atime_nsec); + + stat->st_mtime = iatt->ia_mtime; + ST_MTIM_NSEC_SET (stat, iatt->ia_mtime_nsec); + + stat->st_ctime = iatt->ia_ctime; + ST_CTIM_NSEC_SET (stat, iatt->ia_ctime_nsec); + + return 0; +} + + +#endif /* _IATT_H */ diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c index ff65d101e..15e0ccf78 100644 --- a/libglusterfs/src/inode.c +++ b/libglusterfs/src/inode.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -23,6 +14,7 @@ #endif #include "inode.h" +#include "fd.h" #include "common-utils.h" #include "statedump.h" #include <pthread.h> @@ -32,21 +24,21 @@ #include <time.h> #include <assert.h> -/* TODO: +/* TODO: move latest accessed dentry to list_head of inode */ -#define INODE_DUMP_LIST(head, key_buf, key_prefix, list_type) \ -{ \ - int i = 1;\ - inode_t *inode = NULL;\ - list_for_each_entry (inode, head, list) {\ - gf_proc_dump_build_key(key_buf, key_prefix, "%s.%d",list_type,\ - i++);\ - gf_proc_dump_add_section(key_buf);\ - inode_dump(inode, key);\ - }\ -} +#define INODE_DUMP_LIST(head, key_buf, key_prefix, list_type) \ + { \ + int i = 1; \ + inode_t *inode = NULL; \ + list_for_each_entry (inode, head, list) { \ + gf_proc_dump_build_key(key_buf, key_prefix, \ + "%s.%d",list_type, i++); \ + gf_proc_dump_add_section(key_buf); \ + inode_dump(inode, key); \ + } \ + } static inode_t * __inode_unref (inode_t *inode); @@ -54,10 +46,11 @@ __inode_unref (inode_t *inode); static int inode_table_prune (inode_table_t *table); +void +fd_dump (struct list_head *head, char *prefix); + static int -hash_name (ino_t par, - const char *name, - int mod) +hash_dentry (inode_t *parent, const char *name, int mod) { int hash = 0; int ret = 0; @@ -68,21 +61,20 @@ hash_name (ino_t par, hash = (hash << 5) - hash + *name; } } - ret = (hash + par) % mod; + ret = (hash + (unsigned long)parent) % mod; return ret; } static int -hash_inode (ino_t ino, - int mod) +hash_gfid (uuid_t uuid, int mod) { - int hash = 0; + int ret = 0; - hash = ino % mod; + ret = uuid[15] + (uuid[14] << 8); - return hash; + return ret; } @@ -92,21 +84,28 @@ __dentry_hash (dentry_t *dentry) inode_table_t *table = NULL; int hash = 0; + if (!dentry) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found"); + return; + } + table = dentry->inode->table; - hash = hash_name (dentry->parent->ino, dentry->name, - table->hashsize); + hash = hash_dentry (dentry->parent, 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); } static int __is_dentry_hashed (dentry_t *dentry) { + if (!dentry) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found"); + return 0; + } + return !list_empty (&dentry->hash); } @@ -114,6 +113,11 @@ __is_dentry_hashed (dentry_t *dentry) static void __dentry_unhash (dentry_t *dentry) { + if (!dentry) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found"); + return; + } + list_del_init (&dentry->hash); } @@ -121,120 +125,165 @@ __dentry_unhash (dentry_t *dentry) static void __dentry_unset (dentry_t *dentry) { + if (!dentry) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found"); + return; + } + __dentry_unhash (dentry); list_del_init (&dentry->inode_list); - if (dentry->name) - FREE (dentry->name); + GF_FREE (dentry->name); if (dentry->parent) { - list_del_init (&dentry->parent_list); __inode_unref (dentry->parent); dentry->parent = NULL; } - FREE (dentry); + mem_put (dentry); } -static void -__inode_unhash (inode_t *inode) +static int +__foreach_ancestor_dentry (dentry_t *dentry, + int (per_dentry_fn) (dentry_t *dentry, + void *data), + void *data) { - list_del_init (&inode->hash); -} + inode_t *parent = NULL; + dentry_t *each = NULL; + int ret = 0; + if (!dentry) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found"); + return 0; + } -static int -__is_inode_hashed (inode_t *inode) -{ - return !list_empty (&inode->hash); + ret = per_dentry_fn (dentry, data); + if (ret) { + gf_log (THIS->name, GF_LOG_WARNING, "per dentry fn returned %d", ret); + goto out; + } + + parent = dentry->parent; + if (!parent) { + gf_log (THIS->name, GF_LOG_WARNING, "parent not found"); + goto out; + } + + list_for_each_entry (each, &parent->dentry_list, inode_list) { + ret = __foreach_ancestor_dentry (each, per_dentry_fn, data); + if (ret) + goto out; + } +out: + return ret; } -static void -__inode_hash (inode_t *inode) +static int +__check_cycle (dentry_t *a_dentry, void *data) { - inode_table_t *table = NULL; - int hash = 0; + inode_t *link_inode = NULL; - table = inode->table; - hash = hash_inode (inode->ino, table->hashsize); + link_inode = data; - list_del_init (&inode->hash); - list_add (&inode->hash, &table->inode_hash[hash]); + if (a_dentry->parent == link_inode) + return 1; + + return 0; } -static inode_t * -__inode_search (inode_table_t *table, - ino_t ino) +static int +__is_dentry_cyclic (dentry_t *dentry) { - int hash = 0; + int ret = 0; inode_t *inode = NULL; - inode_t *tmp = NULL; + char *name = "<nul>"; - hash = hash_inode (ino, table->hashsize); + ret = __foreach_ancestor_dentry (dentry, __check_cycle, + dentry->inode); + if (ret) { + inode = dentry->inode; - list_for_each_entry (tmp, &table->inode_hash[hash], hash) { - if (tmp->ino == ino) { - inode = tmp; - break; - } + if (dentry->name) + name = dentry->name; + + gf_log (dentry->inode->table->name, GF_LOG_CRITICAL, + "detected cyclic loop formation during inode linkage." + " inode (%s) linking under itself as %s", + uuid_utoa (inode->gfid), name); } - return inode; + return ret; } -static dentry_t * -__dentry_search_for_inode (inode_t *inode, - ino_t par, - const char *name) +static void +__inode_unhash (inode_t *inode) { - dentry_t *dentry = NULL; - dentry_t *tmp = NULL; + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); + return; + } - list_for_each_entry (tmp, &inode->dentry_list, inode_list) { - if (tmp->parent->ino == par && !strcmp (tmp->name, name)) { - dentry = tmp; - break; - } + list_del_init (&inode->hash); +} + + +static int +__is_inode_hashed (inode_t *inode) +{ + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); + return 0; } - return dentry; + return !list_empty (&inode->hash); } -dentry_t * -dentry_search_for_inode (inode_t *inode, - ino_t par, - const char *name) +static void +__inode_hash (inode_t *inode) { - dentry_t *dentry = NULL; - pthread_mutex_lock (&inode->table->lock); - { - dentry = __dentry_search_for_inode (inode, par, name); + inode_table_t *table = NULL; + int hash = 0; + + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); + return; } - pthread_mutex_unlock (&inode->table->lock); - - return dentry; + + table = inode->table; + hash = hash_gfid (inode->gfid, 65536); + + list_del_init (&inode->hash); + list_add (&inode->hash, &table->inode_hash[hash]); } static dentry_t * -__dentry_search (inode_table_t *table, - ino_t par, - const char *name) +__dentry_search_for_inode (inode_t *inode, uuid_t pargfid, const char *name) { - int hash = 0; dentry_t *dentry = NULL; dentry_t *tmp = NULL; - hash = hash_name (par, name, table->hashsize); + if (!inode || !name) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode || name not found"); + return NULL; + } - list_for_each_entry (tmp, &table->name_hash[hash], hash) { - if (tmp->parent->ino == par && !strcmp (tmp->name, name)) { + /* earlier, just the ino was sent, which could have been 0, now + we deal with gfid, and if sent gfid is null or 0, no need to + continue with the check */ + if (!pargfid || uuid_is_null (pargfid)) + return NULL; + + list_for_each_entry (tmp, &inode->dentry_list, inode_list) { + if ((uuid_compare (tmp->parent->gfid, pargfid) == 0) && + !strcmp (tmp->name, name)) { dentry = tmp; break; } @@ -247,31 +296,45 @@ __dentry_search (inode_table_t *table, static void __inode_destroy (inode_t *inode) { - int index = 0; + int index = 0; xlator_t *xl = NULL; + xlator_t *old_THIS = NULL; - if (!inode->_ctx) - goto noctx; + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); + return; + } + + if (!inode->_ctx) { + gf_log (THIS->name, GF_LOG_WARNING, "_ctx not found"); + 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); - } - } + for (index = 0; index < inode->table->ctxcount; index++) { + if (inode->_ctx[index].xl_key) { + xl = (xlator_t *)(long)inode->_ctx[index].xl_key; + old_THIS = THIS; + THIS = xl; + if (xl->cbks->forget) + xl->cbks->forget (xl, inode); + THIS = old_THIS; + } + } - FREE (inode->_ctx); + GF_FREE (inode->_ctx); noctx: LOCK_DESTROY (&inode->lock); // memset (inode, 0xb, sizeof (*inode)); - FREE (inode); + mem_put (inode); } static void __inode_activate (inode_t *inode) { + if (!inode) + return; + list_move (&inode->list, &inode->table->active); inode->table->active_size++; } @@ -282,9 +345,11 @@ __inode_passivate (inode_t *inode) { dentry_t *dentry = NULL; dentry_t *t = NULL; - inode_table_t *table = NULL; - table = inode->table; + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); + return; + } list_move_tail (&inode->list, &inode->table->lru); inode->table->lru_size++; @@ -301,15 +366,16 @@ __inode_retire (inode_t *inode) { dentry_t *dentry = NULL; dentry_t *t = NULL; - inode_table_t *table = NULL; - table = inode->table; + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); + return; + } list_move_tail (&inode->list, &inode->table->purge); inode->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); @@ -320,17 +386,20 @@ __inode_retire (inode_t *inode) static inode_t * __inode_unref (inode_t *inode) { - if (inode->ino == 1) + if (!inode) + return NULL; + + if (__is_root_gfid(inode->gfid)) return inode; - assert (inode->ref); + GF_ASSERT (inode->ref); --inode->ref; if (!inode->ref) { inode->table->active_size--; - if (inode->nlookup && __is_inode_hashed (inode)) + if (inode->nlookup) __inode_passivate (inode); else __inode_retire (inode); @@ -343,6 +412,9 @@ __inode_unref (inode_t *inode) static inode_t * __inode_ref (inode_t *inode) { + if (!inode) + return NULL; + if (!inode->ref) { inode->table->lru_size--; __inode_activate (inode); @@ -358,6 +430,9 @@ inode_unref (inode_t *inode) { inode_table_t *table = NULL; + if (!inode) + return NULL; + table = inode->table; pthread_mutex_lock (&table->lock); @@ -377,6 +452,9 @@ inode_ref (inode_t *inode) { inode_table_t *table = NULL; + if (!inode) + return NULL; + table = inode->table; pthread_mutex_lock (&table->lock); @@ -390,25 +468,38 @@ inode_ref (inode_t *inode) static dentry_t * -__dentry_create (inode_t *inode, - inode_t *parent, - const char *name) +__dentry_create (inode_t *inode, inode_t *parent, const char *name) { dentry_t *newd = NULL; - newd = (void *) CALLOC (1, sizeof (*newd)); + if (!inode || !parent || !name) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, + "inode || parent || name not found"); + return NULL; + } + + newd = mem_get0 (parent->table->dentry_pool); + if (newd == NULL) { + goto out; + } 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); + newd->name = gf_strdup (name); + if (newd->name == NULL) { + mem_put (newd); + newd = NULL; + goto out; + } + + if (parent) + newd->parent = __inode_ref (parent); list_add (&newd->inode_list, &inode->dentry_list); newd->inode = inode; +out: return newd; } @@ -418,9 +509,15 @@ __inode_create (inode_table_t *table) { inode_t *newi = NULL; - newi = (void *) CALLOC (1, sizeof (*newi)); - if (!newi) + if (!table) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "table not found"); return NULL; + } + + newi = mem_get0 (table->inode_pool); + if (!newi) { + goto out; + } newi->table = table; @@ -430,14 +527,21 @@ __inode_create (inode_table_t *table) INIT_LIST_HEAD (&newi->list); INIT_LIST_HEAD (&newi->hash); INIT_LIST_HEAD (&newi->dentry_list); - INIT_LIST_HEAD (&newi->child_list); + newi->_ctx = GF_CALLOC (1, + (sizeof (struct _inode_ctx) * table->ctxcount), + gf_common_mt_inode_ctx); + if (newi->_ctx == NULL) { + LOCK_DESTROY (&newi->lock); + mem_put (newi); + newi = NULL; + goto out; + } list_add (&newi->list, &table->lru); table->lru_size++; - newi->_ctx = CALLOC (1, (sizeof (struct _inode_ctx) * - table->xl->ctx->xl_count)); +out: return newi; } @@ -448,10 +552,17 @@ inode_new (inode_table_t *table) { inode_t *inode = NULL; + if (!table) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); + return NULL; + } + pthread_mutex_lock (&table->lock); { inode = __inode_create (table); - __inode_ref (inode); + if (inode != NULL) { + __inode_ref (inode); + } } pthread_mutex_unlock (&table->lock); @@ -462,6 +573,9 @@ inode_new (inode_table_t *table) static inode_t * __inode_lookup (inode_t *inode) { + if (!inode) + return NULL; + inode->nlookup++; return inode; @@ -471,7 +585,10 @@ __inode_lookup (inode_t *inode) static inode_t * __inode_forget (inode_t *inode, uint64_t nlookup) { - assert (inode->nlookup >= nlookup); + if (!inode) + return NULL; + + GF_ASSERT (inode->nlookup >= nlookup); inode->nlookup -= nlookup; @@ -482,25 +599,48 @@ __inode_forget (inode_t *inode, uint64_t nlookup) } -inode_t * -inode_search (inode_table_t *table, - ino_t ino, - const char *name) +dentry_t * +__dentry_grep (inode_table_t *table, inode_t *parent, const char *name) { - inode_t *inode = NULL; + int hash = 0; dentry_t *dentry = NULL; + dentry_t *tmp = NULL; + + if (!table || !name || !parent) + return NULL; + + hash = hash_dentry (parent, name, table->hashsize); + + list_for_each_entry (tmp, &table->name_hash[hash], hash) { + if (tmp->parent == parent && !strcmp (tmp->name, name)) { + dentry = tmp; + break; + } + } + + return dentry; +} + + +inode_t * +inode_grep (inode_table_t *table, inode_t *parent, const char *name) +{ + inode_t *inode = NULL; + dentry_t *dentry = NULL; + + if (!table || !parent || !name) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, + "table || parent || name not found"); + return 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; - } - + dentry = __dentry_grep (table, parent, name); + + if (dentry) + inode = dentry->inode; + if (inode) __inode_ref (inode); } @@ -510,138 +650,255 @@ inode_search (inode_table_t *table, } -static void -__copy_dentries (inode_t *oldi, inode_t *newi) +inode_t * +inode_resolve (inode_table_t *table, char *path) { - dentry_t *dentry = NULL; - dentry_t *newd = NULL; - dentry_t *tmp = NULL; + char *tmp = NULL, *bname = NULL, *str = NULL, *saveptr = NULL; + inode_t *inode = NULL, *parent = NULL; - list_for_each_entry (dentry, &oldi->dentry_list, inode_list) { - tmp = __dentry_search_for_inode (newi, dentry->parent->ino, - dentry->name); + if ((path == NULL) || (table == NULL)) { + goto out; + } - if (!tmp) { - newd = __dentry_create (newi, dentry->parent, - dentry->name); - } else { - newd = tmp; + parent = inode_ref (table->root); + str = tmp = gf_strdup (path); + + while (1) { + bname = strtok_r (str, "/", &saveptr); + if (bname == NULL) { + break; } - if (__is_dentry_hashed (dentry)) { - __dentry_unhash (dentry); - __dentry_hash (newd); + if (inode != NULL) { + inode_unref (inode); } + + inode = inode_grep (table, parent, bname); + if (inode == NULL) { + break; + } + + if (parent != NULL) { + inode_unref (parent); + } + + parent = inode_ref (inode); + str = NULL; } + + inode_unref (parent); + GF_FREE (tmp); +out: + return inode; } -static void -__adopt_children (inode_t *oldi, inode_t *newi) +int +inode_grep_for_gfid (inode_table_t *table, inode_t *parent, const char *name, + uuid_t gfid, ia_type_t *type) { - dentry_t *dentry = NULL; + inode_t *inode = NULL; + dentry_t *dentry = NULL; + int ret = -1; + + if (!table || !parent || !name) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, + "table || parent || name not found"); + return ret; + } - list_for_each_entry (dentry, &oldi->child_list, parent_list) { - assert (dentry->parent == oldi); - __inode_unref (dentry->parent); - dentry->parent = __inode_ref (newi); + pthread_mutex_lock (&table->lock); + { + dentry = __dentry_grep (table, parent, name); + + if (dentry) + inode = dentry->inode; + + if (inode) { + uuid_copy (gfid, inode->gfid); + *type = inode->ia_type; + ret = 0; + } } + pthread_mutex_unlock (&table->lock); - list_splice_init (&oldi->child_list, &newi->child_list); + return ret; } -static void -__inode_replace (inode_t *oldi, inode_t *newi) +/* return 1 if gfid is of root, 0 if not */ +gf_boolean_t +__is_root_gfid (uuid_t gfid) { - gf_log (oldi->table->name, GF_LOG_DEBUG, - "inode(%"PRId64") replaced (%"PRId64"", - oldi->ino, newi->ino); + uuid_t root; + + memset (root, 0, 16); + root[15] = 1; - __copy_dentries (oldi, newi); - __adopt_children (oldi, newi); + if (uuid_compare (gfid, root) == 0) + return _gf_true; - newi->nlookup = oldi->nlookup; - newi->generation = oldi->generation; + return _gf_false; +} + + +inode_t * +__inode_find (inode_table_t *table, uuid_t gfid) +{ + inode_t *inode = NULL; + inode_t *tmp = NULL; + int hash = 0; + + if (!table) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "table not found"); + goto out; + } + + if (__is_root_gfid (gfid)) + return table->root; + + hash = hash_gfid (gfid, 65536); + + list_for_each_entry (tmp, &table->inode_hash[hash], hash) { + if (uuid_compare (tmp->gfid, gfid) == 0) { + inode = tmp; + break; + } + } + +out: + return inode; +} + + +inode_t * +inode_find (inode_table_t *table, uuid_t gfid) +{ + inode_t *inode = NULL; - oldi->nlookup = 0; - oldi->generation = 0; + if (!table) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "table not found"); + return NULL; + } - __inode_unhash (oldi); + pthread_mutex_lock (&table->lock); + { + inode = __inode_find (table, gfid); + if (inode) + __inode_ref (inode); + } + pthread_mutex_unlock (&table->lock); - if (newi->ino == 1) - newi->table->root = newi; + return inode; } static inode_t * -__inode_link (inode_t *inode, - inode_t *parent, - const char *name, - struct stat *stbuf) +__inode_link (inode_t *inode, inode_t *parent, const char *name, + struct iatt *iatt) { dentry_t *dentry = NULL; dentry_t *old_dentry = NULL; inode_t *old_inode = NULL; inode_table_t *table = NULL; + inode_t *link_inode = NULL; + + if (!inode) + return NULL; table = inode->table; + if (!table) + return NULL; + + if (parent) { + /* We should prevent inode linking between different + inode tables. This can cause errors which is very + hard to catch/debug. */ + if (inode->table != parent->table) { + GF_ASSERT (!"link attempted b/w inodes of diff table"); + } + } + + link_inode = inode; - if (inode->ino) - assert (inode->ino == stbuf->st_ino); + if (!__is_inode_hashed (inode)) { + if (!iatt) + return NULL; - inode->ino = stbuf->st_ino; - inode->st_mode = stbuf->st_mode; + if (uuid_is_null (iatt->ia_gfid)) + return NULL; - old_inode = __inode_search (table, stbuf->st_ino); + old_inode = __inode_find (table, iatt->ia_gfid); - if (old_inode && old_inode != inode) { - __inode_ref (old_inode); - __inode_replace (old_inode, inode); - __inode_unref (old_inode); + if (old_inode) { + link_inode = old_inode; + } else { + uuid_copy (inode->gfid, iatt->ia_gfid); + inode->ia_type = iatt->ia_type; + __inode_hash (inode); + } } - __inode_hash (inode); + if (name) { + if (!strcmp(name, ".") || !strcmp(name, "..")) + return link_inode; + } + + /* use only link_inode beyond this point */ if (parent) { - dentry = __dentry_search_for_inode (inode, parent->ino, name); - if (!dentry) { - dentry = __dentry_create (inode, parent, name); - } + old_dentry = __dentry_grep (table, parent, name); + + if (!old_dentry || old_dentry->inode != link_inode) { + dentry = __dentry_create (link_inode, parent, name); + if (!dentry) { + gf_log_callingfn (THIS->name, GF_LOG_ERROR, + "dentry create failed on " + "inode %s with parent %s", + uuid_utoa (link_inode->gfid), + uuid_utoa (parent->gfid)); + return NULL; + } + if (old_inode && __is_dentry_cyclic (dentry)) { + __dentry_unset (dentry); + return NULL; + } + __dentry_hash (dentry); - old_dentry = __dentry_search (table, parent->ino, name); - if (old_dentry) { - __dentry_unhash (old_dentry); + if (old_dentry) + __dentry_unset (old_dentry); } + } - __dentry_hash (dentry); - } else if (inode->ino != 1) { - gf_log (table->name, GF_LOG_DEBUG, - "child (%"PRId64") without a parent!", inode->ino); - } - - return inode; + return link_inode; } -int -inode_link (inode_t *inode, - inode_t *parent, - const char *name, - struct stat *stbuf) +inode_t * +inode_link (inode_t *inode, inode_t *parent, const char *name, + struct iatt *iatt) { inode_table_t *table = NULL; + inode_t *linked_inode = NULL; + + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); + return NULL; + } table = inode->table; pthread_mutex_lock (&table->lock); { - inode = __inode_link (inode, parent, name, stbuf); + linked_inode = __inode_link (inode, parent, name, iatt); + + if (linked_inode) + __inode_ref (linked_inode); } pthread_mutex_unlock (&table->lock); inode_table_prune (table); - return 0; + return linked_inode; } @@ -649,20 +906,17 @@ int inode_lookup (inode_t *inode) { inode_table_t *table = NULL; - inode_t *lookup_inode = NULL; + + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); + return -1; + } table = inode->table; - lookup_inode = inode; pthread_mutex_lock (&table->lock); { - if (!__is_inode_hashed (inode)) { - lookup_inode = __inode_search (table, inode->ino); - if (lookup_inode == NULL) - lookup_inode = inode; - } - - __inode_lookup (lookup_inode); + __inode_lookup (inode); } pthread_mutex_unlock (&table->lock); @@ -674,20 +928,17 @@ int inode_forget (inode_t *inode, uint64_t nlookup) { inode_table_t *table = NULL; - inode_t *forget_inode = NULL; + + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); + return -1; + } table = inode->table; - forget_inode = inode; pthread_mutex_lock (&table->lock); { - if (!__is_inode_hashed (inode)) { - forget_inode = __inode_search (table, inode->ino); - if (forget_inode == NULL) - forget_inode = inode; - } - - __inode_forget (forget_inode, nlookup); + __inode_forget (inode, nlookup); } pthread_mutex_unlock (&table->lock); @@ -696,42 +947,86 @@ inode_forget (inode_t *inode, uint64_t nlookup) return 0; } +/* + * Invalidate an inode. This is invoked when a translator decides that an inode's + * cache is no longer valid. Any translator interested in taking action in this + * situation can define the invalidate callback. + */ +int +inode_invalidate(inode_t *inode) +{ + int ret = 0; + xlator_t *xl = NULL; + xlator_t *old_THIS = NULL; + + if (!inode) { + gf_log_callingfn(THIS->name, GF_LOG_WARNING, "inode not found"); + return -1; + } + + /* + * The master xlator is not in the graph but it can define an invalidate + * handler. + */ + xl = inode->table->xl->ctx->master; + if (xl && xl->cbks->invalidate) { + old_THIS = THIS; + THIS = xl; + ret = xl->cbks->invalidate(xl, inode); + THIS = old_THIS; + if (ret) + return ret; + } + + xl = inode->table->xl->graph->first; + while (xl) { + old_THIS = THIS; + THIS = xl; + if (xl->cbks->invalidate) + ret = xl->cbks->invalidate(xl, inode); + THIS = old_THIS; + + if (ret) + break; + + xl = xl->next; + } + + return ret; +} + static void -__inode_unlink (inode_t *inode, - inode_t *parent, - const char *name) +__inode_unlink (inode_t *inode, inode_t *parent, const char *name) { dentry_t *dentry = NULL; - dentry = __dentry_search_for_inode (inode, parent->ino, name); + if (!inode || !parent || !name) + return; + + dentry = __dentry_search_for_inode (inode, parent->gfid, name); - /* dentry NULL for corrupted backend */ - if (dentry) - __dentry_unset (dentry); + /* dentry NULL for corrupted backend */ + if (dentry) + __dentry_unset (dentry); } - + void -inode_unlink (inode_t *inode, - inode_t *parent, - const char *name) +inode_unlink (inode_t *inode, inode_t *parent, const char *name) { inode_table_t *table = NULL; - inode_t *unlink_inode = NULL; + + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); + return; + } table = inode->table; - unlink_inode = inode; pthread_mutex_lock (&table->lock); { - if (!__is_inode_hashed (inode)) { - unlink_inode = __inode_search (table, inode->ino); - if (unlink_inode == NULL) - unlink_inode = inode; - } - - __inode_unlink (unlink_inode, parent, name); + __inode_unlink (inode, parent, name); } pthread_mutex_unlock (&table->lock); @@ -740,33 +1035,21 @@ inode_unlink (inode_t *inode, 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) +inode_rename (inode_table_t *table, inode_t *srcdir, const char *srcname, + inode_t *dstdir, const char *dstname, inode_t *inode, + struct iatt *iatt) { - dentry_t *old_dst = NULL; - inode_t *rename_inode = NULL; + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); + return -1; + } - rename_inode = inode; + table = inode->table; pthread_mutex_lock (&table->lock); { - if (!__is_inode_hashed (inode)) { - rename_inode = __inode_search (table, inode->ino); - if (rename_inode == NULL) - rename_inode = inode; - } - - 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); + __inode_link (inode, dstdir, dstname, iatt); + __inode_unlink (inode, srcdir, srcname); } pthread_mutex_unlock (&table->lock); @@ -779,46 +1062,57 @@ inode_rename (inode_table_t *table, static dentry_t * __dentry_search_arbit (inode_t *inode) { - dentry_t *dentry = NULL; - dentry_t *trav = NULL; + 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 (!inode) + return NULL; - if (!dentry) { - list_for_each_entry (trav, &inode->dentry_list, inode_list) { - dentry = trav; - break; - } - } + list_for_each_entry (trav, &inode->dentry_list, inode_list) { + if (__is_dentry_hashed (trav)) { + dentry = trav; + break; + } + } - return dentry; + 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_parent (inode_t *inode, uuid_t pargfid, const char *name) { inode_t *parent = NULL; inode_table_t *table = NULL; dentry_t *dentry = NULL; + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); + return NULL; + } + table = inode->table; pthread_mutex_lock (&table->lock); { - if (par && name) { - dentry = __dentry_search_for_inode (inode, par, name); + if (pargfid && !uuid_is_null (pargfid) && name) { + dentry = __dentry_search_for_inode (inode, pargfid, name); } else { dentry = __dentry_search_arbit (inode); } if (dentry) - parent = __inode_ref (dentry->parent); + parent = dentry->parent; + + if (parent) + __inode_ref (parent); } pthread_mutex_unlock (&table->lock); @@ -826,108 +1120,136 @@ inode_parent (inode_t *inode, ino_t par, const char *name) } -int32_t -inode_path (inode_t *inode, - const char *name, - char **bufp) +int +__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; - + inode_t *itrav = NULL; + dentry_t *trav = NULL; + size_t i = 0, size = 0; + int64_t ret = 0; + int len = 0; + char *buf = NULL; + + if (!inode || uuid_is_null (inode->gfid)) { + GF_ASSERT (0); + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "invalid inode"); + return -1; + } + 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 (i > PATH_MAX) { - gf_log ("inode", GF_LOG_CRITICAL, - "possible infinite loop detected, " - "forcing break. name=(%s)", name); - ret = -ENOENT; - goto unlock; - } + itrav = inode; + for (trav = __dentry_search_arbit (itrav); trav; + trav = __dentry_search_arbit (itrav)) { + itrav = trav->parent; + i ++; /* "/" */ + i += strlen (trav->name); + if (i > PATH_MAX) { + gf_log (table->name, GF_LOG_CRITICAL, + "possible infinite loop detected, " + "forcing break. name=(%s)", name); + ret = -ENOENT; + goto out; } - - 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 (!__is_root_gfid (itrav->gfid)) { + /* "<gfid:00000000-0000-0000-0000-000000000000>"/path */ + i += GFID_STR_PFX_LEN; + } + + if (name) { + i++; + i += strlen (name); + } + + ret = i; + size = i + 1; + buf = GF_CALLOC (size, sizeof (char), gf_common_mt_char); + if (buf) { + + buf[size - 1] = 0; if (name) { - i++; - i += strlen (name); + len = strlen (name); + strncpy (buf + (i - len), name, len); + buf[i-len-1] = '/'; + i -= (len + 1); } - ret = i; - size = i + 1; - buf = CALLOC (size, sizeof (char)); - if (buf) { + itrav = inode; + for (trav = __dentry_search_arbit (itrav); trav; + trav = __dentry_search_arbit (itrav)) { + itrav = trav->parent; + len = strlen (trav->name); + strncpy (buf + (i - len), trav->name, len); + buf[i-len-1] = '/'; + i -= (len + 1); + } - buf[size - 1] = 0; + if (!__is_root_gfid (itrav->gfid)) { + snprintf (&buf[i-GFID_STR_PFX_LEN], GFID_STR_PFX_LEN, + INODE_PATH_FMT, uuid_utoa (itrav->gfid)); + buf[i-1] = '>'; + } - if (name) { - len = strlen (name); - strncpy (buf + (i - len), name, len); - buf[i-len-1] = '/'; - i -= (len + 1); - } + *bufp = buf; + } else { + ret = -ENOMEM; + } - 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; +out: + if (__is_root_gfid (inode->gfid) && !name) { + ret = 1; + GF_FREE (buf); + buf = GF_CALLOC (ret + 1, sizeof (char), gf_common_mt_char); + if (buf) { + strcpy (buf, "/"); + *bufp = buf; } else { - gf_log (table->name, GF_LOG_ERROR, - "out of memory"); - ret = -ENOMEM; - } + 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; - } - } + if (ret < 0) + *bufp = NULL; + return ret; +} + + +int +inode_path (inode_t *inode, const char *name, char **bufp) +{ + inode_table_t *table = NULL; + int ret = -1; + + if (!inode) + return -1; + + table = inode->table; + + pthread_mutex_lock (&table->lock); + { + ret = __inode_path (inode, name, bufp); + } + pthread_mutex_unlock (&table->lock); 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; + inode_t *del = NULL; + inode_t *tmp = NULL; + inode_t *entry = NULL; + if (!table) + return -1; INIT_LIST_HEAD (&purge); @@ -935,7 +1257,7 @@ inode_table_prune (inode_table_t *table) { while (table->lru_limit && table->lru_size > (table->lru_limit)) { - + entry = list_entry (table->lru.next, inode_t, list); table->lru_size--; @@ -945,7 +1267,7 @@ inode_table_prune (inode_table_t *table) } list_splice_init (&table->purge, &purge); - table->purge_size = 0; + table->purge_size = 0; } pthread_mutex_unlock (&table->lock); @@ -964,15 +1286,19 @@ inode_table_prune (inode_table_t *table) static void __inode_table_init_root (inode_table_t *table) { - inode_t *root = NULL; - struct stat stbuf = {0, }; + inode_t *root = NULL; + struct iatt iatt = {0, }; + + if (!table) + return; root = __inode_create (table); - stbuf.st_ino = 1; - stbuf.st_mode = S_IFDIR|0755; + iatt.ia_gfid[15] = 1; + iatt.ia_ino = 1; + iatt.ia_type = IA_IFDIR; - __inode_link (root, NULL, NULL, &stbuf); + __inode_link (root, NULL, NULL, &iatt); table->root = root; } @@ -981,40 +1307,59 @@ inode_table_t * inode_table_new (size_t lru_limit, xlator_t *xl) { inode_table_t *new = NULL; - int ret = 0; + int ret = -1; int i = 0; - new = (void *)calloc (1, sizeof (*new)); + new = (void *)GF_CALLOC(1, sizeof (*new), gf_common_mt_inode_table_t); if (!new) return NULL; new->xl = xl; + new->ctxcount = xl->graph->xl_count + 1; 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; - } + /* In case FUSE is initing the inode table. */ + if (lru_limit == 0) + lru_limit = DEFAULT_INODE_MEMPOOL_ENTRIES; - new->name_hash = (void *)calloc (new->hashsize, - sizeof (struct list_head)); - if (!new->name_hash) { - FREE (new->inode_hash); - FREE (new); - return NULL; - } + new->inode_pool = mem_pool_new (inode_t, lru_limit); - for (i=0; i<new->hashsize; i++) { + if (!new->inode_pool) + goto out; + + new->dentry_pool = mem_pool_new (dentry_t, lru_limit); + + if (!new->dentry_pool) + goto out; + + new->inode_hash = (void *)GF_CALLOC (65536, + sizeof (struct list_head), + gf_common_mt_list_head); + if (!new->inode_hash) + goto out; + + new->name_hash = (void *)GF_CALLOC (new->hashsize, + sizeof (struct list_head), + gf_common_mt_list_head); + if (!new->name_hash) + goto out; + + /* if number of fd open in one process is more than this, + we may hit perf issues */ + new->fd_mem_pool = mem_pool_new (fd_t, 1024); + + if (!new->fd_mem_pool) + goto out; + + for (i = 0; i < 65536; i++) { INIT_LIST_HEAD (&new->inode_hash[i]); } - for (i=0; i<new->hashsize; i++) { + for (i = 0; i < new->hashsize; i++) { INIT_LIST_HEAD (&new->name_hash[i]); } @@ -1022,16 +1367,31 @@ inode_table_new (size_t lru_limit, xlator_t *xl) INIT_LIST_HEAD (&new->lru); INIT_LIST_HEAD (&new->purge); - ret = asprintf (&new->name, "%s/inode", xl->name); + ret = gf_asprintf (&new->name, "%s/inode", xl->name); if (-1 == ret) { /* TODO: This should be ok to continue, check with avati */ ; } - __inode_table_init_root (new); + __inode_table_init_root (new); pthread_mutex_init (&new->lock, NULL); + ret = 0; +out: + if (ret) { + if (new) { + GF_FREE (new->inode_hash); + GF_FREE (new->name_hash); + if (new->dentry_pool) + mem_pool_destroy (new->dentry_pool); + if (new->inode_pool) + mem_pool_destroy (new->inode_pool); + GF_FREE (new); + new = NULL; + } + } + return new; } @@ -1039,236 +1399,489 @@ inode_table_new (size_t lru_limit, xlator_t *xl) 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); + 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; + + if (!itable || !path) + return NULL; - if (pathname) - free (pathname); + /* top-down approach */ + pathname = gf_strdup (path); + if (pathname == NULL) { + goto out; + } + + root = itable->root; + parent = inode_ref (root); + component = strtok_r (pathname, "/", &strtokptr); + + if (component == NULL) + /* root inode */ + inode = inode_ref (parent); + + while (component) { + curr = inode_grep (itable, parent, component); + + if (curr == NULL) { + 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); - return inode; + GF_FREE (pathname); + +out: + return inode; } + int -__inode_ctx_put (inode_t *inode, xlator_t *xlator, uint64_t value) +__inode_ctx_set2 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p, + uint64_t *value2_p) { int ret = 0; int index = 0; - int put_idx = -1; + int set_idx = -1; + + if (!inode || !xlator) + return -1; - for (index = 0; index < xlator->ctx->xl_count; index++) { - if (!inode->_ctx[index].key) { - if (put_idx == -1) - put_idx = index; + for (index = 0; index < inode->table->ctxcount; index++) { + if (!inode->_ctx[index].xl_key) { + if (set_idx == -1) + set_idx = index; /* dont break, to check if key already exists further on */ } - if (inode->_ctx[index].key == (uint64_t)(long) xlator) { - put_idx = index; + if (inode->_ctx[index].xl_key == xlator) { + set_idx = index; break; } } - - if (put_idx == -1) { + + if (set_idx == -1) { ret = -1; goto out;; } - inode->_ctx[put_idx].key = (uint64_t)(long) xlator; - inode->_ctx[put_idx].value = value; + inode->_ctx[set_idx].xl_key = xlator; + if (value1_p) + inode->_ctx[set_idx].value1 = *value1_p; + if (value2_p) + inode->_ctx[set_idx].value2 = *value2_p; out: return ret; } int -inode_ctx_put (inode_t *inode, xlator_t *xlator, uint64_t value) +__inode_ctx_set0 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p) +{ + return __inode_ctx_set2 (inode, xlator, value1_p, NULL); +} + +int +__inode_ctx_set1 (inode_t *inode, xlator_t *xlator, uint64_t *value2_p) +{ + return __inode_ctx_set2 (inode, xlator, NULL, value2_p); +} + + +int +inode_ctx_set2 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p, + uint64_t *value2_p) { int ret = 0; - if (!inode || !xlator) - return -1; + if (!inode || !xlator) + return -1; LOCK (&inode->lock); { - ret = __inode_ctx_put (inode, xlator, value); + ret = __inode_ctx_set2 (inode, xlator, value1_p, value2_p); } UNLOCK (&inode->lock); - return ret; + return ret; } int -__inode_ctx_get (inode_t *inode, xlator_t *xlator, uint64_t *value) +inode_ctx_set1 (inode_t *inode, xlator_t *xlator, uint64_t *value2_p) { - int index = 0; int ret = 0; - for (index = 0; index < xlator->ctx->xl_count; index++) { - if (inode->_ctx[index].key == (uint64_t)(long)xlator) - break; + + if (!inode || !xlator) + return -1; + + LOCK (&inode->lock); + { + ret = __inode_ctx_set1 (inode, xlator, value2_p); + } + UNLOCK (&inode->lock); + + return ret; +} +int +inode_ctx_set0 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p) +{ + int ret = 0; + + if (!inode || !xlator) + return -1; + + LOCK (&inode->lock); + { + ret = __inode_ctx_set0 (inode, xlator, value1_p); } + UNLOCK (&inode->lock); - if (index == xlator->ctx->xl_count) { - ret = -1; + return ret; +} + + +int +__inode_ctx_get2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2) +{ + int index = 0; + int ret = -1; + + if (!inode || !xlator) goto out; + + for (index = 0; index < inode->table->ctxcount; index++) { + if (inode->_ctx[index].xl_key == xlator) + break; } - if (value) - *value = inode->_ctx[index].value; + if (index == inode->table->ctxcount) + goto out; + if (inode->_ctx[index].value1) { + if (value1) + *value1 = inode->_ctx[index].value1; + ret = 0; + } + if (inode->_ctx[index].value2) { + if (value2) + *value2 = inode->_ctx[index].value2; + ret = 0; + } out: return ret; } -int -inode_ctx_get (inode_t *inode, xlator_t *xlator, uint64_t *value) + + +int +__inode_ctx_get0 (inode_t *inode, xlator_t *xlator, uint64_t *value1) { + uint64_t tmp_value = 0; int ret = 0; - if (!inode || !xlator) - return -1; + ret = __inode_ctx_get2 (inode, xlator, &tmp_value, NULL); + if (!ret) + *value1 = tmp_value; + + return ret; +} + +int +__inode_ctx_get1 (inode_t *inode, xlator_t *xlator, uint64_t *value2) +{ + uint64_t tmp_value = 0; + int ret = 0; + + ret = __inode_ctx_get2 (inode, xlator, NULL, &tmp_value); + if (!ret) + *value2 = tmp_value; + + return ret; +} + + +int +inode_ctx_get2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2) +{ + int ret = 0; + + if (!inode || !xlator) + return -1; LOCK (&inode->lock); { - ret = __inode_ctx_get (inode, xlator, value); + ret = __inode_ctx_get2 (inode, xlator, value1, value2); } UNLOCK (&inode->lock); - return ret; + return ret; } +int +inode_ctx_get1 (inode_t *inode, xlator_t *xlator, uint64_t *value2) +{ + int ret = 0; + + if (!inode || !xlator) + return -1; + + LOCK (&inode->lock); + { + ret = __inode_ctx_get1 (inode, xlator, value2); + } + UNLOCK (&inode->lock); -int -inode_ctx_del (inode_t *inode, xlator_t *xlator, uint64_t *value) + return ret; +} + +int +inode_ctx_get0 (inode_t *inode, xlator_t *xlator, uint64_t *value1) { - int index = 0; int ret = 0; - if (!inode || !xlator) - return -1; + if (!inode || !xlator) + return -1; + + LOCK (&inode->lock); + { + ret = __inode_ctx_get0 (inode, xlator, value1); + } + UNLOCK (&inode->lock); + + return ret; +} + + +int +inode_ctx_del2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2) +{ + int index = 0; + int ret = 0; + + if (!inode || !xlator) + return -1; LOCK (&inode->lock); { - for (index = 0; index < xlator->ctx->xl_count; index++) { - if (inode->_ctx[index].key == (uint64_t)(long)xlator) + for (index = 0; index < inode->table->ctxcount; + index++) { + if (inode->_ctx[index].xl_key == xlator) break; } - if (index == xlator->ctx->xl_count) { + if (index == inode->table->ctxcount) { ret = -1; goto unlock; } - if (value) - *value = inode->_ctx[index].value; + if (inode->_ctx[index].value1 && value1) + *value1 = inode->_ctx[index].value1; + if (inode->_ctx[index].value2 && value2) + *value2 = inode->_ctx[index].value2; - inode->_ctx[index].key = 0; - inode->_ctx[index].value = 0; + inode->_ctx[index].key = 0; + inode->_ctx[index].value1 = 0; + inode->_ctx[index].value2 = 0; } unlock: UNLOCK (&inode->lock); - return ret; + return ret; +} + +/* function behavior: + - if value1 is set, value1 in ctx is reset to 0 with current value passed + back in value1 address. + - if value2 is set, value2 in ctx is reset to 0 with current value passed + back in value2 address. + - if both are set, both fields are reset. +*/ +static int +__inode_ctx_reset2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2) +{ + int index = 0; + int ret = 0; + + if (!inode || !xlator) + return -1; + + LOCK (&inode->lock); + { + for (index = 0; index < inode->table->ctxcount; + index++) { + if (inode->_ctx[index].xl_key == xlator) + break; + } + + if (index == inode->table->ctxcount) { + ret = -1; + goto unlock; + } + + if (inode->_ctx[index].value1 && value1) { + *value1 = inode->_ctx[index].value1; + inode->_ctx[index].value1 = 0; + } + if (inode->_ctx[index].value2 && value2) { + *value2 = inode->_ctx[index].value2; + inode->_ctx[index].value2 = 0; + } + } +unlock: + UNLOCK (&inode->lock); + + return ret; +} + +int +inode_ctx_reset2 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p, + uint64_t *value2_p) +{ + uint64_t tmp_value1 = 0; + uint64_t tmp_value2 = 0; + int ret = 0; + + ret = __inode_ctx_reset2 (inode, xlator, &tmp_value1, &tmp_value2); + if (!ret) { + if (value1_p) + *value1_p = tmp_value1; + if (value2_p) + *value2_p = tmp_value2; + } + return ret; +} + +int +inode_ctx_reset1 (inode_t *inode, xlator_t *xlator, uint64_t *value2_p) +{ + uint64_t tmp_value2 = 0; + int ret = 0; + + ret = __inode_ctx_reset2 (inode, xlator, NULL, &tmp_value2); + + if (!ret && value2_p) + *value2_p = tmp_value2; + + return ret; + +} +int +inode_ctx_reset0 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p) +{ + uint64_t tmp_value1 = 0; + int ret = 0; + + ret = __inode_ctx_reset2 (inode, xlator, &tmp_value1, NULL); + + if (!ret && value1_p) + *value1_p = tmp_value1; + + return ret; } + void inode_dump (inode_t *inode, char *prefix) { - char key[GF_DUMP_MAX_BUF_LEN]; - int ret = -1; - xlator_t *xl = NULL; - int i = 0; - - if (!inode) + int ret = -1; + xlator_t *xl = NULL; + int i = 0; + fd_t *fd = NULL; + struct _inode_ctx *inode_ctx = NULL; + struct list_head fd_list; + + if (!inode) return; - ret = TRY_LOCK(&inode->lock); + INIT_LIST_HEAD (&fd_list); + ret = TRY_LOCK(&inode->lock); if (ret != 0) { - gf_log("", GF_LOG_WARNING, "Unable to dump inode" - " errno: %d", errno); return; } - gf_proc_dump_build_key(key, prefix, "nlookup"); - gf_proc_dump_write(key, "%ld", inode->nlookup); - gf_proc_dump_build_key(key, prefix, "generation"); - gf_proc_dump_write(key, "%ld", inode->generation); - gf_proc_dump_build_key(key, prefix, "ref"); - gf_proc_dump_write(key, "%u", inode->ref); - gf_proc_dump_build_key(key, prefix, "ino"); - gf_proc_dump_write(key, "%ld", inode->ino); - gf_proc_dump_build_key(key, prefix, "st_mode"); - gf_proc_dump_write(key, "%d", inode->st_mode); - UNLOCK(&inode->lock); - if (!inode->_ctx) - goto out; - - for (i = 0; i < inode->table->xl->ctx->xl_count; i++) { - if (inode->_ctx[i].key) { - xl = (xlator_t *)(long)inode->_ctx[i].key; - if (xl->dumpops && xl->dumpops->inodectx) - xl->dumpops->inodectx (xl, inode); - } - } + { + gf_proc_dump_write("gfid", "%s", uuid_utoa (inode->gfid)); + gf_proc_dump_write("nlookup", "%ld", inode->nlookup); + gf_proc_dump_write("fd-count", "%u", inode->fd_count); + gf_proc_dump_write("ref", "%u", inode->ref); + gf_proc_dump_write("ia_type", "%d", inode->ia_type); + if (inode->_ctx) { + inode_ctx = GF_CALLOC (inode->table->ctxcount, + sizeof (*inode_ctx), + gf_common_mt_inode_ctx); + if (inode_ctx == NULL) { + goto unlock; + } + + for (i = 0; i < inode->table->ctxcount; + i++) { + inode_ctx[i] = inode->_ctx[i]; + } + } + + if (dump_options.xl_options.dump_fdctx != _gf_true) + goto unlock; + + + list_for_each_entry (fd, &inode->fd_list, inode_list) { + fd_ctx_dump (fd, prefix); + } + } +unlock: + UNLOCK(&inode->lock); + + if (inode_ctx && (dump_options.xl_options.dump_inodectx == _gf_true)) { + for (i = 0; i < inode->table->ctxcount; i++) { + if (inode_ctx[i].xl_key) { + xl = (xlator_t *)(long)inode_ctx[i].xl_key; + if (xl->dumpops && xl->dumpops->inodectx) + xl->dumpops->inodectx (xl, inode); + } + } + } + + GF_FREE (inode_ctx); -out: return; } void inode_table_dump (inode_table_t *itable, char *prefix) { - + char key[GF_DUMP_MAX_BUF_LEN]; int ret = 0; if (!itable) return; - + memset(key, 0, sizeof(key)); - ret = pthread_mutex_trylock(&itable->lock); + ret = pthread_mutex_trylock(&itable->lock); if (ret != 0) { - gf_log("", GF_LOG_WARNING, "Unable to dump inode table" - " errno: %d", errno); return; } @@ -1276,7 +1889,7 @@ inode_table_dump (inode_table_t *itable, char *prefix) gf_proc_dump_write(key, "%d", itable->hashsize); gf_proc_dump_build_key(key, prefix, "name"); gf_proc_dump_write(key, "%s", itable->name); - + gf_proc_dump_build_key(key, prefix, "lru_limit"); gf_proc_dump_write(key, "%d", itable->lru_limit); gf_proc_dump_build_key(key, prefix, "active_size"); @@ -1293,3 +1906,98 @@ inode_table_dump (inode_table_t *itable, char *prefix) pthread_mutex_unlock(&itable->lock); } +void +inode_dump_to_dict (inode_t *inode, char *prefix, dict_t *dict) +{ + int ret = -1; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + + ret = TRY_LOCK (&inode->lock); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.gfid", prefix); + ret = dict_set_dynstr (dict, key, gf_strdup (uuid_utoa (inode->gfid))); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.nlookup", prefix); + ret = dict_set_uint64 (dict, key, inode->nlookup); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.ref", prefix); + ret = dict_set_uint32 (dict, key, inode->ref); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.ia_type", prefix); + ret = dict_set_int32 (dict, key, inode->ia_type); + +out: + UNLOCK (&inode->lock); + return; +} + +void +inode_table_dump_to_dict (inode_table_t *itable, char *prefix, dict_t *dict) +{ + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + int ret = 0; + inode_t *inode = NULL; + int count = 0; + + ret = pthread_mutex_trylock (&itable->lock); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.itable.active_size", prefix); + ret = dict_set_uint32 (dict, key, itable->active_size); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.itable.lru_size", prefix); + ret = dict_set_uint32 (dict, key, itable->lru_size); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.itable.purge_size", prefix); + ret = dict_set_uint32 (dict, key, itable->purge_size); + if (ret) + goto out; + + list_for_each_entry (inode, &itable->active, list) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.itable.active%d", prefix, + count++); + inode_dump_to_dict (inode, key, dict); + } + count = 0; + + list_for_each_entry (inode, &itable->lru, list) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.itable.lru%d", prefix, + count++); + inode_dump_to_dict (inode, key, dict); + } + count = 0; + + list_for_each_entry (inode, &itable->purge, list) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.itable.purge%d", prefix, + count++); + inode_dump_to_dict (inode, key, dict); + } + +out: + pthread_mutex_unlock (&itable->lock); + + return; +} diff --git a/libglusterfs/src/inode.h b/libglusterfs/src/inode.h index e71c6d899..a88976265 100644 --- a/libglusterfs/src/inode.h +++ b/libglusterfs/src/inode.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _INODE_H @@ -28,6 +19,8 @@ #include <stdint.h> #include <sys/types.h> +#define DEFAULT_INODE_MEMPOOL_ENTRIES 32 * 1024 +#define INODE_PATH_FMT "<gfid:%s>" struct _inode_table; typedef struct _inode_table inode_table_t; @@ -39,6 +32,8 @@ typedef struct _dentry dentry_t; #include "list.h" #include "xlator.h" +#include "iatt.h" +#include "uuid.h" struct _inode_table { @@ -57,43 +52,60 @@ struct _inode_table { 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 mem_pool *inode_pool; /* memory pool for inodes */ + struct mem_pool *dentry_pool; /* memory pool for dentrys */ + struct mem_pool *fd_mem_pool; /* memory pool for fd_t */ + int ctxcount; /* number of slots in inode->ctx */ }; 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]; + union { + uint64_t key; + xlator_t *xl_key; + }; + /* if value1 is 0, then field is not set.. */ + union { + uint64_t value1; + void *ptr1; + }; + /* if value2 is 0, then field is not set.. */ + union { + uint64_t value2; + void *ptr2; + }; }; 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) */ - 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 *table; /* the table this inode belongs to */ + uuid_t gfid; + gf_lock_t lock; + uint64_t nlookup; + uint32_t fd_count; /* Open fd count */ + uint32_t ref; /* reference count on this inode */ + ia_type_t ia_type; /* 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 hash; /* hash table pointers */ + struct list_head list; /* active/lru/purge */ + + struct _inode_ctx *_ctx; /* replacement for dict_t *(inode->ctx) */ }; +#define UUID0_STR "00000000-0000-0000-0000-000000000000" +#define GFID_STR_PFX "<gfid:" UUID0_STR ">" +#define GFID_STR_PFX_LEN (sizeof (GFID_STR_PFX) - 1) + inode_table_t * inode_table_new (size_t lru_limit, xlator_t *xl); @@ -101,19 +113,14 @@ 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); + const char *name, struct iatt *stbuf); void -inode_unlink (inode_t *inode, - inode_t *parent, - const char *name); +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_parent (inode_t *inode, uuid_t pargfid, const char *name); inode_t * inode_ref (inode_t *inode); @@ -125,46 +132,120 @@ int inode_lookup (inode_t *inode); int -inode_forget (inode_t *inode, - uint64_t nlookup); +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); +inode_invalidate(inode_t *inode); +int +inode_rename (inode_table_t *table, inode_t *olddir, const char *oldname, + inode_t *newdir, const char *newname, + inode_t *inode, struct iatt *stbuf); -int32_t -inode_path (inode_t *inode, - const char *name, - char **bufp); +inode_t * +inode_grep (inode_table_t *table, inode_t *parent, const char *name); + +int +inode_grep_for_gfid (inode_table_t *table, inode_t *parent, const char *name, + uuid_t gfid, ia_type_t *type); inode_t * -inode_from_path (inode_table_t *table, - const char *path); +inode_find (inode_table_t *table, uuid_t gfid); -dentry_t * -dentry_search_for_inode (inode_t *inode, - ino_t par, - const char *name); +int +inode_path (inode_t *inode, const char *name, char **bufp); int -__inode_ctx_put (inode_t *inode, xlator_t *xlator, uint64_t value); +__inode_path (inode_t *inode, const char *name, char **bufp); +inode_t * +inode_from_path (inode_table_t *table, const char *path); + +inode_t * +inode_resolve (inode_table_t *table, char *path); + +/* deal with inode ctx's both values */ + +int +inode_ctx_set2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2); +int +__inode_ctx_set2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2); + +int +inode_ctx_get2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2); int -inode_ctx_put (inode_t *inode, xlator_t *xlator, uint64_t value); +__inode_ctx_get2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2); int -__inode_ctx_get (inode_t *inode, xlator_t *xlator, uint64_t *value); +inode_ctx_del2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2); + +int +inode_ctx_reset2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2); + +/* deal with inode ctx's 1st value */ + +int +inode_ctx_set0 (inode_t *inode, xlator_t *xlator, uint64_t *value1); + +int +__inode_ctx_set0 (inode_t *inode, xlator_t *xlator, uint64_t *value1); + +int +inode_ctx_get0 (inode_t *inode, xlator_t *xlator, uint64_t *value1); +int +__inode_ctx_get0 (inode_t *inode, xlator_t *xlator, uint64_t *value1); + +int +inode_ctx_reset0 (inode_t *inode, xlator_t *xlator, uint64_t *value1); + +/* deal with inode ctx's 2st value */ + +int +inode_ctx_set1 (inode_t *inode, xlator_t *xlator, uint64_t *value2); + +int +__inode_ctx_set1 (inode_t *inode, xlator_t *xlator, uint64_t *value2); + +int +inode_ctx_get1 (inode_t *inode, xlator_t *xlator, uint64_t *value2); +int +__inode_ctx_get1 (inode_t *inode, xlator_t *xlator, uint64_t *value2); + +int +inode_ctx_reset1 (inode_t *inode, xlator_t *xlator, uint64_t *value2); + + +static inline int +__inode_ctx_put(inode_t *inode, xlator_t *this, uint64_t v) +{ + return __inode_ctx_set0 (inode, this, &v); +} + +static inline int +inode_ctx_put(inode_t *inode, xlator_t *this, uint64_t v) +{ + return inode_ctx_set0 (inode, this, &v); +} + +#define __inode_ctx_set(i,x,v_p) __inode_ctx_set0(i,x,v_p) + +#define inode_ctx_set(i,x,v_p) inode_ctx_set0(i,x,v_p) + +#define inode_ctx_reset(i,x,v) inode_ctx_reset0(i,x,v) + +#define __inode_ctx_get(i,x,v) __inode_ctx_get0(i,x,v) + +#define inode_ctx_get(i,x,v) inode_ctx_get0(i,x,v) -int -inode_ctx_get (inode_t *inode, xlator_t *xlator, uint64_t *value); +#define inode_ctx_del(i,x,v) inode_ctx_del2(i,x,v,0) -int -inode_ctx_del (inode_t *inode, xlator_t *xlator, uint64_t *value); +gf_boolean_t +__is_root_gfid (uuid_t gfid); #endif /* _INODE_H */ diff --git a/libglusterfs/src/iobuf.c b/libglusterfs/src/iobuf.c index e9408f86b..a89e96267 100644 --- a/libglusterfs/src/iobuf.c +++ b/libglusterfs/src/iobuf.c @@ -1,20 +1,11 @@ /* - Copyright (c) 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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ @@ -27,21 +18,70 @@ TODO: implement destroy margins and prefetching of arenas */ +#define IOBUF_ARENA_MAX_INDEX (sizeof (gf_iobuf_init_config) / \ + (sizeof (struct iobuf_init_config))) + +/* Make sure this array is sorted based on pagesize */ +struct iobuf_init_config gf_iobuf_init_config[] = { + /* { pagesize, num_pages }, */ + {128, 1024}, + {512, 512}, + {2 * 1024, 512}, + {8 * 1024, 128}, + {32 * 1024, 64}, + {128 * 1024, 32}, + {256 * 1024, 8}, + {1 * 1024 * 1024, 2}, +}; + +int +gf_iobuf_get_arena_index (size_t page_size) +{ + int i = -1; + + for (i = 0; i < IOBUF_ARENA_MAX_INDEX; i++) { + if (page_size <= gf_iobuf_init_config[i].pagesize) + break; + } + + if (i >= IOBUF_ARENA_MAX_INDEX) + i = -1; + + return i; +} + +size_t +gf_iobuf_get_pagesize (size_t page_size) +{ + int i = 0; + size_t size = 0; + + for (i = 0; i < IOBUF_ARENA_MAX_INDEX; i++) { + size = gf_iobuf_init_config[i].pagesize; + if (page_size <= size) + break; + } + + if (i >= IOBUF_ARENA_MAX_INDEX) + size = -1; + + return size; +} + void __iobuf_arena_init_iobufs (struct iobuf_arena *iobuf_arena) { - size_t arena_size = 0; - size_t page_size = 0; int iobuf_cnt = 0; struct iobuf *iobuf = NULL; int offset = 0; int i = 0; - arena_size = iobuf_arena->iobuf_pool->arena_size; - page_size = iobuf_arena->iobuf_pool->page_size; - iobuf_cnt = arena_size / page_size; + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_arena, out); - iobuf_arena->iobufs = CALLOC (sizeof (*iobuf), iobuf_cnt); + iobuf_cnt = iobuf_arena->page_count; + + iobuf_arena->iobufs = GF_CALLOC (sizeof (*iobuf), iobuf_cnt, + gf_common_mt_iobuf); if (!iobuf_arena->iobufs) return; @@ -57,67 +97,74 @@ __iobuf_arena_init_iobufs (struct iobuf_arena *iobuf_arena) list_add (&iobuf->list, &iobuf_arena->passive.list); iobuf_arena->passive_cnt++; - offset += page_size; + offset += iobuf_arena->page_size; iobuf++; } + +out: + return; } void __iobuf_arena_destroy_iobufs (struct iobuf_arena *iobuf_arena) { - size_t arena_size = 0; - size_t page_size = 0; int iobuf_cnt = 0; struct iobuf *iobuf = NULL; int i = 0; - arena_size = iobuf_arena->iobuf_pool->arena_size; - page_size = iobuf_arena->iobuf_pool->page_size; - iobuf_cnt = arena_size / page_size; + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_arena, out); - if (!iobuf_arena->iobufs) + iobuf_cnt = iobuf_arena->page_count; + + if (!iobuf_arena->iobufs) { + gf_log_callingfn (THIS->name, GF_LOG_ERROR, "iobufs not found"); return; + } iobuf = iobuf_arena->iobufs; for (i = 0; i < iobuf_cnt; i++) { - assert (iobuf->ref == 0); + GF_ASSERT (iobuf->ref == 0); list_del_init (&iobuf->list); iobuf++; } - FREE (iobuf_arena->iobufs); + GF_FREE (iobuf_arena->iobufs); + +out: + return; } void __iobuf_arena_destroy (struct iobuf_arena *iobuf_arena) { - struct iobuf_pool *iobuf_pool = NULL; - - if (!iobuf_arena) - return; - - iobuf_pool = iobuf_arena->iobuf_pool; + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_arena, out); __iobuf_arena_destroy_iobufs (iobuf_arena); if (iobuf_arena->mem_base && iobuf_arena->mem_base != MAP_FAILED) - munmap (iobuf_arena->mem_base, iobuf_pool->arena_size); + munmap (iobuf_arena->mem_base, iobuf_arena->arena_size); - FREE (iobuf_arena); + GF_FREE (iobuf_arena); +out: + return; } struct iobuf_arena * -__iobuf_arena_alloc (struct iobuf_pool *iobuf_pool) +__iobuf_arena_alloc (struct iobuf_pool *iobuf_pool, size_t page_size, + int32_t num_iobufs) { struct iobuf_arena *iobuf_arena = NULL; - size_t arena_size = 0; + size_t rounded_size = 0; - iobuf_arena = CALLOC (sizeof (*iobuf_arena), 1); + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out); + + iobuf_arena = GF_CALLOC (sizeof (*iobuf_arena), 1, + gf_common_mt_iobuf_arena); if (!iobuf_arena) goto err; @@ -126,15 +173,26 @@ __iobuf_arena_alloc (struct iobuf_pool *iobuf_pool) INIT_LIST_HEAD (&iobuf_arena->passive.list); iobuf_arena->iobuf_pool = iobuf_pool; - arena_size = iobuf_pool->arena_size; - iobuf_arena->mem_base = mmap (NULL, arena_size, PROT_READ|PROT_WRITE, + rounded_size = gf_iobuf_get_pagesize (page_size); + + iobuf_arena->page_size = rounded_size; + iobuf_arena->page_count = num_iobufs; + + iobuf_arena->arena_size = rounded_size * num_iobufs; + + iobuf_arena->mem_base = mmap (NULL, iobuf_arena->arena_size, + PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); - if (iobuf_arena->mem_base == MAP_FAILED) + if (iobuf_arena->mem_base == MAP_FAILED) { + gf_log (THIS->name, GF_LOG_WARNING, "maping failed"); goto err; + } __iobuf_arena_init_iobufs (iobuf_arena); - if (!iobuf_arena->iobufs) + if (!iobuf_arena->iobufs) { + gf_log (THIS->name, GF_LOG_ERROR, "init failed"); goto err; + } iobuf_pool->arena_cnt++; @@ -142,56 +200,87 @@ __iobuf_arena_alloc (struct iobuf_pool *iobuf_pool) err: __iobuf_arena_destroy (iobuf_arena); + +out: return NULL; } struct iobuf_arena * -__iobuf_arena_unprune (struct iobuf_pool *iobuf_pool) +__iobuf_arena_unprune (struct iobuf_pool *iobuf_pool, size_t page_size) { - struct iobuf_arena *iobuf_arena = NULL; - struct iobuf_arena *tmp = NULL; + struct iobuf_arena *iobuf_arena = NULL; + struct iobuf_arena *tmp = NULL; + int index = 0; + + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out); - list_for_each_entry (tmp, &iobuf_pool->purge.list, list) { + index = gf_iobuf_get_arena_index (page_size); + if (index == -1) { + gf_log ("iobuf", GF_LOG_ERROR, "page_size (%zu) of " + "iobufs in arena being added is greater than max " + "available", page_size); + return NULL; + } + + list_for_each_entry (tmp, &iobuf_pool->purge[index], list) { list_del_init (&tmp->list); iobuf_arena = tmp; break; } - +out: return iobuf_arena; } struct iobuf_arena * -__iobuf_pool_add_arena (struct iobuf_pool *iobuf_pool) +__iobuf_pool_add_arena (struct iobuf_pool *iobuf_pool, size_t page_size, + int32_t num_pages) { - struct iobuf_arena *iobuf_arena = NULL; + struct iobuf_arena *iobuf_arena = NULL; + int index = 0; + + index = gf_iobuf_get_arena_index (page_size); + if (index == -1) { + gf_log ("iobuf", GF_LOG_ERROR, "page_size (%zu) of " + "iobufs in arena being added is greater than max " + "available", page_size); + return NULL; + } - iobuf_arena = __iobuf_arena_unprune (iobuf_pool); + iobuf_arena = __iobuf_arena_unprune (iobuf_pool, page_size); if (!iobuf_arena) - iobuf_arena = __iobuf_arena_alloc (iobuf_pool); + iobuf_arena = __iobuf_arena_alloc (iobuf_pool, page_size, + num_pages); - if (!iobuf_arena) + if (!iobuf_arena) { + gf_log (THIS->name, GF_LOG_WARNING, "arena not found"); return NULL; + } - list_add_tail (&iobuf_arena->list, &iobuf_pool->arenas.list); + list_add_tail (&iobuf_arena->list, &iobuf_pool->arenas[index]); return iobuf_arena; } struct iobuf_arena * -iobuf_pool_add_arena (struct iobuf_pool *iobuf_pool) +iobuf_pool_add_arena (struct iobuf_pool *iobuf_pool, size_t page_size, + int32_t num_pages) { struct iobuf_arena *iobuf_arena = NULL; + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out); + pthread_mutex_lock (&iobuf_pool->mutex); { - iobuf_arena = __iobuf_pool_add_arena (iobuf_pool); + iobuf_arena = __iobuf_pool_add_arena (iobuf_pool, page_size, + num_pages); } pthread_mutex_unlock (&iobuf_pool->mutex); +out: return iobuf_arena; } @@ -200,91 +289,167 @@ void iobuf_pool_destroy (struct iobuf_pool *iobuf_pool) { struct iobuf_arena *iobuf_arena = NULL; - struct iobuf_arena *tmp = NULL; + struct iobuf_arena *tmp = NULL; + int i = 0; - if (!iobuf_pool) - return; + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out); - list_for_each_entry_safe (iobuf_arena, tmp, &iobuf_pool->arenas.list, - list) { - - list_del_init (&iobuf_arena->list); - iobuf_pool->arena_cnt--; + for (i = 0; i < IOBUF_ARENA_MAX_INDEX; i++) { + list_for_each_entry_safe (iobuf_arena, tmp, + &iobuf_pool->arenas[i], list) { + list_del_init (&iobuf_arena->list); + iobuf_pool->arena_cnt--; + __iobuf_arena_destroy (iobuf_arena); + } - __iobuf_arena_destroy (iobuf_arena); } + +out: + return; } +static void +iobuf_create_stdalloc_arena (struct iobuf_pool *iobuf_pool) +{ + struct iobuf_arena *iobuf_arena = NULL; + + /* No locking required here as its called only once during init */ + iobuf_arena = GF_CALLOC (sizeof (*iobuf_arena), 1, + gf_common_mt_iobuf_arena); + if (!iobuf_arena) + goto err; + + INIT_LIST_HEAD (&iobuf_arena->list); + INIT_LIST_HEAD (&iobuf_arena->active.list); + INIT_LIST_HEAD (&iobuf_arena->passive.list); + + iobuf_arena->iobuf_pool = iobuf_pool; + + iobuf_arena->page_size = 0x7fffffff; + + list_add_tail (&iobuf_arena->list, + &iobuf_pool->arenas[IOBUF_ARENA_MAX_INDEX]); + +err: + return; +} struct iobuf_pool * -iobuf_pool_new (size_t arena_size, size_t page_size) +iobuf_pool_new (void) { struct iobuf_pool *iobuf_pool = NULL; + int i = 0; + size_t page_size = 0; + size_t arena_size = 0; + int32_t num_pages = 0; - if (arena_size < page_size) - return NULL; - - iobuf_pool = CALLOC (sizeof (*iobuf_pool), 1); + iobuf_pool = GF_CALLOC (sizeof (*iobuf_pool), 1, + gf_common_mt_iobuf_pool); if (!iobuf_pool) - return NULL; + goto out; pthread_mutex_init (&iobuf_pool->mutex, NULL); - INIT_LIST_HEAD (&iobuf_pool->arenas.list); - INIT_LIST_HEAD (&iobuf_pool->filled.list); - INIT_LIST_HEAD (&iobuf_pool->purge.list); + for (i = 0; i <= IOBUF_ARENA_MAX_INDEX; i++) { + INIT_LIST_HEAD (&iobuf_pool->arenas[i]); + INIT_LIST_HEAD (&iobuf_pool->filled[i]); + INIT_LIST_HEAD (&iobuf_pool->purge[i]); + } - iobuf_pool->arena_size = arena_size; - iobuf_pool->page_size = page_size; + iobuf_pool->default_page_size = 128 * GF_UNIT_KB; - iobuf_pool_add_arena (iobuf_pool); + arena_size = 0; + for (i = 0; i < IOBUF_ARENA_MAX_INDEX; i++) { + page_size = gf_iobuf_init_config[i].pagesize; + num_pages = gf_iobuf_init_config[i].num_pages; + + iobuf_pool_add_arena (iobuf_pool, page_size, num_pages); + + arena_size += page_size * num_pages; + } + + /* Need an arena to handle all the bigger iobuf requests */ + iobuf_create_stdalloc_arena (iobuf_pool); + + iobuf_pool->arena_size = arena_size; +out: return iobuf_pool; } void -__iobuf_pool_prune (struct iobuf_pool *iobuf_pool) +__iobuf_arena_prune (struct iobuf_pool *iobuf_pool, + struct iobuf_arena *iobuf_arena, int index) { - struct iobuf_arena *iobuf_arena = NULL; - struct iobuf_arena *tmp = NULL; - - if (list_empty (&iobuf_pool->arenas.list)) - /* buffering - preserve this one arena (if at all) - for __iobuf_arena_unprune */ - return; + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out); + + /* code flow comes here only if the arena is in purge list and we can + * free the arena only if we have atleast one arena in 'arenas' list + * (ie, at least few iobufs free in arena), that way, there won't + * be spurious mmap/unmap of buffers + */ + if (list_empty (&iobuf_pool->arenas[index])) + goto out; - list_for_each_entry_safe (iobuf_arena, tmp, &iobuf_pool->purge.list, - list) { - if (iobuf_arena->active_cnt) - continue; + /* All cases matched, destroy */ + list_del_init (&iobuf_arena->list); + iobuf_pool->arena_cnt--; - list_del_init (&iobuf_arena->list); - iobuf_pool->arena_cnt--; + __iobuf_arena_destroy (iobuf_arena); - __iobuf_arena_destroy (iobuf_arena); - } +out: + return; } void iobuf_pool_prune (struct iobuf_pool *iobuf_pool) { + struct iobuf_arena *iobuf_arena = NULL; + struct iobuf_arena *tmp = NULL; + int i = 0; + + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out); + pthread_mutex_lock (&iobuf_pool->mutex); { - __iobuf_pool_prune (iobuf_pool); + for (i = 0; i < IOBUF_ARENA_MAX_INDEX; i++) { + if (list_empty (&iobuf_pool->arenas[i])) { + continue; + } + + list_for_each_entry_safe (iobuf_arena, tmp, + &iobuf_pool->purge[i], list) { + __iobuf_arena_prune (iobuf_pool, iobuf_arena, i); + } + } } pthread_mutex_unlock (&iobuf_pool->mutex); + +out: + return; } struct iobuf_arena * -__iobuf_select_arena (struct iobuf_pool *iobuf_pool) +__iobuf_select_arena (struct iobuf_pool *iobuf_pool, size_t page_size) { - struct iobuf_arena *iobuf_arena = NULL; - struct iobuf_arena *trav = NULL; + struct iobuf_arena *iobuf_arena = NULL; + struct iobuf_arena *trav = NULL; + int index = 0; + + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out); + + index = gf_iobuf_get_arena_index (page_size); + if (index == -1) { + gf_log ("iobuf", GF_LOG_ERROR, "page_size (%zu) of " + "iobufs in arena being added is greater than max " + "available", page_size); + return NULL; + } /* look for unused iobuf from the head-most arena */ - list_for_each_entry (trav, &iobuf_pool->arenas.list, list) { + list_for_each_entry (trav, &iobuf_pool->arenas[index], list) { if (trav->passive_cnt) { iobuf_arena = trav; break; @@ -292,10 +457,12 @@ __iobuf_select_arena (struct iobuf_pool *iobuf_pool) } if (!iobuf_arena) { - /* all arenas were full */ - iobuf_arena = __iobuf_pool_add_arena (iobuf_pool); + /* all arenas were full, find the right count to add */ + iobuf_arena = __iobuf_pool_add_arena (iobuf_pool, page_size, + gf_iobuf_init_config[index].num_pages); } +out: return iobuf_arena; } @@ -317,12 +484,14 @@ __iobuf_unref (struct iobuf *iobuf) return iobuf; } - struct iobuf * -__iobuf_get (struct iobuf_arena *iobuf_arena) +__iobuf_get (struct iobuf_arena *iobuf_arena, size_t page_size) { - struct iobuf *iobuf = NULL; - struct iobuf_pool *iobuf_pool = NULL; + struct iobuf *iobuf = NULL; + struct iobuf_pool *iobuf_pool = NULL; + int index = 0; + + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_arena, out); iobuf_pool = iobuf_arena->iobuf_pool; @@ -335,51 +504,178 @@ __iobuf_get (struct iobuf_arena *iobuf_arena) list_add (&iobuf->list, &iobuf_arena->active.list); iobuf_arena->active_cnt++; + /* no resetting requied for this element */ + iobuf_arena->alloc_cnt++; + + if (iobuf_arena->max_active < iobuf_arena->active_cnt) + iobuf_arena->max_active = iobuf_arena->active_cnt; + if (iobuf_arena->passive_cnt == 0) { + index = gf_iobuf_get_arena_index (page_size); + if (index == -1) { + gf_log ("iobuf", GF_LOG_ERROR, "page_size (%zu) of " + "iobufs in arena being added is greater " + "than max available", page_size); + goto out; + } + list_del (&iobuf_arena->list); - list_add (&iobuf_arena->list, &iobuf_pool->filled.list); + list_add (&iobuf_arena->list, &iobuf_pool->filled[index]); } +out: return iobuf; } - struct iobuf * -iobuf_get (struct iobuf_pool *iobuf_pool) +iobuf_get_from_stdalloc (struct iobuf_pool *iobuf_pool, size_t page_size) { - struct iobuf *iobuf = NULL; + struct iobuf *iobuf = NULL; struct iobuf_arena *iobuf_arena = NULL; + struct iobuf_arena *trav = NULL; + int ret = -1; + + /* The first arena in the 'MAX-INDEX' will always be used for misc */ + list_for_each_entry (trav, &iobuf_pool->arenas[IOBUF_ARENA_MAX_INDEX], + list) { + iobuf_arena = trav; + break; + } + + iobuf = GF_CALLOC (1, sizeof (*iobuf), gf_common_mt_iobuf); + if (!iobuf) + goto out; + + /* 4096 is the alignment */ + iobuf->free_ptr = GF_CALLOC (1, ((page_size + GF_IOBUF_ALIGN_SIZE) - 1), + gf_common_mt_char); + if (!iobuf->free_ptr) + goto out; + + iobuf->ptr = GF_ALIGN_BUF (iobuf->free_ptr, GF_IOBUF_ALIGN_SIZE); + iobuf->iobuf_arena = iobuf_arena; + LOCK_INIT (&iobuf->lock); + + /* Hold a ref because you are allocating and using it */ + iobuf->ref = 1; + + ret = 0; +out: + if (ret && iobuf) { + GF_FREE (iobuf->free_ptr); + GF_FREE (iobuf); + iobuf = NULL; + } + + return iobuf; +} + + +struct iobuf * +iobuf_get2 (struct iobuf_pool *iobuf_pool, size_t page_size) +{ + struct iobuf *iobuf = NULL; + struct iobuf_arena *iobuf_arena = NULL; + size_t rounded_size = 0; + + if (page_size == 0) { + page_size = iobuf_pool->default_page_size; + } + + rounded_size = gf_iobuf_get_pagesize (page_size); + if (rounded_size == -1) { + /* make sure to provide the requested buffer with standard + memory allocations */ + iobuf = iobuf_get_from_stdalloc (iobuf_pool, page_size); + + gf_log ("iobuf", GF_LOG_DEBUG, "request for iobuf of size %zu " + "is serviced using standard calloc() (%p) as it " + "exceeds the maximum available buffer size", + page_size, iobuf); + + iobuf_pool->request_misses++; + return iobuf; + } pthread_mutex_lock (&iobuf_pool->mutex); { /* most eligible arena for picking an iobuf */ - iobuf_arena = __iobuf_select_arena (iobuf_pool); + iobuf_arena = __iobuf_select_arena (iobuf_pool, rounded_size); if (!iobuf_arena) goto unlock; - iobuf = __iobuf_get (iobuf_arena); + iobuf = __iobuf_get (iobuf_arena, rounded_size); if (!iobuf) goto unlock; __iobuf_ref (iobuf); - } + } unlock: pthread_mutex_unlock (&iobuf_pool->mutex); return iobuf; } +struct iobuf * +iobuf_get (struct iobuf_pool *iobuf_pool) +{ + struct iobuf *iobuf = NULL; + struct iobuf_arena *iobuf_arena = NULL; + + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out); + + pthread_mutex_lock (&iobuf_pool->mutex); + { + /* most eligible arena for picking an iobuf */ + iobuf_arena = __iobuf_select_arena (iobuf_pool, + iobuf_pool->default_page_size); + if (!iobuf_arena) { + gf_log (THIS->name, GF_LOG_WARNING, "arena not found"); + goto unlock; + } + + iobuf = __iobuf_get (iobuf_arena, + iobuf_pool->default_page_size); + if (!iobuf) { + gf_log (THIS->name, GF_LOG_WARNING, "iobuf not found"); + goto unlock; + } + + __iobuf_ref (iobuf); + } +unlock: + pthread_mutex_unlock (&iobuf_pool->mutex); + +out: + return iobuf; +} void __iobuf_put (struct iobuf *iobuf, struct iobuf_arena *iobuf_arena) { struct iobuf_pool *iobuf_pool = NULL; + int index = 0; + + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_arena, out); + GF_VALIDATE_OR_GOTO ("iobuf", iobuf, out); iobuf_pool = iobuf_arena->iobuf_pool; + index = gf_iobuf_get_arena_index (iobuf_arena->page_size); + if (index == -1) { + gf_log ("iobuf", GF_LOG_DEBUG, "freeing the iobuf (%p) " + "allocated with standard calloc()", iobuf); + + /* free up properly without bothering about lists and all */ + LOCK_DESTROY (&iobuf->lock); + GF_FREE (iobuf->free_ptr); + GF_FREE (iobuf); + return; + } + if (iobuf_arena->passive_cnt == 0) { list_del (&iobuf_arena->list); - list_add_tail (&iobuf_arena->list, &iobuf_pool->arenas.list); + list_add_tail (&iobuf_arena->list, &iobuf_pool->arenas[index]); } list_del_init (&iobuf->list); @@ -390,8 +686,11 @@ __iobuf_put (struct iobuf *iobuf, struct iobuf_arena *iobuf_arena) if (iobuf_arena->active_cnt == 0) { list_del (&iobuf_arena->list); - list_add_tail (&iobuf_arena->list, &iobuf_pool->purge.list); + list_add_tail (&iobuf_arena->list, &iobuf_pool->purge[index]); + __iobuf_arena_prune (iobuf_pool, iobuf_arena, index); } +out: + return; } @@ -401,16 +700,19 @@ iobuf_put (struct iobuf *iobuf) struct iobuf_arena *iobuf_arena = NULL; struct iobuf_pool *iobuf_pool = NULL; - if (!iobuf) - return; + GF_VALIDATE_OR_GOTO ("iobuf", iobuf, out); iobuf_arena = iobuf->iobuf_arena; - if (!iobuf_arena) + if (!iobuf_arena) { + gf_log (THIS->name, GF_LOG_WARNING, "arena not found"); return; + } iobuf_pool = iobuf_arena->iobuf_pool; - if (!iobuf_pool) + if (!iobuf_pool) { + gf_log (THIS->name, GF_LOG_WARNING, "iobuf pool not found"); return; + } pthread_mutex_lock (&iobuf_pool->mutex); { @@ -418,7 +720,8 @@ iobuf_put (struct iobuf *iobuf) } pthread_mutex_unlock (&iobuf_pool->mutex); - iobuf_pool_prune (iobuf_pool); +out: + return; } @@ -427,8 +730,7 @@ iobuf_unref (struct iobuf *iobuf) { int ref = 0; - if (!iobuf) - return; + GF_VALIDATE_OR_GOTO ("iobuf", iobuf, out); LOCK (&iobuf->lock); { @@ -439,14 +741,16 @@ iobuf_unref (struct iobuf *iobuf) if (!ref) iobuf_put (iobuf); + +out: + return; } struct iobuf * iobuf_ref (struct iobuf *iobuf) { - if (!iobuf) - return NULL; + GF_VALIDATE_OR_GOTO ("iobuf", iobuf, out); LOCK (&iobuf->lock); { @@ -454,6 +758,7 @@ iobuf_ref (struct iobuf *iobuf) } UNLOCK (&iobuf->lock); +out: return iobuf; } @@ -463,7 +768,8 @@ iobref_new () { struct iobref *iobref = NULL; - iobref = CALLOC (sizeof (*iobref), 1); + iobref = GF_CALLOC (sizeof (*iobref), 1, + gf_common_mt_iobref); if (!iobref) return NULL; @@ -478,8 +784,7 @@ iobref_new () struct iobref * iobref_ref (struct iobref *iobref) { - if (!iobref) - return NULL; + GF_VALIDATE_OR_GOTO ("iobuf", iobref, out); LOCK (&iobref->lock); { @@ -487,6 +792,7 @@ iobref_ref (struct iobref *iobref) } UNLOCK (&iobref->lock); +out: return iobref; } @@ -497,10 +803,9 @@ iobref_destroy (struct iobref *iobref) int i = 0; struct iobuf *iobuf = NULL; - if (!iobref) - return; + GF_VALIDATE_OR_GOTO ("iobuf", iobref, out); - for (i = 0; i < 8; i++) { + for (i = 0; i < GF_IOBREF_IOBUF_COUNT; i++) { iobuf = iobref->iobrefs[i]; iobref->iobrefs[i] = NULL; @@ -508,7 +813,10 @@ iobref_destroy (struct iobref *iobref) iobuf_unref (iobuf); } - FREE (iobref); + GF_FREE (iobref); + +out: + return; } @@ -517,8 +825,7 @@ iobref_unref (struct iobref *iobref) { int ref = 0; - if (!iobref) - return; + GF_VALIDATE_OR_GOTO ("iobuf", iobref, out); LOCK (&iobref->lock); { @@ -528,6 +835,32 @@ iobref_unref (struct iobref *iobref) if (!ref) iobref_destroy (iobref); + +out: + return; +} + + +void +iobref_clear (struct iobref *iobref) +{ + int i = 0; + + GF_VALIDATE_OR_GOTO ("iobuf", iobref, out); + + for (; i < GF_IOBREF_IOBUF_COUNT; i++) { + if (iobref->iobrefs[i] != NULL) { + iobuf_unref (iobref->iobrefs[i]); + } else { + /** iobuf's are attched serially */ + break; + } + } + + iobref_unref (iobref); + + out: + return; } @@ -537,7 +870,10 @@ __iobref_add (struct iobref *iobref, struct iobuf *iobuf) int i = 0; int ret = -ENOMEM; - for (i = 0; i < 8; i++) { + GF_VALIDATE_OR_GOTO ("iobuf", iobref, out); + GF_VALIDATE_OR_GOTO ("iobuf", iobuf, out); + + for (i = 0; i < GF_IOBREF_IOBUF_COUNT; i++) { if (iobref->iobrefs[i] == NULL) { iobref->iobrefs[i] = iobuf_ref (iobuf); ret = 0; @@ -545,6 +881,7 @@ __iobref_add (struct iobref *iobref, struct iobuf *iobuf) } } +out: return ret; } @@ -552,13 +889,10 @@ __iobref_add (struct iobref *iobref, struct iobuf *iobuf) int iobref_add (struct iobref *iobref, struct iobuf *iobuf) { - int ret = 0; - - if (!iobref) - return -EINVAL; + int ret = -EINVAL; - if (!iobuf) - return -EINVAL; + GF_VALIDATE_OR_GOTO ("iobuf", iobref, out); + GF_VALIDATE_OR_GOTO ("iobuf", iobuf, out); LOCK (&iobref->lock); { @@ -566,6 +900,7 @@ iobref_add (struct iobref *iobref, struct iobuf *iobuf) } UNLOCK (&iobref->lock); +out: return ret; } @@ -574,12 +909,15 @@ int iobref_merge (struct iobref *to, struct iobref *from) { int i = 0; - int ret = 0; + int ret = -1; struct iobuf *iobuf = NULL; + GF_VALIDATE_OR_GOTO ("iobuf", to, out); + GF_VALIDATE_OR_GOTO ("iobuf", from, out); + LOCK (&from->lock); { - for (i = 0; i < 8; i++) { + for (i = 0; i < GF_IOBREF_IOBUF_COUNT; i++) { iobuf = from->iobrefs[i]; if (!iobuf) @@ -593,6 +931,7 @@ iobref_merge (struct iobref *to, struct iobref *from) } UNLOCK (&from->lock); +out: return ret; } @@ -602,16 +941,19 @@ iobuf_size (struct iobuf *iobuf) { size_t size = 0; - if (!iobuf) - goto out; + GF_VALIDATE_OR_GOTO ("iobuf", iobuf, out); - if (!iobuf->iobuf_arena) + if (!iobuf->iobuf_arena) { + gf_log (THIS->name, GF_LOG_WARNING, "arena not found"); goto out; + } - if (!iobuf->iobuf_arena->iobuf_pool) + if (!iobuf->iobuf_arena->iobuf_pool) { + gf_log (THIS->name, GF_LOG_WARNING, "pool not found"); goto out; + } - size = iobuf->iobuf_arena->iobuf_pool->page_size; + size = iobuf->iobuf_arena->page_size; out: return size; } @@ -623,120 +965,149 @@ iobref_size (struct iobref *iobref) size_t size = 0; int i = 0; - if (!iobref) - goto out; + GF_VALIDATE_OR_GOTO ("iobuf", iobref, out); LOCK (&iobref->lock); { - for (i = 0; i < 8; i++) { + for (i = 0; i < GF_IOBREF_IOBUF_COUNT; i++) { if (iobref->iobrefs[i]) size += iobuf_size (iobref->iobrefs[i]); } } UNLOCK (&iobref->lock); + out: return size; } -void +void iobuf_info_dump (struct iobuf *iobuf, const char *key_prefix) { char key[GF_DUMP_MAX_BUF_LEN]; struct iobuf my_iobuf; int ret = 0; - if (!iobuf) - return; + GF_VALIDATE_OR_GOTO ("iobuf", iobuf, out); memset(&my_iobuf, 0, sizeof(my_iobuf)); - + ret = TRY_LOCK(&iobuf->lock); if (ret) { - gf_log("", GF_LOG_WARNING, "Unable to dump iobuf" - " errno: %d", errno); return; } memcpy(&my_iobuf, iobuf, sizeof(my_iobuf)); UNLOCK(&iobuf->lock); - gf_proc_dump_build_key(key, key_prefix,"ref"); + gf_proc_dump_build_key(key, key_prefix,"ref"); gf_proc_dump_write(key, "%d", my_iobuf.ref); - gf_proc_dump_build_key(key, key_prefix,"ptr"); + gf_proc_dump_build_key(key, key_prefix,"ptr"); gf_proc_dump_write(key, "%p", my_iobuf.ptr); +out: + return; } -void +void iobuf_arena_info_dump (struct iobuf_arena *iobuf_arena, const char *key_prefix) { - char key[GF_DUMP_MAX_BUF_LEN]; - int i = 1; + char key[GF_DUMP_MAX_BUF_LEN]; + int i = 1; struct iobuf *trav; - if (!iobuf_arena) - return; + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_arena, out); gf_proc_dump_build_key(key, key_prefix,"mem_base"); gf_proc_dump_write(key, "%p", iobuf_arena->mem_base); - gf_proc_dump_build_key(key, key_prefix, "active_cnt"); + gf_proc_dump_build_key(key, key_prefix, "active_cnt"); gf_proc_dump_write(key, "%d", iobuf_arena->active_cnt); - gf_proc_dump_build_key(key, key_prefix, "passive_cnt"); + gf_proc_dump_build_key(key, key_prefix, "passive_cnt"); gf_proc_dump_write(key, "%d", iobuf_arena->passive_cnt); - list_for_each_entry (trav, &iobuf_arena->active.list, list) { + gf_proc_dump_build_key(key, key_prefix, "alloc_cnt"); + gf_proc_dump_write(key, "%"PRIu64, iobuf_arena->alloc_cnt); + gf_proc_dump_build_key(key, key_prefix, "max_active"); + gf_proc_dump_write(key, "%"PRIu64, iobuf_arena->max_active); + gf_proc_dump_build_key(key, key_prefix, "page_size"); + gf_proc_dump_write(key, "%"PRIu64, iobuf_arena->page_size); + list_for_each_entry (trav, &iobuf_arena->active.list, list) { gf_proc_dump_build_key(key, key_prefix,"active_iobuf.%d", i++); gf_proc_dump_add_section(key); iobuf_info_dump(trav, key); } - i = 1; - list_for_each_entry (trav, &iobuf_arena->passive.list, list) { - gf_proc_dump_build_key(key, key_prefix, - "passive_iobuf.%d",i++); - gf_proc_dump_add_section(key); - iobuf_info_dump(trav, key); - } - +out: + return; } void iobuf_stats_dump (struct iobuf_pool *iobuf_pool) { - char msg[1024]; - struct iobuf_arena *trav; + struct iobuf_arena *trav = NULL; int i = 1; + int j = 0; int ret = -1; - if (!iobuf_pool) - return; + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out); memset(msg, 0, sizeof(msg)); ret = pthread_mutex_trylock(&iobuf_pool->mutex); if (ret) { - gf_log("", GF_LOG_WARNING, "Unable to dump iobuf pool" - " errno: %d", errno); return; } gf_proc_dump_add_section("iobuf.global"); - gf_proc_dump_write("iobuf.global.iobuf_pool","%p", iobuf_pool); - gf_proc_dump_write("iobuf.global.iobuf_pool.page_size", "%d", - iobuf_pool->page_size); - gf_proc_dump_write("iobuf.global.iobuf_pool.arena_size", "%d", - iobuf_pool->arena_size); - gf_proc_dump_write("iobuf.global.iobuf_pool.arena_cnt", "%d", - iobuf_pool->arena_cnt); - - list_for_each_entry (trav, &iobuf_pool->arenas.list, list) { - snprintf(msg, sizeof(msg), "iobuf.global.iobuf_pool.arena.%d", - i); - gf_proc_dump_add_section(msg); - iobuf_arena_info_dump(trav,msg); - i++; - } - + gf_proc_dump_write("iobuf_pool","%p", iobuf_pool); + gf_proc_dump_write("iobuf_pool.default_page_size", "%d", + iobuf_pool->default_page_size); + gf_proc_dump_write("iobuf_pool.arena_size", "%d", + iobuf_pool->arena_size); + gf_proc_dump_write("iobuf_pool.arena_cnt", "%d", + iobuf_pool->arena_cnt); + gf_proc_dump_write("iobuf_pool.request_misses", "%"PRId64, + iobuf_pool->request_misses); + + for (j = 0; j < IOBUF_ARENA_MAX_INDEX; j++) { + list_for_each_entry (trav, &iobuf_pool->arenas[j], list) { + snprintf(msg, sizeof(msg), + "arena.%d", i); + gf_proc_dump_add_section(msg); + iobuf_arena_info_dump(trav,msg); + i++; + } + list_for_each_entry (trav, &iobuf_pool->purge[j], list) { + snprintf(msg, sizeof(msg), + "purge.%d", i); + gf_proc_dump_add_section(msg); + iobuf_arena_info_dump(trav,msg); + i++; + } + list_for_each_entry (trav, &iobuf_pool->filled[j], list) { + snprintf(msg, sizeof(msg), + "filled.%d", i); + gf_proc_dump_add_section(msg); + iobuf_arena_info_dump(trav,msg); + i++; + } + + } + pthread_mutex_unlock(&iobuf_pool->mutex); +out: + return; +} + + +void +iobuf_to_iovec(struct iobuf *iob, struct iovec *iov) +{ + GF_VALIDATE_OR_GOTO ("iobuf", iob, out); + GF_VALIDATE_OR_GOTO ("iobuf", iov, out); + + iov->iov_base = iobuf_ptr (iob); + iov->iov_len = iobuf_pagesize (iob); + +out: return; } diff --git a/libglusterfs/src/iobuf.h b/libglusterfs/src/iobuf.h index ad453eee2..5595309e1 100644 --- a/libglusterfs/src/iobuf.h +++ b/libglusterfs/src/iobuf.h @@ -1,20 +1,11 @@ /* - Copyright (c) 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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _IOBUF_H_ @@ -24,6 +15,10 @@ #include "common-utils.h" #include <pthread.h> #include <sys/mman.h> +#include <sys/uio.h> + +#define GF_VARIABLE_IOBUF_COUNT 32 +#define GF_IOBREF_IOBUF_COUNT 16 /* Lets try to define the new anonymous mapping * flag, in case the system is still using the @@ -36,6 +31,11 @@ #define MAP_ANONYMOUS MAP_ANON #endif +#define GF_ALIGN_BUF(ptr,bound) ((void *)((unsigned long)(ptr + bound - 1) & \ + (unsigned long)(~(bound - 1)))) + +#define GF_IOBUF_ALIGN_SIZE 512 + /* one allocatable unit for the consumers of the IOBUF API */ /* each unit hosts @page_size bytes of memory */ struct iobuf; @@ -48,6 +48,10 @@ struct iobuf_arena; /* expandable and contractable pool of memory, internally broken into arenas */ struct iobuf_pool; +struct iobuf_init_config { + size_t pagesize; + int32_t num_pages; +}; struct iobuf { union { @@ -63,6 +67,9 @@ struct iobuf { int ref; /* 0 == passive, >0 == active */ void *ptr; /* usable memory region by the consumer */ + + void *free_ptr; /* in case of stdalloc, this is the + one to be freed */ }; @@ -74,6 +81,13 @@ struct iobuf_arena { struct iobuf_arena *prev; }; }; + + size_t page_size; /* size of all iobufs in this arena */ + size_t arena_size; /* this is equal to + (iobuf_pool->arena_size / page_size) + * page_size */ + size_t page_count; + struct iobuf_pool *iobuf_pool; void *mem_base; @@ -85,34 +99,50 @@ struct iobuf_arena { int passive_cnt; struct iobuf passive; /* head node iobuf (unused by itself) */ + uint64_t alloc_cnt; /* total allocs in this pool */ + int max_active; /* max active buffers at a given time */ }; struct iobuf_pool { pthread_mutex_t mutex; - size_t page_size; /* size of all iobufs in this pool */ - size_t arena_size; /* size of memory region in arena */ + size_t arena_size; /* size of memory region in + arena */ + size_t default_page_size; /* default size of iobuf */ int arena_cnt; - struct iobuf_arena arenas; /* head node arena - (unused by itself) */ - struct iobuf_arena filled; /* arenas without free iobufs */ - struct iobuf_arena purge; /* arenas which can be purged */ -}; + struct list_head arenas[GF_VARIABLE_IOBUF_COUNT]; + /* array of arenas. Each element of the array is a list of arenas + holding iobufs of particular page_size */ + struct list_head filled[GF_VARIABLE_IOBUF_COUNT]; + /* array of arenas without free iobufs */ + struct list_head purge[GF_VARIABLE_IOBUF_COUNT]; + /* array of of arenas which can be purged */ + + uint64_t request_misses; /* mostly the requests for higher + value of iobufs */ +}; -struct iobuf_pool *iobuf_pool_new (size_t arena_size, size_t page_size); +struct iobuf_pool *iobuf_pool_new (void); void iobuf_pool_destroy (struct iobuf_pool *iobuf_pool); struct iobuf *iobuf_get (struct iobuf_pool *iobuf_pool); void iobuf_unref (struct iobuf *iobuf); +struct iobuf *iobuf_ref (struct iobuf *iobuf); +void iobuf_pool_destroy (struct iobuf_pool *iobuf_pool); +void iobuf_to_iovec(struct iobuf *iob, struct iovec *iov); + +#define iobuf_ptr(iob) ((iob)->ptr) +#define iobpool_default_pagesize(iobpool) ((iobpool)->default_page_size) +#define iobuf_pagesize(iob) (iob->iobuf_arena->page_size) struct iobref { gf_lock_t lock; int ref; - struct iobuf *iobrefs[8]; + struct iobuf *iobrefs[GF_IOBREF_IOBUF_COUNT]; }; struct iobref *iobref_new (); @@ -120,10 +150,12 @@ struct iobref *iobref_ref (struct iobref *iobref); void iobref_unref (struct iobref *iobref); int iobref_add (struct iobref *iobref, struct iobuf *iobuf); int iobref_merge (struct iobref *to, struct iobref *from); - +void iobref_clear (struct iobref *iobref); size_t iobuf_size (struct iobuf *iobuf); size_t iobref_size (struct iobref *iobref); void iobuf_stats_dump (struct iobuf_pool *iobuf_pool); +struct iobuf * +iobuf_get2 (struct iobuf_pool *iobuf_pool, size_t page_size); #endif /* !_IOBUF_H_ */ diff --git a/libglusterfs/src/latency.c b/libglusterfs/src/latency.c new file mode 100644 index 000000000..b22f72950 --- /dev/null +++ b/libglusterfs/src/latency.c @@ -0,0 +1,189 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + + +/* + * This file contains functions to support dumping of + * latencies of FOPs broken down by subvolumes. + */ + +#include "glusterfs.h" +#include "stack.h" +#include "xlator.h" +#include "common-utils.h" +#include "statedump.h" + + +void +gf_set_fop_from_fn_pointer (call_frame_t *frame, struct xlator_fops *fops, void *fn) +{ + glusterfs_fop_t fop = -1; + + if (fops->stat == *(fop_stat_t *)&fn) + fop = GF_FOP_STAT; + else if (fops->readlink == *(fop_readlink_t *)&fn) + fop = GF_FOP_READLINK; + else if (fops->mknod == *(fop_mknod_t *)&fn) + fop = GF_FOP_MKNOD; + else if (fops->mkdir == *(fop_mkdir_t *)&fn) + fop = GF_FOP_MKDIR; + else if (fops->unlink == *(fop_unlink_t *)&fn) + fop = GF_FOP_UNLINK; + else if (fops->rmdir == *(fop_rmdir_t *)&fn) + fop = GF_FOP_RMDIR; + else if (fops->symlink == *(fop_symlink_t *)&fn) + fop = GF_FOP_SYMLINK; + else if (fops->rename == *(fop_rename_t *)&fn) + fop = GF_FOP_RENAME; + else if (fops->link == *(fop_link_t *)&fn) + fop = GF_FOP_LINK; + else if (fops->truncate == *(fop_truncate_t *)&fn) + fop = GF_FOP_TRUNCATE; + else if (fops->open == *(fop_open_t *)&fn) + fop = GF_FOP_OPEN; + else if (fops->readv == *(fop_readv_t *)&fn) + fop = GF_FOP_READ; + else if (fops->writev == *(fop_writev_t *)&fn) + fop = GF_FOP_WRITE; + else if (fops->statfs == *(fop_statfs_t *)&fn) + fop = GF_FOP_STATFS; + else if (fops->flush == *(fop_flush_t *)&fn) + fop = GF_FOP_FLUSH; + else if (fops->fsync == *(fop_fsync_t *)&fn) + fop = GF_FOP_FSYNC; + else if (fops->setxattr == *(fop_setxattr_t *)&fn) + fop = GF_FOP_SETXATTR; + else if (fops->getxattr == *(fop_getxattr_t *)&fn) + fop = GF_FOP_GETXATTR; + else if (fops->removexattr == *(fop_removexattr_t *)&fn) + fop = GF_FOP_REMOVEXATTR; + else if (fops->opendir == *(fop_opendir_t *)&fn) + fop = GF_FOP_OPENDIR; + else if (fops->fsyncdir == *(fop_fsyncdir_t *)&fn) + fop = GF_FOP_FSYNCDIR; + else if (fops->access == *(fop_access_t *)&fn) + fop = GF_FOP_ACCESS; + else if (fops->create == *(fop_create_t *)&fn) + fop = GF_FOP_CREATE; + else if (fops->ftruncate == *(fop_ftruncate_t *)&fn) + fop = GF_FOP_FTRUNCATE; + else if (fops->fstat == *(fop_fstat_t *)&fn) + fop = GF_FOP_FSTAT; + else if (fops->lk == *(fop_lk_t *)&fn) + fop = GF_FOP_LK; + else if (fops->lookup == *(fop_lookup_t *)&fn) + fop = GF_FOP_LOOKUP; + else if (fops->readdir == *(fop_readdir_t *)&fn) + fop = GF_FOP_READDIR; + else if (fops->inodelk == *(fop_inodelk_t *)&fn) + fop = GF_FOP_INODELK; + else if (fops->finodelk == *(fop_finodelk_t *)&fn) + fop = GF_FOP_FINODELK; + else if (fops->entrylk == *(fop_entrylk_t *)&fn) + fop = GF_FOP_ENTRYLK; + else if (fops->fentrylk == *(fop_fentrylk_t *)&fn) + fop = GF_FOP_FENTRYLK; + else if (fops->xattrop == *(fop_xattrop_t *)&fn) + fop = GF_FOP_XATTROP; + else if (fops->fxattrop == *(fop_fxattrop_t *)&fn) + fop = GF_FOP_FXATTROP; + else if (fops->fgetxattr == *(fop_fgetxattr_t *)&fn) + fop = GF_FOP_FGETXATTR; + else if (fops->fsetxattr == *(fop_fsetxattr_t *)&fn) + fop = GF_FOP_FSETXATTR; + else if (fops->rchecksum == *(fop_rchecksum_t *)&fn) + fop = GF_FOP_RCHECKSUM; + else if (fops->setattr == *(fop_setattr_t *)&fn) + fop = GF_FOP_SETATTR; + else if (fops->fsetattr == *(fop_fsetattr_t *)&fn) + fop = GF_FOP_FSETATTR; + else if (fops->readdirp == *(fop_readdirp_t *)&fn) + fop = GF_FOP_READDIRP; + else if (fops->getspec == *(fop_getspec_t *)&fn) + fop = GF_FOP_GETSPEC; + else + fop = -1; + + frame->op = fop; +} + + +void +gf_update_latency (call_frame_t *frame) +{ + double elapsed; + struct timeval *begin, *end; + + fop_latency_t *lat; + + begin = &frame->begin; + end = &frame->end; + + elapsed = (end->tv_sec - begin->tv_sec) * 1e6 + + (end->tv_usec - begin->tv_usec); + + lat = &frame->this->latencies[frame->op]; + + lat->total += elapsed; + lat->count++; + lat->mean = lat->mean + (elapsed - lat->mean) / lat->count; +} + +void +gf_latency_begin (call_frame_t *frame, void *fn) +{ + gf_set_fop_from_fn_pointer (frame, frame->this->fops, fn); + + gettimeofday (&frame->begin, NULL); +} + + +void +gf_latency_end (call_frame_t *frame) +{ + gettimeofday (&frame->end, NULL); + + gf_update_latency (frame); +} + +void +gf_proc_dump_latency_info (xlator_t *xl) +{ + char key_prefix[GF_DUMP_MAX_BUF_LEN]; + char key[GF_DUMP_MAX_BUF_LEN]; + int i; + + snprintf (key_prefix, GF_DUMP_MAX_BUF_LEN, "%s.latency", xl->name); + gf_proc_dump_add_section (key_prefix); + + for (i = 0; i < GF_FOP_MAXVALUE; i++) { + gf_proc_dump_build_key (key, key_prefix, + (char *)gf_fop_list[i]); + + gf_proc_dump_write (key, "%.03f,%"PRId64",%.03f", + xl->latencies[i].mean, + xl->latencies[i].count, + xl->latencies[i].total); + } + + memset (xl->latencies, 0, sizeof (xl->latencies)); +} + + +void +gf_latency_toggle (int signum, glusterfs_ctx_t *ctx) +{ + if (ctx) { + ctx->measure_latency = !ctx->measure_latency; + gf_log ("[core]", GF_LOG_INFO, + "Latency measurement turned %s", + ctx->measure_latency ? "on" : "off"); + } +} diff --git a/libglusterfs/src/latency.h b/libglusterfs/src/latency.h new file mode 100644 index 000000000..81acbf484 --- /dev/null +++ b/libglusterfs/src/latency.h @@ -0,0 +1,28 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __LATENCY_H__ +#define __LATENCY_H__ + +#include "glusterfs.h" + +typedef struct fop_latency { + uint64_t min; /* min time for the call (microseconds) */ + uint64_t max; /* max time for the call (microseconds) */ + double total; /* total time (microseconds) */ + double std; /* standard deviation */ + double mean; /* mean (microseconds) */ + uint64_t count; +} fop_latency_t; + +void +gf_latency_toggle (int signum, glusterfs_ctx_t *ctx); + +#endif /* __LATENCY_H__ */ diff --git a/libglusterfs/src/list.h b/libglusterfs/src/list.h index 9ef897fd9..392c22ceb 100644 --- a/libglusterfs/src/list.h +++ b/libglusterfs/src/list.h @@ -1,26 +1,16 @@ /* - Copyright (c) 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/>. + Copyright (c) 2008-2014 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _LLIST_H #define _LLIST_H - struct list_head { struct list_head *next; struct list_head *prev; @@ -54,6 +44,31 @@ list_add_tail (struct list_head *new, struct list_head *head) } +/* This function will insert the element to the list in a order. + Order will be based on the compare function provided as a input. + If element to be inserted in ascending order compare should return: + 0: if both the arguments are equal + >0: if first argument is greater than second argument + <0: if first argument is less than second argument */ +static inline void +list_add_order (struct list_head *new, struct list_head *head, + int (*compare)(struct list_head *, struct list_head *)) +{ + struct list_head *pos = head->prev; + + while ( pos != head ) { + if (compare(new, pos) >= 0) + break; + + /* Iterate the list in the reverse order. This will have + better efficiency if the elements are inserted in the + ascending order */ + pos = pos->prev; + } + + list_add (new, pos); +} + static inline void list_del (struct list_head *old) { @@ -120,6 +135,7 @@ list_splice (struct list_head *list, struct list_head *head) } +/* Splice moves @list to the head of the list at @head. */ static inline void list_splice_init (struct list_head *list, struct list_head *head) { @@ -131,11 +147,43 @@ list_splice_init (struct list_head *list, struct list_head *head) } +static inline void +__list_append (struct list_head *list, struct list_head *head) +{ + (head->prev)->next = (list->next); + (list->next)->prev = (head->prev); + (head->prev) = (list->prev); + (list->prev)->next = head; +} + + +static inline void +list_append (struct list_head *list, struct list_head *head) +{ + if (list_empty (list)) + return; + + __list_append (list, head); +} + + +/* Append moves @list to the end of @head */ +static inline void +list_append_init (struct list_head *list, struct list_head *head) +{ + if (list_empty (list)) + return; + + __list_append (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) \ +#define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) @@ -151,4 +199,16 @@ list_splice_init (struct list_head *list, struct list_head *head) &pos->member != (head); \ pos = n, n = list_entry(n->member.next, typeof(*n), member)) +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + + +#define list_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + n = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.prev, typeof(*n), member)) + #endif /* _LLIST_H */ diff --git a/libglusterfs/src/lkowner.h b/libglusterfs/src/lkowner.h new file mode 100644 index 000000000..969d13e50 --- /dev/null +++ b/libglusterfs/src/lkowner.h @@ -0,0 +1,83 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _LK_OWNER_H +#define _LK_OWNER_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#define GF_MAX_LOCK_OWNER_LEN 1024 /* 1kB as per NLM */ + +/* 16strings-16strings-... */ +#define GF_LKOWNER_BUF_SIZE ((GF_MAX_LOCK_OWNER_LEN * 2) + \ + (GF_MAX_LOCK_OWNER_LEN / 8)) + +typedef struct gf_lkowner_ { + int len; + char data[GF_MAX_LOCK_OWNER_LEN]; +} gf_lkowner_t; + + +/* LKOWNER to string functions */ +static inline void +lkowner_unparse (gf_lkowner_t *lkowner, char *buf, int buf_len) +{ + int i = 0; + int j = 0; + + for (i = 0; i < lkowner->len; i++) { + if (i && !(i % 8)) { + buf[j] = '-'; + j++; + } + sprintf (&buf[j], "%02hhx", lkowner->data[i]); + j += 2; + if (j == buf_len) + break; + } + if (j < buf_len) + buf[j] = '\0'; +} + +static inline void +set_lk_owner_from_ptr (gf_lkowner_t *lkowner, void *data) +{ + int i = 0; + int j = 0; + + lkowner->len = sizeof (unsigned long); + for (i = 0, j = 0; i < lkowner->len; i++, j += 8) { + lkowner->data[i] = (char)((((unsigned long)data) >> j) & 0xff); + } +} + +static inline void +set_lk_owner_from_uint64 (gf_lkowner_t *lkowner, uint64_t data) +{ + int i = 0; + int j = 0; + + lkowner->len = 8; + for (i = 0, j = 0; i < lkowner->len; i++, j += 8) { + lkowner->data[i] = (char)((data >> j) & 0xff); + } +} + +/* Return true if the locks have the same owner */ +static inline int +is_same_lkowner (gf_lkowner_t *l1, gf_lkowner_t *l2) +{ + return ((l1->len == l2->len) && !memcmp(l1->data, l2->data, l1->len)); +} + +#endif /* _LK_OWNER_H */ diff --git a/libglusterfs/src/locking.h b/libglusterfs/src/locking.h index 3c3ea79c4..79c6992af 100644 --- a/libglusterfs/src/locking.h +++ b/libglusterfs/src/locking.h @@ -1,20 +1,11 @@ /* - Copyright (c) 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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _LOCKING_H diff --git a/libglusterfs/src/logging.c b/libglusterfs/src/logging.c index 7e1e56f87..5deb90cda 100644 --- a/libglusterfs/src/logging.c +++ b/libglusterfs/src/logging.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -31,576 +22,1016 @@ #include <string.h> #include <stdlib.h> +#ifdef GF_USE_SYSLOG +#include <libintl.h> +#include <syslog.h> +#include <sys/stat.h> +#include "gf-error-codes.h" + +#define GF_JSON_MSG_LENGTH 8192 +#define GF_SYSLOG_CEE_FORMAT \ + "@cee: {\"msg\": \"%s\", \"gf_code\": \"%u\", \"gf_message\": \"%s\"}" +#define GF_LOG_CONTROL_FILE "/etc/glusterfs/logger.conf" +#endif /* GF_USE_SYSLOG */ + #include "xlator.h" #include "logging.h" #include "defaults.h" +#include "glusterfs.h" -static pthread_mutex_t logfile_mutex; -static char *filename = NULL; -static uint8_t logrotate = 0; +#ifdef GF_LINUX_HOST_OS +#include <syslog.h> +#endif -static FILE *logfile = NULL; -static gf_loglevel_t loglevel = GF_LOG_MAX; +#ifdef HAVE_BACKTRACE +#include <execinfo.h> +#endif -gf_loglevel_t gf_log_loglevel; /* extern'd */ -FILE *gf_log_logfile; +/* Ideally this should get moved to logging.h */ +struct _msg_queue { + struct list_head msgs; +}; +struct _log_msg { + const char *msg; + struct list_head queue; +}; -void +void gf_log_logrotate (int signum) { - logrotate = 1; + THIS->ctx->log.logrotate = 1; } +void +gf_log_enable_syslog (void) +{ + THIS->ctx->log.gf_log_syslog = 1; +} -gf_loglevel_t -gf_log_get_loglevel (void) +void +gf_log_disable_syslog (void) { - return loglevel; + THIS->ctx->log.gf_log_syslog = 0; } +gf_loglevel_t +gf_log_get_loglevel (void) +{ + return THIS->ctx->log.loglevel; +} void gf_log_set_loglevel (gf_loglevel_t level) { - gf_log_loglevel = loglevel = level; + THIS->ctx->log.loglevel = level; } -void -gf_log_fini (void) +gf_loglevel_t +gf_log_get_xl_loglevel (void *this) { - pthread_mutex_destroy (&logfile_mutex); + xlator_t *xl = this; + if (!xl) + return 0; + return xl->loglevel; } +void +gf_log_set_xl_loglevel (void *this, gf_loglevel_t level) +{ + xlator_t *xl = this; + if (!xl) + return; + xl->ctx->log.gf_log_xl_log_set = 1; + xl->loglevel = level; +} -int -gf_log_init (const char *file) +void +gf_log_fini (void) { - 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; + pthread_mutex_destroy (&THIS->ctx->log.logfile_mutex); } -static int -dummy_init (xlator_t *xl) -{ - return 0; +#ifdef GF_USE_SYSLOG +/** + * gf_get_error_message -function to get error message for given error code + * @error_code: error code defined by log book + * + * @return: success: string + * failure: NULL + */ +const char * +gf_get_error_message (int error_code) { + return _gf_get_message (error_code); } -static int -gf_log_notify (xlator_t *this_xl, int event, void *data, ...) +/** + * gf_openlog -function to open syslog specific to gluster based on + * existence of file /etc/glusterfs/logger.conf + * @ident: optional identification string similar to openlog() + * @option: optional value to option to openlog(). Passing -1 uses + * 'LOG_PID | LOG_NDELAY' as default + * @facility: optional facility code similar to openlog(). Passing -1 + * uses LOG_DAEMON as default + * + * @return: void + */ +void +gf_openlog (const char *ident, int option, int facility) { - int ret = 0; - - switch (event) { - case GF_EVENT_CHILD_UP: - break; - - case GF_EVENT_CHILD_DOWN: - break; - - default: - ret = default_notify (this_xl, event, data); - break; - } - - return ret; + int _option = option; + int _facility = facility; + + if (-1 == _option) { + _option = LOG_PID | LOG_NDELAY; + } + if (-1 == _facility) { + _facility = LOG_LOCAL1; + } + + setlocale(LC_ALL, ""); + bindtextdomain("gluster", "/usr/share/locale"); + textdomain("gluster"); + + openlog(ident, _option, _facility); } -/* - * Get a dummy xlator for the purpose of central logging. - * An xlator is needed because a transport cannot exist without - * an xlator. +/** + * _json_escape -function to convert string to json encoded string + * @str: input string + * @buf: buffer to store encoded string + * @len: length of @buf + * + * @return: success: last unprocessed character position by pointer in @str + * failure: NULL + * + * Internal function. Heavily inspired by _ul_str_escape() function in + * libumberlog + * + * Sample output: + * [1] str = "devel error" + * buf = "devel error" + * [2] str = "devel error" + * buf = "devel\terror" + * [3] str = "I/O error on "/tmp/foo" file" + * buf = "I/O error on \"/tmp/foo\" file" + * [4] str = "I/O erroron /tmp/bar file" + * buf = "I/O error\u001bon /tmp/bar file" + * */ - -static xlator_t * -__get_dummy_xlator (glusterfs_ctx_t *ctx, const char *remote_host, - const char *transport, uint32_t remote_port) +char * +_json_escape(const char *str, char *buf, size_t len) { - volume_opt_list_t *vol_opt = NULL; - xlator_t * trav = NULL; - - int ret = 0; - - xlator_t * top = NULL; - xlator_t * trans = NULL; - xlator_list_t * parent = NULL; - xlator_list_t * tmp = NULL; - - top = CALLOC (1, sizeof (*top)); - if (!top) - goto out; + static const unsigned char json_exceptions[UCHAR_MAX + 1] = + { + [0x01] = 1, [0x02] = 1, [0x03] = 1, [0x04] = 1, + [0x05] = 1, [0x06] = 1, [0x07] = 1, [0x08] = 1, + [0x09] = 1, [0x0a] = 1, [0x0b] = 1, [0x0c] = 1, + [0x0d] = 1, [0x0e] = 1, [0x0f] = 1, [0x10] = 1, + [0x11] = 1, [0x12] = 1, [0x13] = 1, [0x14] = 1, + [0x15] = 1, [0x16] = 1, [0x17] = 1, [0x18] = 1, + [0x19] = 1, [0x1a] = 1, [0x1b] = 1, [0x1c] = 1, + [0x1d] = 1, [0x1e] = 1, [0x1f] = 1, + ['\\'] = 1, ['"'] = 1 + }; + static const char json_hex_chars[16] = "0123456789abcdef"; + unsigned char *p = NULL; + size_t pos = 0; + + if (!str || !buf || len <= 0) { + return NULL; + } - trans = CALLOC (1, sizeof (*trans)); - if (!trans) - goto out; - - INIT_LIST_HEAD (&top->volume_options); - INIT_LIST_HEAD (&trans->volume_options); - - top->name = "log-dummy"; - top->ctx = ctx; - top->next = trans; - top->init = dummy_init; - top->notify = gf_log_notify; - top->children = (void *) CALLOC (1, sizeof (*top->children)); - - if (!top->children) - goto out; + for (p = (unsigned char *)str; + *p && (pos + 1) < len; + p++) + { + if (json_exceptions[*p] == 0) { + buf[pos++] = *p; + continue; + } - top->children->xlator = trans; - - trans->name = "log-transport"; - trans->ctx = ctx; - trans->prev = top; - trans->init = dummy_init; - trans->notify = default_notify; - trans->options = get_new_dict (); - - parent = CALLOC (1, sizeof(*parent)); - - if (!parent) - goto out; + if ((pos + 2) >= len) { + break; + } - parent->xlator = top; - - if (trans->parents == NULL) - trans->parents = parent; - else { - tmp = trans->parents; - while (tmp->next) - tmp = tmp->next; - tmp->next = parent; - } - - /* TODO: log on failure to set dict */ - if (remote_host) { - ret = dict_set (trans->options, "remote-host", - str_to_data ((char *)remote_host)); - } - - if (remote_port) - ret = dict_set_uint32 (trans->options, "remote-port", - remote_port); - - /* - * 'option remote-subvolume <x>' is needed here even though - * its not used - */ - ret = dict_set_static_ptr (trans->options, "remote-subvolume", - "brick"); - ret = dict_set_static_ptr (trans->options, "disable-handshake", "on"); - ret = dict_set_static_ptr (trans->options, "non-blocking-io", "off"); - - if (transport) { - char *transport_type = CALLOC (1, strlen (transport) + 10); - ERR_ABORT (transport_type); - strcpy(transport_type, transport); - - if (strchr (transport_type, ':')) - *(strchr (transport_type, ':')) = '\0'; - - ret = dict_set_dynstr (trans->options, "transport-type", - transport_type); - } - - xlator_set_type (trans, "protocol/client"); - - trav = top; - while (trav) { - /* Get the first volume_option */ - if (!list_empty (&trav->volume_options)) { - list_for_each_entry (vol_opt, - &trav->volume_options, list) - break; - if ((ret = - validate_xlator_volume_options (trav, - vol_opt->given_opt)) < 0) { - gf_log (trav->name, GF_LOG_ERROR, - "validating translator failed"); - return NULL; + switch (*p) + { + case '\b': + buf[pos++] = '\\'; + buf[pos++] = 'b'; + break; + case '\n': + buf[pos++] = '\\'; + buf[pos++] = 'n'; + break; + case '\r': + buf[pos++] = '\\'; + buf[pos++] = 'r'; + break; + case '\t': + buf[pos++] = '\\'; + buf[pos++] = 't'; + break; + case '\\': + buf[pos++] = '\\'; + buf[pos++] = '\\'; + break; + case '"': + buf[pos++] = '\\'; + buf[pos++] = '"'; + break; + default: + if ((pos + 6) >= len) { + buf[pos] = '\0'; + return (char *)p; } + buf[pos++] = '\\'; + buf[pos++] = 'u'; + buf[pos++] = '0'; + buf[pos++] = '0'; + buf[pos++] = json_hex_chars[(*p) >> 4]; + buf[pos++] = json_hex_chars[(*p) & 0xf]; + break; } - trav = trav->next; - } - - if (xlator_tree_init (top) != 0) - return NULL; + } -out: - return top; + buf[pos] = '\0'; + return (char *)p; } -/* - * Initialize logging to a central server. - * If successful, log messages will be written both to - * the local file and to the remote server. +/** + * gf_syslog -function to submit message to syslog specific to gluster + * @error_code: error code defined by log book + * @facility_priority: facility_priority of syslog() + * @format: optional format string to syslog() + * + * @return: void */ +void +gf_syslog (int error_code, int facility_priority, char *format, ...) +{ + char *msg = NULL; + char json_msg[GF_JSON_MSG_LENGTH]; + GF_UNUSED char *p = NULL; + const char *error_message = NULL; + char json_error_message[GF_JSON_MSG_LENGTH]; + va_list ap; + + error_message = gf_get_error_message (error_code); + + va_start (ap, format); + if (format) { + vasprintf (&msg, format, ap); + p = _json_escape (msg, json_msg, GF_JSON_MSG_LENGTH); + if (error_message) { + p = _json_escape (error_message, json_error_message, + GF_JSON_MSG_LENGTH); + syslog (facility_priority, GF_SYSLOG_CEE_FORMAT, + json_msg, error_code, json_error_message); + } else { + /* ignore the error code because no error message for it + and use normal syslog */ + syslog (facility_priority, "%s", msg); + } + free (msg); + } else { + if (error_message) { + /* no user message: treat error_message as msg */ + syslog (facility_priority, GF_SYSLOG_CEE_FORMAT, + json_error_message, error_code, + json_error_message); + } else { + /* cannot produce log as neither error_message nor + msg available */ + } + } + va_end (ap); +} +#endif /* GF_USE_SYSLOG */ -static xlator_t * logging_xl = NULL; -static int __central_log_enabled = 0; +void +gf_log_globals_init (void *data) +{ + glusterfs_ctx_t *ctx = data; -static pthread_t logging_thread; + pthread_mutex_init (&ctx->log.logfile_mutex, NULL); -struct _msg_queue { - struct list_head msgs; -}; + ctx->log.loglevel = GF_LOG_INFO; + ctx->log.gf_log_syslog = 1; + ctx->log.sys_log_level = GF_LOG_CRITICAL; + +#ifndef GF_USE_SYSLOG +#ifdef GF_LINUX_HOST_OS + /* For the 'syslog' output. one can grep 'GlusterFS' in syslog + for serious logs */ + openlog ("GlusterFS", LOG_PID, LOG_DAEMON); +#endif +#endif +} -static struct _msg_queue msg_queue; +int +gf_log_init (void *data, const char *file, const char *ident) +{ + glusterfs_ctx_t *ctx = NULL; + int fd = -1; -static pthread_cond_t msg_cond; -static pthread_mutex_t msg_cond_mutex; -static pthread_mutex_t msg_queue_mutex; + ctx = data; -struct _log_msg { - const char *msg; - struct list_head queue; -}; +#if defined(GF_USE_SYSLOG) + { + /* use default ident and option */ + /* TODO: make FACILITY configurable than LOG_DAEMON */ + struct stat buf; + + if (stat (GF_LOG_CONTROL_FILE, &buf) == 0) { + /* use syslog logging */ + ctx->log.log_control_file_found = 1; + if (ident) { + /* we need to keep this value as */ + /* syslog uses it on every logging */ + ctx->log.ident = gf_strdup (ident); + gf_openlog (ctx->log.ident, -1, LOG_DAEMON); + } else { + gf_openlog (NULL, -1, LOG_DAEMON); + } + } else { + /* use old style logging */ + ctx->log.log_control_file_found = 0; + } + } +#endif + if (!file){ + fprintf (stderr, "ERROR: no filename specified\n"); + return -1; + } -int32_t -gf_log_central_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) -{ - struct _log_msg *msg = NULL; + if (strcmp (file, "-") == 0) { + ctx->log.gf_log_logfile = stderr; + ctx->log.logfile = stderr; + return 0; + } - msg = (struct _log_msg *) cookie; + ctx->log.filename = gf_strdup (file); + if (!ctx->log.filename) { + fprintf (stderr, "ERROR: updating log-filename failed: %s\n", + strerror (errno)); + return -1; + } + + fd = open (file, O_CREAT | O_RDONLY, S_IRUSR | S_IWUSR); + if (fd < 0) { + fprintf (stderr, "ERROR: failed to create logfile \"%s\" (%s)\n", + file, strerror (errno)); + return -1; + } + close (fd); - FREE (msg->msg); + ctx->log.logfile = fopen (file, "a"); + if (!ctx->log.logfile){ + fprintf (stderr, "ERROR: failed to open logfile \"%s\" (%s)\n", + file, strerror (errno)); + return -1; + } - STACK_DESTROY (frame->root); + ctx->log.gf_log_logfile = ctx->log.logfile; return 0; } +void +set_sys_log_level (gf_loglevel_t level) +{ + THIS->ctx->log.sys_log_level = level; +} -void * -logging_thread_loop (void *arg) +int +_gf_log_nomem (const char *domain, const char *file, + const char *function, int line, gf_loglevel_t level, + size_t size) { - struct _log_msg *msg; + const char *basename = NULL; + xlator_t *this = NULL; + struct timeval tv = {0,}; + int ret = 0; + char msg[8092] = {0,}; + char timestr[256] = {0,}; + char callstr[4096] = {0,}; + glusterfs_ctx_t *ctx = NULL; + + this = THIS; + ctx = this->ctx; + + if (ctx->log.gf_log_xl_log_set) { + if (this->loglevel && (level > this->loglevel)) + goto out; + } + if (level > ctx->log.loglevel) + goto out; - call_frame_t *frame = NULL; + static char *level_strings[] = {"", /* NONE */ + "M", /* EMERGENCY */ + "A", /* ALERT */ + "C", /* CRITICAL */ + "E", /* ERROR */ + "W", /* WARNING */ + "N", /* NOTICE */ + "I", /* INFO */ + "D", /* DEBUG */ + "T", /* TRACE */ + ""}; - while (1) { - pthread_mutex_lock (&msg_cond_mutex); - { - pthread_cond_wait (&msg_cond, &msg_cond_mutex); - - while (!list_empty (&msg_queue.msgs)) { - pthread_mutex_lock (&msg_queue_mutex); - { - msg = list_entry (msg_queue.msgs.next, - struct _log_msg, - queue); - - list_del_init (&msg->queue); - } - pthread_mutex_unlock (&msg_queue_mutex); - - frame = create_frame (logging_xl, - logging_xl->ctx->pool); - - frame->local = logging_xl->private; - - STACK_WIND_COOKIE (frame, (void *) msg, - gf_log_central_cbk, - logging_xl->children->xlator, - logging_xl->children->xlator->mops->log, - msg->msg); - } + if (!domain || !file || !function) { + fprintf (stderr, + "logging: %s:%s():%d: invalid argument\n", + __FILE__, __PRETTY_FUNCTION__, __LINE__); + return -1; + } + basename = strrchr (file, '/'); + if (basename) + basename++; + else + basename = file; + +#if HAVE_BACKTRACE + /* Print 'calling function' */ + do { + void *array[5]; + char **callingfn = NULL; + size_t bt_size = 0; + + bt_size = backtrace (array, 5); + if (bt_size) + callingfn = backtrace_symbols (&array[2], bt_size-2); + if (!callingfn) + break; + + if (bt_size == 5) + snprintf (callstr, 4096, "(-->%s (-->%s (-->%s)))", + callingfn[2], callingfn[1], callingfn[0]); + if (bt_size == 4) + snprintf (callstr, 4096, "(-->%s (-->%s))", + callingfn[1], callingfn[0]); + if (bt_size == 3) + snprintf (callstr, 4096, "(-->%s)", callingfn[0]); + + free (callingfn); + } while (0); +#endif /* HAVE_BACKTRACE */ + +#if defined(GF_USE_SYSLOG) + if (ctx->log.log_control_file_found) + { + int priority; + /* treat GF_LOG_TRACE and GF_LOG_NONE as LOG_DEBUG and + other level as is */ + if (GF_LOG_TRACE == level || GF_LOG_NONE == level) { + priority = LOG_DEBUG; + } else { + priority = level - 1; } - pthread_mutex_unlock (&msg_cond_mutex); + gf_syslog (GF_ERR_DEV, priority, + "[%s:%d:%s] %s %s: no memory " + "available for size (%"GF_PRI_SIZET")", + basename, line, function, callstr, domain, + size); + goto out; + } +#endif /* GF_USE_SYSLOG */ + ret = gettimeofday (&tv, NULL); + if (-1 == ret) + goto out; + gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT); + snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr), + ".%"GF_PRI_SUSECONDS, tv.tv_usec); + + ret = sprintf (msg, "[%s] %s [%s:%d:%s] %s %s: no memory " + "available for size (%"GF_PRI_SIZET")", + timestr, level_strings[level], + basename, line, function, callstr, + domain, size); + if (-1 == ret) { + goto out; } - return NULL; -} + pthread_mutex_lock (&ctx->log.logfile_mutex); + { + if (ctx->log.logfile) { + fprintf (ctx->log.logfile, "%s\n", msg); + } else { + fprintf (stderr, "%s\n", msg); + } +#ifdef GF_LINUX_HOST_OS + /* We want only serious log in 'syslog', not our debug + and trace logs */ + if (ctx->log.gf_log_syslog && level && + (level <= ctx->log.sys_log_level)) + syslog ((level-1), "%s\n", msg); +#endif + } + + pthread_mutex_unlock (&ctx->log.logfile_mutex); +out: + return ret; + } int -gf_log_central_init (glusterfs_ctx_t *ctx, const char *remote_host, - const char *transport, uint32_t remote_port) +_gf_log_callingfn (const char *domain, const char *file, const char *function, + int line, gf_loglevel_t level, const char *fmt, ...) { - logging_xl = __get_dummy_xlator (ctx, remote_host, transport, - remote_port); - - if (!logging_xl) { - goto out; + const char *basename = NULL; + xlator_t *this = NULL; + char *str1 = NULL; + char *str2 = NULL; + char *msg = NULL; + char timestr[256] = {0,}; + char callstr[4096] = {0,}; + struct timeval tv = {0,}; + size_t len = 0; + int ret = 0; + va_list ap; + glusterfs_ctx_t *ctx = NULL; + + this = THIS; + ctx = this->ctx; + + if (ctx->log.gf_log_xl_log_set) { + if (this->loglevel && (level > this->loglevel)) + goto out; } + if (level > ctx->log.loglevel) + goto out; - __central_log_enabled = 1; + static char *level_strings[] = {"", /* NONE */ + "M", /* EMERGENCY */ + "A", /* ALERT */ + "C", /* CRITICAL */ + "E", /* ERROR */ + "W", /* WARNING */ + "N", /* NOTICE */ + "I", /* INFO */ + "D", /* DEBUG */ + "T", /* TRACE */ + ""}; - INIT_LIST_HEAD (&msg_queue.msgs); + if (!domain || !file || !function || !fmt) { + fprintf (stderr, + "logging: %s:%s():%d: invalid argument\n", + __FILE__, __PRETTY_FUNCTION__, __LINE__); + return -1; + } - pthread_cond_init (&msg_cond, NULL); - pthread_mutex_init (&msg_cond_mutex, NULL); - pthread_mutex_init (&msg_queue_mutex, NULL); + basename = strrchr (file, '/'); + if (basename) + basename++; + else + basename = file; + +#if HAVE_BACKTRACE + /* Print 'calling function' */ + do { + void *array[5]; + char **callingfn = NULL; + size_t size = 0; + + size = backtrace (array, 5); + if (size) + callingfn = backtrace_symbols (&array[2], size-2); + if (!callingfn) + break; - pthread_create (&logging_thread, NULL, logging_thread_loop, NULL); + if (size == 5) + snprintf (callstr, 4096, "(-->%s (-->%s (-->%s)))", + callingfn[2], callingfn[1], callingfn[0]); + if (size == 4) + snprintf (callstr, 4096, "(-->%s (-->%s))", + callingfn[1], callingfn[0]); + if (size == 3) + snprintf (callstr, 4096, "(-->%s)", callingfn[0]); + + free (callingfn); + } while (0); +#endif /* HAVE_BACKTRACE */ + +#if defined(GF_USE_SYSLOG) + if (ctx->log.log_control_file_found) + { + int priority; + /* treat GF_LOG_TRACE and GF_LOG_NONE as LOG_DEBUG and + other level as is */ + if (GF_LOG_TRACE == level || GF_LOG_NONE == level) { + priority = LOG_DEBUG; + } else { + priority = level - 1; + } -out: - return 0; -} + va_start (ap, fmt); + vasprintf (&str2, fmt, ap); + va_end (ap); + gf_syslog (GF_ERR_DEV, priority, + "[%s:%d:%s] %s %d-%s: %s", + basename, line, function, + callstr, + ((this->graph) ? this->graph->id:0), domain, + str2); -int -gf_log_central (const char *msg) -{ - struct _log_msg *lm = NULL; + goto out; + } +#endif /* GF_USE_SYSLOG */ + ret = gettimeofday (&tv, NULL); + if (-1 == ret) + goto out; + va_start (ap, fmt); + gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT); + snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr), + ".%"GF_PRI_SUSECONDS, tv.tv_usec); + + ret = gf_asprintf (&str1, "[%s] %s [%s:%d:%s] %s %d-%s: ", + timestr, level_strings[level], + basename, line, function, callstr, + ((this->graph) ? this->graph->id:0), domain); + if (-1 == ret) { + goto out; + } - lm = CALLOC (1, sizeof (*lm)); - - if (!lm) + ret = vasprintf (&str2, fmt, ap); + if (-1 == ret) { goto out; + } - INIT_LIST_HEAD (&lm->queue); + va_end (ap); - lm->msg = strdup (msg); + len = strlen (str1); + msg = GF_MALLOC (len + strlen (str2) + 1, gf_common_mt_char); - pthread_mutex_lock (&msg_queue_mutex); - { - list_add_tail (&lm->queue, &msg_queue.msgs); - } - pthread_mutex_unlock (&msg_queue_mutex); - - pthread_cond_signal (&msg_cond); + strcpy (msg, str1); + strcpy (msg + len, str2); -out: - return 0; -} + pthread_mutex_lock (&ctx->log.logfile_mutex); + { + if (ctx->log.logfile) { + fprintf (ctx->log.logfile, "%s\n", msg); + } else { + fprintf (stderr, "%s\n", msg); + } +#ifdef GF_LINUX_HOST_OS + /* We want only serious log in 'syslog', not our debug + and trace logs */ + if (ctx->log.gf_log_syslog && level && + (level <= ctx->log.sys_log_level)) + syslog ((level-1), "%s\n", msg); +#endif + } -void -gf_log_lock (void) -{ - pthread_mutex_lock (&logfile_mutex); -} + pthread_mutex_unlock (&ctx->log.logfile_mutex); +out: + GF_FREE (msg); -void -gf_log_unlock (void) -{ - pthread_mutex_unlock (&logfile_mutex); -} + GF_FREE (str1); + FREE (str2); -void -gf_log_cleanup (void) -{ - pthread_mutex_destroy (&logfile_mutex); + return ret; } - int _gf_log (const char *domain, const char *file, const char *function, int line, - gf_loglevel_t level, const char *fmt, ...) + 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]; - - char *str1, *str2, *msg; - size_t len = 0; - int ret = 0; - - static char *level_strings[] = {"", /* NONE */ - "C", /* CRITICAL */ - "E", /* ERROR */ - "W", /* WARNING */ - "N", /* NORMAL */ - "D", /* DEBUG */ + const char *basename = NULL; + FILE *new_logfile = NULL; + va_list ap; + char timestr[256] = {0,}; + struct timeval tv = {0,}; + char *str1 = NULL; + char *str2 = NULL; + char *msg = NULL; + size_t len = 0; + int ret = 0; + int fd = -1; + xlator_t *this = NULL; + glusterfs_ctx_t *ctx = NULL; + + this = THIS; + ctx = this->ctx; + + if (ctx->log.gf_log_xl_log_set) { + if (this->loglevel && (level > this->loglevel)) + goto out; + } + if (level > ctx->log.loglevel) + goto out; + + static char *level_strings[] = {"", /* NONE */ + "M", /* EMERGENCY */ + "A", /* ALERT */ + "C", /* CRITICAL */ + "E", /* ERROR */ + "W", /* WARNING */ + "N", /* NOTICE */ + "I", /* INFO */ + "D", /* DEBUG */ "T", /* TRACE */ - ""}; - - 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; - - ret = asprintf (&str1, "[%s] %s [%s:%d:%s] %s: ", - timestr, level_strings[level], - basename, line, function, - domain); - if (-1 == ret) { - goto out; - } + if (!domain || !file || !function || !fmt) { + fprintf (stderr, + "logging: %s:%s():%d: invalid argument\n", + __FILE__, __PRETTY_FUNCTION__, __LINE__); + return -1; + } - ret = vasprintf (&str2, fmt, ap); - if (-1 == ret) { - goto out; + basename = strrchr (file, '/'); + if (basename) + basename++; + else + basename = file; + +#if defined(GF_USE_SYSLOG) + if (ctx->log.log_control_file_found) + { + int priority; + /* treat GF_LOG_TRACE and GF_LOG_NONE as LOG_DEBUG and + other level as is */ + if (GF_LOG_TRACE == level || GF_LOG_NONE == level) { + priority = LOG_DEBUG; + } else { + priority = level - 1; } - va_end (ap); + va_start (ap, fmt); + vasprintf (&str2, fmt, ap); + va_end (ap); - len = strlen (str1); - msg = malloc (len + strlen (str2) + 1); - - strcpy (msg, str1); - strcpy (msg + len, str2); + gf_syslog (GF_ERR_DEV, priority, + "[%s:%d:%s] %d-%s: %s", + basename, line, function, + ((this->graph) ? this->graph->id:0), domain, str2); + goto err; + } +#endif /* GF_USE_SYSLOG */ - fprintf (logfile, "%s\n", msg); - fflush (logfile); - } - pthread_mutex_unlock (&logfile_mutex); + if (ctx->log.logrotate) { + ctx->log.logrotate = 0; - if (__central_log_enabled && - ((glusterfs_central_log_flag_get ()) == 0)) { - - glusterfs_central_log_flag_set (); + fd = open (ctx->log.filename, + O_CREAT | O_RDONLY, S_IRUSR | S_IWUSR); + if (fd < 0) { + gf_log ("logrotate", GF_LOG_ERROR, + "%s", strerror (errno)); + return -1; + } + close (fd); + + new_logfile = fopen (ctx->log.filename, "a"); + if (!new_logfile) { + gf_log ("logrotate", GF_LOG_CRITICAL, + "failed to open logfile %s (%s)", + ctx->log.filename, strerror (errno)); + goto log; + } + + pthread_mutex_lock (&ctx->log.logfile_mutex); { - gf_log_central (msg); + if (ctx->log.logfile) + fclose (ctx->log.logfile); + + ctx->log.gf_log_logfile = ctx->log.logfile = new_logfile; } - glusterfs_central_log_flag_unset (); + pthread_mutex_unlock (&ctx->log.logfile_mutex); + } - - FREE (msg); - FREE (str1); - FREE (str2); +log: + ret = gettimeofday (&tv, NULL); + if (-1 == ret) + goto out; + va_start (ap, fmt); + gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT); + snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr), + ".%"GF_PRI_SUSECONDS, tv.tv_usec); + + ret = gf_asprintf (&str1, "[%s] %s [%s:%d:%s] %d-%s: ", + timestr, level_strings[level], + basename, line, function, + ((this->graph)?this->graph->id:0), domain); + if (-1 == ret) { + goto err; + } -out: - return (0); -} + ret = vasprintf (&str2, fmt, ap); + if (-1 == ret) { + goto err; + } + va_end (ap); -struct _client_log { - char *identifier; - FILE *file; - struct list_head list; -}; + len = strlen (str1); + msg = GF_MALLOC (len + strlen (str2) + 1, gf_common_mt_char); + + strcpy (msg, str1); + strcpy (msg + len, str2); + + pthread_mutex_lock (&ctx->log.logfile_mutex); + { + + if (ctx->log.logfile) { + fprintf (ctx->log.logfile, "%s\n", msg); + fflush (ctx->log.logfile); + } else { + fprintf (stderr, "%s\n", msg); + fflush (stderr); + } + +#ifdef GF_LINUX_HOST_OS + /* We want only serious log in 'syslog', not our debug + and trace logs */ + if (ctx->log.gf_log_syslog && level && + (level <= ctx->log.sys_log_level)) + syslog ((level-1), "%s\n", msg); +#endif + } + + pthread_mutex_unlock (&ctx->log.logfile_mutex); -struct _client_log *client_logs = NULL; +err: + GF_FREE (msg); + GF_FREE (str1); -static void -client_log_init (struct _client_log *cl, char *identifier) + FREE (str2); + +out: + return (0); +} + +int +_gf_log_eh (const char *function, const char *fmt, ...) { - int ret = 0; - char *path = NULL; + int ret = -1; + va_list ap; + char *str1 = NULL; + char *str2 = NULL; + char *msg = NULL; + xlator_t *this = NULL; + + this = THIS; + + ret = gf_asprintf (&str1, "[%d] %s: ", + ((this->graph)?this->graph->id:0), + function); + if (-1 == ret) { + goto out; + } - cl->identifier = identifier; + va_start (ap, fmt); - ret = asprintf (&path, "%s.client-%s", filename, identifier); + ret = vasprintf (&str2, fmt, ap); if (-1 == ret) { - return; + goto out; } - cl->file = fopen (path, "a"); - FREE (path); - - INIT_LIST_HEAD (&cl->list); -} + va_end (ap); + + msg = GF_MALLOC (strlen (str1) + strlen (str2) + 1, gf_common_mt_char); + if (!msg) { + ret = -1; + goto out; + } + + strcpy (msg, str1); + strcat (msg, str2); + + ret = eh_save_history (this->history, msg); + +out: + GF_FREE (str1); + + /* Use FREE instead of GF_FREE since str2 was allocated by vasprintf */ + if (str2) + FREE (str2); + + return ret; +} -static FILE * -__logfile_for_client (char *identifier) +int +gf_cmd_log_init (const char *filename) { - struct _client_log *client = NULL; + int fd = -1; + xlator_t *this = NULL; + glusterfs_ctx_t *ctx = NULL; - if (!client_logs) { - client = CALLOC (1, sizeof (*client)); - client_log_init (client, identifier); + this = THIS; + ctx = this->ctx; - client_logs = client; + if (!filename){ + gf_log (this->name, GF_LOG_CRITICAL, "gf_cmd_log_init: no " + "filename specified\n"); + return -1; } - list_for_each_entry (client, &client_logs->list, list) { - if (!strcmp (client->identifier, identifier)) - break; + ctx->log.cmd_log_filename = gf_strdup (filename); + if (!ctx->log.cmd_log_filename) { + gf_log (this->name, GF_LOG_CRITICAL, + "gf_cmd_log_init: strdup error\n"); + return -1; + } + /* close and reopen cmdlogfile for log rotate*/ + if (ctx->log.cmdlogfile) { + fclose (ctx->log.cmdlogfile); + ctx->log.cmdlogfile = NULL; + } + + fd = open (ctx->log.cmd_log_filename, + O_CREAT | O_RDONLY, S_IRUSR | S_IWUSR); + if (fd < 0) { + gf_log (this->name, GF_LOG_CRITICAL, + "%s", strerror (errno)); + return -1; } + close (fd); + + ctx->log.cmdlogfile = fopen (ctx->log.cmd_log_filename, "a"); + if (!ctx->log.cmdlogfile){ + gf_log (this->name, GF_LOG_CRITICAL, + "gf_cmd_log_init: failed to open logfile \"%s\" " + "(%s)\n", ctx->log.cmd_log_filename, strerror (errno)); + return -1; + } + return 0; +} - if (!client) { - client = CALLOC (1, sizeof (*client)); +int +gf_cmd_log (const char *domain, const char *fmt, ...) +{ + va_list ap; + char timestr[64]; + struct timeval tv = {0,}; + char *str1 = NULL; + char *str2 = NULL; + char *msg = NULL; + size_t len = 0; + int ret = 0; + glusterfs_ctx_t *ctx = NULL; + + ctx = THIS->ctx; + if (!ctx->log.cmdlogfile) + return -1; + + + if (!domain || !fmt) { + gf_log ("glusterd", GF_LOG_TRACE, + "logging: invalid argument\n"); + return -1; + } - client_log_init (client, identifier); + ret = gettimeofday (&tv, NULL); + if (ret == -1) + goto out; + va_start (ap, fmt); + gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT); + snprintf (timestr + strlen (timestr), 256 - strlen (timestr), + ".%"GF_PRI_SUSECONDS, tv.tv_usec); + + ret = gf_asprintf (&str1, "[%s] %s : ", + timestr, domain); + if (ret == -1) { + goto out; + } - list_add_tail (&client->list, &client_logs->list); + ret = vasprintf (&str2, fmt, ap); + if (ret == -1) { + goto out; } - return client->file; -} + va_end (ap); + len = strlen (str1); + msg = GF_MALLOC (len + strlen (str2) + 1, gf_common_mt_char); -int -gf_log_from_client (const char *msg, char *identifier) -{ - FILE *client_log = NULL; + strcpy (msg, str1); + strcpy (msg + len, str2); - client_log = __logfile_for_client (identifier); + fprintf (ctx->log.cmdlogfile, "%s\n", msg); + fflush (ctx->log.cmdlogfile); - fprintf (client_log, "%s\n", msg); - fflush (client_log); +out: + GF_FREE (msg); - return 0; + GF_FREE (str1); + + FREE (str2); + + return (0); } diff --git a/libglusterfs/src/logging.h b/libglusterfs/src/logging.h index 85f904b7b..cc806a767 100644 --- a/libglusterfs/src/logging.h +++ b/libglusterfs/src/logging.h @@ -1,22 +1,12 @@ /* - Copyright (c) 2006-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/>. -*/ + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ #ifndef __LOGGING_H__ #define __LOGGING_H__ @@ -27,104 +17,149 @@ #endif #include <stdint.h> -#include <stdio.h> +#include <stdio.h> +#include <stdarg.h> +#include <pthread.h> + +#ifdef GF_DARWIN_HOST_OS +#define GF_PRI_FSBLK "u" +#define GF_PRI_DEV PRId32 +#define GF_PRI_NLINK PRIu16 +#define GF_PRI_SUSECONDS "06d" +#else +#define GF_PRI_FSBLK PRIu64 +#define GF_PRI_DEV PRIu64 +#define GF_PRI_NLINK PRIu32 +#define GF_PRI_SUSECONDS "06ld" +#endif +#define GF_PRI_BLKSIZE PRId32 +#define GF_PRI_SIZET "zu" + + +#if 0 +/* Syslog definitions :-) */ +#define LOG_EMERG 0 /* system is unusable */ +#define LOG_ALERT 1 /* action must be taken immediately */ +#define LOG_CRIT 2 /* critical conditions */ +#define LOG_ERR 3 /* error conditions */ +#define LOG_WARNING 4 /* warning conditions */ +#define LOG_NOTICE 5 /* normal but significant condition */ +#define LOG_INFO 6 /* informational */ +#define LOG_DEBUG 7 /* debug-level messages */ +#endif -#define GF_PRI_FSBLK PRId64 -#define GF_PRI_BLKSIZE "ld" -#if GF_LINUX_HOST_OS +typedef enum { + GF_LOG_NONE, + GF_LOG_EMERG, + GF_LOG_ALERT, + GF_LOG_CRITICAL, /* fatal errors */ + GF_LOG_ERROR, /* major failures (not necessarily fatal) */ + GF_LOG_WARNING, /* info about normal operation */ + GF_LOG_NOTICE, + GF_LOG_INFO, /* Normal information */ + GF_LOG_DEBUG, /* internal errors */ + GF_LOG_TRACE, /* full trace of operation */ +} gf_loglevel_t; -# 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 */ +#define DEFAULT_LOG_FILE_DIRECTORY DATADIR "/log/glusterfs" +#define DEFAULT_LOG_LEVEL GF_LOG_INFO + +typedef struct gf_log_handle_ { + pthread_mutex_t logfile_mutex; + uint8_t logrotate; + gf_loglevel_t loglevel; + int gf_log_syslog; + gf_loglevel_t sys_log_level; + char gf_log_xl_log_set; + char *filename; + FILE *logfile; + FILE *gf_log_logfile; + char *cmd_log_filename; + FILE *cmdlogfile; +#ifdef GF_USE_SYSLOG + int log_control_file_found; + char *ident; +#endif /* GF_USE_SYSLOG */ + +} gf_log_handle_t; + +void gf_log_globals_init (void *ctx); +int gf_log_init (void *data, const char *filename, const char *ident); + +void gf_log_logrotate (int signum); -#elif GF_DARWIN_HOST_OS +void gf_log_cleanup (void); -/* 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" +int _gf_log (const char *domain, const char *file, + const char *function, int32_t line, gf_loglevel_t level, + const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 6, 7))); +int _gf_log_callingfn (const char *domain, const char *file, + const char *function, int32_t line, gf_loglevel_t level, + const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 6, 7))); -# undef GF_PRI_FSBLK -# define GF_PRI_FSBLK "u" - -# undef GF_PRI_BLKSIZE -# define GF_PRI_BLKSIZE "u" +int _gf_log_nomem (const char *domain, const char *file, + const char *function, int line, gf_loglevel_t level, + size_t size); -# 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 */ +int _gf_log_eh (const char *function, const char *fmt, ...); -#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 FMT_WARN(fmt...) do { if (0) printf (fmt); } while (0) -#define GF_PRI_DEV GF_PRI_FSBLK +#define gf_log(dom, levl, fmt...) do { \ + FMT_WARN (fmt); \ + _gf_log (dom, __FILE__, __FUNCTION__, __LINE__, \ + levl, ##fmt); \ + } while (0) -typedef enum { - GF_LOG_NONE, - 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, /* internal errors */ - GF_LOG_TRACE, /* full trace of operation */ -} gf_loglevel_t; +#define gf_log_eh(fmt...) do { \ + FMT_WARN (fmt); \ + _gf_log_eh (__FUNCTION__, ##fmt); \ + } while (0) + +#define gf_log_callingfn(dom, levl, fmt...) do { \ + FMT_WARN (fmt); \ + _gf_log_callingfn (dom, __FILE__, __FUNCTION__, __LINE__, \ + levl, ##fmt); \ + } while (0) -#define GF_LOG_MAX GF_LOG_DEBUG -extern gf_loglevel_t gf_log_loglevel; +/* No malloc or calloc should be called in this function */ +#define gf_log_nomem(dom, levl, size) do { \ + _gf_log_nomem (dom, __FILE__, __FUNCTION__, __LINE__, \ + levl, size); \ + } while (0) -#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); \ + gf_log (args); \ } - -void -gf_log_logrotate (int signum); +void gf_log_disable_syslog (void); +void gf_log_enable_syslog (void); +gf_loglevel_t gf_log_get_loglevel (void); +void gf_log_set_loglevel (gf_loglevel_t level); +gf_loglevel_t gf_log_get_xl_loglevel (void *xl); +void gf_log_set_xl_loglevel (void *xl, gf_loglevel_t level); -int gf_log_init (const char *filename); -void gf_log_cleanup (void); +int gf_cmd_log (const char *domain, const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); + +int gf_cmd_log_init (const char *filename); + +void set_sys_log_level (gf_loglevel_t level); -int -_gf_log (const char *domain, const char *file, const char *function, - int32_t line, gf_loglevel_t level, const char *fmt, ...); - -int -gf_log_from_client (const char *msg, char *identifier); - -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_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) #endif /* __LOGGING_H__ */ diff --git a/libglusterfs/src/md5.c b/libglusterfs/src/md5.c deleted file mode 100644 index 6fd6ecbf7..000000000 --- a/libglusterfs/src/md5.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * RFC 1321 compliant MD5 implementation - * - * Copyright (C) 2001-2003 Christophe Devine - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, visit the http://fsf.org website. - */ - - -#include <inttypes.h> -#include <string.h> - -#include "md5.h" - -void md5_begin(md_context *ctx) -{ - ctx->A = 0x67452301; - ctx->B = 0xEFCDAB89; - ctx->C = 0x98BADCFE; - ctx->D = 0x10325476; - - ctx->totalN = ctx->totalN2 = 0; -} - -static void md5_process(md_context *ctx, const uint8_t data[CSUM_CHUNK]) -{ - uint32_t X[16], A, B, C, D; - - A = ctx->A; - B = ctx->B; - C = ctx->C; - D = ctx->D; - - X[0] = IVAL(data, 0); - X[1] = IVAL(data, 4); - X[2] = IVAL(data, 8); - X[3] = IVAL(data, 12); - X[4] = IVAL(data, 16); - X[5] = IVAL(data, 20); - X[6] = IVAL(data, 24); - X[7] = IVAL(data, 28); - X[8] = IVAL(data, 32); - X[9] = IVAL(data, 36); - X[10] = IVAL(data, 40); - X[11] = IVAL(data, 44); - X[12] = IVAL(data, 48); - X[13] = IVAL(data, 52); - X[14] = IVAL(data, 56); - X[15] = IVAL(data, 60); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - -#define P(a,b,c,d,k,s,t) a += F(b,c,d) + X[k] + t, a = S(a,s) + b - -#define F(x,y,z) (z ^ (x & (y ^ z))) - - P(A, B, C, D, 0, 7, 0xD76AA478); - P(D, A, B, C, 1, 12, 0xE8C7B756); - P(C, D, A, B, 2, 17, 0x242070DB); - P(B, C, D, A, 3, 22, 0xC1BDCEEE); - P(A, B, C, D, 4, 7, 0xF57C0FAF); - P(D, A, B, C, 5, 12, 0x4787C62A); - P(C, D, A, B, 6, 17, 0xA8304613); - P(B, C, D, A, 7, 22, 0xFD469501); - P(A, B, C, D, 8, 7, 0x698098D8); - P(D, A, B, C, 9, 12, 0x8B44F7AF); - P(C, D, A, B, 10, 17, 0xFFFF5BB1); - P(B, C, D, A, 11, 22, 0x895CD7BE); - P(A, B, C, D, 12, 7, 0x6B901122); - P(D, A, B, C, 13, 12, 0xFD987193); - P(C, D, A, B, 14, 17, 0xA679438E); - P(B, C, D, A, 15, 22, 0x49B40821); - -#undef F -#define F(x,y,z) (y ^ (z & (x ^ y))) - - P(A, B, C, D, 1, 5, 0xF61E2562); - P(D, A, B, C, 6, 9, 0xC040B340); - P(C, D, A, B, 11, 14, 0x265E5A51); - P(B, C, D, A, 0, 20, 0xE9B6C7AA); - P(A, B, C, D, 5, 5, 0xD62F105D); - P(D, A, B, C, 10, 9, 0x02441453); - P(C, D, A, B, 15, 14, 0xD8A1E681); - P(B, C, D, A, 4, 20, 0xE7D3FBC8); - P(A, B, C, D, 9, 5, 0x21E1CDE6); - P(D, A, B, C, 14, 9, 0xC33707D6); - P(C, D, A, B, 3, 14, 0xF4D50D87); - P(B, C, D, A, 8, 20, 0x455A14ED); - P(A, B, C, D, 13, 5, 0xA9E3E905); - P(D, A, B, C, 2, 9, 0xFCEFA3F8); - P(C, D, A, B, 7, 14, 0x676F02D9); - P(B, C, D, A, 12, 20, 0x8D2A4C8A); - -#undef F -#define F(x,y,z) (x ^ y ^ z) - - P(A, B, C, D, 5, 4, 0xFFFA3942); - P(D, A, B, C, 8, 11, 0x8771F681); - P(C, D, A, B, 11, 16, 0x6D9D6122); - P(B, C, D, A, 14, 23, 0xFDE5380C); - P(A, B, C, D, 1, 4, 0xA4BEEA44); - P(D, A, B, C, 4, 11, 0x4BDECFA9); - P(C, D, A, B, 7, 16, 0xF6BB4B60); - P(B, C, D, A, 10, 23, 0xBEBFBC70); - P(A, B, C, D, 13, 4, 0x289B7EC6); - P(D, A, B, C, 0, 11, 0xEAA127FA); - P(C, D, A, B, 3, 16, 0xD4EF3085); - P(B, C, D, A, 6, 23, 0x04881D05); - P(A, B, C, D, 9, 4, 0xD9D4D039); - P(D, A, B, C, 12, 11, 0xE6DB99E5); - P(C, D, A, B, 15, 16, 0x1FA27CF8); - P(B, C, D, A, 2, 23, 0xC4AC5665); - -#undef F -#define F(x,y,z) (y ^ (x | ~z)) - - P(A, B, C, D, 0, 6, 0xF4292244); - P(D, A, B, C, 7, 10, 0x432AFF97); - P(C, D, A, B, 14, 15, 0xAB9423A7); - P(B, C, D, A, 5, 21, 0xFC93A039); - P(A, B, C, D, 12, 6, 0x655B59C3); - P(D, A, B, C, 3, 10, 0x8F0CCC92); - P(C, D, A, B, 10, 15, 0xFFEFF47D); - P(B, C, D, A, 1, 21, 0x85845DD1); - P(A, B, C, D, 8, 6, 0x6FA87E4F); - P(D, A, B, C, 15, 10, 0xFE2CE6E0); - P(C, D, A, B, 6, 15, 0xA3014314); - P(B, C, D, A, 13, 21, 0x4E0811A1); - P(A, B, C, D, 4, 6, 0xF7537E82); - P(D, A, B, C, 11, 10, 0xBD3AF235); - P(C, D, A, B, 2, 15, 0x2AD7D2BB); - P(B, C, D, A, 9, 21, 0xEB86D391); - -#undef F - - ctx->A += A; - ctx->B += B; - ctx->C += C; - ctx->D += D; -} - -void md5_update(md_context *ctx, const uint8_t *input, uint32_t length) -{ - uint32_t left, fill; - - if (!length) - return; - - left = ctx->totalN & 0x3F; - fill = CSUM_CHUNK - left; - - ctx->totalN += length; - ctx->totalN &= 0xFFFFFFFF; - - if (ctx->totalN < length) - ctx->totalN2++; - - if (left && length >= fill) { - memcpy(ctx->buffer + left, input, fill); - md5_process(ctx, ctx->buffer); - length -= fill; - input += fill; - left = 0; - } - - while (length >= CSUM_CHUNK) { - md5_process(ctx, input); - length -= CSUM_CHUNK; - input += CSUM_CHUNK; - } - - if (length) - memcpy(ctx->buffer + left, input, length); -} - -static uint8_t md5_padding[CSUM_CHUNK] = { 0x80 }; - -void md5_result(md_context *ctx, uint8_t digest[MD5_DIGEST_LEN]) -{ - uint32_t last, padn; - uint32_t high, low; - uint8_t msglen[8]; - - high = (ctx->totalN >> 29) - | (ctx->totalN2 << 3); - low = (ctx->totalN << 3); - - SIVAL(msglen, 0, low); - SIVAL(msglen, 4, high); - - last = ctx->totalN & 0x3F; - padn = last < 56 ? 56 - last : 120 - last; - - md5_update(ctx, md5_padding, padn); - md5_update(ctx, msglen, 8); - - SIVAL(digest, 0, ctx->A); - SIVAL(digest, 4, ctx->B); - SIVAL(digest, 8, ctx->C); - SIVAL(digest, 12, ctx->D); -} - -void get_md5(uint8_t *out, const uint8_t *input, int n) -{ - md_context ctx; - md5_begin(&ctx); - md5_update(&ctx, input, n); - md5_result(&ctx, out); -} - -#ifdef TEST_MD5 - -#include <stdlib.h> -#include <stdio.h> - -/* - * those are the standard RFC 1321 test vectors - */ - -static struct { - char *str, *md5; -} tests[] = { - { "", - "d41d8cd98f00b204e9800998ecf8427e" }, - { "a", - "0cc175b9c0f1b6a831c399e269772661" }, - { "abc", - "900150983cd24fb0d6963f7d28e17f72" }, - { "message digest", - "f96b697d7cb7938d525a2f31aaf161d0" }, - { "abcdefghijklmnopqrstuvwxyz", - "c3fcd3d76192e4007dfb496cca67e13b" }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - "d174ab98d277d9f5a5611c2c9f419d9f" }, - { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", - "57edf4a22be3c955ac49da2e2107b67a" }, - { NULL, NULL } -}; - -int main(int argc, char *argv[]) -{ - FILE *f; - int i, j; - char output[33]; - md_context ctx; - uint8_t buf[1000]; - uint8_t md5sum[MD5_DIGEST_LEN]; - - if (argc < 2) { - printf("\nMD5 Validation Tests:\n\n"); - - for (i = 0; tests[i].str; i++) { - char *str = tests[i].str; - char *chk = tests[i].md5; - - printf(" Test %d ", i + 1); - - get_md5(md5sum, str, strlen(str)); - - for (j = 0; j < MD5_DIGEST_LEN; j++) - sprintf(output + j * 2, "%02x", md5sum[j]); - - if (memcmp(output, chk, 32)) { - printf("failed!\n"); - return 1; - } - - printf("passed.\n"); - } - - printf("\n"); - return 0; - } - - while (--argc) { - if (!(f = fopen(*++argv, "rb"))) { - perror("fopen"); - return 1; - } - - md5_begin(&ctx); - - while ((i = fread(buf, 1, sizeof buf, f)) > 0) - md5_update(&ctx, buf, i); - - md5_result(&ctx, md5sum); - - for (j = 0; j < MD5_DIGEST_LEN; j++) - printf("%02x", md5sum[j]); - - printf(" %s\n", *argv); - } - - return 0; -} - -#endif diff --git a/libglusterfs/src/md5.h b/libglusterfs/src/md5.h deleted file mode 100644 index ba8f08dbc..000000000 --- a/libglusterfs/src/md5.h +++ /dev/null @@ -1,78 +0,0 @@ -/* rsync-3.0.6/byteorder.h */ - -/* - * Simple byteorder handling. - * - * Copyright (C) 1992-1995 Andrew Tridgell - * Copyright (C) 2007-2008 Wayne Davison - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, visit the http://fsf.org website. - */ - -#undef CAREFUL_ALIGNMENT - -/* We know that the x86 can handle misalignment and has the same - * byte order (LSB-first) as the 32-bit numbers we transmit. */ - -#ifdef __i386__ -#define CAREFUL_ALIGNMENT 0 -#endif - -#ifndef CAREFUL_ALIGNMENT -#define CAREFUL_ALIGNMENT 1 -#endif - -#define CVAL(buf,pos) (((unsigned char *)(buf))[pos]) -#define UVAL(buf,pos) ((uint32_t)CVAL(buf,pos)) -#define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val)) - -#if CAREFUL_ALIGNMENT -#define PVAL(buf,pos) (UVAL(buf,pos)|UVAL(buf,(pos)+1)<<8) -#define IVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+2)<<16) -#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) -#define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16)) -#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32_t)(val))) -#else - -/* this handles things for architectures like the 386 that can handle - alignment errors */ - -/* - WARNING: This section is dependent on the length of int32 - being correct. set CAREFUL_ALIGNMENT if it is not. -*/ - -#define IVAL(buf,pos) (*(uint32_t *)((char *)(buf) + (pos))) -#define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32_t)(val)) -#endif - -/* The include file for both the MD4 and MD5 routines. */ - -#define MD5_DIGEST_LEN 16 -#define MAX_DIGEST_LEN MD5_DIGEST_LEN - -#define CSUM_CHUNK 64 - -typedef struct { - uint32_t A, B, C, D; - uint32_t totalN; /* bit count, lower 32 bits */ - uint32_t totalN2; /* bit count, upper 32 bits */ - uint8_t buffer[CSUM_CHUNK]; -} md_context; - -void md5_begin(md_context *ctx); -void md5_update(md_context *ctx, const uint8_t *input, uint32_t length); -void md5_result(md_context *ctx, uint8_t digest[MD5_DIGEST_LEN]); - -void get_md5(uint8_t digest[MD5_DIGEST_LEN], const uint8_t *input, int n); diff --git a/libglusterfs/src/mem-pool.c b/libglusterfs/src/mem-pool.c index 3937fcc37..b901dd7a8 100644 --- a/libglusterfs/src/mem-pool.c +++ b/libglusterfs/src/mem-pool.c @@ -1,106 +1,401 @@ /* - Copyright (c) 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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include "mem-pool.h" #include "logging.h" +#include "xlator.h" #include <stdlib.h> +#include <stdarg.h> - -#define GF_MEM_POOL_PAD_BOUNDARY (sizeof(struct list_head)) +#define GF_MEM_POOL_LIST_BOUNDARY (sizeof(struct list_head)) +#define GF_MEM_POOL_PTR (sizeof(struct mem_pool*)) +#define GF_MEM_POOL_PAD_BOUNDARY (GF_MEM_POOL_LIST_BOUNDARY + GF_MEM_POOL_PTR + sizeof(int)) #define mem_pool_chunkhead2ptr(head) ((head) + GF_MEM_POOL_PAD_BOUNDARY) #define mem_pool_ptr2chunkhead(ptr) ((ptr) - GF_MEM_POOL_PAD_BOUNDARY) +#define is_mem_chunk_in_use(ptr) (*ptr == 1) +#define mem_pool_from_ptr(ptr) ((ptr) + GF_MEM_POOL_LIST_BOUNDARY) + +#define GF_MEM_HEADER_SIZE (4 + sizeof (size_t) + sizeof (xlator_t *) + 4 + 8) +#define GF_MEM_TRAILER_SIZE 8 + +#define GF_MEM_HEADER_MAGIC 0xCAFEBABE +#define GF_MEM_TRAILER_MAGIC 0xBAADF00D + +#define GLUSTERFS_ENV_MEM_ACCT_STR "GLUSTERFS_DISABLE_MEM_ACCT" + +void +gf_mem_acct_enable_set (void *data) +{ + glusterfs_ctx_t *ctx = NULL; + + ctx = data; + + GF_ASSERT (ctx); + + ctx->mem_acct_enable = 1; + + return; +} + +void +gf_mem_set_acct_info (xlator_t *xl, char **alloc_ptr, + size_t size, uint32_t type) +{ + + char *ptr = NULL; + + if (!alloc_ptr) + return; + + ptr = (char *) (*alloc_ptr); + + GF_ASSERT (xl != NULL); + + GF_ASSERT (xl->mem_acct.rec != NULL); + + GF_ASSERT (type <= xl->mem_acct.num_types); + + LOCK(&xl->mem_acct.rec[type].lock); + { + xl->mem_acct.rec[type].size += size; + xl->mem_acct.rec[type].num_allocs++; + xl->mem_acct.rec[type].total_allocs++; + xl->mem_acct.rec[type].max_size = + max (xl->mem_acct.rec[type].max_size, + xl->mem_acct.rec[type].size); + xl->mem_acct.rec[type].max_num_allocs = + max (xl->mem_acct.rec[type].max_num_allocs, + xl->mem_acct.rec[type].num_allocs); + } + UNLOCK(&xl->mem_acct.rec[type].lock); + + *(uint32_t *)(ptr) = type; + ptr = ptr + 4; + memcpy (ptr, &size, sizeof(size_t)); + ptr += sizeof (size_t); + memcpy (ptr, &xl, sizeof(xlator_t *)); + ptr += sizeof (xlator_t *); + *(uint32_t *)(ptr) = GF_MEM_HEADER_MAGIC; + ptr = ptr + 4; + ptr = ptr + 8; //padding + *(uint32_t *) (ptr + size) = GF_MEM_TRAILER_MAGIC; + + *alloc_ptr = (void *)ptr; + return; +} + + +void * +__gf_calloc (size_t nmemb, size_t size, uint32_t type) +{ + size_t tot_size = 0; + size_t req_size = 0; + char *ptr = NULL; + xlator_t *xl = NULL; + + if (!THIS->ctx->mem_acct_enable) + return CALLOC (nmemb, size); + + xl = THIS; + + req_size = nmemb * size; + tot_size = req_size + GF_MEM_HEADER_SIZE + GF_MEM_TRAILER_SIZE; + + ptr = calloc (1, tot_size); + + if (!ptr) { + gf_log_nomem ("", GF_LOG_ALERT, tot_size); + return NULL; + } + gf_mem_set_acct_info (xl, &ptr, req_size, type); + + return (void *)ptr; +} + +void * +__gf_malloc (size_t size, uint32_t type) +{ + size_t tot_size = 0; + char *ptr = NULL; + xlator_t *xl = NULL; + + if (!THIS->ctx->mem_acct_enable) + return MALLOC (size); + + xl = THIS; + + tot_size = size + GF_MEM_HEADER_SIZE + GF_MEM_TRAILER_SIZE; + + ptr = malloc (tot_size); + if (!ptr) { + gf_log_nomem ("", GF_LOG_ALERT, tot_size); + return NULL; + } + gf_mem_set_acct_info (xl, &ptr, size, type); + + return (void *)ptr; +} + +void * +__gf_realloc (void *ptr, size_t size) +{ + size_t tot_size = 0; + char *orig_ptr = NULL; + xlator_t *xl = NULL; + uint32_t type = 0; + + if (!THIS->ctx->mem_acct_enable) + return REALLOC (ptr, size); + + tot_size = size + GF_MEM_HEADER_SIZE + GF_MEM_TRAILER_SIZE; + + orig_ptr = (char *)ptr - 8 - 4; + + GF_ASSERT (*(uint32_t *)orig_ptr == GF_MEM_HEADER_MAGIC); + + orig_ptr = orig_ptr - sizeof(xlator_t *); + xl = *((xlator_t **)orig_ptr); + + orig_ptr = (char *)ptr - GF_MEM_HEADER_SIZE; + type = *(uint32_t *)orig_ptr; + + ptr = realloc (orig_ptr, tot_size); + if (!ptr) { + gf_log_nomem ("", GF_LOG_ALERT, tot_size); + return NULL; + } + + gf_mem_set_acct_info (xl, (char **)&ptr, size, type); + + return (void *)ptr; +} + +int +gf_vasprintf (char **string_ptr, const char *format, va_list arg) +{ + va_list arg_save; + char *str = NULL; + int size = 0; + int rv = 0; + + if (!string_ptr || !format) + return -1; + + va_copy (arg_save, arg); + + size = vsnprintf (NULL, 0, format, arg); + size++; + str = GF_MALLOC (size, gf_common_mt_asprintf); + if (str == NULL) { + /* log is done in GF_MALLOC itself */ + return -1; + } + rv = vsnprintf (str, size, format, arg_save); + + *string_ptr = str; + return (rv); +} + +int +gf_asprintf (char **string_ptr, const char *format, ...) +{ + va_list arg; + int rv = 0; + + va_start (arg, format); + rv = gf_vasprintf (string_ptr, format, arg); + va_end (arg); + + return rv; +} + +void +__gf_free (void *free_ptr) +{ + size_t req_size = 0; + char *ptr = NULL; + uint32_t type = 0; + xlator_t *xl = NULL; + + if (!THIS->ctx->mem_acct_enable) { + FREE (free_ptr); + return; + } + + if (!free_ptr) + return; + + ptr = (char *)free_ptr - 8 - 4; + + //Possible corruption, assert here + GF_ASSERT (GF_MEM_HEADER_MAGIC == *(uint32_t *)ptr); + + *(uint32_t *)ptr = 0; + + ptr = ptr - sizeof(xlator_t *); + memcpy (&xl, ptr, sizeof(xlator_t *)); + + //gf_free expects xl to be available + GF_ASSERT (xl != NULL); + + if (!xl->mem_acct.rec) { + ptr = (char *)free_ptr - GF_MEM_HEADER_SIZE; + goto free; + } + + + ptr = ptr - sizeof(size_t); + memcpy (&req_size, ptr, sizeof (size_t)); + ptr = ptr - 4; + type = *(uint32_t *)ptr; + + // This points to a memory overrun + GF_ASSERT (GF_MEM_TRAILER_MAGIC == + *(uint32_t *)((char *)free_ptr + req_size)); + + *(uint32_t *) ((char *)free_ptr + req_size) = 0; + + LOCK (&xl->mem_acct.rec[type].lock); + { + xl->mem_acct.rec[type].size -= req_size; + xl->mem_acct.rec[type].num_allocs--; + } + UNLOCK (&xl->mem_acct.rec[type].lock); +free: + FREE (ptr); +} + struct mem_pool * mem_pool_new_fn (unsigned long sizeof_type, - unsigned long count) + unsigned long count, char *name) { - struct mem_pool *mem_pool = NULL; - 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; - } + struct mem_pool *mem_pool = NULL; + unsigned long padded_sizeof_type = 0; + void *pool = NULL; + int i = 0; + int ret = 0; + struct list_head *list = NULL; + glusterfs_ctx_t *ctx = NULL; + + if (!sizeof_type || !count) { + gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument"); + return NULL; + } padded_sizeof_type = sizeof_type + GF_MEM_POOL_PAD_BOUNDARY; - - 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 = GF_CALLOC (sizeof (*mem_pool), 1, gf_common_mt_mem_pool); + if (!mem_pool) + return NULL; + + ret = gf_asprintf (&mem_pool->name, "%s:%s", THIS->name, name); + if (ret < 0) + return NULL; + + if (!mem_pool->name) { + GF_FREE (mem_pool); + return NULL; + } + + LOCK_INIT (&mem_pool->lock); + INIT_LIST_HEAD (&mem_pool->list); + INIT_LIST_HEAD (&mem_pool->global_list); - mem_pool->padded_sizeof_type = padded_sizeof_type; - mem_pool->cold_count = count; + mem_pool->padded_sizeof_type = padded_sizeof_type; + mem_pool->cold_count = count; mem_pool->real_sizeof_type = sizeof_type; - pool = CALLOC (count, padded_sizeof_type); - if (!pool) { - FREE (mem_pool); - return NULL; + pool = GF_CALLOC (count, padded_sizeof_type, gf_common_mt_long); + if (!pool) { + GF_FREE (mem_pool->name); + GF_FREE (mem_pool); + return NULL; } - for (i = 0; i < count; i++) { - list = pool + (i * (padded_sizeof_type)); - INIT_LIST_HEAD (list); - list_add_tail (list, &mem_pool->list); - } + for (i = 0; i < count; i++) { + list = pool + (i * (padded_sizeof_type)); + INIT_LIST_HEAD (list); + list_add_tail (list, &mem_pool->list); + } + + mem_pool->pool = pool; + mem_pool->pool_end = pool + (count * (padded_sizeof_type)); + + /* add this pool to the global list */ + ctx = THIS->ctx; + if (!ctx) + goto out; - mem_pool->pool = pool; - mem_pool->pool_end = pool + (count * (padded_sizeof_type)); + list_add (&mem_pool->global_list, &ctx->mempool_list); - return mem_pool; +out: + return mem_pool; } +void* +mem_get0 (struct mem_pool *mem_pool) +{ + void *ptr = NULL; + + if (!mem_pool) { + gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument"); + return NULL; + } + + ptr = mem_get(mem_pool); + + if (ptr) + memset(ptr, 0, mem_pool->real_sizeof_type); + + return ptr; +} 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; + struct list_head *list = NULL; + void *ptr = NULL; + int *in_use = NULL; + struct mem_pool **pool_ptr = NULL; + + if (!mem_pool) { + gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument"); + return NULL; + } + + LOCK (&mem_pool->lock); + { + mem_pool->alloc_count++; + if (mem_pool->cold_count) { + list = mem_pool->list.next; + list_del (list); + + mem_pool->hot_count++; + mem_pool->cold_count--; + + if (mem_pool->max_alloc < mem_pool->hot_count) + mem_pool->max_alloc = mem_pool->hot_count; + + ptr = list; + in_use = (ptr + GF_MEM_POOL_LIST_BOUNDARY + + GF_MEM_POOL_PTR); + *in_use = 1; + goto fwd_addr_out; - } + } /* This is a problem area. If we've run out of * chunks in our slab above, we need to allocate * enough memory to service this request. - * The problem is, these indvidual chunks will fail + * The problem is, these individual chunks will fail * the first address range check in __is_member. Now, since * we're not allocating a full second slab, we wont have * enough info perform the range check in __is_member. @@ -117,73 +412,104 @@ mem_get (struct mem_pool *mem_pool) * because it is too much work knowing that a better slab * allocator is coming RSN. */ - ptr = MALLOC (mem_pool->real_sizeof_type); + mem_pool->pool_misses++; + mem_pool->curr_stdalloc++; + if (mem_pool->max_stdalloc < mem_pool->curr_stdalloc) + mem_pool->max_stdalloc = mem_pool->curr_stdalloc; + ptr = GF_CALLOC (1, mem_pool->padded_sizeof_type, + gf_common_mt_mem_pool); /* Memory coming from the heap need not be transformed from a * chunkhead to a usable pointer since it is not coming from * the pool. */ - goto unlocked_out; - } + } fwd_addr_out: + pool_ptr = mem_pool_from_ptr (ptr); + *pool_ptr = (struct mem_pool *)mem_pool; ptr = mem_pool_chunkhead2ptr (ptr); -unlocked_out: UNLOCK (&mem_pool->lock); - return ptr; + 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 ((mem_pool_ptr2chunkhead (ptr) - pool->pool) - % pool->padded_sizeof_type) - return -1; - - return 1; + if (!pool || !ptr) { + gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument"); + return -1; + } + + if (ptr < pool->pool || ptr >= pool->pool_end) + return 0; + + if ((mem_pool_ptr2chunkhead (ptr) - pool->pool) + % pool->padded_sizeof_type) + return -1; + + return 1; } void -mem_put (struct mem_pool *pool, void *ptr) +mem_put (void *ptr) { - struct list_head *list = NULL; - - if (!pool || !ptr) { - gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument"); - return; - } - - LOCK (&pool->lock); - { - - switch (__is_member (pool, ptr)) - { - case 1: - list = mem_pool_ptr2chunkhead (ptr); - pool->hot_count--; - pool->cold_count++; - list_add (list, &pool->list); - break; - case -1: + struct list_head *list = NULL; + int *in_use = NULL; + void *head = NULL; + struct mem_pool **tmp = NULL; + struct mem_pool *pool = NULL; + + if (!ptr) { + gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument"); + return; + } + + list = head = mem_pool_ptr2chunkhead (ptr); + tmp = mem_pool_from_ptr (head); + if (!tmp) { + gf_log_callingfn ("mem-pool", GF_LOG_ERROR, + "ptr header is corrupted"); + return; + } + + pool = *tmp; + if (!pool) { + gf_log_callingfn ("mem-pool", GF_LOG_ERROR, + "mem-pool ptr is NULL"); + return; + } + LOCK (&pool->lock); + { + + switch (__is_member (pool, ptr)) + { + case 1: + in_use = (head + GF_MEM_POOL_LIST_BOUNDARY + + GF_MEM_POOL_PTR); + if (!is_mem_chunk_in_use(in_use)) { + gf_log_callingfn ("mem-pool", GF_LOG_CRITICAL, + "mem_put called on freed ptr %p of mem " + "pool %p", ptr, pool); + break; + } + pool->hot_count--; + pool->cold_count++; + *in_use = 0; + list_add (list, &pool->list); + break; + case -1: /* For some reason, the address given is within * the address range of the mem-pool but does not align * with the expected start of a chunk that includes * the list headers also. Sounds like a problem in * layers of clouds up above us. ;) */ - abort (); - break; - case 0: + abort (); + break; + case 0: /* The address is outside the range of the mem-pool. We * assume here that this address was allocated at a * point when the mem-pool was out of chunks in mem_get @@ -192,26 +518,32 @@ mem_put (struct mem_pool *pool, void *ptr) * not have enough info to distinguish between the two * situations. */ - FREE (ptr); - break; - default: - /* log error */ - break; - } - } - UNLOCK (&pool->lock); + pool->curr_stdalloc--; + GF_FREE (list); + break; + default: + /* log error */ + break; + } + } + UNLOCK (&pool->lock); } - void mem_pool_destroy (struct mem_pool *pool) { if (!pool) return; + gf_log (THIS->name, GF_LOG_INFO, "size=%lu max=%d total=%"PRIu64, + pool->padded_sizeof_type, pool->max_alloc, pool->alloc_count); + + list_del (&pool->global_list); + LOCK_DESTROY (&pool->lock); - FREE (pool->pool); - FREE (pool); + GF_FREE (pool->name); + GF_FREE (pool->pool); + GF_FREE (pool); return; } diff --git a/libglusterfs/src/mem-pool.h b/libglusterfs/src/mem-pool.h index 152c17bb4..31f49f75c 100644 --- a/libglusterfs/src/mem-pool.h +++ b/libglusterfs/src/mem-pool.h @@ -1,20 +1,11 @@ /* - Copyright (c) 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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _MEM_POOL_H_ @@ -22,36 +13,184 @@ #include "list.h" #include "locking.h" +#include "logging.h" +#include "mem-types.h" +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> +#include <stdarg.h> + + +struct mem_acct { + uint32_t num_types; + struct mem_acct_rec *rec; +}; + +struct mem_acct_rec { + size_t size; + size_t max_size; + uint32_t num_allocs; + uint32_t total_allocs; + uint32_t max_num_allocs; + gf_lock_t lock; +}; + + +void * +__gf_calloc (size_t cnt, size_t size, uint32_t type); + +void * +__gf_malloc (size_t size, uint32_t type); + +void * +__gf_realloc (void *ptr, size_t size); + +int +gf_vasprintf (char **string_ptr, const char *format, va_list arg); + +int +gf_asprintf (char **string_ptr, const char *format, ...); + +void +__gf_free (void *ptr); + + +static inline +void* __gf_default_malloc (size_t size) +{ + void *ptr = NULL; + + ptr = malloc (size); + if (!ptr) + gf_log_nomem ("", GF_LOG_ALERT, size); + + return ptr; +} + +static inline +void* __gf_default_calloc (int cnt, size_t size) +{ + void *ptr = NULL; + + ptr = calloc (cnt, size); + if (!ptr) + gf_log_nomem ("", GF_LOG_ALERT, (cnt * size)); + + return ptr; +} + +static inline +void* __gf_default_realloc (void *oldptr, size_t size) +{ + void *ptr = NULL; + ptr = realloc (oldptr, size); + if (!ptr) + gf_log_nomem ("", GF_LOG_ALERT, size); -#define MALLOC(size) malloc(size) -#define CALLOC(cnt,size) calloc(cnt,size) + return ptr; +} -#define FREE(ptr) \ - if (ptr != NULL) { \ - free ((void *)ptr); \ - ptr = (void *)0xeeeeeeee; \ - } +#define MALLOC(size) __gf_default_malloc(size) +#define CALLOC(cnt,size) __gf_default_calloc(cnt,size) +#define REALLOC(ptr,size) __gf_default_realloc(ptr,size) + +#define FREE(ptr) \ + if (ptr != NULL) { \ + free ((void *)ptr); \ + ptr = (void *)0xeeeeeeee; \ + } + +#define GF_CALLOC(nmemb, size, type) __gf_calloc (nmemb, size, type) + +#define GF_MALLOC(size, type) __gf_malloc (size, type) + +#define GF_REALLOC(ptr, size) __gf_realloc (ptr, size) + +#define GF_FREE(free_ptr) __gf_free (free_ptr) + +static inline +char *gf_strndup (const char *src, size_t len) +{ + char *dup_str = NULL; + + if (!src) { + goto out; + } + + dup_str = GF_CALLOC (1, len + 1, gf_common_mt_strdup); + if (!dup_str) { + goto out; + } + + memcpy (dup_str, src, len); +out: + return dup_str; +} + +static inline +char * gf_strdup (const char *src) +{ + + char *dup_str = NULL; + size_t len = 0; + + len = strlen (src) + 1; + + dup_str = GF_CALLOC(1, len, gf_common_mt_strdup); + + if (!dup_str) + return NULL; + + memcpy (dup_str, src, len); + + return dup_str; +} + +static inline void * +gf_memdup (const void *src, size_t size) +{ + void *dup_mem = NULL; + + dup_mem = GF_CALLOC(1, size, gf_common_mt_strdup); + if (!dup_mem) + goto out; + + memcpy (dup_mem, src, size); + +out: + return dup_mem; +} 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 list_head list; + int hot_count; + int cold_count; + gf_lock_t lock; + unsigned long padded_sizeof_type; + void *pool; + void *pool_end; int real_sizeof_type; + uint64_t alloc_count; + uint64_t pool_misses; + int max_alloc; + int curr_stdalloc; + int max_stdalloc; + char *name; + struct list_head global_list; }; struct mem_pool * -mem_pool_new_fn (unsigned long sizeof_type, unsigned long count); +mem_pool_new_fn (unsigned long sizeof_type, unsigned long count, char *name); -#define mem_pool_new(type,count) mem_pool_new_fn (sizeof(type), count) +#define mem_pool_new(type,count) mem_pool_new_fn (sizeof(type), count, #type) -void mem_put (struct mem_pool *pool, void *ptr); +void mem_put (void *ptr); void *mem_get (struct mem_pool *pool); +void *mem_get0 (struct mem_pool *pool); void mem_pool_destroy (struct mem_pool *pool); +void gf_mem_acct_enable_set (void *ctx); + #endif /* _MEM_POOL_H */ diff --git a/libglusterfs/src/mem-types.h b/libglusterfs/src/mem-types.h new file mode 100644 index 000000000..666bd120a --- /dev/null +++ b/libglusterfs/src/mem-types.h @@ -0,0 +1,125 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __MEM_TYPES_H__ +#define __MEM_TYPES_H__ + + +enum gf_common_mem_types_ { + gf_common_mt_call_stub_t = 0, + gf_common_mt_dnscache6 = 1, + gf_common_mt_data_pair_t = 2, + gf_common_mt_data_t = 3, + gf_common_mt_dict_t = 4, + gf_common_mt_event_pool = 5, + gf_common_mt_reg = 6, + gf_common_mt_pollfd = 7, + gf_common_mt_epoll_event = 8, + gf_common_mt_fdentry_t = 9, + gf_common_mt_fdtable_t = 10, + gf_common_mt_fd_t = 11, + gf_common_mt_fd_ctx = 12, + gf_common_mt_gf_dirent_t = 13, + gf_common_mt_glusterfs_ctx_t = 14, + gf_common_mt_dentry_t = 15, + gf_common_mt_inode_t = 16, + gf_common_mt_inode_ctx = 17, + gf_common_mt_list_head = 18, + gf_common_mt_inode_table_t = 19, + gf_common_mt_xlator_t = 20, + gf_common_mt_xlator_list_t = 21, + gf_common_mt_log_msg = 22, + gf_common_mt_client_log = 23, + gf_common_mt_volume_opt_list_t = 24, + gf_common_mt_gf_hdr_common_t = 25, + gf_common_mt_call_frame_t = 26, + gf_common_mt_call_stack_t = 27, + gf_common_mt_gf_timer_t = 28, + gf_common_mt_gf_timer_registry_t = 29, + gf_common_mt_transport = 30, + gf_common_mt_transport_msg = 31, + gf_common_mt_auth_handle_t = 32, + gf_common_mt_iobuf = 33, + gf_common_mt_iobuf_arena = 34, + gf_common_mt_iobref = 35, + gf_common_mt_iobuf_pool = 36, + gf_common_mt_iovec = 37, + gf_common_mt_memdup = 38, + gf_common_mt_asprintf = 39, + gf_common_mt_strdup = 40, + gf_common_mt_socket_private_t = 41, + gf_common_mt_ioq = 42, + gf_common_mt_transport_t = 43, + gf_common_mt_socket_local_t = 44, + gf_common_mt_char = 45, + gf_common_mt_rbthash_table_t = 46, + gf_common_mt_rbthash_bucket = 47, + gf_common_mt_mem_pool = 48, + gf_common_mt_long = 49, + gf_common_mt_rpcsvc_auth_list = 50, + gf_common_mt_rpcsvc_t = 51, + gf_common_mt_rpcsvc_conn_t = 52, + gf_common_mt_rpcsvc_program_t = 53, + gf_common_mt_rpcsvc_listener_t = 54, + gf_common_mt_rpcsvc_wrapper_t = 55, + gf_common_mt_rpcsvc_stage_t = 56, + gf_common_mt_rpcclnt_t = 57, + gf_common_mt_rpcclnt_savedframe_t = 58, + gf_common_mt_rpc_trans_t = 59, + gf_common_mt_rpc_trans_pollin_t = 60, + gf_common_mt_rpc_trans_handover_t = 61, + gf_common_mt_rpc_trans_reqinfo_t = 62, + gf_common_mt_rpc_trans_rsp_t = 63, + gf_common_mt_glusterfs_graph_t = 64, + gf_common_mt_rdma_private_t = 65, + gf_common_mt_rdma_ioq_t = 66, + gf_common_mt_rpc_transport_t = 67, + gf_common_mt_rdma_local_t = 68, + gf_common_mt_rdma_post_t = 69, + gf_common_mt_qpent = 70, + gf_common_mt_rdma_device_t = 71, + gf_common_mt_rdma_context_t = 72, + gf_common_mt_sge = 73, + gf_common_mt_rpcclnt_cb_program_t = 74, + gf_common_mt_libxl_marker_local = 75, + gf_common_mt_graph_buf = 76, + gf_common_mt_trie_trie = 77, + gf_common_mt_trie_data = 78, + gf_common_mt_trie_node = 79, + gf_common_mt_trie_buf = 80, + gf_common_mt_trie_end = 81, + gf_common_mt_run_argv = 82, + gf_common_mt_run_logbuf = 83, + gf_common_mt_fd_lk_ctx_t = 84, + gf_common_mt_fd_lk_ctx_node_t = 85, + gf_common_mt_buffer_t = 86, + gf_common_mt_circular_buffer_t = 87, + gf_common_mt_eh_t = 88, + gf_common_mt_store_handle_t = 89, + gf_common_mt_store_iter_t = 90, + gf_common_mt_drc_client_t = 91, + gf_common_mt_drc_globals_t = 92, + gf_common_mt_drc_rbtree_node_t = 93, + gf_common_mt_iov_base_t = 94, + gf_common_mt_groups_t = 95, + gf_common_mt_cliententry_t = 96, + gf_common_mt_clienttable_t = 97, + gf_common_mt_client_t = 98, + gf_common_mt_client_ctx = 99, + gf_common_mt_lock_table = 100, + gf_common_mt_locker = 101, + gf_common_mt_auxgids = 102, + gf_common_mt_syncopctx = 103, + gf_common_mt_uuid_t = 104, + gf_common_mt_mgmt_v3_lock_obj_t = 105, + gf_common_mt_txn_opinfo_obj_t = 106, + gf_common_mt_end = 107 +}; +#endif diff --git a/libglusterfs/src/options.c b/libglusterfs/src/options.c new file mode 100644 index 000000000..842b6413a --- /dev/null +++ b/libglusterfs/src/options.c @@ -0,0 +1,1127 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <fnmatch.h> + +#include "xlator.h" +#include "defaults.h" + +#define GF_OPTION_LIST_EMPTY(_opt) (_opt->value[0] == NULL) + + +static int +xlator_option_validate_path (xlator_t *xl, const char *key, const char *value, + volume_option_t *opt, char **op_errstr) +{ + int ret = -1; + char errstr[256]; + + if (strstr (value, "../")) { + snprintf (errstr, 256, + "invalid path given '%s'", + value); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + + /* Make sure the given path is valid */ + if (value[0] != '/') { + snprintf (errstr, 256, + "option %s %s: '%s' is not an " + "absolute path name", + key, value, value); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + + ret = 0; +out: + if (ret && op_errstr) + *op_errstr = gf_strdup (errstr); + return ret; +} + +static int +xlator_option_validate_int (xlator_t *xl, const char *key, const char *value, + volume_option_t *opt, char **op_errstr) +{ + long long inputll = 0; + int ret = -1; + char errstr[256]; + + /* Check the range */ + if (gf_string2longlong (value, &inputll) != 0) { + snprintf (errstr, 256, + "invalid number format \"%s\" in option \"%s\"", + value, key); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + + if ((opt->min == 0) && (opt->max == 0) && + (opt->validate == GF_OPT_VALIDATE_BOTH)) { + gf_log (xl->name, GF_LOG_TRACE, + "no range check required for 'option %s %s'", + key, value); + ret = 0; + goto out; + } + + if ((opt->validate == GF_OPT_VALIDATE_MIN)) { + if (inputll < opt->min) { + snprintf (errstr, 256, + "'%lld' in 'option %s %s' is smaller than " + "minimum value '%.0f'", inputll, key, + value, opt->min); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + } else if ((opt->validate == GF_OPT_VALIDATE_MAX)) { + if ((inputll > opt->max)) { + snprintf (errstr, 256, + "'%lld' in 'option %s %s' is greater than " + "maximum value '%.0f'", inputll, key, + value, opt->max); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + } else if ((inputll < opt->min) || (inputll > opt->max)) { + snprintf (errstr, 256, + "'%lld' in 'option %s %s' is out of range " + "[%.0f - %.0f]", + inputll, key, value, opt->min, opt->max); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + + ret = 0; +out: + if (ret && op_errstr) + *op_errstr = gf_strdup (errstr); + return ret; +} + + +static int +xlator_option_validate_sizet (xlator_t *xl, const char *key, const char *value, + volume_option_t *opt, char **op_errstr) +{ + uint64_t size = 0; + int ret = 0; + char errstr[256]; + + /* Check the range */ + if (gf_string2bytesize (value, &size) != 0) { + snprintf (errstr, 256, + "invalid number format \"%s\" in option \"%s\"", + value, key); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + ret = -1; + goto out; + } + + if ((opt->min == 0) && (opt->max == 0)) { + gf_log (xl->name, GF_LOG_TRACE, + "no range check required for 'option %s %s'", + key, value); + goto out; + } + + if ((size < opt->min) || (size > opt->max)) { + if ((strncmp (key, "cache-size", 10) == 0) && + (size > opt->max)) { + snprintf (errstr, 256, "Cache size %"PRId64" is out of " + "range [%.0f - %.0f]", + size, opt->min, opt->max); + gf_log (xl->name, GF_LOG_WARNING, "%s", errstr); + } else { + snprintf (errstr, 256, + "'%"PRId64"' in 'option %s %s' " + "is out of range [%.0f - %.0f]", + size, key, value, opt->min, opt->max); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + ret = -1; + } + } + +out: + if (ret && op_errstr) + *op_errstr = gf_strdup (errstr); + return ret; +} + + +static int +xlator_option_validate_bool (xlator_t *xl, const char *key, const char *value, + volume_option_t *opt, char **op_errstr) +{ + int ret = -1; + char errstr[256]; + gf_boolean_t bool; + + + /* Check if the value is one of + '0|1|on|off|no|yes|true|false|enable|disable' */ + + if (gf_string2boolean (value, &bool) != 0) { + snprintf (errstr, 256, + "option %s %s: '%s' is not a valid boolean value", + key, value, value); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + + ret = 0; +out: + if (ret && op_errstr) + *op_errstr = gf_strdup (errstr); + return ret; +} + + +static int +xlator_option_validate_xlator (xlator_t *xl, const char *key, const char *value, + volume_option_t *opt, char **op_errstr) +{ + int ret = -1; + char errstr[256]; + xlator_t *xlopt = NULL; + + + /* Check if the value is one of the xlators */ + xlopt = xl; + while (xlopt->prev) + xlopt = xlopt->prev; + + while (xlopt) { + if (strcmp (value, xlopt->name) == 0) { + ret = 0; + break; + } + xlopt = xlopt->next; + } + + if (!xlopt) { + snprintf (errstr, 256, + "option %s %s: '%s' is not a valid volume name", + key, value, value); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + + ret = 0; +out: + if (ret && op_errstr) + *op_errstr = gf_strdup (errstr); + return ret; +} + +void +set_error_str (char *errstr, size_t len, volume_option_t *opt, const char *key, + const char *value) +{ + int i = 0; + char given_array[4096] = {0,}; + + for (i = 0; (i < ZR_OPTION_MAX_ARRAY_SIZE) && opt->value[i];) { + strcat (given_array, opt->value[i]); + if (((++i) < ZR_OPTION_MAX_ARRAY_SIZE) && + (opt->value[i])) + strcat (given_array, ", "); + else + strcat (given_array, "."); + } + snprintf (errstr, len, "option %s %s: '%s' is not valid " + "(possible options are %s)", key, value, value, given_array); + return; +} + +int +is_all_whitespaces (const char *value) +{ + int i = 0; + size_t len = 0; + + if (value == NULL) + return -1; + + len = strlen (value); + + for (i = 0; i < len; i++) { + if (value[i] == ' ') + continue; + else + return 0; + } + + return 1; +} + +static int +xlator_option_validate_str (xlator_t *xl, const char *key, const char *value, + volume_option_t *opt, char **op_errstr) +{ + int ret = -1; + int i = 0; + char errstr[4096] = {0,}; + + /* Check if the '*str' is valid */ + if (GF_OPTION_LIST_EMPTY(opt)) { + ret = 0; + goto out; + } + + if (is_all_whitespaces (value) == 1) + goto out; + + for (i = 0; (i < ZR_OPTION_MAX_ARRAY_SIZE) && opt->value[i]; i++) { + #ifdef GF_DARWIN_HOST_OS + if (fnmatch (opt->value[i], value, 0) == 0) { + ret = 0; + break; + } + #else + if (fnmatch (opt->value[i], value, FNM_EXTMATCH) == 0) { + ret = 0; + break; + } + #endif + } + + if ((i == ZR_OPTION_MAX_ARRAY_SIZE) || (!opt->value[i])) + goto out; + /* 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. + */ + + ret = 0; + +out: + if (ret) { + set_error_str (errstr, sizeof (errstr), opt, key, value); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + if (op_errstr) + *op_errstr = gf_strdup (errstr); + } + return ret; +} + + +static int +xlator_option_validate_percent (xlator_t *xl, const char *key, const char *value, + volume_option_t *opt, char **op_errstr) +{ + double percent = 0; + int ret = -1; + char errstr[256]; + + /* Check if the value is valid percentage */ + if (gf_string2percent (value, &percent) != 0) { + snprintf (errstr, 256, + "invalid percent format \"%s\" in \"option %s\"", + value, key); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + + if ((percent < 0.0) || (percent > 100.0)) { + snprintf (errstr, 256, + "'%lf' in 'option %s %s' is out of range [0 - 100]", + percent, key, value); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + + ret = 0; +out: + if (ret && op_errstr) + *op_errstr = gf_strdup (errstr); + return ret; +} + +static int +xlator_option_validate_percent_or_sizet (xlator_t *xl, const char *key, + const char *value, + volume_option_t *opt, char **op_errstr) +{ + int ret = -1; + char errstr[256]; + uint64_t size = 0; + gf_boolean_t is_percent = _gf_false; + + if (gf_string2percent_or_bytesize (value, &size, &is_percent) == 0) { + if (is_percent) { + ret = 0; + goto out; + } + /* Check the range */ + if ((opt->min == 0) && (opt->max == 0)) { + gf_log (xl->name, GF_LOG_TRACE, + "no range check required for " + "'option %s %s'", + key, value); + ret = 0; + goto out; + } + if ((size < opt->min) || (size > opt->max)) { + snprintf (errstr, 256, + "'%"PRId64"' in 'option %s %s'" + " is out of range [%.0f - %.0f]", + size, key, value, opt->min, opt->max); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + ret = 0; + goto out; + } + + /* If control reaches here, invalid argument */ + + snprintf (errstr, 256, + "invalid number format \"%s\" in \"option %s\"", + value, key); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + + +out: + if (ret && op_errstr) + *op_errstr = gf_strdup (errstr); + return ret; +} + + +static int +xlator_option_validate_time (xlator_t *xl, const char *key, const char *value, + volume_option_t *opt, char **op_errstr) +{ + int ret = -1; + char errstr[256]; + uint32_t input_time = 0; + + /* Check if the value is valid time */ + if (gf_string2time (value, &input_time) != 0) { + snprintf (errstr, 256, + "invalid time format \"%s\" in " + "\"option %s\"", + value, key); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + + if ((opt->min == 0) && (opt->max == 0)) { + gf_log (xl->name, GF_LOG_TRACE, + "no range check required for " + "'option %s %s'", + key, value); + ret = 0; + goto out; + } + + if ((input_time < opt->min) || (input_time > opt->max)) { + snprintf (errstr, 256, + "'%"PRIu32"' in 'option %s %s' is " + "out of range [%.0f - %.0f]", + input_time, key, value, + opt->min, opt->max); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + + ret = 0; +out: + if (ret && op_errstr) + *op_errstr = gf_strdup (errstr); + return ret; +} + + +static int +xlator_option_validate_double (xlator_t *xl, const char *key, const char *value, + volume_option_t *opt, char **op_errstr) +{ + double input = 0.0; + int ret = -1; + char errstr[256]; + + /* Check the range */ + if (gf_string2double (value, &input) != 0) { + snprintf (errstr, 256, + "invalid number format \"%s\" in option \"%s\"", + value, key); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + + if ((opt->min == 0) && (opt->max == 0) && + (opt->validate == GF_OPT_VALIDATE_BOTH)) { + gf_log (xl->name, GF_LOG_TRACE, + "no range check required for 'option %s %s'", + key, value); + ret = 0; + goto out; + } + + if ((opt->validate == GF_OPT_VALIDATE_MIN)) { + if (input < opt->min) { + snprintf (errstr, 256, + "'%f' in 'option %s %s' is smaller than " + "minimum value '%f'", input, key, + value, opt->min); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + } else if ((opt->validate == GF_OPT_VALIDATE_MAX)) { + if ((input > opt->max)) { + snprintf (errstr, 256, + "'%f' in 'option %s %s' is greater than " + "maximum value '%f'", input, key, + value, opt->max); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + } else if ((input < opt->min) || (input > opt->max)) { + snprintf (errstr, 256, + "'%f' in 'option %s %s' is out of range " + "[%f - %f]", + input, key, value, opt->min, opt->max); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + + ret = 0; +out: + if (ret && op_errstr) + *op_errstr = gf_strdup (errstr); + return ret; +} + + +static int +xlator_option_validate_addr (xlator_t *xl, const char *key, const char *value, + volume_option_t *opt, char **op_errstr) +{ + int ret = -1; + char errstr[256]; + + if (!valid_internet_address ((char *)value, _gf_false)) { + snprintf (errstr, 256, + "option %s %s: '%s' is not a valid internet-address," + " it does not conform to standards.", + key, value, value); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + if (op_errstr) + *op_errstr = gf_strdup (errstr); + } + + ret = 0; + + return ret; +} + +static int +xlator_option_validate_addr_list (xlator_t *xl, const char *key, + const char *value, volume_option_t *opt, + char **op_errstr) +{ + int ret = -1; + char *dup_val = NULL; + char *addr_tok = NULL; + char *save_ptr = NULL; + char errstr[4096] = {0,}; + + dup_val = gf_strdup (value); + if (!dup_val) + goto out; + + addr_tok = strtok_r (dup_val, ",", &save_ptr); + if (addr_tok == NULL) + goto out; + while (addr_tok) { + if (!valid_internet_address (addr_tok, _gf_true)) + goto out; + + addr_tok = strtok_r (NULL, ",", &save_ptr); + } + ret = 0; + +out: + if (ret) { + snprintf (errstr, sizeof (errstr), "option %s %s: '%s' is not " + "a valid internet-address-list", key, value, value); + gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); + if (op_errstr) + *op_errstr = gf_strdup (errstr); + } + GF_FREE (dup_val); + + return ret; +} + +/*XXX: the rules to validate are as per block-size required for stripe xlator */ +static int +gf_validate_size (const char *sizestr, volume_option_t *opt) +{ + uint64_t value = 0; + int ret = 0; + + GF_ASSERT (opt); + + if (gf_string2bytesize (sizestr, &value) != 0 || + value < opt->min || + value % 512) { + ret = -1; + goto out; + } + + out: + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +static int +gf_validate_number (const char *numstr, volume_option_t *opt) +{ + int32_t value; + return gf_string2int32 (numstr, &value); +} + +/* Parses the string to be of the form <key1>:<value1>,<key2>:<value2>... * + * takes two optional validaters key_validator and value_validator */ +static int +validate_list_elements (const char *string, volume_option_t *opt, + int (key_validator)( const char *), + int (value_validator)( const char *, volume_option_t *)) +{ + + char *dup_string = NULL; + char *str_sav = NULL; + char *substr_sav = NULL; + char *str_ptr = NULL; + char *key = NULL; + char *value = NULL; + int ret = 0; + + GF_ASSERT (string); + + dup_string = gf_strdup (string); + if (NULL == dup_string) + goto out; + + str_ptr = strtok_r (dup_string, ",", &str_sav); + if (str_ptr == NULL) { + ret = -1; + goto out; + } + while (str_ptr) { + + key = strtok_r (str_ptr, ":", &substr_sav); + if (!key || + (key_validator && key_validator(key))) { + ret = -1; + gf_log (THIS->name, GF_LOG_WARNING, + "invalid list '%s', key '%s' not valid.", + string, key); + goto out; + } + + value = strtok_r (NULL, ":", &substr_sav); + if (!value || + (value_validator && value_validator(value, opt))) { + ret = -1; + gf_log (THIS->name, GF_LOG_WARNING, + "invalid list '%s', value '%s' not valid.", + string, key); + goto out; + } + + str_ptr = strtok_r (NULL, ",", &str_sav); + substr_sav = NULL; + } + + out: + GF_FREE (dup_string); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +static int +xlator_option_validate_priority_list (xlator_t *xl, const char *key, + const char *value, volume_option_t *opt, + char **op_errstr) +{ + int ret =0; + char errstr[1024] = {0, }; + + GF_ASSERT (value); + + ret = validate_list_elements (value, opt, NULL, &gf_validate_number); + if (ret) { + snprintf (errstr, 1024, + "option %s %s: '%s' is not a valid " + "priority-list", key, value, value); + *op_errstr = gf_strdup (errstr); + } + + return ret; +} + +static int +xlator_option_validate_size_list (xlator_t *xl, const char *key, + const char *value, volume_option_t *opt, + char **op_errstr) +{ + + int ret = 0; + char errstr[1024] = {0, }; + + GF_ASSERT (value); + + ret = gf_validate_size (value, opt); + if (ret) + ret = validate_list_elements (value, opt, NULL, &gf_validate_size); + + if (ret) { + snprintf (errstr, 1024, + "option %s %s: '%s' is not a valid " + "size-list", key, value, value); + *op_errstr = gf_strdup (errstr); + } + + return ret; + +} + +static int +xlator_option_validate_any (xlator_t *xl, const char *key, const char *value, + volume_option_t *opt, char **op_errstr) +{ + return 0; +} + +typedef int (xlator_option_validator_t) (xlator_t *xl, const char *key, + const char *value, + volume_option_t *opt, char **operrstr); + +int +xlator_option_validate (xlator_t *xl, char *key, char *value, + volume_option_t *opt, char **op_errstr) +{ + int ret = -1; + xlator_option_validator_t *validate; + xlator_option_validator_t *validators[] = { + [GF_OPTION_TYPE_PATH] = xlator_option_validate_path, + [GF_OPTION_TYPE_INT] = xlator_option_validate_int, + [GF_OPTION_TYPE_SIZET] = xlator_option_validate_sizet, + [GF_OPTION_TYPE_BOOL] = xlator_option_validate_bool, + [GF_OPTION_TYPE_XLATOR] = xlator_option_validate_xlator, + [GF_OPTION_TYPE_STR] = xlator_option_validate_str, + [GF_OPTION_TYPE_PERCENT] = xlator_option_validate_percent, + [GF_OPTION_TYPE_PERCENT_OR_SIZET] = + xlator_option_validate_percent_or_sizet, + [GF_OPTION_TYPE_TIME] = xlator_option_validate_time, + [GF_OPTION_TYPE_DOUBLE] = xlator_option_validate_double, + [GF_OPTION_TYPE_INTERNET_ADDRESS] = xlator_option_validate_addr, + [GF_OPTION_TYPE_INTERNET_ADDRESS_LIST] = + xlator_option_validate_addr_list, + [GF_OPTION_TYPE_PRIORITY_LIST] = + xlator_option_validate_priority_list, + [GF_OPTION_TYPE_SIZE_LIST] = xlator_option_validate_size_list, + [GF_OPTION_TYPE_ANY] = xlator_option_validate_any, + [GF_OPTION_TYPE_MAX] = NULL, + }; + + if (opt->type < 0 || opt->type >= GF_OPTION_TYPE_MAX) { + gf_log (xl->name, GF_LOG_ERROR, + "unknown option type '%d'", opt->type); + goto out; + } + + validate = validators[opt->type]; + + ret = validate (xl, key, value, opt, op_errstr); +out: + return ret; +} + + +volume_option_t * +xlator_volume_option_get_list (volume_opt_list_t *vol_list, const char *key) +{ + volume_option_t *opt = NULL; + volume_opt_list_t *opt_list = NULL; + volume_option_t *found = NULL; + int index = 0; + int i = 0; + char *cmp_key = NULL; + + if (!vol_list->given_opt) { + opt_list = list_entry (vol_list->list.next, volume_opt_list_t, + list); + opt = opt_list->given_opt; + } else + opt = vol_list->given_opt; + + for (index = 0; opt[index].key[0]; index++) { + for (i = 0; i < ZR_VOLUME_MAX_NUM_KEY; i++) { + cmp_key = opt[index].key[i]; + if (!cmp_key) + break; + if (fnmatch (cmp_key, key, FNM_NOESCAPE) == 0) { + found = &opt[index]; + goto out; + } + } + } +out: + return found; +} + + +volume_option_t * +xlator_volume_option_get (xlator_t *xl, const char *key) +{ + volume_opt_list_t *vol_list = NULL; + volume_option_t *found = NULL; + + list_for_each_entry (vol_list, &xl->volume_options, list) { + found = xlator_volume_option_get_list (vol_list, key); + if (found) + break; + } + + return found; +} + + +static int +xl_opt_validate (dict_t *dict, char *key, data_t *value, void *data) +{ + xlator_t *xl = NULL; + volume_opt_list_t *vol_opt = NULL; + volume_option_t *opt = NULL; + int ret = 0; + char *errstr = NULL; + + struct { + xlator_t *this; + volume_opt_list_t *vol_opt; + char *errstr; + } *stub; + + stub = data; + xl = stub->this; + vol_opt = stub->vol_opt; + + opt = xlator_volume_option_get_list (vol_opt, key); + if (!opt) + return 0; + + ret = xlator_option_validate (xl, key, value->data, opt, &errstr); + if (ret) + gf_log (xl->name, GF_LOG_WARNING, "validate of %s returned %d", + key, ret); + + if (errstr) + /* possible small leak of previously set stub->errstr */ + stub->errstr = errstr; + + if (fnmatch (opt->key[0], key, FNM_NOESCAPE) != 0) { + gf_log (xl->name, GF_LOG_WARNING, "option '%s' is deprecated, " + "preferred is '%s', continuing with correction", + key, opt->key[0]); + dict_set (dict, opt->key[0], value); + dict_del (dict, key); + } + return 0; +} + + +int +xlator_options_validate_list (xlator_t *xl, dict_t *options, + volume_opt_list_t *vol_opt, char **op_errstr) +{ + int ret = 0; + struct { + xlator_t *this; + volume_opt_list_t *vol_opt; + char *errstr; + } stub; + + stub.this = xl; + stub.vol_opt = vol_opt; + stub.errstr = NULL; + + dict_foreach (options, xl_opt_validate, &stub); + if (stub.errstr) { + ret = -1; + if (op_errstr) + *op_errstr = stub.errstr; + } + + return ret; +} + + +int +xlator_options_validate (xlator_t *xl, dict_t *options, char **op_errstr) +{ + int ret = 0; + volume_opt_list_t *vol_opt = NULL; + + + if (!xl) { + gf_log (THIS->name, GF_LOG_DEBUG, "'this' not a valid ptr"); + ret = -1; + goto out; + } + + if (list_empty (&xl->volume_options)) + goto out; + + list_for_each_entry (vol_opt, &xl->volume_options, list) { + ret = xlator_options_validate_list (xl, options, vol_opt, + op_errstr); + } +out: + return ret; +} + + +int +xlator_validate_rec (xlator_t *xlator, char **op_errstr) +{ + int ret = -1; + xlator_list_t *trav = NULL; + xlator_t *old_THIS = NULL; + + GF_VALIDATE_OR_GOTO ("xlator", xlator, out); + + trav = xlator->children; + + while (trav) { + if (xlator_validate_rec (trav->xlator, op_errstr)) { + gf_log ("xlator", GF_LOG_WARNING, "validate_rec failed"); + goto out; + } + + trav = trav->next; + } + + if (xlator_dynload (xlator)) + gf_log (xlator->name, GF_LOG_DEBUG, "Did not load the symbols"); + + old_THIS = THIS; + THIS = xlator; + + /* Need this here, as this graph has not yet called init() */ + if (!xlator->mem_acct.num_types) { + if (!xlator->mem_acct_init) + xlator->mem_acct_init = default_mem_acct_init; + xlator->mem_acct_init (xlator); + } + + ret = xlator_options_validate (xlator, xlator->options, op_errstr); + THIS = old_THIS; + + if (ret) { + gf_log (xlator->name, GF_LOG_INFO, "%s", *op_errstr); + goto out; + } + + gf_log (xlator->name, GF_LOG_DEBUG, "Validated options"); + + ret = 0; +out: + return ret; +} + + +int +graph_reconf_validateopt (glusterfs_graph_t *graph, char **op_errstr) +{ + xlator_t *xlator = NULL; + int ret = -1; + + GF_ASSERT (graph); + + xlator = graph->first; + + ret = xlator_validate_rec (xlator, op_errstr); + + return ret; +} + + +static int +xlator_reconfigure_rec (xlator_t *old_xl, xlator_t *new_xl) +{ + xlator_list_t *trav1 = NULL; + xlator_list_t *trav2 = NULL; + int32_t ret = -1; + xlator_t *old_THIS = NULL; + + GF_VALIDATE_OR_GOTO ("xlator", old_xl, out); + GF_VALIDATE_OR_GOTO ("xlator", new_xl, out); + + trav1 = old_xl->children; + trav2 = new_xl->children; + + while (trav1 && trav2) { + ret = xlator_reconfigure_rec (trav1->xlator, trav2->xlator); + if (ret) + goto out; + + gf_log (trav1->xlator->name, GF_LOG_DEBUG, "reconfigured"); + + trav1 = trav1->next; + trav2 = trav2->next; + } + + if (old_xl->reconfigure) { + old_THIS = THIS; + THIS = old_xl; + + ret = old_xl->reconfigure (old_xl, new_xl->options); + + THIS = old_THIS; + + if (ret) + goto out; + } else { + gf_log (old_xl->name, GF_LOG_DEBUG, "No reconfigure() found"); + } + + ret = 0; +out: + return ret; +} + + +int +xlator_tree_reconfigure (xlator_t *old_xl, xlator_t *new_xl) +{ + xlator_t *new_top = NULL; + xlator_t *old_top = NULL; + + GF_ASSERT (old_xl); + GF_ASSERT (new_xl); + + old_top = old_xl; + new_top = new_xl; + + return xlator_reconfigure_rec (old_top, new_top); +} + + +int +xlator_option_info_list (volume_opt_list_t *list, char *key, + char **def_val, char **descr) +{ + int ret = -1; + volume_option_t *opt = NULL; + + + opt = xlator_volume_option_get_list (list, key); + if (!opt) + goto out; + + if (def_val) + *def_val = opt->default_value; + if (descr) + *descr = opt->description; + + ret = 0; +out: + return ret; +} + + +static int +pass (char *in, char **out) +{ + *out = in; + return 0; +} + + +static int +xl_by_name (char *in, xlator_t **out) +{ + xlator_t *xl = NULL; + + xl = xlator_search_by_name (THIS, in); + + if (!xl) + return -1; + *out = xl; + return 0; +} + + +static int +pc_or_size (char *in, double *out) +{ + double pc = 0; + int ret = 0; + uint64_t size = 0; + + if (gf_string2percent (in, &pc) == 0) { + if (pc > 100.0) { + ret = gf_string2bytesize (in, &size); + if (!ret) + *out = size; + } else { + *out = pc; + } + } else { + ret = gf_string2bytesize (in, &size); + if (!ret) + *out = size; + } + return ret; +} + +DEFINE_INIT_OPT(char *, str, pass); +DEFINE_INIT_OPT(uint64_t, uint64, gf_string2uint64); +DEFINE_INIT_OPT(int64_t, int64, gf_string2int64); +DEFINE_INIT_OPT(uint32_t, uint32, gf_string2uint32); +DEFINE_INIT_OPT(int32_t, int32, gf_string2int32); +DEFINE_INIT_OPT(uint64_t, size, gf_string2bytesize); +DEFINE_INIT_OPT(double, percent, gf_string2percent); +DEFINE_INIT_OPT(double, percent_or_size, pc_or_size); +DEFINE_INIT_OPT(gf_boolean_t, bool, gf_string2boolean); +DEFINE_INIT_OPT(xlator_t *, xlator, xl_by_name); +DEFINE_INIT_OPT(char *, path, pass); +DEFINE_INIT_OPT(double, double, gf_string2double); + + + +DEFINE_RECONF_OPT(char *, str, pass); +DEFINE_RECONF_OPT(uint64_t, uint64, gf_string2uint64); +DEFINE_RECONF_OPT(int64_t, int64, gf_string2int64); +DEFINE_RECONF_OPT(uint32_t, uint32, gf_string2uint32); +DEFINE_RECONF_OPT(int32_t, int32, gf_string2int32); +DEFINE_RECONF_OPT(uint64_t, size, gf_string2bytesize); +DEFINE_RECONF_OPT(double, percent, gf_string2percent); +DEFINE_RECONF_OPT(double, percent_or_size, pc_or_size); +DEFINE_RECONF_OPT(gf_boolean_t, bool, gf_string2boolean); +DEFINE_RECONF_OPT(xlator_t *, xlator, xl_by_name); +DEFINE_RECONF_OPT(char *, path, pass); +DEFINE_RECONF_OPT(double, double, gf_string2double); diff --git a/libglusterfs/src/options.h b/libglusterfs/src/options.h new file mode 100644 index 000000000..e2a25baa9 --- /dev/null +++ b/libglusterfs/src/options.h @@ -0,0 +1,259 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _OPTIONS_H +#define _OPTIONS_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdint.h> +#include <inttypes.h> + +#include "xlator.h" +/* 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_PERCENT_OR_SIZET, + GF_OPTION_TYPE_BOOL, + GF_OPTION_TYPE_XLATOR, + GF_OPTION_TYPE_PATH, + GF_OPTION_TYPE_TIME, + GF_OPTION_TYPE_DOUBLE, + GF_OPTION_TYPE_INTERNET_ADDRESS, + GF_OPTION_TYPE_INTERNET_ADDRESS_LIST, + GF_OPTION_TYPE_PRIORITY_LIST, + GF_OPTION_TYPE_SIZE_LIST, + GF_OPTION_TYPE_MAX, +} volume_option_type_t; + +typedef enum { + GF_OPT_VALIDATE_BOTH = 0, + GF_OPT_VALIDATE_MIN, + GF_OPT_VALIDATE_MAX, +} opt_validate_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; + double min; /* 0 means no range */ + double max; /* 0 means no range */ + char *value[ZR_OPTION_MAX_ARRAY_SIZE]; + /* If specified, will check for one of + the value from this array */ + char *default_value; + char *description; /* about the key */ + /* Required for int options where only the min value + * is given and is 0. This will cause validation not to + * happen + */ + opt_validate_type_t validate; +} volume_option_t; + + +typedef struct vol_opt_list { + struct list_head list; + volume_option_t *given_opt; +} volume_opt_list_t; + + +int xlator_tree_reconfigure (xlator_t *old_xl, xlator_t *new_xl); +int xlator_validate_rec (xlator_t *xlator, char **op_errstr); +int graph_reconf_validateopt (glusterfs_graph_t *graph, char **op_errstr); +int xlator_option_info_list (volume_opt_list_t *list, char *key, + char **def_val, char **descr); +/* +int validate_xlator_volume_options (xlator_t *xl, dict_t *options, + volume_option_t *opt, char **op_errstr); +*/ +int xlator_options_validate_list (xlator_t *xl, dict_t *options, + volume_opt_list_t *list, char **op_errstr); +int xlator_option_validate (xlator_t *xl, char *key, char *value, + volume_option_t *opt, char **op_errstr); +int xlator_options_validate (xlator_t *xl, dict_t *options, char **errstr); +volume_option_t * +xlator_volume_option_get (xlator_t *xl, const char *key); + +volume_option_t * +xlator_volume_option_get_list (volume_opt_list_t *vol_list, const char *key); + + +#define DECLARE_INIT_OPT(type_t, type) \ +int \ +xlator_option_init_##type (xlator_t *this, dict_t *options, char *key, \ + type_t *val_p); + +DECLARE_INIT_OPT(char *, str); +DECLARE_INIT_OPT(uint64_t, uint64); +DECLARE_INIT_OPT(int64_t, int64); +DECLARE_INIT_OPT(uint32_t, uint32); +DECLARE_INIT_OPT(int32_t, int32); +DECLARE_INIT_OPT(uint64_t, size); +DECLARE_INIT_OPT(double, percent); +DECLARE_INIT_OPT(double, percent_or_size); +DECLARE_INIT_OPT(gf_boolean_t, bool); +DECLARE_INIT_OPT(xlator_t *, xlator); +DECLARE_INIT_OPT(char *, path); +DECLARE_INIT_OPT(double, double); + + +#define DEFINE_INIT_OPT(type_t, type, conv) \ +int \ +xlator_option_init_##type (xlator_t *this, dict_t *options, char *key, \ + type_t *val_p) \ +{ \ + int ret = 0; \ + volume_option_t *opt = NULL; \ + char *def_value = NULL; \ + char *set_value = NULL; \ + char *value = NULL; \ + xlator_t *old_THIS = NULL; \ + \ + opt = xlator_volume_option_get (this, key); \ + if (!opt) { \ + gf_log (this->name, GF_LOG_WARNING, \ + "unknown option: %s", key); \ + ret = -1; \ + return ret; \ + } \ + def_value = opt->default_value; \ + ret = dict_get_str (options, key, &set_value); \ + \ + if (def_value) \ + value = def_value; \ + if (set_value) \ + value = set_value; \ + if (!value) { \ + gf_log (this->name, GF_LOG_TRACE, "option %s not set", \ + key); \ + *val_p = (type_t)0; \ + return 0; \ + } \ + if (value == def_value) { \ + gf_log (this->name, GF_LOG_TRACE, \ + "option %s using default value %s", \ + key, value); \ + } else { \ + gf_log (this->name, GF_LOG_DEBUG, \ + "option %s using set value %s", \ + key, value); \ + } \ + old_THIS = THIS; \ + THIS = this; \ + ret = conv (value, val_p); \ + THIS = old_THIS; \ + if (ret) \ + return ret; \ + ret = xlator_option_validate (this, key, value, opt, NULL); \ + return ret; \ +} + +#define GF_OPTION_INIT(key, val, type, err_label) do { \ + int val_ret = 0; \ + val_ret = xlator_option_init_##type (THIS, THIS->options, \ + key, &(val)); \ + if (val_ret) \ + goto err_label; \ + } while (0) + + + +#define DECLARE_RECONF_OPT(type_t, type) \ +int \ +xlator_option_reconf_##type (xlator_t *this, dict_t *options, char *key,\ + type_t *val_p); + +DECLARE_RECONF_OPT(char *, str); +DECLARE_RECONF_OPT(uint64_t, uint64); +DECLARE_RECONF_OPT(int64_t, int64); +DECLARE_RECONF_OPT(uint32_t, uint32); +DECLARE_RECONF_OPT(int32_t, int32); +DECLARE_RECONF_OPT(uint64_t, size); +DECLARE_RECONF_OPT(double, percent); +DECLARE_RECONF_OPT(double, percent_or_size); +DECLARE_RECONF_OPT(gf_boolean_t, bool); +DECLARE_RECONF_OPT(xlator_t *, xlator); +DECLARE_RECONF_OPT(char *, path); +DECLARE_RECONF_OPT(double, double); + + +#define DEFINE_RECONF_OPT(type_t, type, conv) \ +int \ +xlator_option_reconf_##type (xlator_t *this, dict_t *options, char *key, \ + type_t *val_p) \ +{ \ + int ret = 0; \ + volume_option_t *opt = NULL; \ + char *def_value = NULL; \ + char *set_value = NULL; \ + char *value = NULL; \ + xlator_t *old_THIS = NULL; \ + \ + opt = xlator_volume_option_get (this, key); \ + if (!opt) { \ + gf_log (this->name, GF_LOG_WARNING, \ + "unknown option: %s", key); \ + ret = -1; \ + return ret; \ + } \ + def_value = opt->default_value; \ + ret = dict_get_str (options, key, &set_value); \ + \ + if (def_value) \ + value = def_value; \ + if (set_value) \ + value = set_value; \ + if (!value) { \ + gf_log (this->name, GF_LOG_TRACE, "option %s not set", \ + key); \ + *val_p = (type_t)0; \ + return 0; \ + } \ + if (value == def_value) { \ + gf_log (this->name, GF_LOG_TRACE, \ + "option %s using default value %s", \ + key, value); \ + } else { \ + gf_log (this->name, GF_LOG_DEBUG, \ + "option %s using set value %s", \ + key, value); \ + } \ + old_THIS = THIS; \ + THIS = this; \ + ret = conv (value, val_p); \ + THIS = old_THIS; \ + if (ret) \ + return ret; \ + ret = xlator_option_validate (this, key, value, opt, NULL); \ + return ret; \ +} + +#define GF_OPTION_RECONF(key, val, opt, type, err_label) do { \ + int val_ret = 0; \ + val_ret = xlator_option_reconf_##type (THIS, opt, key, \ + &(val)); \ + if (val_ret) \ + goto err_label; \ + } while (0) + + +#endif /* !_OPTIONS_H */ diff --git a/libglusterfs/src/protocol.h b/libglusterfs/src/protocol.h deleted file mode 100644 index f163d0ed4..000000000 --- a/libglusterfs/src/protocol.h +++ /dev/null @@ -1,1013 +0,0 @@ -/* - Copyright (c) 2006-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 _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" - -/* Any changes in the protocol structure or adding new '[f,m]ops' needs to - * bump the protocol version by "0.1" - */ - -#define GF_PROTOCOL_VERSION "2.1" - -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); -} - - -#define GF_O_ACCMODE 003 -#define GF_O_RDONLY 00 -#define GF_O_WRONLY 01 -#define GF_O_RDWR 02 -#define GF_O_CREAT 0100 -#define GF_O_EXCL 0200 -#define GF_O_NOCTTY 0400 -#define GF_O_TRUNC 01000 -#define GF_O_APPEND 02000 -#define GF_O_NONBLOCK 04000 -#define GF_O_SYNC 010000 -#define GF_O_ASYNC 020000 - -#define GF_O_DIRECT 040000 -#define GF_O_DIRECTORY 0200000 -#define GF_O_NOFOLLOW 0400000 -#define GF_O_NOATIME 01000000 -#define GF_O_CLOEXEC 02000000 - -#define GF_O_LARGEFILE 0100000 - -#define XLATE_BIT(from, to, bit) do { \ - if (from & bit) \ - to = to | GF_##bit; \ - } while (0) - -#define UNXLATE_BIT(from, to, bit) do { \ - if (from & GF_##bit) \ - to = to | bit; \ - } while (0) - -#define XLATE_ACCESSMODE(from, to) do { \ - switch (from & O_ACCMODE) { \ - case O_RDONLY: to |= GF_O_RDONLY; \ - break; \ - case O_WRONLY: to |= GF_O_WRONLY; \ - break; \ - case O_RDWR: to |= GF_O_RDWR; \ - break; \ - } \ - } while (0) - -#define UNXLATE_ACCESSMODE(from, to) do { \ - switch (from & GF_O_ACCMODE) { \ - case GF_O_RDONLY: to |= O_RDONLY; \ - break; \ - case GF_O_WRONLY: to |= O_WRONLY; \ - break; \ - case GF_O_RDWR: to |= O_RDWR; \ - break; \ - } \ - } while (0) - -static inline uint32_t -gf_flags_from_flags (uint32_t flags) -{ - uint32_t gf_flags = 0; - - XLATE_ACCESSMODE (flags, gf_flags); - - XLATE_BIT (flags, gf_flags, O_CREAT); - XLATE_BIT (flags, gf_flags, O_EXCL); - XLATE_BIT (flags, gf_flags, O_NOCTTY); - XLATE_BIT (flags, gf_flags, O_TRUNC); - XLATE_BIT (flags, gf_flags, O_APPEND); - XLATE_BIT (flags, gf_flags, O_NONBLOCK); - XLATE_BIT (flags, gf_flags, O_SYNC); - XLATE_BIT (flags, gf_flags, O_ASYNC); - - XLATE_BIT (flags, gf_flags, O_DIRECT); - XLATE_BIT (flags, gf_flags, O_DIRECTORY); - XLATE_BIT (flags, gf_flags, O_NOFOLLOW); -#ifdef O_NOATIME - XLATE_BIT (flags, gf_flags, O_NOATIME); -#endif -#ifdef O_CLOEXEC - XLATE_BIT (flags, gf_flags, O_CLOEXEC); -#endif - XLATE_BIT (flags, gf_flags, O_LARGEFILE); - - return gf_flags; -} - -static inline uint32_t -gf_flags_to_flags (uint32_t gf_flags) -{ - uint32_t flags = 0; - - UNXLATE_ACCESSMODE (gf_flags, flags); - - UNXLATE_BIT (gf_flags, flags, O_CREAT); - UNXLATE_BIT (gf_flags, flags, O_EXCL); - UNXLATE_BIT (gf_flags, flags, O_NOCTTY); - UNXLATE_BIT (gf_flags, flags, O_TRUNC); - UNXLATE_BIT (gf_flags, flags, O_APPEND); - UNXLATE_BIT (gf_flags, flags, O_NONBLOCK); - UNXLATE_BIT (gf_flags, flags, O_SYNC); - UNXLATE_BIT (gf_flags, flags, O_ASYNC); - - UNXLATE_BIT (gf_flags, flags, O_DIRECT); - UNXLATE_BIT (gf_flags, flags, O_DIRECTORY); - UNXLATE_BIT (gf_flags, flags, O_NOFOLLOW); -#ifdef O_NOATIME - UNXLATE_BIT (gf_flags, flags, O_NOATIME); -#endif -#ifdef O_CLOEXEC - UNXLATE_BIT (gf_flags, flags, O_CLOEXEC); -#endif - UNXLATE_BIT (gf_flags, flags, O_LARGEFILE); - - return flags; -} - - -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 { - struct gf_stat buf; - 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; - struct gf_stat preparent; - struct gf_stat postparent; -} __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; - struct gf_stat preparent; - struct gf_stat postparent; -} __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 { - struct gf_stat preparent; - struct gf_stat postparent; -} __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 { - struct gf_stat preparent; - struct gf_stat postparent; -} __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; - struct gf_stat preparent; - struct gf_stat postparent; -}__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; - struct gf_stat preoldparent; - struct gf_stat postoldparent; - struct gf_stat prenewparent; - struct gf_stat postnewparent; -} __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; - struct gf_stat preparent; - struct gf_stat postparent; -} __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 prestat; - struct gf_stat poststat; -} __attribute__((packed)) gf_fop_truncate_rsp_t; - - -typedef struct { - uint64_t ino; - uint32_t flags; - uint32_t wbflags; - 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 prestat; - struct gf_stat poststat; -} __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 { - struct gf_stat prestat; - struct gf_stat poststat; -} __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; - int64_t fd; - uint32_t flags; - uint32_t dict_len; - char dict[0]; -} __attribute__((packed)) gf_fop_fsetxattr_req_t; -typedef struct { } __attribute__((packed)) gf_fop_fsetxattr_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; - int64_t fd; - uint32_t namelen; - char name[0]; -} __attribute__((packed)) gf_fop_fgetxattr_req_t; -typedef struct { - uint32_t dict_len; - char dict[0]; -} __attribute__((packed)) gf_fop_fgetxattr_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; - int64_t fd; - uint64_t offset; - uint32_t size; -} __attribute__((packed)) gf_fop_readdirp_req_t; -typedef struct { - uint32_t size; - char buf[0]; -} __attribute__((packed)) gf_fop_readdirp_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; - struct gf_stat preparent; - struct gf_stat postparent; -} __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 prestat; - struct gf_stat poststat; -} __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]; - char volume[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; - char volume[0]; -} __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]; - char volume[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]; - char volume[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; - struct gf_stat postparent; - 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 { - uint64_t ino; - struct gf_stat stbuf; - int32_t valid; - char path[0]; -} __attribute__((packed)) gf_fop_setattr_req_t; -typedef struct { - struct gf_stat statpre; - struct gf_stat statpost; -} __attribute__((packed)) gf_fop_setattr_rsp_t; - -typedef struct { - int64_t fd; - struct gf_stat stbuf; - int32_t valid; -} __attribute__((packed)) gf_fop_fsetattr_req_t; -typedef struct { - struct gf_stat statpre; - struct gf_stat statpost; -} __attribute__((packed)) gf_fop_fsetattr_rsp_t; - -typedef struct { - int64_t fd; - uint64_t offset; - uint32_t len; -} __attribute__((packed)) gf_fop_rchecksum_req_t; -typedef struct { - uint32_t weak_checksum; - unsigned char strong_checksum[0]; -} __attribute__((packed)) gf_fop_rchecksum_rsp_t; - - -typedef struct { - uint64_t ino; - int32_t timeout; -} __attribute__((packed)) gf_fop_lock_notify_req_t; -typedef struct { } __attribute__((packed)) gf_fop_lock_notify_rsp_t; - - -typedef struct { - int64_t fd; - int32_t timeout; -} __attribute__((packed)) gf_fop_lock_fnotify_req_t; -typedef struct { } __attribute__((packed)) gf_fop_lock_fnotify_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 msglen; - char msg[0]; -} __attribute__((packed)) gf_mop_log_req_t; -typedef struct { -} __attribute__((packed)) gf_mop_log_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/rbthash.c b/libglusterfs/src/rbthash.c new file mode 100644 index 000000000..0d7b9e521 --- /dev/null +++ b/libglusterfs/src/rbthash.c @@ -0,0 +1,458 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + + +#include "rbthash.h" +#include "rb.h" +#include "locking.h" +#include "mem-pool.h" +#include "logging.h" + +#include <pthread.h> +#include <string.h> + + +int +rbthash_comparator (void *entry1, void *entry2, void *param) +{ + int ret = 0; + rbthash_entry_t *e1 = NULL; + rbthash_entry_t *e2 = NULL; + + if ((!entry1) || (!entry2) || (!param)) + return -1; + + e1 = (rbthash_entry_t *)entry1; + e2 = (rbthash_entry_t *)entry2; + + if (e1->keylen != e2->keylen) { + if (e1->keylen < e2->keylen) + ret = -1; + else if (e1->keylen > e2->keylen) + ret = 1; + } else + ret = memcmp (e1->key, e2->key, e1->keylen); + + return ret; +} + + +int +__rbthash_init_buckets (rbthash_table_t *tbl, int buckets) +{ + int i = 0; + int ret = -1; + + if (!tbl) + return -1; + + for (; i < buckets; i++) { + LOCK_INIT (&tbl->buckets[i].bucketlock); + tbl->buckets[i].bucket = rb_create ((rb_comparison_func *)rbthash_comparator, tbl, NULL); + if (!tbl->buckets[i].bucket) { + gf_log (GF_RBTHASH, GF_LOG_ERROR, "Failed to create rb" + " table bucket"); + ret = -1; + goto err; + } + } + + ret = 0; +err: + return ret; +} + + +/* + * rbthash_table_init - Initialize a RBT based hash table + * @buckets - Number of buckets in the hash table + * @hfunc - hashing function + * @dfunc - destroyer for data in the RBT + * @expected_entries - Number of entries expected in RBT. Mutually exclusive + * with entrypool. + * @entrypool - Memory pool in lieu of expected_entries. + */ + +rbthash_table_t * +rbthash_table_init (int buckets, rbt_hasher_t hfunc, + rbt_data_destroyer_t dfunc, + unsigned long expected_entries, + struct mem_pool *entrypool) +{ + rbthash_table_t *newtab = NULL; + int ret = -1; + + if (!hfunc) { + gf_log (GF_RBTHASH, GF_LOG_ERROR, "Hash function not given"); + return NULL; + } + + if (!entrypool && !expected_entries) { + gf_log (GF_RBTHASH, GF_LOG_ERROR, + "Both mem-pool and expected entries not provided"); + return NULL; + } + + if (entrypool && expected_entries) { + gf_log (GF_RBTHASH, GF_LOG_ERROR, + "Both mem-pool and expected entries are provided"); + return NULL; + } + + + newtab = GF_CALLOC (1, sizeof (*newtab), + gf_common_mt_rbthash_table_t); + if (!newtab) + return NULL; + + newtab->buckets = GF_CALLOC (buckets, sizeof (struct rbthash_bucket), + gf_common_mt_rbthash_bucket); + if (!newtab->buckets) { + goto free_newtab; + } + + if (expected_entries) { + newtab->entrypool = + mem_pool_new (rbthash_entry_t, expected_entries); + if (!newtab->entrypool) { + gf_log (GF_RBTHASH, GF_LOG_ERROR, + "Failed to allocate mem-pool"); + goto free_buckets; + } + newtab->pool_alloced = _gf_true; + } else { + newtab->entrypool = entrypool; + } + + LOCK_INIT (&newtab->tablelock); + INIT_LIST_HEAD (&newtab->list); + newtab->numbuckets = buckets; + ret = __rbthash_init_buckets (newtab, buckets); + + if (ret == -1) { + gf_log (GF_RBTHASH, GF_LOG_ERROR, "Failed to init buckets"); + if (newtab->pool_alloced) + mem_pool_destroy (newtab->entrypool); + } else { + gf_log (GF_RBTHASH, GF_LOG_TRACE, "Inited hash table: buckets:" + " %d", buckets); + } + + newtab->hashfunc = hfunc; + newtab->dfunc = dfunc; + +free_buckets: + if (ret == -1) + GF_FREE (newtab->buckets); + +free_newtab: + if (ret == -1) { + GF_FREE (newtab); + newtab = NULL; + } + + return newtab; +} + +rbthash_entry_t * +rbthash_init_entry (rbthash_table_t *tbl, void *data, void *key, int keylen) +{ + int ret = -1; + rbthash_entry_t *entry = NULL; + + if ((!tbl) || (!data) || (!key)) + return NULL; + + entry = mem_get (tbl->entrypool); + if (!entry) { + gf_log (GF_RBTHASH, GF_LOG_ERROR, "Failed to get entry from" + " mem-pool"); + goto ret; + } + + entry->data = data; + entry->key = GF_CALLOC (keylen, sizeof (char), gf_common_mt_char); + if (!entry->key) { + goto free_entry; + } + + INIT_LIST_HEAD (&entry->list); + memcpy (entry->key, key, keylen); + entry->keylen = keylen; + entry->keyhash = tbl->hashfunc (entry->key, entry->keylen); + gf_log (GF_RBTHASH, GF_LOG_TRACE, "HASH: %u", entry->keyhash); + + ret = 0; +free_entry: + if (ret == -1) { + mem_put (entry); + entry = NULL; + } + +ret: + return entry; +} + + +void +rbthash_deinit_entry (rbthash_table_t *tbl, rbthash_entry_t *entry) +{ + + if (!entry) + return; + + GF_FREE (entry->key); + + if (tbl) { + if ((entry->data) && (tbl->dfunc)) + tbl->dfunc (entry->data); + + LOCK (&tbl->tablelock); + { + list_del_init (&entry->list); + } + UNLOCK (&tbl->tablelock); + + mem_put (entry); + } + + return; +} + + +static inline struct rbthash_bucket * +rbthash_entry_bucket (rbthash_table_t *tbl, rbthash_entry_t * entry) +{ + int nbucket = 0; + + nbucket = (entry->keyhash % tbl->numbuckets); + gf_log (GF_RBTHASH, GF_LOG_TRACE, "BUCKET: %d", nbucket); + return &tbl->buckets[nbucket]; +} + + +int +rbthash_insert_entry (rbthash_table_t *tbl, rbthash_entry_t *entry) +{ + struct rbthash_bucket *bucket = NULL; + int ret = -1; + + if ((!tbl) || (!entry)) + return -1; + + bucket = rbthash_entry_bucket (tbl, entry); + if (!bucket) { + gf_log (GF_RBTHASH, GF_LOG_ERROR, "Failed to get bucket"); + goto err; + } + + ret = 0; + LOCK (&bucket->bucketlock); + { + if (!rb_probe (bucket->bucket, (void *)entry)) { + gf_log (GF_RBTHASH, GF_LOG_ERROR, "Failed to insert" + " entry"); + ret = -1; + } + } + UNLOCK (&bucket->bucketlock); + +err: + return ret; +} + + +int +rbthash_insert (rbthash_table_t *tbl, void *data, void *key, int keylen) +{ + rbthash_entry_t *entry = NULL; + int ret = -1; + + if ((!tbl) || (!data) || (!key)) + return -1; + + entry = rbthash_init_entry (tbl, data, key, keylen); + if (!entry) { + gf_log (GF_RBTHASH, GF_LOG_ERROR, "Failed to init entry"); + goto err; + } + + ret = rbthash_insert_entry (tbl, entry); + + if (ret == -1) { + gf_log (GF_RBTHASH, GF_LOG_ERROR, "Failed to insert entry"); + rbthash_deinit_entry (tbl, entry); + } + + LOCK (&tbl->tablelock); + { + list_add_tail (&entry->list, &tbl->list); + } + UNLOCK (&tbl->tablelock); + +err: + return ret; +} + +static inline struct rbthash_bucket * +rbthash_key_bucket (rbthash_table_t *tbl, void *key, int keylen) +{ + uint32_t keyhash = 0; + int nbucket = 0; + + if ((!tbl) || (!key)) + return NULL; + + keyhash = tbl->hashfunc (key, keylen); + gf_log (GF_RBTHASH, GF_LOG_TRACE, "HASH: %u", keyhash); + nbucket = (keyhash % tbl->numbuckets); + gf_log (GF_RBTHASH, GF_LOG_TRACE, "BUCKET: %u", nbucket); + + return &tbl->buckets[nbucket]; +} + + +void * +rbthash_get (rbthash_table_t *tbl, void *key, int keylen) +{ + struct rbthash_bucket *bucket = NULL; + rbthash_entry_t *entry = NULL; + rbthash_entry_t searchentry = {0, }; + + if ((!tbl) || (!key)) + return NULL; + + bucket = rbthash_key_bucket (tbl, key, keylen); + if (!bucket) { + gf_log (GF_RBTHASH, GF_LOG_ERROR, "Failed to get bucket"); + return NULL; + } + + searchentry.key = key; + searchentry.keylen = keylen; + LOCK (&bucket->bucketlock); + { + entry = rb_find (bucket->bucket, &searchentry); + } + UNLOCK (&bucket->bucketlock); + + if (!entry) + return NULL; + + return entry->data; +} + + +void * +rbthash_remove (rbthash_table_t *tbl, void *key, int keylen) +{ + struct rbthash_bucket *bucket = NULL; + rbthash_entry_t *entry = NULL; + rbthash_entry_t searchentry = {0, }; + void *dataref = NULL; + + if ((!tbl) || (!key)) + return NULL; + + bucket = rbthash_key_bucket (tbl, key, keylen); + if (!bucket) { + gf_log (GF_RBTHASH, GF_LOG_ERROR, "Failed to get bucket"); + return NULL; + } + + searchentry.key = key; + searchentry.keylen = keylen; + + LOCK (&bucket->bucketlock); + { + entry = rb_delete (bucket->bucket, &searchentry); + } + UNLOCK (&bucket->bucketlock); + + if (!entry) + return NULL; + + GF_FREE (entry->key); + dataref = entry->data; + + LOCK (&tbl->tablelock); + { + list_del_init (&entry->list); + } + UNLOCK (&tbl->tablelock); + + mem_put (entry); + + return dataref; +} + + +void +rbthash_entry_deiniter (void *entry, void *rbparam) +{ + if (!entry) + return; + + rbthash_deinit_entry (rbparam, entry); +} + + +void +rbthash_table_destroy_buckets (rbthash_table_t *tbl) +{ + int x = 0; + if (!tbl) + return; + + for (;x < tbl->numbuckets; x++) { + LOCK_DESTROY (&tbl->buckets[x].bucketlock); + rb_destroy (tbl->buckets[x].bucket, rbthash_entry_deiniter); + } + + return; +} + + +void +rbthash_table_destroy (rbthash_table_t *tbl) +{ + if (!tbl) + return; + + rbthash_table_destroy_buckets (tbl); + if (tbl->pool_alloced) + mem_pool_destroy (tbl->entrypool); + + GF_FREE (tbl->buckets); + GF_FREE (tbl); +} + + +void +rbthash_table_traverse (rbthash_table_t *tbl, rbt_traverse_t traverse, + void *mydata) +{ + rbthash_entry_t *entry = NULL; + + if ((tbl == NULL) || (traverse == NULL)) { + goto out; + } + + LOCK (&tbl->tablelock); + { + list_for_each_entry (entry, &tbl->list, list) { + traverse (entry->data, mydata); + } + } + UNLOCK (&tbl->tablelock); + +out: + return; +} diff --git a/libglusterfs/src/rbthash.h b/libglusterfs/src/rbthash.h new file mode 100644 index 000000000..b093ce998 --- /dev/null +++ b/libglusterfs/src/rbthash.h @@ -0,0 +1,77 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __RBTHASH_TABLE_H_ +#define __RBTHASH_TABLE_H_ +#include "rb.h" +#include "locking.h" +#include "mem-pool.h" +#include "logging.h" +#include "common-utils.h" +#include "list.h" + +#include <pthread.h> + +#define GF_RBTHASH_MEMPOOL 16384 //1048576 +#define GF_RBTHASH "rbthash" + +struct rbthash_bucket { + struct rb_table *bucket; + gf_lock_t bucketlock; +}; + +typedef struct rbthash_entry { + void *data; + void *key; + int keylen; + uint32_t keyhash; + struct list_head list; +} rbthash_entry_t; + +typedef uint32_t (*rbt_hasher_t) (void *data, int len); +typedef void (*rbt_data_destroyer_t) (void *data); +typedef void (*rbt_traverse_t) (void *data, void *mydata); + +typedef struct rbthash_table { + int size; + int numbuckets; + struct mem_pool *entrypool; + gf_lock_t tablelock; + struct rbthash_bucket *buckets; + rbt_hasher_t hashfunc; + rbt_data_destroyer_t dfunc; + gf_boolean_t pool_alloced; + struct list_head list; +} rbthash_table_t; + +extern rbthash_table_t * +rbthash_table_init (int buckets, rbt_hasher_t hfunc, + rbt_data_destroyer_t dfunc, unsigned long expected_entries, + struct mem_pool *entrypool); + +extern int +rbthash_insert (rbthash_table_t *tbl, void *data, void *key, int keylen); + +extern void * +rbthash_get (rbthash_table_t *tbl, void *key, int keylen); + +extern void * +rbthash_remove (rbthash_table_t *tbl, void *key, int keylen); + +extern void * +rbthash_replace (rbthash_table_t *tbl, void *key, int keylen, void *newdata); + +extern void +rbthash_table_destroy (rbthash_table_t *tbl); + +extern void +rbthash_table_traverse (rbthash_table_t *tbl, rbt_traverse_t traverse, + void *mydata); +#endif diff --git a/libglusterfs/src/revision.h b/libglusterfs/src/revision.h index 03c887fc0..c1ea4a9e9 100644 --- a/libglusterfs/src/revision.h +++ b/libglusterfs/src/revision.h @@ -1 +1 @@ -#define GLUSTERFS_REPOSITORY_REVISION "git://git.sv.gnu.org/gluster.git" +#define GLUSTERFS_REPOSITORY_REVISION "git://git.gluster.com/glusterfs.git" diff --git a/libglusterfs/src/run.c b/libglusterfs/src/run.c new file mode 100644 index 000000000..4fd2a3a0d --- /dev/null +++ b/libglusterfs/src/run.c @@ -0,0 +1,513 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <dirent.h> +#include <assert.h> +#include <signal.h> +#include <sys/wait.h> +#include <sys/resource.h> + +#ifdef RUN_STANDALONE +#define GF_CALLOC(n, s, t) calloc(n, s) +#define GF_ASSERT(cond) assert(cond) +#define GF_REALLOC(p, s) realloc(p, s) +#define GF_FREE(p) free(p) +#define gf_strdup(s) strdup(s) +#define gf_vasprintf(p, f, va) vasprintf(p, f, va) +#define gf_loglevel_t int +#define gf_log(dom, levl, fmt, args...) printf("LOG: " fmt "\n", ##args) +#define LOG_DEBUG 0 +#ifdef __linux__ +#define GF_LINUX_HOST_OS +#endif +#else /* ! RUN_STANDALONE */ +#include "glusterfs.h" +#include "common-utils.h" +#endif + +#include "run.h" + +void +runinit (runner_t *runner) +{ + int i = 0; + + runner->argvlen = 64; + runner->argv = GF_CALLOC (runner->argvlen, + sizeof (*runner->argv), + gf_common_mt_run_argv); + runner->runerr = runner->argv ? 0 : errno; + runner->chpid = -1; + for (i = 0; i < 3; i++) { + runner->chfd[i] = -1; + runner->chio[i] = NULL; + } +} + +FILE * +runner_chio (runner_t *runner, int fd) +{ + GF_ASSERT (fd > 0 && fd < 3); + + if ((fd > 0) && (fd < 3)) + return runner->chio[fd]; + + return NULL; +} + +static void +runner_insert_arg (runner_t *runner, char *arg) +{ + int i = 0; + + GF_ASSERT (arg); + + if (runner->runerr) + return; + + for (i = 0; i < runner->argvlen; i++) { + if (runner->argv[i] == NULL) + break; + } + GF_ASSERT (i < runner->argvlen); + + if (i == runner->argvlen - 1) { + runner->argv = GF_REALLOC (runner->argv, + runner->argvlen * 2 * sizeof (*runner->argv)); + if (!runner->argv) { + runner->runerr = errno; + return; + } + memset (/* "+" is aware of the type of its left side, + * no need to multiply with type-size */ + runner->argv + runner->argvlen, + 0, runner->argvlen * sizeof (*runner->argv)); + runner->argvlen *= 2; + } + + runner->argv[i] = arg; +} + +void +runner_add_arg (runner_t *runner, const char *arg) +{ + arg = gf_strdup (arg); + if (!arg) { + runner->runerr = errno; + return; + } + + runner_insert_arg (runner, (char *)arg); +} + +static void +runner_va_add_args (runner_t *runner, va_list argp) +{ + const char *arg; + + while ((arg = va_arg (argp, const char *))) + runner_add_arg (runner, arg); +} + +void +runner_add_args (runner_t *runner, ...) +{ + va_list argp; + + va_start (argp, runner); + runner_va_add_args (runner, argp); + va_end (argp); +} + +void +runner_argprintf (runner_t *runner, const char *format, ...) +{ + va_list argva; + char *arg = NULL; + int ret = 0; + + va_start (argva, format); + ret = gf_vasprintf (&arg, format, argva); + va_end (argva); + + if (ret < 0) { + runner->runerr = errno; + return; + } + + runner_insert_arg (runner, arg); +} + +void +runner_log (runner_t *runner, const char *dom, gf_loglevel_t lvl, + const char *msg) +{ + char *buf = NULL; + size_t len = 0; + int i = 0; + + if (runner->runerr) + return; + + for (i = 0;; i++) { + if (runner->argv[i] == NULL) + break; + len += (strlen (runner->argv[i]) + 1); + } + + buf = GF_CALLOC (1, len + 1, gf_common_mt_run_logbuf); + if (!buf) { + runner->runerr = errno; + return; + } + for (i = 0;; i++) { + if (runner->argv[i] == NULL) + break; + strcat (buf, runner->argv[i]); + strcat (buf, " "); + } + if (len > 0) + buf[len - 1] = '\0'; + + gf_log_callingfn (dom, lvl, "%s: %s", msg, buf); + + GF_FREE (buf); +} + +void +runner_redir (runner_t *runner, int fd, int tgt_fd) +{ + GF_ASSERT (fd > 0 && fd < 3); + + if ((fd > 0) && (fd < 3)) + runner->chfd[fd] = (tgt_fd >= 0) ? tgt_fd : -2; +} + +int +runner_start (runner_t *runner) +{ + int pi[3][2] = {{-1, -1}, {-1, -1}, {-1, -1}}; + int xpi[2]; + int ret = 0; + int errno_priv = 0; + int i = 0; + sigset_t set; + + if (runner->runerr) { + errno = runner->runerr; + return -1; + } + + GF_ASSERT (runner->argv[0]); + + /* set up a channel to child to communicate back + * possible execve(2) failures + */ + ret = pipe(xpi); + if (ret != -1) + ret = fcntl (xpi[1], F_SETFD, FD_CLOEXEC); + + for (i = 0; i < 3; i++) { + if (runner->chfd[i] != -2) + continue; + ret = pipe (pi[i]); + if (ret != -1) { + runner->chio[i] = fdopen (pi[i][i ? 0 : 1], i ? "r" : "w"); + if (!runner->chio[i]) + ret = -1; + } + } + + if (ret != -1) + runner->chpid = fork (); + switch (runner->chpid) { + case -1: + errno_priv = errno; + close (xpi[0]); + close (xpi[1]); + for (i = 0; i < 3; i++) { + close (pi[i][0]); + close (pi[i][1]); + } + errno = errno_priv; + return -1; + case 0: + for (i = 0; i < 3; i++) + close (pi[i][i ? 0 : 1]); + close (xpi[0]); + ret = 0; + + for (i = 0; i < 3; i++) { + if (ret == -1) + break; + switch (runner->chfd[i]) { + case -1: + /* no redir */ + break; + case -2: + /* redir to pipe */ + ret = dup2 (pi[i][i ? 1 : 0], i); + break; + default: + /* redir to file */ + ret = dup2 (runner->chfd[i], i); + } + } + + if (ret != -1 ) { +#ifdef GF_LINUX_HOST_OS + DIR *d = NULL; + struct dirent *de = NULL; + char *e = NULL; + + d = opendir ("/proc/self/fd"); + if (d) { + while ((de = readdir (d))) { + i = strtoul (de->d_name, &e, 10); + if (*e == '\0' && i > 2 && + i != dirfd (d) && i != xpi[1]) + close (i); + } + closedir (d); + } else + ret = -1; +#else + struct rlimit rl; + ret = getrlimit (RLIMIT_NOFILE, &rl); + GF_ASSERT (ret == 0); + + for (i = 3; i < rl.rlim_cur; i++) { + if (i != xpi[1]) + close (i); + } +#endif + } + + if (ret != -1) { + /* save child from inheriting our singal handling */ + sigemptyset (&set); + sigprocmask (SIG_SETMASK, &set, NULL); + + execvp (runner->argv[0], runner->argv); + } + ret = write (xpi[1], &errno, sizeof (errno)); + _exit (1); + } + + errno_priv = errno; + for (i = 0; i < 3; i++) + close (pi[i][i ? 1 : 0]); + close (xpi[1]); + if (ret == -1) { + for (i = 0; i < 3; i++) { + if (runner->chio[i]) { + fclose (runner->chio[i]); + runner->chio[i] = NULL; + } + } + } else { + ret = read (xpi[0], (char *)&errno_priv, sizeof (errno_priv)); + close (xpi[0]); + if (ret <= 0) + return 0; + GF_ASSERT (ret == sizeof (errno_priv)); + } + errno = errno_priv; + return -1; +} + +int +runner_end_reuse (runner_t *runner) +{ + int i = 0; + int ret = -1; + int chstat = 0; + + if (runner->chpid > 0) { + if (waitpid (runner->chpid, &chstat, 0) == runner->chpid) + ret = chstat; + } + + for (i = 0; i < 3; i++) { + if (runner->chio[i]) { + fclose (runner->chio[i]); + runner->chio[i] = NULL; + } + } + + return ret; +} + +int +runner_end (runner_t *runner) +{ + int i = 0; + int ret = -1; + char **p = NULL; + + ret = runner_end_reuse (runner); + + if (runner->argv) { + for (p = runner->argv; *p; p++) + GF_FREE (*p); + GF_FREE (runner->argv); + } + for (i = 0; i < 3; i++) + close (runner->chfd[i]); + + return ret; +} + +static int +runner_run_generic (runner_t *runner, int (*rfin)(runner_t *runner)) +{ + int ret = 0; + + ret = runner_start (runner); + + return -(rfin (runner) || ret); +} + +int +runner_run (runner_t *runner) +{ + return runner_run_generic (runner, runner_end); +} + + +int +runner_run_nowait (runner_t *runner) +{ + int pid; + + pid = fork (); + + if (!pid) { + setsid (); + _exit (runner_start (runner)); + } + + if (pid > 0) + runner->chpid = pid; + return runner_end (runner); +} + + +int +runner_run_reuse (runner_t *runner) +{ + return runner_run_generic (runner, runner_end_reuse); +} + +int +runcmd (const char *arg, ...) +{ + runner_t runner; + va_list argp; + + runinit (&runner); + /* ISO C requires a named argument before '...' */ + runner_add_arg (&runner, arg); + + va_start (argp, arg); + runner_va_add_args (&runner, argp); + va_end (argp); + + return runner_run (&runner); +} + +#ifdef RUN_DO_TESTS +static void +TBANNER (const char *txt) +{ + printf("######\n### testing %s\n", txt); +} + +int +main (int argc, char **argv) +{ + runner_t runner; + char buf[80]; + char *wdbuf;; + int ret; + int fd; + long pathmax = pathconf ("/", _PC_PATH_MAX); + struct timeval tv = {0,}; + struct timeval *tvp = NULL; + + wdbuf = malloc (pathmax); + assert (wdbuf); + getcwd (wdbuf, pathmax); + + TBANNER ("basic functionality"); + runcmd ("echo", "a", "b", NULL); + + TBANNER ("argv extension"); + runcmd ("echo", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", + "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", + "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", + "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", + "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", + "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", + "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", + "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", + "91", "92", "93", "94", "95", "96", "97", "98", "99", "100", NULL); + + TBANNER ("add_args, argprintf, log, and popen-style functionality"); + runinit (&runner); + runner_add_args (&runner, "echo", "pid:", NULL); + runner_argprintf (&runner, "%d\n", getpid()); + runner_add_arg (&runner, "wd:"); + runner_add_arg (&runner, wdbuf); + runner_redir (&runner, 1, RUN_PIPE); + runner_start (&runner); + runner_log (&runner, "(x)", LOG_DEBUG, "starting program"); + while (fgets (buf, sizeof(buf), runner_chio (&runner, 1))) + printf ("got: %s", buf); + runner_end (&runner); + + TBANNER ("execve error reporting"); + ret = runcmd ("bafflavvitty", NULL); + printf ("%d %d [%s]\n", ret, errno, strerror (errno)); + + TBANNER ("output redirection"); + fd = mkstemp ("/tmp/foof"); + assert (fd != -1); + runinit (&runner); + runner_add_args (&runner, "echo", "foo", NULL); + runner_redir (&runner, 1, fd); + ret = runner_run (&runner); + printf ("%d", ret); + if (ret != 0) + printf (" %d [%s]", errno, strerror (errno)); + putchar ('\n'); + + if (argc > 1) { + tv.tv_sec = strtoul (argv[1], NULL, 10); + if (tv.tv_sec > 0) + tvp = &tv; + select (0, 0, 0, 0, tvp); + } + + return 0; +} +#endif diff --git a/libglusterfs/src/run.h b/libglusterfs/src/run.h new file mode 100644 index 000000000..d7554ef6d --- /dev/null +++ b/libglusterfs/src/run.h @@ -0,0 +1,194 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __RUN_H__ +#define __RUN_H__ + +#define RUN_PIPE -1 + +struct runner { + char **argv; + unsigned argvlen; + int runerr; + pid_t chpid; + int chfd[3]; + FILE *chio[3]; +}; + +typedef struct runner runner_t; + +/** + * initialize runner_t instance. + * + * @param runner pointer to runner_t instance + */ +void runinit (runner_t *runner); + +/** + * get FILE pointer to which child's stdio is redirected. + * + * @param runner pointer to runner_t instance + * @param fd specifies which standard file descriptor is + * is asked for + * + * @see runner_redir() + */ +FILE *runner_chio (runner_t *runner, int fd); + +/** + * add an argument. + * + * 'arg' is duplicated. + * + * Errors are deferred, no error handling is necessary. + * + * @param runner pointer to runner_t instance + * @param arg command line argument + */ +void runner_add_arg (runner_t *runner, const char *arg); + +/** + * add a sequence of arguments. + * + * Variadic function, calls runner_add_arg() on each vararg. + * Argument sequence MUST be NULL terminated. + * + * Errors are deferred, no error handling is necessary. + * + * @param runner pointer to runner_t instance + * + * @see runner_add_arg() + */ +void runner_add_args (runner_t *runner, ...); + +/** + * add an argument with printf style formatting. + * + * Errors are deferred, no error handling is necessary. + * + * @param runner pointer to runner_t instance + * @param format printf style format specifier + */ +void runner_argprintf (runner_t *runner, const char *format, ...); + +/** + * log a message about the command to be run. + * + * @param runner pointer to runner_t instance + * + * @param dom log domain + * @param lvl log level + * @param msg message with which the command is prefixed in log + * + * @see gf_log() + */ +void runner_log (runner_t *runner, const char *dom, gf_loglevel_t lvl, + const char *msg); + +/** + * set up redirection for child. + * + * @param runner pointer to runner_t instance + * + * @param fd fd of child to redirect (0, 1, or 2) + * @param tgt_fd fd on parent side to redirect to. + * Note that runner_end() will close tgt_fd, + * if user needs it in another context it should + * be dup'd beforehand. + * RUN_PIPE can be used for requiring a + * pipe from child to parent. The FILE + * created for this purpose will be + * accessible via runner_chio() (after + * runner_start() has been invoked). + * + * @see runner_start(), dup(2), runner_chio(), runner_start() + */ +void +runner_redir (runner_t *runner, int fd, int tgt_fd); + +/** + * spawn child with accumulated arg list. + * + * @param runner pointer to runner_t instance + * + * @return 0 on succesful spawn + * -1 on failure (either due to earlier errors or execve(2) failing) + * + * @see runner_cout() + */ +int runner_start (runner_t *runner); + +/** + * complete operation and free resources. + * + * If child exists, waits for it. Redirections will be closed. + * Dynamically allocated memory shall be freed. + * + * @param runner pointer to runner_t instance + * + * @return 0 if child terminated successfully + * -1 if there is no running child + * n > 0 if child failed; value to be interpreted as status + * in waitpid(2) + * + * @see waitpid(2) + */ +int runner_end (runner_t *runner); + +/** + * variant of runner_end() which does not free internal data + * so that the runner instance can be run again. + * + * @see runner_end() + */ +int runner_end_reuse (runner_t *runner); + +/** + * spawn and child, take it to completion and free resources. + * + * Essentially it's a concatenation of runner_start() and runner_end() + * with simplified return semantics. + * + * @param runner pointer to runner_t instance + * + * @return 0 on success + * -1 on failuire + * + * @see runner_start(), runner_end() + */ +int runner_run (runner_t *runner); + +/** + * variant for runner_run() which does not wait for acknowledgement + * from child, and always assumes it succeeds. + */ +int runner_run_nowait (runner_t *runner); + +/** + * variant of runner_run() which does not free internal data + * so that the runner instance can be run again. + * + * @see runner_run() + */ +int runner_run_reuse (runner_t *runner); + +/** + * run a command with args. + * + * Variadic function, child process is spawned with + * the given sequence of args and waited for. + * Argument sequence MUST be NULL terminated. + * + * @return 0 on success + * -1 on failure + */ +int runcmd (const char *arg, ...); + +#endif diff --git a/libglusterfs/src/scheduler.c b/libglusterfs/src/scheduler.c deleted file mode 100644 index f799b52fc..000000000 --- a/libglusterfs/src/scheduler.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - Copyright (c) 2006-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 _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; - int ret = 0; - - if (name == NULL) { - gf_log ("scheduler", GF_LOG_ERROR, - "'name' not specified, EINVAL"); - return NULL; - } - - ret = asprintf (&sched_file, "%s/%s.so", SCHEDULERDIR, name); - if (-1 == ret) { - gf_log ("scheduler", GF_LOG_ERROR, "asprintf failed"); - return NULL; - } - - 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 deleted file mode 100644 index 5b5628955..000000000 --- a/libglusterfs/src/scheduler.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - Copyright (c) 2006-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 _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 deleted file mode 100644 index 341689c3a..000000000 --- a/libglusterfs/src/spec.l +++ /dev/null @@ -1,94 +0,0 @@ -/* - Copyright (c) 2006-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/>. -*/ - - -%x STRING -%option yylineno -%option noinput -%{ - -#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 deleted file mode 100644 index f1cffe5d9..000000000 --- a/libglusterfs/src/spec.y +++ /dev/null @@ -1,606 +0,0 @@ -/* - Copyright (c) 2006-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/>. -*/ - - -%token SECTION_BEGIN SECTION_END OPTION NEWLINE SUBSECTION ID WHITESPACE COMMENT TYPE STRING_TOK - -%{ -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/wait.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 (8 * 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: Please specify volume 'type'.", - complete_tree->name, yylineno); - gf_log ("parser", GF_LOG_ERROR, - "Volume '%s', before line %d: Please specify volume 'type'.", - complete_tree->name, yylineno); - return; -} - -static void -sub_error (void) -{ - extern int yylineno; - - fprintf (stderr, "Volume %s, before line %d: Please specify subvolumes for the volume. ", - complete_tree->name, yylineno); - gf_log ("parser", GF_LOG_ERROR, - "Volume %s, before line %d: Please specify subvolumes for the volume. ", - complete_tree->name, yylineno); - return; -} - -static void -option_error (void) -{ - extern int yylineno; - - fprintf (stderr, "Volume %s, before line %d: Please specify " - "option <key> <value> \n", - complete_tree->name, yylineno); - gf_log ("parser", GF_LOG_ERROR, - "Volume %s, before line %d: Please specify " - "option <key> <value>", - 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_TRACE, "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_TRACE, "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_TRACE, "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_TRACE, "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_TRACE, "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, size_t size) -{ - FILE *fpp = NULL; - int i = 0, status = 0; - int character = 0; - char *buf = *result; - - fpp = popen (cmd, "r"); - if (!fpp) { - gf_log ("parser", GF_LOG_ERROR, "%s: failed to popen", cmd); - return -1; - } - - while ((character = fgetc (fpp)) != EOF) { - if (i == size) { - size *= 2; - buf = *result = realloc (*result, size); - } - - buf[i++] = character; - } - - if (i > 0) { - i--; - buf[i] = '\0'; - } - - status = pclose (fpp); - if (status == -1 || !WIFEXITED (status) || - ((WEXITSTATUS (status)) != 0)) { - i = -1; - buf[0] = '\0'; - } - - return i; -} - -static int -parse_backtick (FILE *srcfp, FILE *dstfp) -{ - int ret = 0, i = 0; - char *cmd = NULL, *result = NULL; - size_t cmd_buf_size = GF_CMD_BUFFER_LEN; - char escaped = 0, in_backtick = 0; - int line = 1, column = 0, backtick_line = 0, backtick_column = 0; - int character = 0; - - fseek (srcfp, 0L, SEEK_SET); - fseek (dstfp, 0L, SEEK_SET); - - cmd = CALLOC (cmd_buf_size, 1); - if (cmd == NULL) { - return -1; - } - - result = CALLOC (cmd_buf_size * 2, 1); - if (result == NULL) { - return -1; - } - - while ((character = fgetc (srcfp)) != EOF) { - if ((character == '`') && !escaped) { - if (in_backtick) { - cmd[i] = '\0'; - result[0] = '\0'; - - ret = execute_cmd (cmd, &result, - 2 * cmd_buf_size); - if (ret < 0) { - ret = -1; - goto out; - } - fwrite (result, ret, 1, dstfp); - } else { - i = 0; - cmd[i] = '\0'; - - backtick_column = column; - backtick_line = line; - } - - in_backtick = !in_backtick; - } else { - if (in_backtick) { - if (i == cmd_buf_size) { - cmd_buf_size *= 2; - cmd = realloc (cmd, cmd_buf_size); - if (cmd == NULL) { - return -1; - } - - result = realloc (result, - 2 * cmd_buf_size); - if (result == NULL) { - return -1; - } - } - - cmd[i++] = character; - } else { - fputc (character, dstfp); - } - } - - if (character == '\\') { - escaped = !escaped; - } else { - escaped = 0; - } - - if (character == '\n') { - line++; - column = 0; - } else { - column++; - } - } - - if (in_backtick) { - gf_log ("parser", GF_LOG_ERROR, - "Unterminated backtick in volume specfication file at line (%d), column (%d).", - line, column); - ret = -1; - } - -out: - fseek (srcfp, 0L, SEEK_SET); - fseek (dstfp, 0L, SEEK_SET); - free (cmd); - free (result); - - 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; - char *buffer = NULL; - - tmp_file = tmpfile (); - if (NULL == tmp_file) { - gf_log ("parser", GF_LOG_ERROR, - "cannot create temparory file"); - 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.c b/libglusterfs/src/stack.c index 453248479..37b338f51 100644 --- a/libglusterfs/src/stack.c +++ b/libglusterfs/src/stack.c @@ -1,27 +1,18 @@ /* - Copyright (c) 2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include "statedump.h" #include "stack.h" static inline -int call_frames_count (call_frame_t *call_frame) +int call_frames_count (call_frame_t *call_frame) { call_frame_t *pos; int32_t count = 0; @@ -35,46 +26,105 @@ int call_frames_count (call_frame_t *call_frame) return count; } +call_frame_t * +create_frame (xlator_t *xl, call_pool_t *pool) +{ + call_stack_t *stack = NULL; + + if (!xl || !pool) { + return NULL; + } + + stack = mem_get0 (pool->stack_mem_pool); + if (!stack) + return NULL; + + stack->pool = pool; + stack->frames.root = stack; + stack->frames.this = xl; + stack->ctx = xl->ctx; + + if (stack->ctx->measure_latency) { + if (gettimeofday (&stack->tv, NULL) == -1) + gf_log ("stack", GF_LOG_ERROR, "gettimeofday () failed." + " (%s)", strerror (errno)); + memcpy (&stack->frames.begin, &stack->tv, sizeof (stack->tv)); + } + + LOCK (&pool->lock); + { + list_add (&stack->all_frames, &pool->all_frames); + pool->cnt++; + } + UNLOCK (&pool->lock); + + LOCK_INIT (&stack->frames.lock); + LOCK_INIT (&stack->stack_lock); + + return &stack->frames; +} + void gf_proc_dump_call_frame (call_frame_t *call_frame, const char *key_buf,...) { - + char prefix[GF_DUMP_MAX_BUF_LEN]; va_list ap; - char key[GF_DUMP_MAX_BUF_LEN]; call_frame_t my_frame; int ret = -1; + char timestr[256] = {0,}; if (!call_frame) return; - assert(key_buf); + GF_ASSERT (key_buf); memset(prefix, 0, sizeof(prefix)); memset(&my_frame, 0, sizeof(my_frame)); va_start(ap, key_buf); - vsnprintf(prefix, GF_DUMP_MAX_BUF_LEN, key_buf, ap); + vsnprintf(prefix, GF_DUMP_MAX_BUF_LEN, key_buf, ap); va_end(ap); ret = TRY_LOCK(&call_frame->lock); - if (ret) { - gf_log("", GF_LOG_WARNING, "Unable to dump call frame" - " errno: %d", errno); - return; - } + if (ret) + goto out; memcpy(&my_frame, call_frame, sizeof(my_frame)); UNLOCK(&call_frame->lock); - gf_proc_dump_build_key(key, prefix,"ref_count"); - gf_proc_dump_write(key, "%d", my_frame.ref_count); - gf_proc_dump_build_key(key, prefix,"translator"); - gf_proc_dump_write(key, "%s", my_frame.this->name); - gf_proc_dump_build_key(key, prefix,"complete"); - gf_proc_dump_write(key, "%d", my_frame.complete); - if (my_frame.parent) { - gf_proc_dump_build_key(key, prefix,"parent"); - gf_proc_dump_write(key, "%s", my_frame.parent->this->name); + if (my_frame.this->ctx->measure_latency) { + gf_time_fmt (timestr, sizeof timestr, my_frame.begin.tv_sec, + gf_timefmt_FT); + snprintf (timestr + strlen (timestr), + sizeof timestr - strlen (timestr), + ".%"GF_PRI_SUSECONDS, my_frame.begin.tv_usec); + gf_proc_dump_write("frame-creation-time", "%s", timestr); + } + + gf_proc_dump_write("ref_count", "%d", my_frame.ref_count); + gf_proc_dump_write("translator", "%s", my_frame.this->name); + gf_proc_dump_write("complete", "%d", my_frame.complete); + if (my_frame.parent) + gf_proc_dump_write("parent", "%s", my_frame.parent->this->name); + + if (my_frame.wind_from) + gf_proc_dump_write("wind_from", "%s", my_frame.wind_from); + + if (my_frame.wind_to) + gf_proc_dump_write("wind_to", "%s", my_frame.wind_to); + + if (my_frame.unwind_from) + gf_proc_dump_write("unwind_from", "%s", my_frame.unwind_from); + + if (my_frame.unwind_to) + gf_proc_dump_write("unwind_to", "%s", my_frame.unwind_to); + + ret = 0; +out: + if (ret) { + gf_proc_dump_write("Unable to dump the frame information", + "(Lock acquisition failed) %p", my_frame); + return; } } @@ -86,45 +136,43 @@ gf_proc_dump_call_stack (call_stack_t *call_stack, const char *key_buf,...) va_list ap; call_frame_t *trav; int32_t cnt, i; - char key[GF_DUMP_MAX_BUF_LEN]; + char timestr[256] = {0,}; if (!call_stack) return; - assert(key_buf); + GF_ASSERT (key_buf); cnt = call_frames_count(&call_stack->frames); memset(prefix, 0, sizeof(prefix)); va_start(ap, key_buf); - vsnprintf(prefix, GF_DUMP_MAX_BUF_LEN, key_buf, ap); + vsnprintf(prefix, GF_DUMP_MAX_BUF_LEN, key_buf, ap); va_end(ap); - gf_proc_dump_build_key(key, prefix,"uid"); - gf_proc_dump_write(key, "%d", call_stack->uid); - gf_proc_dump_build_key(key, prefix,"gid"); - gf_proc_dump_write(key, "%d", call_stack->gid); - gf_proc_dump_build_key(key, prefix,"pid"); - gf_proc_dump_write(key, "%d", call_stack->pid); - gf_proc_dump_build_key(key, prefix,"unique"); - gf_proc_dump_write(key, "%Ld", call_stack->unique); - - gf_proc_dump_build_key(key, prefix,"op"); - if ((call_stack->type == GF_OP_TYPE_FOP_REQUEST) || - (call_stack->type == GF_OP_TYPE_FOP_REPLY)) { - gf_proc_dump_write(key, "%s", gf_fop_list[call_stack->op]); - } else if ((call_stack->type == GF_OP_TYPE_MOP_REQUEST) || - (call_stack->type == GF_OP_TYPE_MOP_REPLY)) { - gf_proc_dump_write(key, "%s", gf_mop_list[call_stack->op]); - } else if ((call_stack->type == GF_OP_TYPE_CBK_REQUEST) || - (call_stack->type == GF_OP_TYPE_CBK_REPLY)) { - gf_proc_dump_write(key, "%s", gf_cbk_list[call_stack->op]); - } - - gf_proc_dump_build_key(key, prefix,"type"); - gf_proc_dump_write(key, "%d", call_stack->type); - gf_proc_dump_build_key(key, prefix,"cnt"); - gf_proc_dump_write(key, "%d", cnt); + if (call_stack->ctx->measure_latency) { + gf_time_fmt (timestr, sizeof timestr, call_stack->tv.tv_sec, + gf_timefmt_FT); + snprintf (timestr + strlen (timestr), + sizeof timestr - strlen (timestr), + ".%"GF_PRI_SUSECONDS, call_stack->tv.tv_usec); + gf_proc_dump_write("callstack-creation-time", "%s", timestr); + } + + gf_proc_dump_write("uid", "%d", call_stack->uid); + gf_proc_dump_write("gid", "%d", call_stack->gid); + gf_proc_dump_write("pid", "%d", call_stack->pid); + gf_proc_dump_write("unique", "%Ld", call_stack->unique); + gf_proc_dump_write("lk-owner", "%s", lkowner_utoa (&call_stack->lk_owner)); + + if (call_stack->type == GF_OP_TYPE_FOP) + gf_proc_dump_write("op", "%s", + (char *)gf_fop_list[call_stack->op]); + else + gf_proc_dump_write("op", "stack"); + + gf_proc_dump_write("type", "%d", call_stack->type); + gf_proc_dump_write("cnt", "%d", cnt); trav = &call_stack->frames; @@ -132,7 +180,7 @@ gf_proc_dump_call_stack (call_stack_t *call_stack, const char *key_buf,...) if (trav) { gf_proc_dump_add_section("%s.frame.%d", prefix, i); gf_proc_dump_call_frame(trav, "%s.frame.%d", prefix, i); - trav = trav->next; + trav = trav->next; } } } @@ -140,25 +188,24 @@ gf_proc_dump_call_stack (call_stack_t *call_stack, const char *key_buf,...) void gf_proc_dump_pending_frames (call_pool_t *call_pool) { - + call_stack_t *trav = NULL; int i = 1; int ret = -1; + gf_boolean_t section_added = _gf_true; if (!call_pool) return; ret = TRY_LOCK (&(call_pool->lock)); - if (ret) { - gf_log("", GF_LOG_WARNING, "Unable to dump call pool" - " errno: %d", errno); - return; - } + if (ret) + goto out; + - gf_proc_dump_add_section("global.callpool"); - gf_proc_dump_write("global.callpool","%p", call_pool); - gf_proc_dump_write("global.callpool.cnt","%d", call_pool->cnt); + section_added = _gf_true; + gf_proc_dump_write("callpool_address","%p", call_pool); + gf_proc_dump_write("callpool.cnt","%d", call_pool->cnt); list_for_each_entry (trav, &call_pool->all_frames, all_frames) { @@ -166,6 +213,220 @@ gf_proc_dump_pending_frames (call_pool_t *call_pool) gf_proc_dump_call_stack(trav, "global.callpool.stack.%d", i); i++; } - UNLOCK (&(call_pool->lock)); + UNLOCK (&(call_pool->lock)); + + ret = 0; +out: + if (ret) { + if (_gf_false == section_added) + gf_proc_dump_add_section("global.callpool"); + gf_proc_dump_write("Unable to dump the callpool", + "(Lock acquisition failed) %p", + call_pool); + } + return; } +void +gf_proc_dump_call_frame_to_dict (call_frame_t *call_frame, + char *prefix, dict_t *dict) +{ + int ret = -1; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + call_frame_t tmp_frame = {0,}; + + if (!call_frame || !dict) + return; + + ret = TRY_LOCK (&call_frame->lock); + if (ret) + return; + memcpy (&tmp_frame, call_frame, sizeof (tmp_frame)); + UNLOCK (&call_frame->lock); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.refcount", prefix); + ret = dict_set_int32 (dict, key, tmp_frame.ref_count); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.translator", prefix); + ret = dict_set_dynstr (dict, key, gf_strdup (tmp_frame.this->name)); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.complete", prefix); + ret = dict_set_int32 (dict, key, tmp_frame.complete); + if (ret) + return; + + if (tmp_frame.parent) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.parent", prefix); + ret = dict_set_dynstr (dict, key, + gf_strdup (tmp_frame.parent->this->name)); + if (ret) + return; + } + + if (tmp_frame.wind_from) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.windfrom", prefix); + ret = dict_set_dynstr (dict, key, + gf_strdup (tmp_frame.wind_from)); + if (ret) + return; + } + + if (tmp_frame.wind_to) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.windto", prefix); + ret = dict_set_dynstr (dict, key, + gf_strdup (tmp_frame.wind_to)); + if (ret) + return; + } + + if (tmp_frame.unwind_from) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.unwindfrom", prefix); + ret = dict_set_dynstr (dict, key, + gf_strdup (tmp_frame.unwind_from)); + if (ret) + return; + } + + if (tmp_frame.unwind_to) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.unwind_to", prefix); + ret = dict_set_dynstr (dict, key, + gf_strdup (tmp_frame.unwind_to)); + } + + return; +} + +void +gf_proc_dump_call_stack_to_dict (call_stack_t *call_stack, + char *prefix, dict_t *dict) +{ + int ret = -1; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + call_frame_t *trav = NULL; + int count = 0; + int i = 0; + + if (!call_stack || !dict) + return; + + count = call_frames_count (&call_stack->frames); + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.uid", prefix); + ret = dict_set_int32 (dict, key, call_stack->uid); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.gid", prefix); + ret = dict_set_int32 (dict, key, call_stack->gid); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.pid", prefix); + ret = dict_set_int32 (dict, key, call_stack->pid); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.unique", prefix); + ret = dict_set_uint64 (dict, key, call_stack->unique); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.op", prefix); + if (call_stack->type == GF_OP_TYPE_FOP) + ret = dict_set_str (dict, key, + (char *)gf_fop_list[call_stack->op]); + else + ret = dict_set_str (dict, key, "other"); + + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.type", prefix); + ret = dict_set_int32 (dict, key, call_stack->type); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.count", prefix); + ret = dict_set_int32 (dict, key, count); + if (ret) + return; + + trav = &call_stack->frames; + for (i = 0; i < count; i++) { + if (trav) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.frame%d", + prefix, i); + gf_proc_dump_call_frame_to_dict (trav, key, dict); + trav = trav->next; + } + } + + return; +} + +void +gf_proc_dump_pending_frames_to_dict (call_pool_t *call_pool, dict_t *dict) +{ + int ret = -1; + call_stack_t *trav = NULL; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + int i = 0; + + if (!call_pool || !dict) + return; + + ret = TRY_LOCK (&call_pool->lock); + if (ret) { + gf_log (THIS->name, GF_LOG_WARNING, "Unable to dump call pool" + " to dict. errno: %d", errno); + return; + } + + ret = dict_set_int32 (dict, "callpool.count", call_pool->cnt); + if (ret) + goto out; + + list_for_each_entry (trav, &call_pool->all_frames, all_frames) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "callpool.stack%d", i); + gf_proc_dump_call_stack_to_dict (trav, key, dict); + i++; + } + +out: + UNLOCK (&call_pool->lock); + + return; +} + +gf_boolean_t +__is_fuse_call (call_frame_t *frame) +{ + gf_boolean_t is_fuse_call = _gf_false; + GF_ASSERT (frame); + GF_ASSERT (frame->root); + + if (NFS_PID != frame->root->pid) + is_fuse_call = _gf_true; + return is_fuse_call; +} diff --git a/libglusterfs/src/stack.h b/libglusterfs/src/stack.h index e03f95ca1..f2d2ef950 100644 --- a/libglusterfs/src/stack.h +++ b/libglusterfs/src/stack.h @@ -1,20 +1,11 @@ -/* - Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com> +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ /* @@ -34,274 +25,438 @@ 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; +struct call_pool; +typedef struct call_pool call_pool_t; + +#include <sys/time.h> #include "xlator.h" #include "dict.h" #include "list.h" #include "common-utils.h" #include "globals.h" +#include "lkowner.h" +#include "client_t.h" - +#define NFS_PID 1 +#define LOW_PRIO_PROC_PID -1 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; + call_frame_t *prev_frame, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + ...); + +struct call_pool { + 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 mem_pool *frame_mem_pool; + struct mem_pool *stack_mem_pool; }; 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 */ - gf_boolean_t complete; + call_stack_t *root; /* stack root */ + call_frame_t *parent; /* previous BP */ + call_frame_t *next; + call_frame_t *prev; /* maintenance 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 */ + gf_boolean_t complete; + + glusterfs_fop_t op; + struct timeval begin; /* when this frame was created */ + struct timeval end; /* when this frame completed */ + const char *wind_from; + const char *wind_to; + const char *unwind_from; + const char *unwind_to; }; +#define SMALL_GROUP_COUNT 128 + 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; - - int32_t op; - int8_t type; + union { + struct list_head all_frames; + struct { + call_stack_t *next_call; + call_stack_t *prev_call; + }; + }; + call_pool_t *pool; + gf_lock_t stack_lock; + client_t *client; + uint64_t unique; + void *state; /* pointer to request state */ + uid_t uid; + gid_t gid; + pid_t pid; + uint16_t ngrps; + uint32_t groups_small[SMALL_GROUP_COUNT]; + uint32_t *groups_large; + uint32_t *groups; + gf_lkowner_t lk_owner; + glusterfs_ctx_t *ctx; + + call_frame_t frames; + + int32_t op; + int8_t type; + struct timeval tv; }; +#define frame_set_uid_gid(frm, u, g) \ + do { \ + if (frm) { \ + (frm)->root->uid = u; \ + (frm)->root->gid = g; \ + (frm)->root->ngrps = 0; \ + } \ + } while (0); \ + + +struct xlator_fops; + +void +gf_latency_begin (call_frame_t *frame, void *fn); + +void +gf_latency_end (call_frame_t *frame); + 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); + void *local = NULL; + if (frame->next) + frame->next->prev = frame->prev; + if (frame->prev) + frame->prev->next = frame->next; + if (frame->local) { + local = frame->local; + frame->local = NULL; + + } + + LOCK_DESTROY (&frame->lock); + mem_put (frame); + + if (local) + mem_put (local); } 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); + void *local = NULL; + + 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); + if (stack->frames.local) { + local = stack->frames.local; + stack->frames.local = NULL; + } - LOCK_DESTROY (&stack->frames.lock); + LOCK_DESTROY (&stack->frames.lock); + LOCK_DESTROY (&stack->stack_lock); - while (stack->frames.next) { - FRAME_DESTROY (stack->frames.next); - } - FREE (stack); + while (stack->frames.next) { + FRAME_DESTROY (stack->frames.next); + } + + GF_FREE (stack->groups_large); + + mem_put (stack); + + if (local) + mem_put (local); } +static inline void +STACK_RESET (call_stack_t *stack) +{ + void *local = NULL; + + if (stack->frames.local) { + local = stack->frames.local; + stack->frames.local = NULL; + } + + while (stack->frames.next) { + FRAME_DESTROY (stack->frames.next); + } + + if (local) + mem_put (local); +} #define cbk(x) cbk_##x +#define FRAME_SU_DO(frm, local_type) \ + do { \ + local_type *__local = (frm)->local; \ + __local->uid = frm->root->uid; \ + __local->gid = frm->root->gid; \ + frm->root->uid = 0; \ + frm->root->gid = 0; \ + } while (0); \ + +#define FRAME_SU_UNDO(frm, local_type) \ + do { \ + local_type *__local = (frm)->local; \ + frm->root->uid = __local->uid; \ + frm->root->gid = __local->gid; \ + } while (0); \ + /* make a call */ -#define STACK_WIND(frame, rfn, obj, fn, params ...) \ - do { \ - call_frame_t *_new = NULL; \ +#define STACK_WIND(frame, rfn, obj, fn, params ...) \ + do { \ + call_frame_t *_new = NULL; \ xlator_t *old_THIS = 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++; \ - \ + \ + _new = mem_get0 (frame->root->pool->frame_mem_pool); \ + if (!_new) { \ + gf_log ("stack", GF_LOG_ERROR, "alloc failed"); \ + break; \ + } \ + typeof(fn##_cbk) tmp_cbk = rfn; \ + _new->root = frame->root; \ + _new->this = obj; \ + _new->ret = (ret_fn_t) tmp_cbk; \ + _new->parent = frame; \ + _new->cookie = _new; \ + _new->wind_from = __FUNCTION__; \ + _new->wind_to = #fn; \ + _new->unwind_to = #rfn; \ + \ + LOCK_INIT (&_new->lock); \ + LOCK(&frame->root->stack_lock); \ + { \ + _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; \ + frame->ref_count++; \ + } \ + UNLOCK(&frame->root->stack_lock); \ + old_THIS = THIS; \ + THIS = obj; \ + if (frame->this->ctx->measure_latency) \ + gf_latency_begin (_new, fn); \ + fn (_new, obj, params); \ + THIS = old_THIS; \ + } while (0) + + +/* make a call without switching frames */ +#define STACK_WIND_TAIL(frame, obj, fn, params ...) \ + do { \ + xlator_t *old_THIS = NULL; \ + \ + frame->this = obj; \ + frame->wind_to = #fn; \ old_THIS = THIS; \ THIS = obj; \ - fn (_new, obj, params); \ + fn (frame, obj, params); \ THIS = old_THIS; \ - } while (0) + } while (0) /* make a call with a cookie */ -#define STACK_WIND_COOKIE(frame, rfn, cky, obj, fn, params ...) \ - do { \ +#define STACK_WIND_COOKIE(frame, rfn, cky, obj, fn, params ...) \ + do { \ call_frame_t *_new = NULL; \ xlator_t *old_THIS = 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 = cky; \ - LOCK_INIT (&_new->lock); \ - frame->ref_count++; \ - fn##_cbk = rfn; \ - \ + _new = mem_get0 (frame->root->pool->frame_mem_pool); \ + if (!_new) { \ + gf_log ("stack", GF_LOG_ERROR, "alloc failed"); \ + break; \ + } \ + typeof(fn##_cbk) tmp_cbk = rfn; \ + _new->root = frame->root; \ + _new->this = obj; \ + _new->ret = (ret_fn_t) tmp_cbk; \ + _new->parent = frame; \ + _new->cookie = cky; \ + _new->wind_from = __FUNCTION__; \ + _new->wind_to = #fn; \ + _new->unwind_to = #rfn; \ + LOCK_INIT (&_new->lock); \ + LOCK(&frame->root->stack_lock); \ + { \ + frame->ref_count++; \ + _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; \ + } \ + UNLOCK(&frame->root->stack_lock); \ + fn##_cbk = rfn; \ old_THIS = THIS; \ THIS = obj; \ - fn (_new, obj, params); \ + if (obj->ctx->measure_latency) \ + gf_latency_begin (_new, fn); \ + fn (_new, obj, params); \ THIS = old_THIS; \ - } while (0) + } while (0) /* return from function */ -#define STACK_UNWIND(frame, params ...) \ - do { \ - ret_fn_t fn = NULL; \ - call_frame_t *_parent = NULL; \ +#define STACK_UNWIND(frame, params ...) \ + do { \ + ret_fn_t fn = NULL; \ + call_frame_t *_parent = NULL; \ xlator_t *old_THIS = NULL; \ - \ + if (!frame) { \ + gf_log ("stack", GF_LOG_CRITICAL, "!frame"); \ + break; \ + } \ fn = frame->ret; \ _parent = frame->parent; \ - _parent->ref_count--; \ + LOCK(&frame->root->stack_lock); \ + { \ + _parent->ref_count--; \ + } \ + UNLOCK(&frame->root->stack_lock); \ old_THIS = THIS; \ THIS = _parent->this; \ frame->complete = _gf_true; \ - fn (_parent, frame->cookie, _parent->this, params); \ + frame->unwind_from = __FUNCTION__; \ + if (frame->this->ctx->measure_latency) \ + gf_latency_end (frame); \ + fn (_parent, frame->cookie, _parent->this, params); \ THIS = old_THIS; \ - } while (0) + } while (0) /* return from function in type-safe way */ #define STACK_UNWIND_STRICT(op, frame, params ...) \ - do { \ - fop_##op##_cbk_t fn = NULL; \ - call_frame_t *_parent = NULL; \ + do { \ + fop_##op##_cbk_t fn = NULL; \ + call_frame_t *_parent = NULL; \ xlator_t *old_THIS = NULL; \ \ + if (!frame) { \ + gf_log ("stack", GF_LOG_CRITICAL, "!frame"); \ + break; \ + } \ fn = (fop_##op##_cbk_t )frame->ret; \ _parent = frame->parent; \ - _parent->ref_count--; \ + LOCK(&frame->root->stack_lock); \ + { \ + _parent->ref_count--; \ + } \ + UNLOCK(&frame->root->stack_lock); \ old_THIS = THIS; \ THIS = _parent->this; \ frame->complete = _gf_true; \ - fn (_parent, frame->cookie, _parent->this, params); \ + frame->unwind_from = __FUNCTION__; \ + if (frame->this->ctx->measure_latency) \ + gf_latency_end (frame); \ + fn (_parent, frame->cookie, _parent->this, params); \ THIS = old_THIS; \ - } while (0) + } while (0) -static inline call_frame_t * -copy_frame (call_frame_t *frame) +static inline int +call_stack_alloc_groups (call_stack_t *stack, int ngrps) { - call_stack_t *newstack = NULL; - call_stack_t *oldstack = NULL; - - if (!frame) { - return NULL; + if (ngrps <= SMALL_GROUP_COUNT) { + stack->groups = stack->groups_small; + } else { + stack->groups_large = GF_CALLOC (sizeof (gid_t), ngrps, + gf_common_mt_groups_t); + if (!stack->groups_large) + return -1; + stack->groups = stack->groups_large; } - newstack = (void *) CALLOC (1, sizeof (*newstack)); - if (newstack == NULL) { - return NULL; - } - - 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; + stack->ngrps = ngrps; - 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; + return 0; } static inline call_frame_t * -create_frame (xlator_t *xl, call_pool_t *pool) +copy_frame (call_frame_t *frame) { - call_stack_t *stack = NULL; + call_stack_t *newstack = NULL; + call_stack_t *oldstack = NULL; - if (!xl || !pool) { - return NULL; - } + if (!frame) { + return NULL; + } - stack = CALLOC (1, sizeof (*stack)); - if (!stack) - return NULL; + newstack = mem_get0 (frame->root->pool->stack_mem_pool); + if (newstack == NULL) { + return NULL; + } - stack->pool = pool; - stack->frames.root = stack; - stack->frames.this = xl; + oldstack = frame->root; - LOCK (&pool->lock); - { - list_add (&stack->all_frames, &pool->all_frames); - pool->cnt++; + newstack->uid = oldstack->uid; + newstack->gid = oldstack->gid; + newstack->pid = oldstack->pid; + newstack->ngrps = oldstack->ngrps; + newstack->op = oldstack->op; + newstack->type = oldstack->type; + if (call_stack_alloc_groups (newstack, oldstack->ngrps) != 0) { + mem_put (newstack); + return NULL; } - UNLOCK (&pool->lock); + memcpy (newstack->groups, oldstack->groups, + sizeof (gid_t) * oldstack->ngrps); + newstack->unique = oldstack->unique; + + newstack->frames.this = frame->this; + newstack->frames.root = newstack; + newstack->pool = oldstack->pool; + newstack->lk_owner = oldstack->lk_owner; + newstack->ctx = oldstack->ctx; + + if (newstack->ctx->measure_latency) { + if (gettimeofday (&newstack->tv, NULL) == -1) + gf_log ("stack", GF_LOG_ERROR, "gettimeofday () failed." + " (%s)", strerror (errno)); + memcpy (&newstack->frames.begin, &newstack->tv, + sizeof (newstack->tv)); + } - LOCK_INIT (&stack->frames.lock); + LOCK_INIT (&newstack->frames.lock); + LOCK_INIT (&newstack->stack_lock); - return &stack->frames; -} + LOCK (&oldstack->pool->lock); + { + list_add (&newstack->all_frames, &oldstack->all_frames); + newstack->pool->cnt++; + } + UNLOCK (&oldstack->pool->lock); -void -gf_proc_dump_pending_frames(call_pool_t *call_pool); + return &newstack->frames; +} +void gf_proc_dump_pending_frames(call_pool_t *call_pool); +void gf_proc_dump_pending_frames_to_dict (call_pool_t *call_pool, + dict_t *dict); +call_frame_t *create_frame (xlator_t *xl, call_pool_t *pool); +gf_boolean_t __is_fuse_call (call_frame_t *frame); #endif /* _STACK_H */ diff --git a/libglusterfs/src/statedump.c b/libglusterfs/src/statedump.c index 6839c28f6..8175faba4 100644 --- a/libglusterfs/src/statedump.c +++ b/libglusterfs/src/statedump.c @@ -1,118 +1,237 @@ /* - Copyright (c) 2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include <stdarg.h> -#include <malloc.h> #include "glusterfs.h" #include "logging.h" #include "iobuf.h" #include "statedump.h" #include "stack.h" +#include "common-utils.h" + +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#endif /* MALLOC_H */ + +/* We don't want gf_log in this function because it may cause + 'deadlock' with statedump. This is because statedump happens + inside a signal handler and cannot afford to block on a lock.*/ +#ifdef gf_log +# undef gf_log +#endif + +#define GF_PROC_DUMP_IS_OPTION_ENABLED(opt) \ + (dump_options.dump_##opt == _gf_true) +#define GF_PROC_DUMP_IS_XL_OPTION_ENABLED(opt) \ + (dump_options.xl_options.dump_##opt == _gf_true) + +extern xlator_t global_xlator; static pthread_mutex_t gf_proc_dump_mutex; static int gf_dump_fd = -1; +gf_dump_options_t dump_options; + -static void +static void gf_proc_dump_lock (void) { - pthread_mutex_lock(&gf_proc_dump_mutex); + pthread_mutex_lock (&gf_proc_dump_mutex); } -static void + +static void gf_proc_dump_unlock (void) { - pthread_mutex_unlock(&gf_proc_dump_mutex); -} + pthread_mutex_unlock (&gf_proc_dump_mutex); +} static int -gf_proc_dump_open (void) +gf_proc_dump_open (char *tmpname) { - char path[256]; int dump_fd = -1; - memset(path, 0, sizeof(path)); - snprintf(path, sizeof(path), "%s.%d",GF_DUMP_LOGFILE_ROOT, getpid()); - - dump_fd = open(path, O_CREAT|O_RDWR|O_TRUNC|O_APPEND, 0600); - if (dump_fd < 0) { - gf_log("", GF_LOG_ERROR, "Unable to open file: %s" - " errno: %d", path, errno); + dump_fd = mkstemp (tmpname); + if (dump_fd < 0) return -1; - } - gf_dump_fd = dump_fd; + gf_dump_fd = dump_fd; return 0; } static void gf_proc_dump_close (void) { - close(gf_dump_fd); + close (gf_dump_fd); gf_dump_fd = -1; } -void -gf_proc_dump_add_section (char *key, ...) +static int +gf_proc_dump_set_path (char *dump_options_file) { - + int ret = -1; + FILE *fp = NULL; + char buf[256]; + char *key = NULL, *value = NULL; + char *saveptr = NULL; + + fp = fopen (dump_options_file, "r"); + if (!fp) + goto out; + + ret = fscanf (fp, "%s", buf); + + while (ret != EOF) { + key = strtok_r (buf, "=", &saveptr); + if (!key) { + ret = fscanf (fp, "%s", buf); + continue; + } + + value = strtok_r (NULL, "=", &saveptr); + + if (!value) { + ret = fscanf (fp, "%s", buf); + continue; + } + if (!strcmp (key, "path")) { + dump_options.dump_path = gf_strdup (value); + break; + } + } + +out: + if (fp) + fclose (fp); + return ret; +} + +int +gf_proc_dump_add_section (char *key, ...) +{ + char buf[GF_DUMP_MAX_BUF_LEN]; va_list ap; - int ret; - assert(key); - - memset(buf, 0, sizeof(buf)); - snprintf(buf, GF_DUMP_MAX_BUF_LEN, "\n["); - va_start(ap, key); - vsnprintf(buf + strlen(buf), - GF_DUMP_MAX_BUF_LEN - strlen(buf), key, ap); - va_end(ap); - snprintf(buf + strlen(buf), - GF_DUMP_MAX_BUF_LEN - strlen(buf), "]\n"); - ret = write(gf_dump_fd, buf, strlen(buf)); + GF_ASSERT(key); + + memset (buf, 0, sizeof(buf)); + snprintf (buf, GF_DUMP_MAX_BUF_LEN, "\n["); + va_start (ap, key); + vsnprintf (buf + strlen(buf), + GF_DUMP_MAX_BUF_LEN - strlen (buf), key, ap); + va_end (ap); + snprintf (buf + strlen(buf), + GF_DUMP_MAX_BUF_LEN - strlen (buf), "]\n"); + return write (gf_dump_fd, buf, strlen (buf)); } -void -gf_proc_dump_write (char *key, char *value,...) -{ - - char buf[GF_DUMP_MAX_BUF_LEN]; - int offset = 0; - va_list ap; - int ret; - - offset = strlen(key); - - memset(buf, 0, GF_DUMP_MAX_BUF_LEN); - snprintf(buf, GF_DUMP_MAX_BUF_LEN, "%s",key); - snprintf(buf + offset, GF_DUMP_MAX_BUF_LEN - offset, "="); + +int +gf_proc_dump_write (char *key, char *value,...) +{ + + char buf[GF_DUMP_MAX_BUF_LEN]; + int offset = 0; + va_list ap; + + GF_ASSERT (key); + + offset = strlen (key); + + memset (buf, 0, GF_DUMP_MAX_BUF_LEN); + snprintf (buf, GF_DUMP_MAX_BUF_LEN, "%s", key); + snprintf (buf + offset, GF_DUMP_MAX_BUF_LEN - offset, "="); offset += 1; - va_start(ap, value); - vsnprintf(buf + offset, GF_DUMP_MAX_BUF_LEN - offset, value, ap); - va_end(ap); + va_start (ap, value); + vsnprintf (buf + offset, GF_DUMP_MAX_BUF_LEN - offset, value, ap); + va_end (ap); + + offset = strlen (buf); + snprintf (buf + offset, GF_DUMP_MAX_BUF_LEN - offset, "\n"); + return write (gf_dump_fd, buf, strlen (buf)); +} + +static void +gf_proc_dump_xlator_mem_info (xlator_t *xl) +{ + int i = 0; + struct mem_acct rec = {0,}; + + if (!xl) + return; - offset = strlen(buf); - snprintf(buf + offset, GF_DUMP_MAX_BUF_LEN - offset, "\n"); - ret = write(gf_dump_fd, buf, strlen(buf)); + if (!xl->mem_acct.rec) + return; + + gf_proc_dump_add_section ("%s.%s - Memory usage", xl->type, xl->name); + gf_proc_dump_write ("num_types", "%d", xl->mem_acct.num_types); + + for (i = 0; i < xl->mem_acct.num_types; i++) { + if (!(memcmp (&xl->mem_acct.rec[i], &rec, + sizeof (struct mem_acct)))) + continue; + + gf_proc_dump_add_section ("%s.%s - usage-type %d memusage", + xl->type, xl->name, i); + gf_proc_dump_write ("size", "%u", xl->mem_acct.rec[i].size); + gf_proc_dump_write ("num_allocs", "%u", + xl->mem_acct.rec[i].num_allocs); + gf_proc_dump_write ("max_size", "%u", + xl->mem_acct.rec[i].max_size); + gf_proc_dump_write ("max_num_allocs", "%u", + xl->mem_acct.rec[i].max_num_allocs); + gf_proc_dump_write ("total_allocs", "%u", + xl->mem_acct.rec[i].total_allocs); + } + + return; } +static void +gf_proc_dump_xlator_mem_info_only_in_use (xlator_t *xl) +{ + int i = 0; + + if (!xl) + return; + + if (!xl->mem_acct.rec) + return; + + gf_proc_dump_add_section ("%s.%s - Memory usage", xl->type, xl->name); + gf_proc_dump_write ("num_types", "%d", xl->mem_acct.num_types); + + for (i = 0; i < xl->mem_acct.num_types; i++) { + if (!xl->mem_acct.rec[i].size) + continue; + + gf_proc_dump_add_section ("%s.%s - usage-type %d", xl->type, + xl->name,i); + + gf_proc_dump_write ("size", "%u", + xl->mem_acct.rec[i].size); + gf_proc_dump_write ("max_size", "%u", + xl->mem_acct.rec[i].max_size); + gf_proc_dump_write ("num_allocs", "%u", + xl->mem_acct.rec[i].num_allocs); + gf_proc_dump_write ("max_num_allocs", "%u", + xl->mem_acct.rec[i].max_num_allocs); + gf_proc_dump_write ("total_allocs", "%u", + xl->mem_acct.rec[i].total_allocs); + } + + return; +} + + /* Currently this dumps only mallinfo. More can be built on here */ void @@ -121,93 +240,594 @@ gf_proc_dump_mem_info () #ifdef HAVE_MALLOC_STATS struct mallinfo info; - memset(&info, 0, sizeof(struct mallinfo)); - info = mallinfo(); - - gf_proc_dump_add_section("mallinfo"); - gf_proc_dump_write("mallinfo_arena", "%d", info.arena); - gf_proc_dump_write("mallinfo_ordblks", "%d", info.ordblks); - gf_proc_dump_write("mallinfo_smblks","%d", info.smblks); - gf_proc_dump_write("mallinfo_hblks","%d", info.hblks); - gf_proc_dump_write("mallinfo_hblkhd", "%d", info.hblkhd); - gf_proc_dump_write("mallinfo_usmblks","%d", info.usmblks); - gf_proc_dump_write("mallinfo_fsmblks","%d", info.fsmblks); - gf_proc_dump_write("mallinfo_uordblks","%d", info.uordblks); - gf_proc_dump_write("mallinfo_fordblks", "%d", info.fordblks); - gf_proc_dump_write("mallinfo_keepcost", "%d", info.keepcost); + memset (&info, 0, sizeof (struct mallinfo)); + info = mallinfo (); + + gf_proc_dump_add_section ("mallinfo"); + gf_proc_dump_write ("mallinfo_arena", "%d", info.arena); + gf_proc_dump_write ("mallinfo_ordblks", "%d", info.ordblks); + gf_proc_dump_write ("mallinfo_smblks", "%d", info.smblks); + gf_proc_dump_write ("mallinfo_hblks", "%d", info.hblks); + gf_proc_dump_write ("mallinfo_hblkhd", "%d", info.hblkhd); + gf_proc_dump_write ("mallinfo_usmblks", "%d", info.usmblks); + gf_proc_dump_write ("mallinfo_fsmblks", "%d", info.fsmblks); + gf_proc_dump_write ("mallinfo_uordblks", "%d", info.uordblks); + gf_proc_dump_write ("mallinfo_fordblks", "%d", info.fordblks); + gf_proc_dump_write ("mallinfo_keepcost", "%d", info.keepcost); +#endif + gf_proc_dump_xlator_mem_info(&global_xlator); + +} + +void +gf_proc_dump_mem_info_to_dict (dict_t *dict) +{ + if (!dict) + return; +#ifdef HAVE_MALLOC_STATS + struct mallinfo info; + int ret = -1; + + memset (&info, 0, sizeof(struct mallinfo)); + info = mallinfo (); + + ret = dict_set_int32 (dict, "mallinfo.arena", info.arena); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.ordblks", info.ordblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.smblks", info.smblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.hblks", info.hblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.hblkhd", info.hblkhd); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.usmblks", info.usmblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.fsmblks", info.fsmblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.uordblks", info.uordblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.fordblks", info.fordblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.keepcost", info.keepcost); + if (ret) + return; #endif + return; +} + +void +gf_proc_dump_mempool_info (glusterfs_ctx_t *ctx) +{ + struct mem_pool *pool = NULL; + + gf_proc_dump_add_section ("mempool"); + + list_for_each_entry (pool, &ctx->mempool_list, global_list) { + gf_proc_dump_write ("-----", "-----"); + gf_proc_dump_write ("pool-name", "%s", pool->name); + gf_proc_dump_write ("hot-count", "%d", pool->hot_count); + gf_proc_dump_write ("cold-count", "%d", pool->cold_count); + gf_proc_dump_write ("padded_sizeof", "%lu", + pool->padded_sizeof_type); + gf_proc_dump_write ("alloc-count", "%"PRIu64, pool->alloc_count); + gf_proc_dump_write ("max-alloc", "%d", pool->max_alloc); + + gf_proc_dump_write ("pool-misses", "%"PRIu64, pool->pool_misses); + gf_proc_dump_write ("max-stdalloc", "%d", pool->max_stdalloc); + } +} +void +gf_proc_dump_mempool_info_to_dict (glusterfs_ctx_t *ctx, dict_t *dict) +{ + struct mem_pool *pool = NULL; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + int count = 0; + int ret = -1; + + if (!ctx || !dict) + return; + + list_for_each_entry (pool, &ctx->mempool_list, global_list) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.name", count); + ret = dict_set_str (dict, key, pool->name); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.hotcount", count); + ret = dict_set_int32 (dict, key, pool->hot_count); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.coldcount", count); + ret = dict_set_int32 (dict, key, pool->cold_count); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.paddedsizeof", count); + ret = dict_set_uint64 (dict, key, pool->padded_sizeof_type); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.alloccount", count); + ret = dict_set_uint64 (dict, key, pool->alloc_count); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.max_alloc", count); + ret = dict_set_int32 (dict, key, pool->max_alloc); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.max-stdalloc", count); + ret = dict_set_int32 (dict, key, pool->max_stdalloc); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.pool-misses", count); + ret = dict_set_uint64 (dict, key, pool->pool_misses); + if (ret) + return; + count++; + } + ret = dict_set_int32 (dict, "mempool-count", count); + + return; } +void gf_proc_dump_latency_info (xlator_t *xl); void -gf_proc_dump_xlator_info (xlator_t *this_xl) +gf_proc_dump_xlator_info (xlator_t *top) +{ + xlator_t *trav = NULL; + glusterfs_ctx_t *ctx = NULL; + char itable_key[1024] = {0,}; + + if (!top) + return; + + ctx = top->ctx; + + trav = top; + while (trav) { + + if (ctx->measure_latency) + gf_proc_dump_latency_info (trav); + + gf_proc_dump_xlator_mem_info(trav); + + if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED (inode) && + (trav->itable)) { + snprintf (itable_key, 1024, "%d.%s.itable", + ctx->graph_id, trav->name); + } + + if (!trav->dumpops) { + trav = trav->next; + continue; + } + + if (trav->dumpops->priv && + GF_PROC_DUMP_IS_XL_OPTION_ENABLED (priv)) + trav->dumpops->priv (trav); + + if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED (inode) && + (trav->dumpops->inode)) + trav->dumpops->inode (trav); + + if (trav->dumpops->fd && + GF_PROC_DUMP_IS_XL_OPTION_ENABLED (fd)) + trav->dumpops->fd (trav); + + if (trav->dumpops->history && + GF_PROC_DUMP_IS_XL_OPTION_ENABLED (history)) + trav->dumpops->history (trav); + + trav = trav->next; + } + + return; +} + +static void +gf_proc_dump_oldgraph_xlator_info (xlator_t *top) { + xlator_t *trav = NULL; - if (!this_xl) + if (!top) return; - while (this_xl) { - if (!this_xl->dumpops) { - this_xl = this_xl->next; + trav = top; + while (trav) { + gf_proc_dump_xlator_mem_info_only_in_use (trav); + + if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED (inode) && + (trav->itable)) { + /*TODO: dump inode table info if necessary by + printing the graph id (taken by glusterfs_cbtx_t) + in the key + */ + } + + if (!trav->dumpops) { + trav = trav->next; continue; } - if (this_xl->dumpops->priv) - this_xl->dumpops->priv(this_xl); - if (this_xl->dumpops->inode) - this_xl->dumpops->inode(this_xl); - if (this_xl->dumpops->fd) - this_xl->dumpops->fd(this_xl); - this_xl = this_xl->next; + + if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED (inode) && + (trav->dumpops->inode)) + trav->dumpops->inode (trav); + + if (trav->dumpops->fd && + GF_PROC_DUMP_IS_XL_OPTION_ENABLED (fd)) + trav->dumpops->fd (trav); + + trav = trav->next; } return; } +static int +gf_proc_dump_enable_all_options () +{ + + GF_PROC_DUMP_SET_OPTION (dump_options.dump_mem, _gf_true); + GF_PROC_DUMP_SET_OPTION (dump_options.dump_iobuf, _gf_true); + GF_PROC_DUMP_SET_OPTION (dump_options.dump_callpool, _gf_true); + GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_priv, _gf_true); + GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_inode, _gf_true); + GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_fd, _gf_true); + GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_inodectx, + _gf_true); + GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_fdctx, _gf_true); + GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_history, + _gf_true); + + return 0; +} + +gf_boolean_t +is_gf_proc_dump_all_disabled () +{ + gf_boolean_t all_disabled = _gf_true; + + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.dump_mem, all_disabled, out); + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.dump_iobuf, all_disabled, out); + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.dump_callpool, all_disabled, + out); + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_priv, + all_disabled, out); + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_inode, + all_disabled, out); + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_fd, + all_disabled, out); + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_inodectx, + all_disabled, out); + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_fdctx, + all_disabled, out); + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_history, + all_disabled, out); + +out: + return all_disabled; +} + +/* These options are dumped by default if glusterdump.options + file exists and it is emtpty +*/ +static int +gf_proc_dump_enable_default_options () +{ + GF_PROC_DUMP_SET_OPTION (dump_options.dump_mem, _gf_true); + GF_PROC_DUMP_SET_OPTION (dump_options.dump_callpool, _gf_true); + + return 0; +} + +static int +gf_proc_dump_disable_all_options () +{ + + GF_PROC_DUMP_SET_OPTION (dump_options.dump_mem, _gf_false); + GF_PROC_DUMP_SET_OPTION (dump_options.dump_iobuf, _gf_false); + GF_PROC_DUMP_SET_OPTION (dump_options.dump_callpool, _gf_false); + GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_priv, _gf_false); + GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_inode, + _gf_false); + GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_fd, _gf_false); + GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_inodectx, + _gf_false); + GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_fdctx, _gf_false); + GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_history, + _gf_false); + return 0; +} + +static int +gf_proc_dump_parse_set_option (char *key, char *value) +{ + gf_boolean_t *opt_key = NULL; + gf_boolean_t opt_value = _gf_false; + char buf[GF_DUMP_MAX_BUF_LEN]; + int ret = -1; + + if (!strcasecmp (key, "all")) { + (void)gf_proc_dump_enable_all_options (); + return 0; + } else if (!strcasecmp (key, "mem")) { + opt_key = &dump_options.dump_mem; + } else if (!strcasecmp (key, "iobuf")) { + opt_key = &dump_options.dump_iobuf; + } else if (!strcasecmp (key, "callpool")) { + opt_key = &dump_options.dump_callpool; + } else if (!strcasecmp (key, "priv")) { + opt_key = &dump_options.xl_options.dump_priv; + } else if (!strcasecmp (key, "fd")) { + opt_key = &dump_options.xl_options.dump_fd; + } else if (!strcasecmp (key, "inode")) { + opt_key = &dump_options.xl_options.dump_inode; + } else if (!strcasecmp (key, "inodectx")) { + opt_key = &dump_options.xl_options.dump_inodectx; + } else if (!strcasecmp (key, "fdctx")) { + opt_key = &dump_options.xl_options.dump_fdctx; + } else if (!strcasecmp (key, "history")) { + opt_key = &dump_options.xl_options.dump_history; + } + + if (!opt_key) { + //None of dump options match the key, return back + snprintf (buf, sizeof (buf), "[Warning]:None of the options " + "matched key : %s\n", key); + ret = write (gf_dump_fd, buf, strlen (buf)); + + if (ret >= 0) + ret = -1; + goto out; + + } + + opt_value = (strncasecmp (value, "yes", 3) ? + _gf_false: _gf_true); + + GF_PROC_DUMP_SET_OPTION (*opt_key, opt_value); + + ret = 0; +out: + return ret; +} + +static int +gf_proc_dump_options_init () +{ + int ret = -1; + FILE *fp = NULL; + char buf[256]; + char *key = NULL, *value = NULL; + char *saveptr = NULL; + char dump_option_file[PATH_MAX]; + + /* glusterd will create a file glusterdump.<pid>.options and + sets the statedump options for the process and the file is removed + after the statedump is taken. Direct issue of SIGUSR1 does not have + mechanism for considering the statedump options. So to have a way + of configuring the statedump of all the glusterfs processes through + both cli command and SIGUSR1, glusterdump.options file is searched + and the options mentioned in it are given the higher priority. + */ + snprintf (dump_option_file, sizeof (dump_option_file), + DEFAULT_VAR_RUN_DIRECTORY + "/glusterdump.options"); + fp = fopen (dump_option_file, "r"); + if (!fp) { + snprintf (dump_option_file, sizeof (dump_option_file), + DEFAULT_VAR_RUN_DIRECTORY + "/glusterdump.%d.options", getpid ()); + + fp = fopen (dump_option_file, "r"); + + if (!fp) { + //ENOENT, return success + (void) gf_proc_dump_enable_all_options (); + return 0; + } + } + + (void) gf_proc_dump_disable_all_options (); + + // swallow the errors if setting statedump file path is failed. + ret = gf_proc_dump_set_path (dump_option_file); + + ret = fscanf (fp, "%s", buf); + + while (ret != EOF) { + key = strtok_r (buf, "=", &saveptr); + if (!key) { + ret = fscanf (fp, "%s", buf); + continue; + } + + value = strtok_r (NULL, "=", &saveptr); + + if (!value) { + ret = fscanf (fp, "%s", buf); + continue; + } + + gf_proc_dump_parse_set_option (key, value); + } + + if (is_gf_proc_dump_all_disabled ()) + (void) gf_proc_dump_enable_default_options (); + + if (fp) + fclose (fp); + + return 0; +} void -gf_proc_dump_info (int signum) -{ - int ret = -1; - glusterfs_ctx_t *ctx = NULL; - - gf_proc_dump_lock(); - ret = gf_proc_dump_open(); - if (ret < 0) +gf_proc_dump_info (int signum, glusterfs_ctx_t *ctx) +{ + int i = 0; + int ret = -1; + glusterfs_graph_t *trav = NULL; + char brick_name[PATH_MAX] = {0,}; + char timestr[256] = {0,}; + char sign_string[512] = {0,}; + char tmp_dump_name[PATH_MAX] = {0,}; + char path[PATH_MAX] = {0,}; + struct timeval tv = {0,}; + + gf_proc_dump_lock (); + + if (!ctx) + goto out; + + if (ctx->cmd_args.brick_name) { + GF_REMOVE_SLASH_FROM_PATH (ctx->cmd_args.brick_name, brick_name); + } else + strncpy (brick_name, "glusterdump", sizeof (brick_name)); + + ret = gf_proc_dump_options_init (); + if (ret < 0) goto out; - gf_proc_dump_mem_info(); - ctx = get_global_ctx_ptr(); - if (ctx) { - iobuf_stats_dump(ctx->iobuf_pool); - gf_proc_dump_pending_frames(ctx->pool); - gf_proc_dump_xlator_info(ctx->graph); - } - - gf_proc_dump_close(); + + snprintf (path, sizeof (path), "%s/%s.%d.dump.%"PRIu64, + ((dump_options.dump_path != NULL)?dump_options.dump_path: + ((ctx->statedump_path != NULL)?ctx->statedump_path: + DEFAULT_VAR_RUN_DIRECTORY)), brick_name, getpid(), + (uint64_t) time (NULL)); + + snprintf (tmp_dump_name, PATH_MAX, "%s/dumpXXXXXX", + ((dump_options.dump_path != NULL)?dump_options.dump_path: + ((ctx->statedump_path != NULL)?ctx->statedump_path: + DEFAULT_VAR_RUN_DIRECTORY))); + + ret = gf_proc_dump_open (tmp_dump_name); + if (ret < 0) + goto out; + + //continue even though gettimeofday() has failed + ret = gettimeofday (&tv, NULL); + if (0 == ret) { + gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT); + snprintf (timestr + strlen (timestr), + sizeof timestr - strlen (timestr), + ".%"GF_PRI_SUSECONDS, tv.tv_usec); + } + + snprintf (sign_string, sizeof (sign_string), "DUMP-START-TIME: %s\n", + timestr); + + //swallow the errors of write for start and end marker + ret = write (gf_dump_fd, sign_string, strlen (sign_string)); + + memset (sign_string, 0, sizeof (sign_string)); + memset (timestr, 0, sizeof (timestr)); + memset (&tv, 0, sizeof (tv)); + + if (GF_PROC_DUMP_IS_OPTION_ENABLED (mem)) { + gf_proc_dump_mem_info (); + gf_proc_dump_mempool_info (ctx); + } + + if (GF_PROC_DUMP_IS_OPTION_ENABLED (iobuf)) + iobuf_stats_dump (ctx->iobuf_pool); + if (GF_PROC_DUMP_IS_OPTION_ENABLED (callpool)) + gf_proc_dump_pending_frames (ctx->pool); + + if (ctx->master) { + gf_proc_dump_add_section ("fuse"); + gf_proc_dump_xlator_info (ctx->master); + } + + if (ctx->active) { + gf_proc_dump_add_section ("active graph - %d", ctx->graph_id); + gf_proc_dump_xlator_info (ctx->active->top); + } + + i = 0; + list_for_each_entry (trav, &ctx->graphs, list) { + if (trav == ctx->active) + continue; + + gf_proc_dump_add_section ("oldgraph[%d]", i); + + gf_proc_dump_oldgraph_xlator_info (trav->top); + i++; + } + + ret = gettimeofday (&tv, NULL); + if (0 == ret) { + gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT); + snprintf (timestr + strlen (timestr), + sizeof timestr - strlen (timestr), + ".%"GF_PRI_SUSECONDS, tv.tv_usec); + } + + snprintf (sign_string, sizeof (sign_string), "\nDUMP-END-TIME: %s", + timestr); + ret = write (gf_dump_fd, sign_string, strlen (sign_string)); + out: - gf_proc_dump_unlock(); + if (gf_dump_fd != -1) + gf_proc_dump_close (); + rename (tmp_dump_name, path); + GF_FREE (dump_options.dump_path); + dump_options.dump_path = NULL; + gf_proc_dump_unlock (); return; } -void + +void gf_proc_dump_fini (void) { - pthread_mutex_destroy(&gf_proc_dump_mutex); + pthread_mutex_destroy (&gf_proc_dump_mutex); } void gf_proc_dump_init () { - pthread_mutex_init(&gf_proc_dump_mutex, NULL); + pthread_mutex_init (&gf_proc_dump_mutex, NULL); - return; + return; } + void gf_proc_dump_cleanup (void) { - pthread_mutex_destroy(&gf_proc_dump_mutex); + pthread_mutex_destroy (&gf_proc_dump_mutex); } - diff --git a/libglusterfs/src/statedump.h b/libglusterfs/src/statedump.h index 1997c65b9..8342b120a 100644 --- a/libglusterfs/src/statedump.h +++ b/libglusterfs/src/statedump.h @@ -1,33 +1,40 @@ /* - Copyright (c) 2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef STATEDUMP_H -#define STATEDUMP_H +#define STATEDUMP_H #include <stdarg.h> #include "inode.h" #define GF_DUMP_MAX_BUF_LEN 4096 -#define GF_DUMP_LOGFILE_ROOT "/tmp/glusterdump" -#define GF_DUMP_LOGFILE_ROOT_LEN 256 +typedef struct gf_dump_xl_options_ { + gf_boolean_t dump_priv; + gf_boolean_t dump_inode; + gf_boolean_t dump_fd; + gf_boolean_t dump_inodectx; + gf_boolean_t dump_fdctx; + gf_boolean_t dump_history; +} gf_dump_xl_options_t; + +typedef struct gf_dump_options_ { + gf_boolean_t dump_mem; + gf_boolean_t dump_iobuf; + gf_boolean_t dump_callpool; + gf_dump_xl_options_t xl_options; //options for all xlators + char *dump_path; +} gf_dump_options_t; + +extern gf_dump_options_t dump_options; static inline void _gf_proc_dump_build_key (char *key, const char *prefix, char *fmt,...) @@ -39,38 +46,49 @@ void _gf_proc_dump_build_key (char *key, const char *prefix, char *fmt,...) va_start(ap, fmt); vsnprintf(buf, GF_DUMP_MAX_BUF_LEN, fmt, ap); va_end(ap); - snprintf(key, GF_DUMP_MAX_BUF_LEN, "%s.%s", prefix, buf); + snprintf(key, GF_DUMP_MAX_BUF_LEN, "%s.%s", prefix, buf); } -#define gf_proc_dump_build_key(key, key_prefix, fmt...) \ -{\ - _gf_proc_dump_build_key(key, key_prefix, ##fmt);\ -} +#define gf_proc_dump_build_key(key, key_prefix, fmt...) \ + { \ + _gf_proc_dump_build_key(key, key_prefix, ##fmt); \ + } + +#define GF_PROC_DUMP_SET_OPTION(opt,val) opt = val + +#define GF_CHECK_DUMP_OPTION_ENABLED(option_dump, var, label) \ + do { \ + if (option_dump == _gf_true) { \ + var = _gf_false; \ + goto label; \ + } \ + } while (0); + +void gf_proc_dump_init(); + +void gf_proc_dump_fini(void); + +void gf_proc_dump_cleanup(void); + +void gf_proc_dump_info(int signum, glusterfs_ctx_t *ctx); + +int gf_proc_dump_add_section(char *key,...); -void -gf_proc_dump_init(); +int gf_proc_dump_write(char *key, char *value,...); -void -gf_proc_dump_fini(void); +void inode_table_dump(inode_table_t *itable, char *prefix); -void -gf_proc_dump_cleanup(void); +void inode_table_dump_to_dict (inode_table_t *itable, char *prefix, dict_t *dict); -void -gf_proc_dump_info(int signum); +void fdtable_dump(fdtable_t *fdtable, char *prefix); -void -gf_proc_dump_add_section(char *key,...); +void fdtable_dump_to_dict (fdtable_t *fdtable, char *prefix, dict_t *dict); -void -gf_proc_dump_write(char *key, char *value,...); +void inode_dump(inode_t *inode, char *prefix); -void -inode_table_dump(inode_table_t *itable, char *prefix); +void gf_proc_dump_mem_info_to_dict (dict_t *dict); -void -fdtable_dump(fdtable_t *fdtable, char *prefix); +void gf_proc_dump_mempool_info_to_dict (glusterfs_ctx_t *ctx, dict_t *dict); -void -inode_dump(inode_t *inode, char *prefix); +void glusterd_init (int sig); #endif /* STATEDUMP_H */ diff --git a/libglusterfs/src/store.c b/libglusterfs/src/store.c new file mode 100644 index 000000000..1e6601837 --- /dev/null +++ b/libglusterfs/src/store.c @@ -0,0 +1,709 @@ +/* + Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <inttypes.h> +#include <libgen.h> + +#include "glusterfs.h" +#include "store.h" +#include "dict.h" +#include "xlator.h" + +int32_t +gf_store_mkdir (char *path) +{ + int32_t ret = -1; + + ret = mkdir (path, 0777); + + if ((-1 == ret) && (EEXIST != errno)) { + gf_log ("", GF_LOG_ERROR, "mkdir() failed on path %s," + "errno: %s", path, strerror (errno)); + } else { + ret = 0; + } + + return ret; +} + +int32_t +gf_store_handle_create_on_absence (gf_store_handle_t **shandle, + char *path) +{ + GF_ASSERT (shandle); + int32_t ret = 0; + + if (*shandle == NULL) { + ret = gf_store_handle_new (path, shandle); + + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to create store" + " handle for path: %s", path); + } + } + return ret; +} + +int32_t +gf_store_mkstemp (gf_store_handle_t *shandle) +{ + int fd = -1; + char tmppath[PATH_MAX] = {0,}; + + GF_ASSERT (shandle); + GF_ASSERT (shandle->path); + + snprintf (tmppath, sizeof (tmppath), "%s.tmp", shandle->path); + fd = open (tmppath, O_RDWR | O_CREAT | O_TRUNC | O_SYNC, 0600); + if (fd <= 0) { + gf_log ("", GF_LOG_ERROR, "Failed to open %s, error: %s", + tmppath, strerror (errno)); + } + + return fd; +} + +int +gf_store_sync_direntry (char *path) +{ + int ret = -1; + int dirfd = -1; + char *dir = NULL; + char *pdir = NULL; + xlator_t *this = NULL; + + this = THIS; + + dir = gf_strdup (path); + if (!dir) + goto out; + + pdir = dirname (dir); + dirfd = open (pdir, O_RDONLY); + if (dirfd == -1) { + gf_log (this->name, GF_LOG_ERROR, "Failed to open directory " + "%s, due to %s", pdir, strerror (errno)); + goto out; + } + + ret = fsync (dirfd); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to fsync %s, due to " + "%s", pdir, strerror (errno)); + goto out; + } + + ret = 0; +out: + if (dirfd >= 0) { + ret = close (dirfd); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to close " + "%s, due to %s", pdir, strerror (errno)); + } + } + + if (dir) + GF_FREE (dir); + + return ret; +} + +int32_t +gf_store_rename_tmppath (gf_store_handle_t *shandle) +{ + int32_t ret = -1; + char tmppath[PATH_MAX] = {0,}; + + GF_ASSERT (shandle); + GF_ASSERT (shandle->path); + + snprintf (tmppath, sizeof (tmppath), "%s.tmp", shandle->path); + ret = rename (tmppath, shandle->path); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Failed to rename %s to %s, " + "error: %s", tmppath, shandle->path, strerror (errno)); + goto out; + } + + ret = gf_store_sync_direntry (tmppath); +out: + return ret; +} + +int32_t +gf_store_unlink_tmppath (gf_store_handle_t *shandle) +{ + int32_t ret = -1; + char tmppath[PATH_MAX] = {0,}; + + GF_ASSERT (shandle); + GF_ASSERT (shandle->path); + + snprintf (tmppath, sizeof (tmppath), "%s.tmp", shandle->path); + ret = unlink (tmppath); + if (ret && (errno != ENOENT)) { + gf_log ("", GF_LOG_ERROR, "Failed to mv %s to %s, error: %s", + tmppath, shandle->path, strerror (errno)); + } else { + ret = 0; + } + + return ret; +} + +int +gf_store_read_and_tokenize (FILE *file, char *str, char **iter_key, + char **iter_val, gf_store_op_errno_t *store_errno) +{ + int32_t ret = -1; + char *savetok = NULL; + char *key = NULL; + char *value = NULL; + char *temp = NULL; + size_t str_len = 0; + + GF_ASSERT (file); + GF_ASSERT (str); + GF_ASSERT (iter_key); + GF_ASSERT (iter_val); + GF_ASSERT (store_errno); + + temp = fgets (str, PATH_MAX, file); + if (temp == NULL || feof (file)) { + ret = -1; + *store_errno = GD_STORE_EOF; + goto out; + } + + str_len = strlen(str); + str[str_len - 1] = '\0'; + /* Truncate the "\n", as fgets stores "\n" in str */ + + key = strtok_r (str, "=", &savetok); + if (!key) { + ret = -1; + *store_errno = GD_STORE_KEY_NULL; + goto out; + } + + value = strtok_r (NULL, "=", &savetok); + if (!value) { + ret = -1; + *store_errno = GD_STORE_VALUE_NULL; + goto out; + } + + *iter_key = key; + *iter_val = value; + *store_errno = GD_STORE_SUCCESS; + ret = 0; +out: + return ret; +} + +int32_t +gf_store_retrieve_value (gf_store_handle_t *handle, char *key, char **value) +{ + int32_t ret = -1; + char *scan_str = NULL; + char *iter_key = NULL; + char *iter_val = NULL; + char *free_str = NULL; + struct stat st = {0,}; + gf_store_op_errno_t store_errno = GD_STORE_SUCCESS; + + GF_ASSERT (handle); + + if (handle->locked == F_ULOCK) + /* no locking is used handle->fd gets closed() after usage */ + handle->fd = open (handle->path, O_RDWR); + else + /* handle->fd is valid already, kept open for lockf() */ + lseek (handle->fd, 0, SEEK_SET); + + if (handle->fd == -1) { + gf_log ("", GF_LOG_ERROR, "Unable to open file %s errno: %s", + handle->path, strerror (errno)); + goto out; + } + if (!handle->read) + handle->read = fdopen (dup(handle->fd), "r"); + else + fseek (handle->read, 0, SEEK_SET); + + if (!handle->read) { + gf_log ("", GF_LOG_ERROR, "Unable to open file %s errno: %s", + handle->path, strerror (errno)); + goto out; + } + + ret = fstat (handle->fd, &st); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "stat on file %s failed", + handle->path); + ret = -1; + store_errno = GD_STORE_STAT_FAILED; + goto out; + } + + /* "st.st_size + 1" is used as we are fetching each + * line of a file using fgets, fgets will append "\0" + * to the end of the string + */ + scan_str = GF_CALLOC (1, st.st_size + 1, + gf_common_mt_char); + + if (scan_str == NULL) { + ret = -1; + store_errno = GD_STORE_ENOMEM; + goto out; + } + + free_str = scan_str; + + do { + ret = gf_store_read_and_tokenize (handle->read, scan_str, + &iter_key, &iter_val, + &store_errno); + if (ret < 0) { + gf_log ("", GF_LOG_TRACE, "error while reading key " + "'%s': %s", key, + gf_store_strerror (store_errno)); + goto out; + } + + gf_log ("", GF_LOG_TRACE, "key %s read", iter_key); + + if (!strcmp (key, iter_key)) { + gf_log ("", GF_LOG_DEBUG, "key %s found", key); + ret = 0; + if (iter_val) + *value = gf_strdup (iter_val); + goto out; + } + } while (1); +out: + if (handle->read) { + fclose (handle->read); + handle->read = NULL; + } + + if (handle->fd > 0 && handle->locked == F_ULOCK) { + /* only invalidate handle->fd if not locked */ + close (handle->fd); + } + + GF_FREE (free_str); + + return ret; +} + +int32_t +gf_store_save_value (int fd, char *key, char *value) +{ + int32_t ret = -1; + int dup_fd = -1; + FILE *fp = NULL; + + GF_ASSERT (fd > 0); + GF_ASSERT (key); + GF_ASSERT (value); + + dup_fd = dup (fd); + if (dup_fd == -1) + goto out; + + fp = fdopen (dup_fd, "a+"); + if (fp == NULL) { + gf_log ("", GF_LOG_WARNING, "fdopen failed."); + ret = -1; + goto out; + } + + ret = fprintf (fp, "%s=%s\n", key, value); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "Unable to store key: %s," + "value: %s, error: %s", key, value, + strerror (errno)); + ret = -1; + goto out; + } + + ret = fflush (fp); + if (feof (fp)) { + gf_log ("", GF_LOG_WARNING, + "fflush failed, error: %s", + strerror (errno)); + ret = -1; + goto out; + } + + ret = 0; +out: + if (fp) + fclose (fp); + + gf_log ("", GF_LOG_DEBUG, "returning: %d", ret); + return ret; +} + +int32_t +gf_store_handle_new (char *path, gf_store_handle_t **handle) +{ + int32_t ret = -1; + gf_store_handle_t *shandle = NULL; + int fd = -1; + char *spath = NULL; + + shandle = GF_CALLOC (1, sizeof (*shandle), gf_common_mt_store_handle_t); + if (!shandle) + goto out; + + spath = gf_strdup (path); + + if (!spath) + goto out; + + fd = open (path, O_RDWR | O_CREAT | O_APPEND, 0600); + if (fd <= 0) { + gf_log ("", GF_LOG_ERROR, "Failed to open file: %s, error: %s", + path, strerror (errno)); + goto out; + } + + ret = gf_store_sync_direntry (spath); + if (ret) + goto out; + + shandle->path = spath; + shandle->locked = F_ULOCK; + *handle = shandle; + + ret = 0; +out: + if (fd > 0) + close (fd); + + if (ret == -1) { + GF_FREE (spath); + GF_FREE (shandle); + } + + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int +gf_store_handle_retrieve (char *path, gf_store_handle_t **handle) +{ + int32_t ret = -1; + struct stat statbuf = {0}; + + ret = stat (path, &statbuf); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Path corresponding to " + "%s, returned error: (%s)", + path, strerror (errno)); + goto out; + } + ret = gf_store_handle_new (path, handle); +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +int32_t +gf_store_handle_destroy (gf_store_handle_t *handle) +{ + int32_t ret = -1; + + if (!handle) { + ret = 0; + goto out; + } + + GF_FREE (handle->path); + + GF_FREE (handle); + + ret = 0; + +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +int32_t +gf_store_iter_new (gf_store_handle_t *shandle, gf_store_iter_t **iter) +{ + int32_t ret = -1; + FILE *fp = NULL; + gf_store_iter_t *tmp_iter = NULL; + + GF_ASSERT (shandle); + GF_ASSERT (iter); + + fp = fopen (shandle->path, "r"); + if (!fp) { + gf_log ("", GF_LOG_ERROR, "Unable to open file %s errno: %d", + shandle->path, errno); + goto out; + } + + tmp_iter = GF_CALLOC (1, sizeof (*tmp_iter), + gf_common_mt_store_iter_t); + if (!tmp_iter) + goto out; + + strncpy (tmp_iter->filepath, shandle->path, sizeof (tmp_iter->filepath)); + tmp_iter->filepath[sizeof (tmp_iter->filepath) - 1] = 0; + tmp_iter->file = fp; + + *iter = tmp_iter; + tmp_iter = NULL; + ret = 0; + +out: + if (ret && fp) + fclose (fp); + + GF_FREE (tmp_iter); + + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + return ret; +} + +int32_t +gf_store_validate_key_value (char *storepath, char *key, char *val, + gf_store_op_errno_t *op_errno) +{ + int ret = 0; + + GF_ASSERT (op_errno); + GF_ASSERT (storepath); + + if ((key == NULL) && (val == NULL)) { + ret = -1; + gf_log ("", GF_LOG_ERROR, "Glusterd store may be corrupted, " + "Invalid key and value (null) in %s", storepath); + *op_errno = GD_STORE_KEY_VALUE_NULL; + } else if (key == NULL) { + ret = -1; + gf_log ("", GF_LOG_ERROR, "Glusterd store may be corrupted, " + "Invalid key (null) in %s", storepath); + *op_errno = GD_STORE_KEY_NULL; + } else if (val == NULL) { + ret = -1; + gf_log ("", GF_LOG_ERROR, "Glusterd store may be corrupted, " + "Invalid value (null) for key %s in %s", key, + storepath); + *op_errno = GD_STORE_VALUE_NULL; + } else { + ret = 0; + *op_errno = GD_STORE_SUCCESS; + } + + return ret; +} + +int32_t +gf_store_iter_get_next (gf_store_iter_t *iter, char **key, char **value, + gf_store_op_errno_t *op_errno) +{ + int32_t ret = -1; + char *scan_str = NULL; + char *iter_key = NULL; + char *iter_val = NULL; + struct stat st = {0,}; + gf_store_op_errno_t store_errno = GD_STORE_SUCCESS; + + GF_ASSERT (iter); + GF_ASSERT (key); + GF_ASSERT (value); + + ret = stat (iter->filepath, &st); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "stat on file failed"); + ret = -1; + store_errno = GD_STORE_STAT_FAILED; + goto out; + } + + /* "st.st_size + 1" is used as we are fetching each + * line of a file using fgets, fgets will append "\0" + * to the end of the string + */ + scan_str = GF_CALLOC (1, st.st_size + 1, + gf_common_mt_char); + if (!scan_str) { + ret = -1; + store_errno = GD_STORE_ENOMEM; + goto out; + } + + ret = gf_store_read_and_tokenize (iter->file, scan_str, + &iter_key, &iter_val, + &store_errno); + if (ret < 0) { + goto out; + } + + ret = gf_store_validate_key_value (iter->filepath, iter_key, + iter_val, &store_errno); + if (ret) + goto out; + + *key = gf_strdup (iter_key); + if (!*key) { + ret = -1; + store_errno = GD_STORE_ENOMEM; + goto out; + } + *value = gf_strdup (iter_val); + if (!*value) { + ret = -1; + store_errno = GD_STORE_ENOMEM; + goto out; + } + ret = 0; + +out: + GF_FREE (scan_str); + if (ret) { + GF_FREE (*key); + GF_FREE (*value); + *key = NULL; + *value = NULL; + } + if (op_errno) + *op_errno = store_errno; + + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + return ret; +} + +int32_t +gf_store_iter_get_matching (gf_store_iter_t *iter, char *key, char **value) +{ + int32_t ret = -1; + char *tmp_key = NULL; + char *tmp_value = NULL; + + ret = gf_store_iter_get_next (iter, &tmp_key, &tmp_value, NULL); + while (!ret) { + if (!strncmp (key, tmp_key, strlen (key))){ + *value = tmp_value; + GF_FREE (tmp_key); + goto out; + } + GF_FREE (tmp_key); + tmp_key = NULL; + GF_FREE (tmp_value); + tmp_value = NULL; + ret = gf_store_iter_get_next (iter, &tmp_key, &tmp_value, + NULL); + } +out: + return ret; +} + +int32_t +gf_store_iter_destroy (gf_store_iter_t *iter) +{ + int32_t ret = -1; + + if (!iter) + return 0; + + /* gf_store_iter_new will not return a valid iter object with iter->file + * being NULL*/ + ret = fclose (iter->file); + if (ret) + gf_log ("", GF_LOG_ERROR, "Unable to close file: %s, ret: %d, " + "errno: %d" ,iter->filepath, ret, errno); + + GF_FREE (iter); + return ret; +} + +char* +gf_store_strerror (gf_store_op_errno_t op_errno) +{ + switch (op_errno) { + case GD_STORE_SUCCESS: + return "Success"; + case GD_STORE_KEY_NULL: + return "Invalid Key"; + case GD_STORE_VALUE_NULL: + return "Invalid Value"; + case GD_STORE_KEY_VALUE_NULL: + return "Invalid Key and Value"; + case GD_STORE_EOF: + return "No data"; + case GD_STORE_ENOMEM: + return "No memory"; + default: + return "Invalid errno"; + } + return "Invalid errno"; +} + +int +gf_store_lock (gf_store_handle_t *sh) +{ + int ret; + + GF_ASSERT (sh); + GF_ASSERT (sh->path); + GF_ASSERT (sh->locked == F_ULOCK); + + sh->fd = open (sh->path, O_RDWR); + if (sh->fd == -1) { + gf_log ("", GF_LOG_ERROR, "Failed to open '%s': %s", sh->path, + strerror (errno)); + return -1; + } + + ret = lockf (sh->fd, F_LOCK, 0); + if (ret) + gf_log ("", GF_LOG_ERROR, "Failed to gain lock on '%s': %s", + sh->path, strerror (errno)); + else + /* sh->locked is protected by the lockf(sh->fd) above */ + sh->locked = F_LOCK; + + return ret; +} + +void +gf_store_unlock (gf_store_handle_t *sh) +{ + GF_ASSERT (sh); + GF_ASSERT (sh->locked == F_LOCK); + + sh->locked = F_ULOCK; + lockf (sh->fd, F_ULOCK, 0); + close (sh->fd); +} + +int +gf_store_locked_local (gf_store_handle_t *sh) +{ + GF_ASSERT (sh); + + return (sh->locked == F_LOCK); +} diff --git a/libglusterfs/src/store.h b/libglusterfs/src/store.h new file mode 100644 index 000000000..337103ff7 --- /dev/null +++ b/libglusterfs/src/store.h @@ -0,0 +1,112 @@ +/* + Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ +#ifndef _GLUSTERD_STORE_H_ +#define _GLUSTERD_STORE_H_ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "glusterfs.h" + +struct gf_store_handle_ { + char *path; + int fd; + FILE *read; + int locked; /* state of lockf() */ +}; + +typedef struct gf_store_handle_ gf_store_handle_t; + +struct gf_store_iter_ { + FILE *file; + char filepath[PATH_MAX]; +}; + +typedef struct gf_store_iter_ gf_store_iter_t; + +typedef enum { + GD_STORE_SUCCESS, + GD_STORE_KEY_NULL, + GD_STORE_VALUE_NULL, + GD_STORE_KEY_VALUE_NULL, + GD_STORE_EOF, + GD_STORE_ENOMEM, + GD_STORE_STAT_FAILED +} gf_store_op_errno_t; + +int32_t +gf_store_mkdir (char *path); + +int32_t +gf_store_handle_create_on_absence (gf_store_handle_t **shandle, char *path); + +int32_t +gf_store_mkstemp (gf_store_handle_t *shandle); + +int +gf_store_sync_direntry (char *path); + +int32_t +gf_store_rename_tmppath (gf_store_handle_t *shandle); + +int32_t +gf_store_unlink_tmppath (gf_store_handle_t *shandle); + +int +gf_store_read_and_tokenize (FILE *file, char *str, char **iter_key, + char **iter_val, gf_store_op_errno_t *store_errno); + +int32_t +gf_store_retrieve_value (gf_store_handle_t *handle, char *key, char **value); + +int32_t +gf_store_save_value (int fd, char *key, char *value); + +int32_t +gf_store_handle_new (char *path, gf_store_handle_t **handle); + +int +gf_store_handle_retrieve (char *path, gf_store_handle_t **handle); + +int32_t +gf_store_handle_destroy (gf_store_handle_t *handle); + +int32_t +gf_store_iter_new (gf_store_handle_t *shandle, gf_store_iter_t **iter); + +int32_t +gf_store_validate_key_value (char *storepath, char *key, char *val, + gf_store_op_errno_t *op_errno); + +int32_t +gf_store_iter_get_next (gf_store_iter_t *iter, char **key, char **value, + gf_store_op_errno_t *op_errno); + +int32_t +gf_store_iter_get_matching (gf_store_iter_t *iter, char *key, char **value); + +int32_t +gf_store_iter_destroy (gf_store_iter_t *iter); + +char* +gf_store_strerror (gf_store_op_errno_t op_errno); + +int +gf_store_lock (gf_store_handle_t *sh); + +void +gf_store_unlock (gf_store_handle_t *sh); + +int +gf_store_locked_local (gf_store_handle_t *sh); + +#endif diff --git a/libglusterfs/src/syncop.c b/libglusterfs/src/syncop.c new file mode 100644 index 000000000..c1620bb70 --- /dev/null +++ b/libglusterfs/src/syncop.c @@ -0,0 +1,2237 @@ +/* + Copyright (c) 2008-2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "syncop.h" + +int +syncopctx_setfsuid (void *uid) +{ + struct syncopctx *opctx = NULL; + int ret = 0; + + /* In args check */ + if (!uid) { + ret = -1; + errno = EINVAL; + goto out; + } + + opctx = syncopctx_getctx (); + + /* alloc for this thread the first time */ + if (!opctx) { + opctx = GF_CALLOC (1, sizeof (*opctx), gf_common_mt_syncopctx); + if (!opctx) { + ret = -1; + goto out; + } + + ret = syncopctx_setctx (opctx); + if (ret != 0) { + GF_FREE (opctx); + opctx = NULL; + goto out; + } + } + +out: + if (opctx && uid) { + opctx->uid = *(uid_t *)uid; + opctx->valid |= SYNCOPCTX_UID; + } + + return ret; +} + +int +syncopctx_setfsgid (void *gid) +{ + struct syncopctx *opctx = NULL; + int ret = 0; + + /* In args check */ + if (!gid) { + ret = -1; + errno = EINVAL; + goto out; + } + + opctx = syncopctx_getctx (); + + /* alloc for this thread the first time */ + if (!opctx) { + opctx = GF_CALLOC (1, sizeof (*opctx), gf_common_mt_syncopctx); + if (!opctx) { + ret = -1; + goto out; + } + + ret = syncopctx_setctx (opctx); + if (ret != 0) { + GF_FREE (opctx); + opctx = NULL; + goto out; + } + } + +out: + if (opctx && gid) { + opctx->gid = *(gid_t *)gid; + opctx->valid |= SYNCOPCTX_GID; + } + + return ret; +} + +int +syncopctx_setfsgroups (int count, const void *groups) +{ + struct syncopctx *opctx = NULL; + gid_t *tmpgroups = NULL; + int ret = 0; + + /* In args check */ + if (count != 0 && !groups) { + ret = -1; + errno = EINVAL; + goto out; + } + + opctx = syncopctx_getctx (); + + /* alloc for this thread the first time */ + if (!opctx) { + opctx = GF_CALLOC (1, sizeof (*opctx), gf_common_mt_syncopctx); + if (!opctx) { + ret = -1; + goto out; + } + + ret = syncopctx_setctx (opctx); + if (ret != 0) { + GF_FREE (opctx); + opctx = NULL; + goto out; + } + } + + /* resize internal groups as required */ + if (count && opctx->grpsize < count) { + if (opctx->groups) { + tmpgroups = GF_REALLOC (opctx->groups, + (sizeof (gid_t) * count)); + /* NOTE: Not really required to zero the reallocation, + * as ngrps controls the validity of data, + * making a note irrespective */ + if (tmpgroups == NULL) { + opctx->grpsize = 0; + GF_FREE (opctx->groups); + opctx->groups = NULL; + ret = -1; + goto out; + } + } + else { + tmpgroups = GF_CALLOC (count, sizeof (gid_t), + gf_common_mt_syncopctx); + if (tmpgroups == NULL) { + opctx->grpsize = 0; + ret = -1; + goto out; + } + } + + opctx->groups = tmpgroups; + opctx->grpsize = count; + } + + /* copy out the groups passed */ + if (count) + memcpy (opctx->groups, groups, (sizeof (gid_t) * count)); + + /* set/reset the ngrps, this is where reset of groups is handled */ + opctx->ngrps = count; + opctx->valid |= SYNCOPCTX_GROUPS; + +out: + return ret; +} + +static void +__run (struct synctask *task) +{ + struct syncenv *env = NULL; + + env = task->env; + + list_del_init (&task->all_tasks); + switch (task->state) { + case SYNCTASK_INIT: + case SYNCTASK_SUSPEND: + break; + case SYNCTASK_RUN: + gf_log (task->xl->name, GF_LOG_DEBUG, + "re-running already running task"); + env->runcount--; + break; + case SYNCTASK_WAIT: + env->waitcount--; + break; + case SYNCTASK_DONE: + gf_log (task->xl->name, GF_LOG_WARNING, + "running completed task"); + return; + case SYNCTASK_ZOMBIE: + gf_log (task->xl->name, GF_LOG_WARNING, + "attempted to wake up zombie!!"); + return; + } + + list_add_tail (&task->all_tasks, &env->runq); + env->runcount++; + task->state = SYNCTASK_RUN; +} + + +static void +__wait (struct synctask *task) +{ + struct syncenv *env = NULL; + + env = task->env; + + list_del_init (&task->all_tasks); + switch (task->state) { + case SYNCTASK_INIT: + case SYNCTASK_SUSPEND: + break; + case SYNCTASK_RUN: + env->runcount--; + break; + case SYNCTASK_WAIT: + gf_log (task->xl->name, GF_LOG_WARNING, + "re-waiting already waiting task"); + env->waitcount--; + break; + case SYNCTASK_DONE: + gf_log (task->xl->name, GF_LOG_WARNING, + "running completed task"); + return; + case SYNCTASK_ZOMBIE: + gf_log (task->xl->name, GF_LOG_WARNING, + "attempted to sleep a zombie!!"); + return; + } + + list_add_tail (&task->all_tasks, &env->waitq); + env->waitcount++; + task->state = SYNCTASK_WAIT; +} + + +void +synctask_yield (struct synctask *task) +{ + xlator_t *oldTHIS = THIS; + +#if defined(__NetBSD__) && defined(_UC_TLSBASE) + /* Preserve pthread private pointer through swapcontex() */ + task->proc->sched.uc_flags &= ~_UC_TLSBASE; +#endif + + if (task->state != SYNCTASK_DONE) + task->state = SYNCTASK_SUSPEND; + if (swapcontext (&task->ctx, &task->proc->sched) < 0) { + gf_log ("syncop", GF_LOG_ERROR, + "swapcontext failed (%s)", strerror (errno)); + } + + THIS = oldTHIS; +} + + +void +synctask_wake (struct synctask *task) +{ + struct syncenv *env = NULL; + + env = task->env; + + pthread_mutex_lock (&env->mutex); + { + task->woken = 1; + + if (task->slept) + __run (task); + + pthread_cond_broadcast (&env->cond); + } + pthread_mutex_unlock (&env->mutex); +} + +void +synctask_wrap (struct synctask *old_task) +{ + struct synctask *task = NULL; + + /* Do not trust the pointer received. It may be + wrong and can lead to crashes. */ + + task = synctask_get (); + task->ret = task->syncfn (task->opaque); + if (task->synccbk) + task->synccbk (task->ret, task->frame, task->opaque); + + task->state = SYNCTASK_DONE; + + synctask_yield (task); +} + + +void +synctask_destroy (struct synctask *task) +{ + if (!task) + return; + + FREE (task->stack); + + if (task->opframe) + STACK_DESTROY (task->opframe->root); + + if (task->synccbk == NULL) { + pthread_mutex_destroy (&task->mutex); + pthread_cond_destroy (&task->cond); + } + + FREE (task); +} + + +void +synctask_done (struct synctask *task) +{ + if (task->synccbk) { + synctask_destroy (task); + return; + } + + pthread_mutex_lock (&task->mutex); + { + task->state = SYNCTASK_ZOMBIE; + task->done = 1; + pthread_cond_broadcast (&task->cond); + } + pthread_mutex_unlock (&task->mutex); +} + + +int +synctask_setid (struct synctask *task, uid_t uid, gid_t gid) +{ + if (!task) + return -1; + + if (uid != -1) + task->uid = uid; + + if (gid != -1) + task->gid = gid; + + return 0; +} + + +struct synctask * +synctask_create (struct syncenv *env, synctask_fn_t fn, synctask_cbk_t cbk, + call_frame_t *frame, void *opaque) +{ + struct synctask *newtask = NULL; + xlator_t *this = THIS; + + VALIDATE_OR_GOTO (env, err); + VALIDATE_OR_GOTO (fn, err); + + newtask = CALLOC (1, sizeof (*newtask)); + if (!newtask) + return NULL; + + newtask->frame = frame; + if (!frame) { + newtask->opframe = create_frame (this, this->ctx->pool); + } else { + newtask->opframe = copy_frame (frame); + } + if (!newtask->opframe) + goto err; + newtask->env = env; + newtask->xl = this; + newtask->syncfn = fn; + newtask->synccbk = cbk; + newtask->opaque = opaque; + + /* default to the uid/gid of the passed frame */ + newtask->uid = newtask->opframe->root->uid; + newtask->gid = newtask->opframe->root->gid; + + INIT_LIST_HEAD (&newtask->all_tasks); + INIT_LIST_HEAD (&newtask->waitq); + + if (getcontext (&newtask->ctx) < 0) { + gf_log ("syncop", GF_LOG_ERROR, + "getcontext failed (%s)", + strerror (errno)); + goto err; + } + + newtask->stack = CALLOC (1, env->stacksize); + if (!newtask->stack) { + gf_log ("syncop", GF_LOG_ERROR, + "out of memory for stack"); + goto err; + } + + newtask->ctx.uc_stack.ss_sp = newtask->stack; + newtask->ctx.uc_stack.ss_size = env->stacksize; + + makecontext (&newtask->ctx, (void (*)(void)) synctask_wrap, 2, newtask); + + newtask->state = SYNCTASK_INIT; + + newtask->slept = 1; + + if (!cbk) { + pthread_mutex_init (&newtask->mutex, NULL); + pthread_cond_init (&newtask->cond, NULL); + newtask->done = 0; + } + + synctask_wake (newtask); + /* + * Make sure someone's there to execute anything we just put on the + * run queue. + */ + syncenv_scale(env); + + return newtask; +err: + if (newtask) { + FREE (newtask->stack); + if (newtask->opframe) + STACK_DESTROY (newtask->opframe->root); + FREE (newtask); + } + + return NULL; +} + + +int +synctask_join (struct synctask *task) +{ + int ret = 0; + + pthread_mutex_lock (&task->mutex); + { + while (!task->done) + pthread_cond_wait (&task->cond, &task->mutex); + } + pthread_mutex_unlock (&task->mutex); + + ret = task->ret; + + synctask_destroy (task); + + return ret; +} + + +int +synctask_new (struct syncenv *env, synctask_fn_t fn, synctask_cbk_t cbk, + call_frame_t *frame, void *opaque) +{ + struct synctask *newtask = NULL; + int ret = 0; + + newtask = synctask_create (env, fn, cbk, frame, opaque); + if (!newtask) + return -1; + + if (!cbk) + ret = synctask_join (newtask); + + return ret; +} + + +struct synctask * +syncenv_task (struct syncproc *proc) +{ + struct syncenv *env = NULL; + struct synctask *task = NULL; + struct timespec sleep_till = {0, }; + int ret = 0; + + env = proc->env; + + pthread_mutex_lock (&env->mutex); + { + while (list_empty (&env->runq)) { + sleep_till.tv_sec = time (NULL) + SYNCPROC_IDLE_TIME; + ret = pthread_cond_timedwait (&env->cond, &env->mutex, + &sleep_till); + if (!list_empty (&env->runq)) + break; + if ((ret == ETIMEDOUT) && + (env->procs > env->procmin)) { + task = NULL; + env->procs--; + memset (proc, 0, sizeof (*proc)); + goto unlock; + } + } + + task = list_entry (env->runq.next, struct synctask, all_tasks); + + list_del_init (&task->all_tasks); + env->runcount--; + + task->woken = 0; + task->slept = 0; + + task->proc = proc; + } +unlock: + pthread_mutex_unlock (&env->mutex); + + return task; +} + + +void +synctask_switchto (struct synctask *task) +{ + struct syncenv *env = NULL; + + env = task->env; + + synctask_set (task); + THIS = task->xl; + +#if defined(__NetBSD__) && defined(_UC_TLSBASE) + /* Preserve pthread private pointer through swapcontex() */ + task->ctx.uc_flags &= ~_UC_TLSBASE; +#endif + + if (swapcontext (&task->proc->sched, &task->ctx) < 0) { + gf_log ("syncop", GF_LOG_ERROR, + "swapcontext failed (%s)", strerror (errno)); + } + + if (task->state == SYNCTASK_DONE) { + synctask_done (task); + return; + } + + pthread_mutex_lock (&env->mutex); + { + if (task->woken) { + __run (task); + } else { + task->slept = 1; + __wait (task); + } + } + pthread_mutex_unlock (&env->mutex); +} + +void * +syncenv_processor (void *thdata) +{ + struct syncenv *env = NULL; + struct syncproc *proc = NULL; + struct synctask *task = NULL; + + proc = thdata; + env = proc->env; + + for (;;) { + task = syncenv_task (proc); + if (!task) + break; + + synctask_switchto (task); + + syncenv_scale (env); + } + + return NULL; +} + + +void +syncenv_scale (struct syncenv *env) +{ + int diff = 0; + int scale = 0; + int i = 0; + int ret = 0; + + pthread_mutex_lock (&env->mutex); + { + if (env->procs > env->runcount) + goto unlock; + + scale = env->runcount; + if (scale > env->procmax) + scale = env->procmax; + if (scale > env->procs) + diff = scale - env->procs; + while (diff) { + diff--; + for (; (i < env->procmax); i++) { + if (env->proc[i].processor == 0) + break; + } + + env->proc[i].env = env; + ret = gf_thread_create (&env->proc[i].processor, NULL, + syncenv_processor, &env->proc[i]); + if (ret) + break; + env->procs++; + i++; + } + } +unlock: + pthread_mutex_unlock (&env->mutex); +} + + +void +syncenv_destroy (struct syncenv *env) +{ + +} + + +struct syncenv * +syncenv_new (size_t stacksize, int procmin, int procmax) +{ + struct syncenv *newenv = NULL; + int ret = 0; + int i = 0; + + if (!procmin || procmin < 0) + procmin = SYNCENV_PROC_MIN; + if (!procmax || procmax > SYNCENV_PROC_MAX) + procmax = SYNCENV_PROC_MAX; + + if (procmin > procmax) + return NULL; + + newenv = CALLOC (1, sizeof (*newenv)); + + if (!newenv) + return NULL; + + pthread_mutex_init (&newenv->mutex, NULL); + pthread_cond_init (&newenv->cond, NULL); + + INIT_LIST_HEAD (&newenv->runq); + INIT_LIST_HEAD (&newenv->waitq); + + newenv->stacksize = SYNCENV_DEFAULT_STACKSIZE; + if (stacksize) + newenv->stacksize = stacksize; + newenv->procmin = procmin; + newenv->procmax = procmax; + + for (i = 0; i < newenv->procmin; i++) { + newenv->proc[i].env = newenv; + ret = gf_thread_create (&newenv->proc[i].processor, NULL, + syncenv_processor, &newenv->proc[i]); + if (ret) + break; + newenv->procs++; + } + + if (ret != 0) + syncenv_destroy (newenv); + + return newenv; +} + + +int +synclock_init (synclock_t *lock) +{ + if (!lock) + return -1; + + pthread_cond_init (&lock->cond, 0); + lock->lock = 0; + INIT_LIST_HEAD (&lock->waitq); + + return pthread_mutex_init (&lock->guard, 0); +} + + +int +synclock_destroy (synclock_t *lock) +{ + if (!lock) + return -1; + + pthread_cond_destroy (&lock->cond); + return pthread_mutex_destroy (&lock->guard); +} + + +static int +__synclock_lock (struct synclock *lock) +{ + struct synctask *task = NULL; + + if (!lock) + return -1; + + task = synctask_get (); + + while (lock->lock) { + if (task) { + /* called within a synctask */ + list_add_tail (&task->waitq, &lock->waitq); + pthread_mutex_unlock (&lock->guard); + synctask_yield (task); + /* task is removed from waitq in unlock, + * under lock->guard.*/ + pthread_mutex_lock (&lock->guard); + } else { + /* called by a non-synctask */ + pthread_cond_wait (&lock->cond, &lock->guard); + } + } + + lock->lock = _gf_true; + lock->owner = task; + + return 0; +} + + +int +synclock_lock (synclock_t *lock) +{ + int ret = 0; + + pthread_mutex_lock (&lock->guard); + { + ret = __synclock_lock (lock); + } + pthread_mutex_unlock (&lock->guard); + + return ret; +} + + +int +synclock_trylock (synclock_t *lock) +{ + int ret = 0; + + errno = 0; + + pthread_mutex_lock (&lock->guard); + { + if (lock->lock) { + errno = EBUSY; + ret = -1; + goto unlock; + } + + ret = __synclock_lock (lock); + } +unlock: + pthread_mutex_unlock (&lock->guard); + + return ret; +} + + +static int +__synclock_unlock (synclock_t *lock) +{ + struct synctask *task = NULL; + struct synctask *curr = NULL; + + if (!lock) + return -1; + + curr = synctask_get (); + + if (lock->owner != curr) { + /* warn ? */ + } + + lock->lock = _gf_false; + + /* There could be both synctasks and non synctasks + waiting (or none, or either). As a mid-approach + between maintaining too many waiting counters + at one extreme and a thundering herd on unlock + at the other, call a cond_signal (which wakes + one waiter) and first synctask waiter. So at + most we have two threads waking up to grab the + just released lock. + */ + pthread_cond_signal (&lock->cond); + if (!list_empty (&lock->waitq)) { + task = list_entry (lock->waitq.next, struct synctask, waitq); + list_del_init (&task->waitq); + synctask_wake (task); + } + + return 0; +} + + +int +synclock_unlock (synclock_t *lock) +{ + int ret = 0; + + pthread_mutex_lock (&lock->guard); + { + ret = __synclock_unlock (lock); + } + pthread_mutex_unlock (&lock->guard); + + return ret; +} + +/* Barriers */ + +int +syncbarrier_init (struct syncbarrier *barrier) +{ + if (!barrier) { + errno = EINVAL; + return -1; + } + + pthread_cond_init (&barrier->cond, 0); + barrier->count = 0; + INIT_LIST_HEAD (&barrier->waitq); + + return pthread_mutex_init (&barrier->guard, 0); +} + + +int +syncbarrier_destroy (struct syncbarrier *barrier) +{ + if (!barrier) { + errno = EINVAL; + return -1; + } + + pthread_cond_destroy (&barrier->cond); + return pthread_mutex_destroy (&barrier->guard); +} + + +static int +__syncbarrier_wait (struct syncbarrier *barrier, int waitfor) +{ + struct synctask *task = NULL; + + if (!barrier) { + errno = EINVAL; + return -1; + } + + task = synctask_get (); + + while (barrier->count < waitfor) { + if (task) { + /* called within a synctask */ + list_add_tail (&task->waitq, &barrier->waitq); + pthread_mutex_unlock (&barrier->guard); + synctask_yield (task); + pthread_mutex_lock (&barrier->guard); + } else { + /* called by a non-synctask */ + pthread_cond_wait (&barrier->cond, &barrier->guard); + } + } + + barrier->count = 0; + + return 0; +} + + +int +syncbarrier_wait (struct syncbarrier *barrier, int waitfor) +{ + int ret = 0; + + pthread_mutex_lock (&barrier->guard); + { + ret = __syncbarrier_wait (barrier, waitfor); + } + pthread_mutex_unlock (&barrier->guard); + + return ret; +} + + +static int +__syncbarrier_wake (struct syncbarrier *barrier) +{ + struct synctask *task = NULL; + + if (!barrier) { + errno = EINVAL; + return -1; + } + + barrier->count++; + + pthread_cond_signal (&barrier->cond); + if (!list_empty (&barrier->waitq)) { + task = list_entry (barrier->waitq.next, struct synctask, waitq); + list_del_init (&task->waitq); + synctask_wake (task); + } + + return 0; +} + + +int +syncbarrier_wake (struct syncbarrier *barrier) +{ + int ret = 0; + + pthread_mutex_lock (&barrier->guard); + { + ret = __syncbarrier_wake (barrier); + } + pthread_mutex_unlock (&barrier->guard); + + return ret; +} + + +/* FOPS */ + + +int +syncop_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, inode_t *inode, + struct iatt *iatt, dict_t *xdata, struct iatt *parent) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + if (op_ret == 0) { + args->iatt1 = *iatt; + args->iatt2 = *parent; + if (xdata) + args->xdata = dict_ref (xdata); + } + + __wake (args); + + return 0; +} + + +int +syncop_lookup (xlator_t *subvol, loc_t *loc, dict_t *xdata_req, + struct iatt *iatt, dict_t **xdata_rsp, struct iatt *parent) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_lookup_cbk, subvol->fops->lookup, + loc, xdata_req); + + if (iatt) + *iatt = args.iatt1; + if (parent) + *parent = args.iatt2; + if (xdata_rsp) + *xdata_rsp = args.xdata; + else if (args.xdata) + dict_unref (args.xdata); + + errno = args.op_errno; + return args.op_ret; +} + +static gf_dirent_t * +entry_copy (gf_dirent_t *source) +{ + gf_dirent_t *sink = NULL; + + sink = gf_dirent_for_name (source->d_name); + + sink->d_off = source->d_off; + sink->d_ino = source->d_ino; + sink->d_type = source->d_type; + sink->d_stat = source->d_stat; + + if (source->inode) + sink->inode = inode_ref (source->inode); + return sink; +} + +int32_t +syncop_readdirp_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + gf_dirent_t *entries, dict_t *xdata) +{ + struct syncargs *args = NULL; + gf_dirent_t *entry = NULL; + gf_dirent_t *tmp = NULL; + + int count = 0; + + args = cookie; + + INIT_LIST_HEAD (&args->entries.list); + + args->op_ret = op_ret; + args->op_errno = op_errno; + + if (op_ret >= 0) { + list_for_each_entry (entry, &entries->list, list) { + tmp = entry_copy (entry); + gf_log (this->name, GF_LOG_TRACE, + "adding entry=%s, count=%d", + tmp->d_name, count); + list_add_tail (&tmp->list, &(args->entries.list)); + count++; + } + } + + __wake (args); + + return 0; + +} + +int +syncop_readdirp (xlator_t *subvol, + fd_t *fd, + size_t size, + off_t off, + dict_t *dict, + gf_dirent_t *entries) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_readdirp_cbk, subvol->fops->readdirp, + fd, size, off, dict); + + if (entries) + list_splice_init (&args.entries.list, &entries->list); + /* TODO: need to free all the 'args.entries' in 'else' case */ + + errno = args.op_errno; + return args.op_ret; + +} + +int32_t +syncop_readdir_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + gf_dirent_t *entries, dict_t *xdata) +{ + struct syncargs *args = NULL; + gf_dirent_t *entry = NULL; + gf_dirent_t *tmp = NULL; + + int count = 0; + + args = cookie; + + INIT_LIST_HEAD (&args->entries.list); + + args->op_ret = op_ret; + args->op_errno = op_errno; + + if (op_ret >= 0) { + list_for_each_entry (entry, &entries->list, list) { + tmp = entry_copy (entry); + gf_log (this->name, GF_LOG_TRACE, + "adding entry=%s, count=%d", + tmp->d_name, count); + list_add_tail (&tmp->list, &(args->entries.list)); + count++; + } + } + + __wake (args); + + return 0; + +} + +int +syncop_readdir (xlator_t *subvol, + fd_t *fd, + size_t size, + off_t off, + gf_dirent_t *entries) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_readdir_cbk, subvol->fops->readdir, + fd, size, off, NULL); + + if (entries) + list_splice_init (&args.entries.list, &entries->list); + /* TODO: need to free all the 'args.entries' in 'else' case */ + + errno = args.op_errno; + return args.op_ret; + +} + +int32_t +syncop_opendir_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + fd_t *fd, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + +int +syncop_opendir (xlator_t *subvol, + loc_t *loc, + fd_t *fd) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_opendir_cbk, subvol->fops->opendir, + loc, fd, NULL); + + errno = args.op_errno; + return args.op_ret; + +} + +int +syncop_fsyncdir_cbk (call_frame_t *frame, void* cookie, xlator_t *this, + int op_ret, int op_errno, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + +int +syncop_fsyncdir (xlator_t *subvol, fd_t *fd, int datasync) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_fsyncdir_cbk, subvol->fops->fsyncdir, + fd, datasync, NULL); + + errno = args.op_errno; + return args.op_ret; +} + +int +syncop_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + +int +syncop_removexattr (xlator_t *subvol, loc_t *loc, const char *name) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_removexattr_cbk, subvol->fops->removexattr, + loc, name, NULL); + + errno = args.op_errno; + return args.op_ret; +} + +int +syncop_fremovexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + +int +syncop_fremovexattr (xlator_t *subvol, fd_t *fd, const char *name) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_fremovexattr_cbk, + subvol->fops->fremovexattr, fd, name, NULL); + + errno = args.op_errno; + return args.op_ret; +} + +int +syncop_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + + +int +syncop_setxattr (xlator_t *subvol, loc_t *loc, dict_t *dict, int32_t flags) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_setxattr_cbk, subvol->fops->setxattr, + loc, dict, flags, NULL); + + errno = args.op_errno; + return args.op_ret; +} + +int +syncop_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + + +int +syncop_fsetxattr (xlator_t *subvol, fd_t *fd, dict_t *dict, int32_t flags) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_fsetxattr_cbk, subvol->fops->fsetxattr, + fd, dict, flags, NULL); + + errno = args.op_errno; + return args.op_ret; +} + +int +syncop_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, dict_t *dict, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + if (op_ret >= 0) + args->xattr = dict_ref (dict); + + __wake (args); + + return 0; +} + +int +syncop_listxattr (xlator_t *subvol, loc_t *loc, dict_t **dict) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_getxattr_cbk, subvol->fops->getxattr, + loc, NULL, NULL); + + if (dict) + *dict = args.xattr; + else if (args.xattr) + dict_unref (args.xattr); + + errno = args.op_errno; + return args.op_ret; +} + +int +syncop_getxattr (xlator_t *subvol, loc_t *loc, dict_t **dict, const char *key) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_getxattr_cbk, subvol->fops->getxattr, + loc, key, NULL); + + if (dict) + *dict = args.xattr; + else if (args.xattr) + dict_unref (args.xattr); + + errno = args.op_errno; + return args.op_ret; +} + +int +syncop_fgetxattr (xlator_t *subvol, fd_t *fd, dict_t **dict, const char *key) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_getxattr_cbk, subvol->fops->fgetxattr, + fd, key, NULL); + + if (dict) + *dict = args.xattr; + else if (args.xattr) + dict_unref (args.xattr); + + errno = args.op_errno; + return args.op_ret; +} + +int +syncop_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + struct statvfs *buf, dict_t *xdata) + +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + if (op_ret == 0) { + args->statvfs_buf = *buf; + } + + __wake (args); + + return 0; +} + + +int +syncop_statfs (xlator_t *subvol, loc_t *loc, struct statvfs *buf) + +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_statfs_cbk, subvol->fops->statfs, + loc, NULL); + + if (buf) + *buf = args.statvfs_buf; + + errno = args.op_errno; + return args.op_ret; +} + +int +syncop_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, + struct iatt *preop, struct iatt *postop, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + if (op_ret == 0) { + args->iatt1 = *preop; + args->iatt2 = *postop; + } + + __wake (args); + + return 0; +} + + +int +syncop_setattr (xlator_t *subvol, loc_t *loc, struct iatt *iatt, int valid, + struct iatt *preop, struct iatt *postop) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_setattr_cbk, subvol->fops->setattr, + loc, iatt, valid, NULL); + + if (preop) + *preop = args.iatt1; + if (postop) + *postop = args.iatt2; + + errno = args.op_errno; + return args.op_ret; +} + + +int +syncop_fsetattr (xlator_t *subvol, fd_t *fd, struct iatt *iatt, int valid, + struct iatt *preop, struct iatt *postop) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_setattr_cbk, subvol->fops->fsetattr, + fd, iatt, valid, NULL); + + if (preop) + *preop = args.iatt1; + if (postop) + *postop = args.iatt2; + + errno = args.op_errno; + return args.op_ret; +} + + +int32_t +syncop_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + +int +syncop_open (xlator_t *subvol, loc_t *loc, int32_t flags, fd_t *fd) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_open_cbk, subvol->fops->open, + loc, flags, fd, NULL); + + errno = args.op_errno; + return args.op_ret; + +} + + +int32_t +syncop_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 iatt *stbuf, struct iobref *iobref, + dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + INIT_LIST_HEAD (&args->entries.list); + + args->op_ret = op_ret; + args->op_errno = op_errno; + + if (args->op_ret >= 0) { + if (iobref) + args->iobref = iobref_ref (iobref); + args->vector = iov_dup (vector, count); + args->count = count; + } + + __wake (args); + + return 0; + +} + +int +syncop_readv (xlator_t *subvol, fd_t *fd, size_t size, off_t off, + uint32_t flags, struct iovec **vector, int *count, + struct iobref **iobref) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_readv_cbk, subvol->fops->readv, + fd, size, off, flags, NULL); + + if (args.op_ret < 0) + goto out; + + if (vector) + *vector = args.vector; + else + GF_FREE (args.vector); + + if (count) + *count = args.count; + + /* Do we need a 'ref' here? */ + if (iobref) + *iobref = args.iobref; + else if (args.iobref) + iobref_unref (args.iobref); + +out: + errno = args.op_errno; + return args.op_ret; + +} + +int +syncop_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + +int +syncop_writev (xlator_t *subvol, fd_t *fd, const struct iovec *vector, + int32_t count, off_t offset, struct iobref *iobref, + uint32_t flags) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_writev_cbk, subvol->fops->writev, + fd, (struct iovec *) vector, count, offset, flags, iobref, + NULL); + + errno = args.op_errno; + return args.op_ret; +} + +int syncop_write (xlator_t *subvol, fd_t *fd, const char *buf, int size, + off_t offset, struct iobref *iobref, uint32_t flags) +{ + struct syncargs args = {0,}; + struct iovec vec = {0,}; + + vec.iov_len = size; + vec.iov_base = (void *)buf; + + SYNCOP (subvol, (&args), syncop_writev_cbk, subvol->fops->writev, + fd, &vec, 1, offset, flags, iobref, NULL); + + errno = args.op_errno; + return args.op_ret; +} + + +int +syncop_close (fd_t *fd) +{ + if (fd) + fd_unref (fd); + return 0; +} + +int32_t +syncop_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 iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + if (buf) + args->iatt1 = *buf; + + __wake (args); + + return 0; +} + +int +syncop_create (xlator_t *subvol, loc_t *loc, int32_t flags, mode_t mode, + fd_t *fd, dict_t *xdata, struct iatt *iatt) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_create_cbk, subvol->fops->create, + loc, flags, mode, 0, fd, xdata); + + errno = args.op_errno; + if (iatt) + *iatt = args.iatt1; + + return args.op_ret; + +} + +int +syncop_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + +int +syncop_unlink (xlator_t *subvol, loc_t *loc) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_unlink_cbk, subvol->fops->unlink, loc, + 0, NULL); + + errno = args.op_errno; + return args.op_ret; +} + +int +syncop_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + +int +syncop_rmdir (xlator_t *subvol, loc_t *loc) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_rmdir_cbk, subvol->fops->rmdir, loc, + 0, NULL); + + errno = args.op_errno; + return args.op_ret; +} + + +int +syncop_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + + +int +syncop_link (xlator_t *subvol, loc_t *oldloc, loc_t *newloc) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_link_cbk, subvol->fops->link, + oldloc, newloc, NULL); + + errno = args.op_errno; + + return args.op_ret; +} + + +int +syncop_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *buf, + struct iatt *preoldparent, struct iatt *postoldparent, + struct iatt *prenewparent, struct iatt *postnewparent, + dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + + +int +syncop_rename (xlator_t *subvol, loc_t *oldloc, loc_t *newloc) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_rename_cbk, subvol->fops->rename, + oldloc, newloc, NULL); + + errno = args.op_errno; + + return args.op_ret; +} + + +int +syncop_ftruncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + +int +syncop_ftruncate (xlator_t *subvol, fd_t *fd, off_t offset) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_ftruncate_cbk, subvol->fops->ftruncate, + fd, offset, NULL); + + errno = args.op_errno; + return args.op_ret; +} + +int +syncop_truncate (xlator_t *subvol, loc_t *loc, off_t offset) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_ftruncate_cbk, subvol->fops->truncate, + loc, offset, NULL); + + errno = args.op_errno; + return args.op_ret; +} + +int +syncop_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; + +} + +int +syncop_fsync (xlator_t *subvol, fd_t *fd, int dataonly) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_fsync_cbk, subvol->fops->fsync, + fd, dataonly, NULL); + + errno = args.op_errno; + return args.op_ret; + +} + + +int +syncop_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; + +} + +int +syncop_flush (xlator_t *subvol, fd_t *fd) +{ + struct syncargs args = {0}; + + SYNCOP (subvol, (&args), syncop_flush_cbk, subvol->fops->flush, + fd, NULL); + + errno = args.op_errno; + return args.op_ret; + +} + +int +syncop_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *stbuf, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + if (op_ret == 0) + args->iatt1 = *stbuf; + + __wake (args); + + return 0; + +} + +int +syncop_fstat (xlator_t *subvol, fd_t *fd, struct iatt *stbuf) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_fstat_cbk, subvol->fops->fstat, + fd, NULL); + + if (stbuf) + *stbuf = args.iatt1; + + errno = args.op_errno; + return args.op_ret; + +} + +int +syncop_stat (xlator_t *subvol, loc_t *loc, struct iatt *stbuf) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_fstat_cbk, subvol->fops->stat, + loc, NULL); + + if (stbuf) + *stbuf = args.iatt1; + + errno = args.op_errno; + return args.op_ret; + +} + +int32_t +syncop_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + if (buf) + args->iatt1 = *buf; + + __wake (args); + + return 0; +} + +int +syncop_symlink (xlator_t *subvol, loc_t *loc, const char *newpath, dict_t *dict, + struct iatt *iatt) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_symlink_cbk, subvol->fops->symlink, + newpath, loc, 0, dict); + + errno = args.op_errno; + if (iatt) + *iatt = args.iatt1; + + return args.op_ret; + +} + +int +syncop_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, const char *path, + struct iatt *stbuf, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + if ((op_ret != -1) && path) + args->buffer = gf_strdup (path); + + __wake (args); + + return 0; +} + +int +syncop_readlink (xlator_t *subvol, loc_t *loc, char **buffer, size_t size) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_readlink_cbk, subvol->fops->readlink, + loc, size, NULL); + + if (buffer) + *buffer = args.buffer; + else GF_FREE (args.buffer); + + errno = args.op_errno; + return args.op_ret; +} + +int +syncop_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + if (buf) + args->iatt1 = *buf; + + __wake (args); + + return 0; +} + +int +syncop_mknod (xlator_t *subvol, loc_t *loc, mode_t mode, dev_t rdev, + dict_t *dict, struct iatt *iatt) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_mknod_cbk, subvol->fops->mknod, + loc, mode, rdev, 0, dict); + + errno = args.op_errno; + if (iatt) + *iatt = args.iatt1; + + return args.op_ret; + +} + + +int +syncop_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + if (buf) + args->iatt1 = *buf; + + __wake (args); + + return 0; +} + + +int +syncop_mkdir (xlator_t *subvol, loc_t *loc, mode_t mode, dict_t *dict, + struct iatt *iatt) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_mkdir_cbk, subvol->fops->mkdir, + loc, mode, 0, dict); + + errno = args.op_errno; + if (iatt) + *iatt = args.iatt1; + + return args.op_ret; + +} + +int +syncop_access_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + __wake (args); + + return 0; +} + +int +syncop_access (xlator_t *subvol, loc_t *loc, int32_t mask) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_access_cbk, subvol->fops->access, + loc, mask, NULL); + + errno = args.op_errno; + return args.op_ret; +} + + +int +syncop_fallocate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + +int +syncop_fallocate(xlator_t *subvol, fd_t *fd, int32_t keep_size, off_t offset, + size_t len) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_fallocate_cbk, subvol->fops->fallocate, + fd, keep_size, offset, len, NULL); + + errno = args.op_errno; + return args.op_ret; +} + + +int +syncop_discard_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + +int +syncop_discard(xlator_t *subvol, fd_t *fd, off_t offset, size_t len) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_discard_cbk, subvol->fops->discard, + fd, offset, len, NULL); + + errno = args.op_errno; + return args.op_ret; +} + +int +syncop_zerofill_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + __wake (args); + + return 0; +} + +int +syncop_zerofill(xlator_t *subvol, fd_t *fd, off_t offset, size_t len) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_zerofill_cbk, subvol->fops->zerofill, + fd, offset, len, NULL); + + errno = args.op_errno; + return args.op_ret; +} + + +int +syncop_lk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, struct gf_flock *flock, + dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + if (flock) + args->flock = *flock; + __wake (args); + + return 0; +} + + +int +syncop_lk (xlator_t *subvol, fd_t *fd, int cmd, struct gf_flock *flock) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_lk_cbk, subvol->fops->lk, + fd, cmd, flock, NULL); + + errno = args.op_errno; + *flock = args.flock; + + return args.op_ret; +} diff --git a/libglusterfs/src/syncop.h b/libglusterfs/src/syncop.h new file mode 100644 index 000000000..f790981f0 --- /dev/null +++ b/libglusterfs/src/syncop.h @@ -0,0 +1,412 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _SYNCOP_H +#define _SYNCOP_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "xlator.h" +#include <sys/time.h> +#include <pthread.h> +#include <ucontext.h> + +#define SYNCENV_PROC_MAX 16 +#define SYNCENV_PROC_MIN 2 +#define SYNCPROC_IDLE_TIME 600 + +/* + * Flags for syncopctx valid elements + */ +#define SYNCOPCTX_UID 0x00000001 +#define SYNCOPCTX_GID 0x00000002 +#define SYNCOPCTX_GROUPS 0x00000004 + +struct synctask; +struct syncproc; +struct syncenv; + + +typedef int (*synctask_cbk_t) (int ret, call_frame_t *frame, void *opaque); + +typedef int (*synctask_fn_t) (void *opaque); + + +typedef enum { + SYNCTASK_INIT = 0, + SYNCTASK_RUN, + SYNCTASK_SUSPEND, + SYNCTASK_WAIT, + SYNCTASK_DONE, + SYNCTASK_ZOMBIE, +} synctask_state_t; + +/* for one sequential execution of @syncfn */ +struct synctask { + struct list_head all_tasks; + struct syncenv *env; + xlator_t *xl; + call_frame_t *frame; + call_frame_t *opframe; + synctask_cbk_t synccbk; + synctask_fn_t syncfn; + synctask_state_t state; + void *opaque; + void *stack; + int woken; + int slept; + int ret; + + uid_t uid; + gid_t gid; + + ucontext_t ctx; + struct syncproc *proc; + + pthread_mutex_t mutex; /* for synchronous spawning of synctask */ + pthread_cond_t cond; + int done; + + struct list_head waitq; /* can wait only "once" at a time */ +}; + + +struct syncproc { + pthread_t processor; + ucontext_t sched; + struct syncenv *env; + struct synctask *current; +}; + +/* hosts the scheduler thread and framework for executing synctasks */ +struct syncenv { + struct syncproc proc[SYNCENV_PROC_MAX]; + int procs; + + struct list_head runq; + int runcount; + struct list_head waitq; + int waitcount; + + int procmin; + int procmax; + + pthread_mutex_t mutex; + pthread_cond_t cond; + + size_t stacksize; +}; + + +struct synclock { + pthread_mutex_t guard; /* guard the remaining members, pair @cond */ + pthread_cond_t cond; /* waiting non-synctasks */ + struct list_head waitq; /* waiting synctasks */ + gf_boolean_t lock; /* _gf_true or _gf_false, lock status */ + struct synctask *owner; /* NULL if current owner is not a synctask */ +}; +typedef struct synclock synclock_t; + + +struct syncbarrier { + pthread_mutex_t guard; /* guard the remaining members, pair @cond */ + pthread_cond_t cond; /* waiting non-synctasks */ + struct list_head waitq; /* waiting synctasks */ + int count; /* count the number of wakes */ +}; +typedef struct syncbarrier syncbarrier_t; + + +struct syncargs { + int op_ret; + int op_errno; + struct iatt iatt1; + struct iatt iatt2; + dict_t *xattr; + gf_dirent_t entries; + struct statvfs statvfs_buf; + struct iovec *vector; + int count; + struct iobref *iobref; + char *buffer; + dict_t *xdata; + struct gf_flock flock; + + /* some more _cbk needs */ + uuid_t uuid; + char *errstr; + dict_t *dict; + pthread_mutex_t lock_dict; + + syncbarrier_t barrier; + + /* do not touch */ + struct synctask *task; + pthread_mutex_t mutex; + pthread_cond_t cond; + int done; +}; + +struct syncopctx { + unsigned int valid; /* valid flags for elements that are set */ + uid_t uid; + gid_t gid; + int grpsize; + int ngrps; + gid_t *groups; +}; + +#define __yawn(args) do { \ + args->task = synctask_get (); \ + if (args->task) \ + break; \ + pthread_mutex_init (&args->mutex, NULL); \ + pthread_cond_init (&args->cond, NULL); \ + args->done = 0; \ + } while (0) + + +#define __wake(args) do { \ + if (args->task) { \ + synctask_wake (args->task); \ + } else { \ + pthread_mutex_lock (&args->mutex); \ + { \ + args->done = 1; \ + pthread_cond_signal (&args->cond); \ + } \ + pthread_mutex_unlock (&args->mutex); \ + } \ + } while (0) + + +#define __yield(args) do { \ + if (args->task) { \ + synctask_yield (args->task); \ + } else { \ + pthread_mutex_lock (&args->mutex); \ + { \ + while (!args->done) \ + pthread_cond_wait (&args->cond, \ + &args->mutex); \ + } \ + pthread_mutex_unlock (&args->mutex); \ + pthread_mutex_destroy (&args->mutex); \ + pthread_cond_destroy (&args->cond); \ + } \ + } while (0) + + +#define SYNCOP(subvol, stb, cbk, op, params ...) do { \ + struct synctask *task = NULL; \ + call_frame_t *frame = NULL; \ + \ + task = synctask_get (); \ + stb->task = task; \ + if (task) \ + frame = task->opframe; \ + else \ + frame = syncop_create_frame (THIS); \ + \ + if (task) { \ + frame->root->uid = task->uid; \ + frame->root->gid = task->gid; \ + } \ + \ + __yawn (stb); \ + \ + STACK_WIND_COOKIE (frame, cbk, (void *)stb, subvol, \ + op, params); \ + \ + __yield (stb); \ + if (task) \ + STACK_RESET (frame->root); \ + else \ + STACK_DESTROY (frame->root); \ + } while (0) + + +#define SYNCENV_DEFAULT_STACKSIZE (2 * 1024 * 1024) + +struct syncenv * syncenv_new (size_t stacksize, int procmin, int procmax); +void syncenv_destroy (struct syncenv *); +void syncenv_scale (struct syncenv *env); + +int synctask_new (struct syncenv *, synctask_fn_t, synctask_cbk_t, call_frame_t* frame, void *); +struct synctask *synctask_create (struct syncenv *, synctask_fn_t, + synctask_cbk_t, call_frame_t *, void *); +int synctask_join (struct synctask *task); +void synctask_wake (struct synctask *task); +void synctask_yield (struct synctask *task); +void synctask_waitfor (struct synctask *task, int count); + +#define synctask_barrier_init(args) syncbarrier_init (&args->barrier) +#define synctask_barrier_wait(args, n) syncbarrier_wait (&args->barrier, n) +#define synctask_barrier_wake(args) syncbarrier_wake (&args->barrier) + +int synctask_setid (struct synctask *task, uid_t uid, gid_t gid); +#define SYNCTASK_SETID(uid, gid) synctask_setid (synctask_get(), uid, gid); + +int syncopctx_setfsuid (void *uid); +int syncopctx_setfsgid (void *gid); +int syncopctx_setfsgroups (int count, const void *groups); + +static inline call_frame_t * +syncop_create_frame (xlator_t *this) +{ + call_frame_t *frame = NULL; + int ngrps = -1; + struct syncopctx *opctx = NULL; + + frame = create_frame (this, this->ctx->pool); + if (!frame) + return NULL; + + frame->root->pid = getpid (); + + opctx = syncopctx_getctx (); + if (opctx && (opctx->valid & SYNCOPCTX_UID)) + frame->root->uid = opctx->uid; + else + frame->root->uid = geteuid (); + + if (opctx && (opctx->valid & SYNCOPCTX_GID)) + frame->root->gid = opctx->gid; + else + frame->root->gid = getegid (); + + if (opctx && (opctx->valid & SYNCOPCTX_GROUPS)) { + ngrps = opctx->ngrps; + + if (ngrps != 0 && opctx->groups != NULL) { + if (call_stack_alloc_groups (frame->root, ngrps) != 0) { + STACK_DESTROY (frame->root); + return NULL; + } + + memcpy (frame->root->groups, opctx->groups, + (sizeof (gid_t) * ngrps)); + } + } + else { + ngrps = getgroups (0, 0); + if (ngrps < 0) { + STACK_DESTROY (frame->root); + return NULL; + } + + if (call_stack_alloc_groups (frame->root, ngrps) != 0) { + STACK_DESTROY (frame->root); + return NULL; + } + + if (getgroups (ngrps, frame->root->groups) < 0) { + STACK_DESTROY (frame->root); + return NULL; + } + } + + return frame; +} + +int synclock_init (synclock_t *lock); +int synclock_destory (synclock_t *lock); +int synclock_lock (synclock_t *lock); +int synclock_trylock (synclock_t *lock); +int synclock_unlock (synclock_t *lock); + + +int syncbarrier_init (syncbarrier_t *barrier); +int syncbarrier_wait (syncbarrier_t *barrier, int waitfor); +int syncbarrier_wake (syncbarrier_t *barrier); +int syncbarrier_destroy (syncbarrier_t *barrier); + +int syncop_lookup (xlator_t *subvol, loc_t *loc, dict_t *xattr_req, + /* out */ + struct iatt *iatt, dict_t **xattr_rsp, struct iatt *parent); + +int syncop_readdirp (xlator_t *subvol, fd_t *fd, size_t size, off_t off, + dict_t *dict, + /* out */ + gf_dirent_t *entries); + +int syncop_readdir (xlator_t *subvol, fd_t *fd, size_t size, off_t off, + gf_dirent_t *entries); + +int syncop_opendir (xlator_t *subvol, loc_t *loc, fd_t *fd); + +int syncop_setattr (xlator_t *subvol, loc_t *loc, struct iatt *iatt, int valid, + /* out */ + struct iatt *preop, struct iatt *postop); + +int syncop_fsetattr (xlator_t *subvol, fd_t *fd, struct iatt *iatt, int valid, + /* out */ + struct iatt *preop, struct iatt *postop); + +int syncop_statfs (xlator_t *subvol, loc_t *loc, struct statvfs *buf); + +int syncop_setxattr (xlator_t *subvol, loc_t *loc, dict_t *dict, int32_t flags); +int syncop_fsetxattr (xlator_t *subvol, fd_t *fd, dict_t *dict, int32_t flags); +int syncop_listxattr (xlator_t *subvol, loc_t *loc, dict_t **dict); +int syncop_getxattr (xlator_t *xl, loc_t *loc, dict_t **dict, const char *key); +int syncop_fgetxattr (xlator_t *xl, fd_t *fd, dict_t **dict, const char *key); +int syncop_removexattr (xlator_t *subvol, loc_t *loc, const char *name); +int syncop_fremovexattr (xlator_t *subvol, fd_t *fd, const char *name); + +int syncop_create (xlator_t *subvol, loc_t *loc, int32_t flags, mode_t mode, + fd_t *fd, dict_t *dict, struct iatt *iatt); +int syncop_open (xlator_t *subvol, loc_t *loc, int32_t flags, fd_t *fd); +int syncop_close (fd_t *fd); + +int syncop_write (xlator_t *subvol, fd_t *fd, const char *buf, int size, + off_t offset, struct iobref *iobref, uint32_t flags); +int syncop_writev (xlator_t *subvol, fd_t *fd, const struct iovec *vector, + int32_t count, off_t offset, struct iobref *iobref, + uint32_t flags); +int syncop_readv (xlator_t *subvol, fd_t *fd, size_t size, off_t off, + uint32_t flags, + /* out */ + struct iovec **vector, int *count, struct iobref **iobref); + +int syncop_ftruncate (xlator_t *subvol, fd_t *fd, off_t offset); +int syncop_truncate (xlator_t *subvol, loc_t *loc, off_t offset); + +int syncop_unlink (xlator_t *subvol, loc_t *loc); +int syncop_rmdir (xlator_t *subvol, loc_t *loc); + +int syncop_fsync (xlator_t *subvol, fd_t *fd, int dataonly); +int syncop_flush (xlator_t *subvol, fd_t *fd); +int syncop_fstat (xlator_t *subvol, fd_t *fd, struct iatt *stbuf); +int syncop_stat (xlator_t *subvol, loc_t *loc, struct iatt *stbuf); + +int syncop_symlink (xlator_t *subvol, loc_t *loc, const char *newpath, + dict_t *dict, struct iatt *iatt); +int syncop_readlink (xlator_t *subvol, loc_t *loc, char **buffer, size_t size); +int syncop_mknod (xlator_t *subvol, loc_t *loc, mode_t mode, dev_t rdev, + dict_t *dict, struct iatt *iatt); +int syncop_mkdir (xlator_t *subvol, loc_t *loc, mode_t mode, dict_t *dict, + struct iatt *iatt); +int syncop_link (xlator_t *subvol, loc_t *oldloc, loc_t *newloc); +int syncop_fsyncdir (xlator_t *subvol, fd_t *fd, int datasync); +int syncop_access (xlator_t *subvol, loc_t *loc, int32_t mask); +int syncop_fallocate(xlator_t *subvol, fd_t *fd, int32_t keep_size, off_t offset, + size_t len); +int syncop_discard(xlator_t *subvol, fd_t *fd, off_t offset, size_t len); + +int syncop_zerofill(xlator_t *subvol, fd_t *fd, off_t offset, size_t len); + +int syncop_rename (xlator_t *subvol, loc_t *oldloc, loc_t *newloc); + +int syncop_lk (xlator_t *subvol, fd_t *fd, int cmd, struct gf_flock *flock); + +#endif /* _SYNCOP_H */ diff --git a/libglusterfs/src/syscall.c b/libglusterfs/src/syscall.c index d350710e2..e8954cc23 100644 --- a/libglusterfs/src/syscall.c +++ b/libglusterfs/src/syscall.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -43,7 +34,7 @@ sys_stat (const char *path, struct stat *buf) } -int +int sys_fstat (int fd, struct stat *buf) { return fstat (fd, buf); @@ -64,14 +55,14 @@ sys_readdir (DIR *dir) } -ssize_t +ssize_t sys_readlink (const char *path, char *buf, size_t bufsiz) { return readlink (path, buf, bufsiz); } -int +int sys_closedir (DIR *dir) { return closedir (dir); @@ -85,28 +76,31 @@ sys_mknod (const char *pathname, mode_t mode, dev_t dev) } -int +int sys_mkdir (const char *pathname, mode_t mode) { return mkdir (pathname, mode); } -int +int sys_unlink (const char *pathname) { +#ifdef GF_SOLARIS_HOST_OS + return solaris_unlink (pathname); +#endif return unlink (pathname); } -int +int sys_rmdir (const char *pathname) { return rmdir (pathname); } -int +int sys_symlink (const char *oldpath, const char *newpath) { return symlink (oldpath, newpath); @@ -116,11 +110,14 @@ sys_symlink (const char *oldpath, const char *newpath) int sys_rename (const char *oldpath, const char *newpath) { +#ifdef GF_SOLARIS_HOST_OS + return solaris_rename (oldpath, newpath); +#endif return rename (oldpath, newpath); } -int +int sys_link (const char *oldpath, const char *newpath) { return link (oldpath, newpath); @@ -141,7 +138,7 @@ sys_fchmod (int fd, mode_t mode) } -int +int sys_chown (const char *path, uid_t owner, gid_t group) { return chown (path, owner, group); @@ -162,21 +159,21 @@ sys_lchown (const char *path, uid_t owner, gid_t group) } -int +int sys_truncate (const char *path, off_t length) { return truncate (path, length); } -int +int sys_ftruncate (int fd, off_t length) { return ftruncate (fd, length); } -int +int sys_utimes (const char *filename, const struct timeval times[2]) { return utimes (filename, times); @@ -211,7 +208,7 @@ sys_read (int fd, void *buf, size_t count) } -ssize_t +ssize_t sys_write (int fd, const void *buf, size_t count) { return write (fd, buf, count); @@ -232,21 +229,26 @@ sys_statvfs (const char *path, struct statvfs *buf) } -int +int sys_close (int fd) { - return close (fd); + int ret = -1; + + if (fd >= 0) + ret = close (fd); + + return ret; } -int +int sys_fsync (int fd) { return fsync (fd); } -int +int sys_fdatasync (int fd) { #ifdef HAVE_FDATASYNC @@ -257,44 +259,44 @@ sys_fdatasync (int fd) } -int -sys_lsetxattr (const char *path, const char *name, const void *value, - size_t size, int flags) +int +sys_lsetxattr (const char *path, const char *name, const void *value, + size_t size, int flags) { - -#ifdef GF_LINUX_HOST_OS + +#if defined(GF_LINUX_HOST_OS) || defined(__NetBSD__) return lsetxattr (path, name, value, size, flags); #endif #ifdef GF_BSD_HOST_OS - return extattr_set_link (path, EXTATTR_NAMESPACE_USER, + return extattr_set_link (path, EXTATTR_NAMESPACE_USER, name, value, size); #endif - + #ifdef GF_SOLARIS_HOST_OS return solaris_setxattr (path, name, value, size, flags); #endif #ifdef GF_DARWIN_HOST_OS - return setxattr (path, name, value, size, 0, + return setxattr (path, name, value, size, 0, flags|XATTR_NOFOLLOW); #endif - + } ssize_t -sys_llistxattr (const char *path, char *list, size_t size) +sys_llistxattr (const char *path, char *list, size_t size) { - -#ifdef GF_LINUX_HOST_OS + +#if defined(GF_LINUX_HOST_OS) || defined(__NetBSD__) return llistxattr (path, list, size); #endif #ifdef GF_BSD_HOST_OS return extattr_list_link (path, EXTATTR_NAMESPACE_USER, list, size); #endif - + #ifdef GF_SOLARIS_HOST_OS return solaris_listxattr (path, list, size); #endif @@ -302,23 +304,23 @@ sys_llistxattr (const char *path, char *list, size_t size) #ifdef GF_DARWIN_HOST_OS return listxattr (path, list, size, XATTR_NOFOLLOW); #endif - + } ssize_t -sys_lgetxattr (const char *path, const char *name, void *value, size_t size) +sys_lgetxattr (const char *path, const char *name, void *value, size_t size) { - -#ifdef GF_LINUX_HOST_OS + +#if defined(GF_LINUX_HOST_OS) || defined(__NetBSD__) return lgetxattr (path, name, value, size); #endif #ifdef GF_BSD_HOST_OS - return extattr_get_link (path, EXTATTR_NAMESPACE_USER, name, value, + return extattr_get_link (path, EXTATTR_NAMESPACE_USER, name, value, size); #endif - + #ifdef GF_SOLARIS_HOST_OS return solaris_getxattr (path, name, value, size); #endif @@ -330,19 +332,19 @@ sys_lgetxattr (const char *path, const char *name, void *value, size_t size) } -ssize_t -sys_fgetxattr (int filedes, const char *name, void *value, size_t size) +ssize_t +sys_fgetxattr (int filedes, const char *name, void *value, size_t size) { - -#ifdef GF_LINUX_HOST_OS + +#if defined(GF_LINUX_HOST_OS) || defined(__NetBSD__) return fgetxattr (filedes, name, value, size); #endif #ifdef GF_BSD_HOST_OS - return extattr_get_fd (filedes, EXTATTR_NAMESPACE_USER, name, + return extattr_get_fd (filedes, EXTATTR_NAMESPACE_USER, name, value, size); #endif - + #ifdef GF_SOLARIS_HOST_OS return solaris_fgetxattr (filedes, name, value, size); #endif @@ -354,20 +356,46 @@ sys_fgetxattr (int filedes, const char *name, void *value, size_t size) } -int -sys_fsetxattr (int filedes, const char *name, const void *value, +int +sys_fremovexattr (int filedes, const char *name) +{ + +#if defined(GF_LINUX_HOST_OS) || defined(__NetBSD__) + return fremovexattr (filedes, name); +#endif + + errno = ENOSYS; + return -1; +#if 0 /* TODO: to port to other OSes, fill in each of below */ +#ifdef GF_BSD_HOST_OS + return extattr_remove_fd (filedes, EXTATTR_NAMESPACE_USER, name); +#endif + +#ifdef GF_SOLARIS_HOST_OS + return solaris_fremovexattr (filedes, name); +#endif + +#ifdef GF_DARWIN_HOST_OS + return fremovexattr (filedes, name, 0); +#endif +#endif +} + + +int +sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags) { -#ifdef GF_LINUX_HOST_OS +#if defined(GF_LINUX_HOST_OS) || defined(__NetBSD__) return fsetxattr (filedes, name, value, size, flags); #endif #ifdef GF_BSD_HOST_OS - return extattr_set_fd (filedes, EXTATTR_NAMESPACE_USER, name, + return extattr_set_fd (filedes, EXTATTR_NAMESPACE_USER, name, value, size); #endif - + #ifdef GF_SOLARIS_HOST_OS return solaris_fsetxattr (filedes, name, value, size, flags); #endif @@ -379,11 +407,11 @@ sys_fsetxattr (int filedes, const char *name, const void *value, } -ssize_t -sys_flistxattr (int filedes, char *list, size_t size) +ssize_t +sys_flistxattr (int filedes, char *list, size_t size) { - -#ifdef GF_LINUX_HOST_OS + +#if defined(GF_LINUX_HOST_OS) || defined(__NetBSD__) return flistxattr (filedes, list, size); #endif @@ -402,18 +430,18 @@ sys_flistxattr (int filedes, char *list, size_t size) } -int +int sys_lremovexattr (const char *path, const char *name) { - -#ifdef GF_LINUX_HOST_OS + +#if defined(GF_LINUX_HOST_OS) || defined(__NetBSD__) return lremovexattr (path, name); #endif #ifdef GF_BSD_HOST_OS return extattr_delete_link (path, EXTATTR_NAMESPACE_USER, name); #endif - + #ifdef GF_SOLARIS_HOST_OS return solaris_removexattr (path, name); #endif @@ -425,8 +453,31 @@ sys_lremovexattr (const char *path, const char *name) } -int +int sys_access (const char *pathname, int mode) { return access (pathname, mode); } + + +int +sys_fallocate(int fd, int mode, off_t offset, off_t len) +{ +#ifdef HAVE_FALLOCATE + return fallocate(fd, mode, offset, len); +#endif + +#ifdef HAVE_POSIX_FALLOCATE + if (mode) { + /* keep size not supported */ + errno = EOPNOTSUPP; + return -1; + } + + return posix_fallocate(fd, offset, len); +#endif + + errno = ENOSYS; + return -1; +} + diff --git a/libglusterfs/src/syscall.h b/libglusterfs/src/syscall.h index d9cbb8fd4..f1c9f58c3 100644 --- a/libglusterfs/src/syscall.h +++ b/libglusterfs/src/syscall.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef __SYSCALL_H__ @@ -26,7 +17,7 @@ sys_lstat (const char *path, struct stat *buf); int sys_stat (const char *path, struct stat *buf); -int +int sys_fstat (int fd, struct stat *buf); DIR * @@ -35,31 +26,31 @@ sys_opendir (const char *name); struct dirent * sys_readdir (DIR *dir); -ssize_t +ssize_t sys_readlink (const char *path, char *buf, size_t bufsiz); -int +int sys_closedir (DIR *dir); int sys_mknod (const char *pathname, mode_t mode, dev_t dev); -int +int sys_mkdir (const char *pathname, mode_t mode); -int +int sys_unlink (const char *pathname); -int +int sys_rmdir (const char *pathname); -int +int sys_symlink (const char *oldpath, const char *newpath); int sys_rename (const char *oldpath, const char *newpath); -int +int sys_link (const char *oldpath, const char *newpath); int @@ -68,7 +59,7 @@ sys_chmod (const char *path, mode_t mode); int sys_fchmod (int fd, mode_t mode); -int +int sys_chown (const char *path, uid_t owner, gid_t group); int @@ -77,13 +68,13 @@ sys_fchown (int fd, uid_t owner, gid_t group); int sys_lchown (const char *path, uid_t owner, gid_t group); -int +int sys_truncate (const char *path, off_t length); -int +int sys_ftruncate (int fd, off_t length); -int +int sys_utimes (const char *filename, const struct timeval times[2]); int @@ -98,7 +89,7 @@ sys_writev (int fd, const struct iovec *iov, int iovcnt); ssize_t sys_read (int fd, void *buf, size_t count); -ssize_t +ssize_t sys_write (int fd, const void *buf, size_t count); off_t @@ -107,42 +98,47 @@ sys_lseek (int fd, off_t offset, int whence); int sys_statvfs (const char *path, struct statvfs *buf); -int +int sys_close (int fd); -int +int sys_fsync (int fd); -int +int sys_fdatasync (int fd); -int -sys_lsetxattr (const char *path, const char *name, const void *value, - size_t size, int flags); +int +sys_lsetxattr (const char *path, const char *name, const void *value, + size_t size, int flags); ssize_t -sys_llistxattr (const char *path, char *list, size_t size); +sys_llistxattr (const char *path, char *list, size_t size); ssize_t -sys_lgetxattr (const char *path, const char *name, void *value, size_t size); +sys_lgetxattr (const char *path, const char *name, void *value, size_t size); -ssize_t -sys_fgetxattr (int filedes, const char *name, void *value, size_t size); +ssize_t +sys_fgetxattr (int filedes, const char *name, void *value, size_t size); -int -sys_fsetxattr (int filedes, const char *name, const void *value, +int +sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags); -ssize_t -sys_flistxattr (int filedes, char *list, size_t size); +ssize_t +sys_flistxattr (int filedes, char *list, size_t size); -int +int sys_lremovexattr (const char *path, const char *name); -int +int +sys_fremovexattr (int filedes, const char *name); + +int sys_access (const char *pathname, int mode); -int +int sys_ftruncate (int fd, off_t length); +int sys_fallocate(int fd, int mode, off_t offset, off_t len); + #endif /* __SYSCALL_H__ */ diff --git a/libglusterfs/src/timer.c b/libglusterfs/src/timer.c index a84fa8cdf..a059cc212 100644 --- a/libglusterfs/src/timer.c +++ b/libglusterfs/src/timer.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-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/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -25,45 +16,43 @@ #include "timer.h" #include "logging.h" #include "common-utils.h" - -#define TS(tv) ((((unsigned long long) tv.tv_sec) * 1000000) + (tv.tv_usec)) +#include "globals.h" +#include "timespec.h" gf_timer_t * gf_timer_call_after (glusterfs_ctx_t *ctx, - struct timeval delta, - gf_timer_cbk_t cbk, + struct timespec delta, + gf_timer_cbk_t callbk, void *data) { gf_timer_registry_t *reg = NULL; gf_timer_t *event = NULL; gf_timer_t *trav = NULL; - unsigned long long at = 0L; - + uint64_t at = 0; + if (ctx == NULL) { - gf_log ("timer", GF_LOG_ERROR, "invalid argument"); + gf_log_callingfn ("timer", GF_LOG_ERROR, "invalid argument"); return NULL; } reg = gf_timer_registry_init (ctx); if (!reg) { - gf_log ("timer", GF_LOG_ERROR, "!reg"); + gf_log_callingfn ("timer", GF_LOG_ERROR, "!reg"); return NULL; } - event = CALLOC (1, sizeof (*event)); + event = GF_CALLOC (1, sizeof (*event), gf_common_mt_gf_timer_t); 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; + timespec_now (&event->at); + timespec_adjust_delta (&event->at, delta); at = TS (event->at); - event->cbk = cbk; + event->callbk = callbk; event->data = data; + event->xl = THIS; pthread_mutex_lock (®->lock); { trav = reg->active.prev; @@ -87,10 +76,10 @@ gf_timer_call_stale (gf_timer_registry_t *reg, { if (reg == NULL || event == NULL) { - gf_log ("timer", GF_LOG_ERROR, "invalid argument"); + gf_log_callingfn ("timer", GF_LOG_ERROR, "invalid argument"); return 0; } - + event->next->prev = event->prev; event->prev->next = event->next; event->next = ®->stale; @@ -106,16 +95,17 @@ 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"); + gf_log_callingfn ("timer", GF_LOG_ERROR, "invalid argument"); return 0; } - + reg = gf_timer_registry_init (ctx); if (!reg) { gf_log ("timer", GF_LOG_ERROR, "!reg"); + GF_FREE (event); return 0; } @@ -126,7 +116,7 @@ gf_timer_call_cancel (glusterfs_ctx_t *ctx, } pthread_mutex_unlock (®->lock); - FREE (event); + GF_FREE (event); return 0; } @@ -134,13 +124,14 @@ void * gf_timer_proc (void *ctx) { gf_timer_registry_t *reg = NULL; - + const struct timespec sleepts = {.tv_sec = 1, .tv_nsec = 0, }; + if (ctx == NULL) { - gf_log ("timer", GF_LOG_ERROR, "invalid argument"); + gf_log_callingfn ("timer", GF_LOG_ERROR, "invalid argument"); return NULL; } - + reg = gf_timer_registry_init (ctx); if (!reg) { gf_log ("timer", GF_LOG_ERROR, "!reg"); @@ -148,14 +139,14 @@ gf_timer_proc (void *ctx) } while (!reg->fin) { - unsigned long long now; - struct timeval now_tv; + uint64_t now; + struct timespec now_ts; gf_timer_t *event = NULL; - gettimeofday (&now_tv, NULL); - now = TS (now_tv); + timespec_now (&now_ts); + now = TS (now_ts); while (1) { - unsigned long long at; + uint64_t at; char need_cbk = 0; pthread_mutex_lock (®->lock); @@ -168,13 +159,15 @@ gf_timer_proc (void *ctx) } } pthread_mutex_unlock (®->lock); + if (event->xl) + THIS = event->xl; if (need_cbk) - event->cbk (event->data); + event->callbk (event->data); else break; } - usleep (1000000); + nanosleep (&sleepts, NULL); } pthread_mutex_lock (®->lock); @@ -189,7 +182,7 @@ gf_timer_proc (void *ctx) } pthread_mutex_unlock (®->lock); pthread_mutex_destroy (®->lock); - FREE (((glusterfs_ctx_t *)ctx)->timer); + GF_FREE (((glusterfs_ctx_t *)ctx)->timer); return NULL; } @@ -197,24 +190,28 @@ gf_timer_proc (void *ctx) gf_timer_registry_t * gf_timer_registry_init (glusterfs_ctx_t *ctx) { - if (ctx == NULL) - { - gf_log ("timer", GF_LOG_ERROR, "invalid argument"); + if (ctx == NULL) { + gf_log_callingfn ("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); + reg = GF_CALLOC (1, sizeof (*reg), + gf_common_mt_gf_timer_registry_t); + if (!reg) + goto out; + 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); + ctx->timer = reg; + gf_thread_create (®->th, NULL, gf_timer_proc, ctx); } +out: return ctx->timer; } diff --git a/libglusterfs/src/timer.h b/libglusterfs/src/timer.h index 4a8cdff21..2f963adbf 100644 --- a/libglusterfs/src/timer.h +++ b/libglusterfs/src/timer.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2009 Z RESEARCH, Inc. <http://www.zresearch.com> - This file is part of GlusterFS. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _TIMER_H @@ -26,24 +17,26 @@ #endif #include "glusterfs.h" +#include "xlator.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 *next, *prev; + struct timespec at; + gf_timer_cbk_t callbk; + void *data; + xlator_t *xl; }; struct _gf_timer_registry { - pthread_t th; - char fin; - struct _gf_timer stale; - struct _gf_timer active; - pthread_mutex_t lock; + pthread_t th; + char fin; + struct _gf_timer stale; + struct _gf_timer active; + pthread_mutex_t lock; }; typedef struct _gf_timer gf_timer_t; @@ -51,13 +44,13 @@ 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); + struct timespec delta, + gf_timer_cbk_t cbk, + void *data); int32_t gf_timer_call_cancel (glusterfs_ctx_t *ctx, - gf_timer_t *event); + gf_timer_t *event); void * gf_timer_proc (void *data); diff --git a/libglusterfs/src/timespec.c b/libglusterfs/src/timespec.c new file mode 100644 index 000000000..a0c281a1e --- /dev/null +++ b/libglusterfs/src/timespec.c @@ -0,0 +1,68 @@ +/* + Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include <stdio.h> +#include <inttypes.h> +#if defined GF_LINUX_HOST_OS || defined GF_SOLARIS_HOST_OS || defined GF_BSD_HOST_OS +#include <time.h> +#include <sys/time.h> +#endif + +#if defined GF_DARWIN_HOST_OS +#include <mach/mach_time.h> +#endif + +#include "logging.h" +#include "time.h" + + +void tv2ts (struct timeval tv, struct timespec *ts) +{ + ts->tv_sec = tv.tv_sec; + ts->tv_nsec = tv.tv_usec * 1000; +} + +void timespec_now (struct timespec *ts) +{ +#if defined GF_LINUX_HOST_OS || defined GF_SOLARIS_HOST_OS || defined GF_BSD_HOST_OS + + if (0 == clock_gettime(CLOCK_MONOTONIC, ts)) + return; + else { + struct timeval tv; + if (0 == gettimeofday(&tv, NULL)) + tv2ts(tv, ts); + } +#elif defined GF_DARWIN_HOST_OS + mach_timebase_info_data_t tb = { 0 }; + static double timebase = 0.0; + uint64_t time = 0; + mach_timebase_info (&tb); + + timebase *= info.numer; + timebase /= info.denom; + + time = mach_absolute_time(); + time *= timebase; + + ts->tv_sec = (time * NANO); + ts->tv_nsec = (time - (ts.tv_sec * GIGA)); + +#endif /* Platform verification */ + gf_log_callingfn ("timer", GF_LOG_DEBUG, "%"PRIu64".%09"PRIu64, + ts->tv_sec, ts->tv_nsec); +} + +void timespec_adjust_delta (struct timespec *ts, struct timespec delta) +{ + ts->tv_nsec = ((ts->tv_nsec + delta.tv_nsec) % 1000000000); + ts->tv_sec += ((ts->tv_nsec + delta.tv_nsec) / 1000000000); + ts->tv_sec += delta.tv_sec; +} diff --git a/libglusterfs/src/timespec.h b/libglusterfs/src/timespec.h new file mode 100644 index 000000000..490255df9 --- /dev/null +++ b/libglusterfs/src/timespec.h @@ -0,0 +1,24 @@ +/* + Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef __INCLUDE_TIMESPEC_H__ +#define __INCLUDE_TIMESPEC_H__ + +#include <stdint.h> + +#define TS(ts) ((ts.tv_sec * 1000000000LL) + ts.tv_nsec) +#define NANO (+1.0E-9) +#define GIGA UINT64_C(1000000000) + +void tv2ts (struct timeval tv, struct timespec *ts); +void timespec_now (struct timespec *ts); +void timespec_adjust_delta (struct timespec *ts, struct timespec delta); + +#endif /* __INCLUDE_TIMESPEC_H__ */ diff --git a/libglusterfs/src/transport.c b/libglusterfs/src/transport.c deleted file mode 100644 index 7464ffd66..000000000 --- a/libglusterfs/src/transport.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - Copyright (c) 2006-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 <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; - } - - ret = asprintf (&name, "%s/%s.so", TRANSPORTDIR, type); - if (-1 == ret) { - gf_log ("transport", GF_LOG_ERROR, "asprintf failed"); - goto fail; - } - 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, - struct iobref *iobref) -{ - int32_t ret = -1; - transport_t *peer_trans = NULL; - struct iobuf *iobuf = NULL; - struct transport_msg *msg = NULL; - - if (this->peer_trans) { - peer_trans = this->peer_trans; - - msg = CALLOC (1, sizeof (*msg)); - if (!msg) { - return -ENOMEM; - } - - msg->hdr = buf; - msg->hdrlen = len; - - if (vector) { - iobuf = iobuf_get (this->xl->ctx->iobuf_pool); - if (!iobuf) { - FREE (msg->hdr); - FREE (msg); - return -ENOMEM; - } - - iov_unload (iobuf->ptr, vector, count); - msg->iobuf = iobuf; - } - - pthread_mutex_lock (&peer_trans->handover.mutex); - { - list_add_tail (&msg->list, &peer_trans->handover.msgs); - pthread_cond_broadcast (&peer_trans->handover.cond); - } - pthread_mutex_unlock (&peer_trans->handover.mutex); - - return 0; - } - - GF_VALIDATE_OR_GOTO("transport", this, fail); - GF_VALIDATE_OR_GOTO("transport", this->ops, fail); - - ret = this->ops->submit (this, buf, len, vector, count, iobref); -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, - struct iobuf **iobuf_p) -{ - int32_t ret = -1; - - GF_VALIDATE_OR_GOTO("transport", this, fail); - - if (this->peer_trans) { - *hdr_p = this->handover.msg->hdr; - *hdrlen_p = this->handover.msg->hdrlen; - *iobuf_p = this->handover.msg->iobuf; - - return 0; - } - - ret = this->ops->receive (this, hdr_p, hdrlen_p, iobuf_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; -} - - -void * -transport_peerproc (void *trans_data) -{ - transport_t *trans = NULL; - struct transport_msg *msg = NULL; - - trans = trans_data; - - while (1) { - pthread_mutex_lock (&trans->handover.mutex); - { - while (list_empty (&trans->handover.msgs)) - pthread_cond_wait (&trans->handover.cond, - &trans->handover.mutex); - - msg = list_entry (trans->handover.msgs.next, - struct transport_msg, list); - - list_del_init (&msg->list); - } - pthread_mutex_unlock (&trans->handover.mutex); - - trans->handover.msg = msg; - - trans->xl->notify (trans->xl, GF_EVENT_POLLIN, trans); - - FREE (msg); - } -} - - -int -transport_setpeer (transport_t *trans, transport_t *peer_trans) -{ - trans->peer_trans = peer_trans; - - INIT_LIST_HEAD (&trans->handover.msgs); - pthread_cond_init (&trans->handover.cond, NULL); - pthread_mutex_init (&trans->handover.mutex, NULL); - pthread_create (&trans->handover.thread, NULL, - transport_peerproc, trans); - - peer_trans->peer_trans = trans; - - INIT_LIST_HEAD (&peer_trans->handover.msgs); - pthread_cond_init (&peer_trans->handover.cond, NULL); - pthread_mutex_init (&peer_trans->handover.mutex, NULL); - pthread_create (&peer_trans->handover.thread, NULL, - transport_peerproc, peer_trans); - - return 0; -} diff --git a/libglusterfs/src/transport.h b/libglusterfs/src/transport.h deleted file mode 100644 index 2d85c76cc..000000000 --- a/libglusterfs/src/transport.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - Copyright (c) 2006-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 __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_msg { - struct list_head list; - char *hdr; - int hdrlen; - struct iobuf *iobuf; -}; - -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; - - transport_t *peer_trans; - struct { - pthread_mutex_t mutex; - pthread_cond_t cond; - pthread_t thread; - struct list_head msgs; - struct transport_msg *msg; - } handover; - -}; - -struct transport_ops { - int32_t (*receive) (transport_t *this, char **hdr_p, size_t *hdrlen_p, - struct iobuf **iobuf_p); - int32_t (*submit) (transport_t *this, char *buf, int len, - struct iovec *vector, int count, - struct iobref *iobref); - 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, - struct iobref *iobref); -int32_t transport_receive (transport_t *this, char **hdr_p, size_t *hdrlen_p, - struct iobuf **iobuf_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); - -int transport_setpeer (transport_t *trans, transport_t *trans_peer); - -#endif /* __TRANSPORT_H__ */ diff --git a/libglusterfs/src/trie.c b/libglusterfs/src/trie.c new file mode 100644 index 000000000..f96bbebf6 --- /dev/null +++ b/libglusterfs/src/trie.c @@ -0,0 +1,387 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> + +#include "common-utils.h" +#include "trie.h" + +#define DISTANCE_EDIT 1 +#define DISTANCE_INS 1 +#define DISTANCE_DEL 1 + + +struct trienode { + char id; + char eow; + int depth; + void *data; + struct trie *trie; + struct trienode *parent; + struct trienode *subnodes[255]; +}; + +struct trie { + struct trienode root; + int nodecnt; + size_t len; +}; + + +trie_t * +trie_new () +{ + trie_t *trie = NULL; + + trie = GF_CALLOC (1, sizeof (*trie), gf_common_mt_trie_trie); + if (!trie) + return NULL; + + trie->root.trie = trie; + + return trie; +} + + +static trienode_t * +trie_subnode (trienode_t *node, int id) +{ + trienode_t *subnode = NULL; + + subnode = node->subnodes[id]; + if (!subnode) { + subnode = GF_CALLOC (1, sizeof (*subnode), + gf_common_mt_trie_node); + if (!subnode) + return NULL; + + subnode->id = id; + subnode->depth = node->depth + 1; + node->subnodes[id] = subnode; + subnode->parent = node; + subnode->trie = node->trie; + node->trie->nodecnt++; + } + + return subnode; +} + + +int +trie_add (trie_t *trie, const char *dword) +{ + trienode_t *node = NULL; + int i = 0; + char id = 0; + trienode_t *subnode = NULL; + + node = &trie->root; + + for (i = 0; i < strlen (dword); i++) { + id = dword[i]; + + subnode = trie_subnode (node, id); + if (!subnode) + return -1; + node = subnode; + } + + node->eow = 1; + + return 0; +} + +static void +trienode_free (trienode_t *node) +{ + trienode_t *trav = NULL; + int i = 0; + + for (i = 0; i < 255; i++) { + trav = node->subnodes[i]; + + if (trav) + trienode_free (trav); + } + + GF_FREE (node->data); + GF_FREE (node); +} + + +void +trie_destroy (trie_t *trie) +{ + trienode_free ((trienode_t *)trie); +} + + +void +trie_destroy_bynode (trienode_t *node) +{ + trie_destroy (node->trie); +} + + +static int +trienode_walk (trienode_t *node, int (*fn)(trienode_t *node, void *data), + void *data, int eowonly) +{ + trienode_t *trav = NULL; + int i = 0; + int cret = 0; + int ret = 0; + + if (!eowonly || node->eow) + ret = fn (node, data); + + if (ret) + goto out; + + for (i = 0; i < 255; i++) { + trav = node->subnodes[i]; + if (!trav) + continue; + + cret = trienode_walk (trav, fn, data, eowonly); + if (cret < 0) { + ret = cret; + goto out; + } + ret += cret; + } + +out: + return ret; +} + + +static int +trie_walk (trie_t *trie, int (*fn)(trienode_t *node, void *data), + void *data, int eowonly) +{ + return trienode_walk (&trie->root, fn, data, eowonly); +} + + +static void +print_node (trienode_t *node, char **buf) +{ + if (!node->parent) + return; + + if (node->parent) { + print_node (node->parent, buf); + *(*buf)++ = node->id; + } +} + + +int +trienode_get_word (trienode_t *node, char **bufp) +{ + char *buf = NULL; + + buf = GF_CALLOC (1, node->depth + 1, gf_common_mt_trie_buf); + if (!buf) + return -1; + *bufp = buf; + + print_node (node, &buf); + + return 0; +} + + +static int +calc_dist (trienode_t *node, void *data) +{ + const char *word = NULL; + int i = 0; + int *row = NULL; + int *uprow = NULL; + int distu = 0; + int distl = 0; + int distul = 0; + + word = data; + + node->data = GF_CALLOC (node->trie->len, sizeof (int), + gf_common_mt_trie_data); + if (!node->data) + return -1; + row = node->data; + + if (!node->parent) { + for (i = 0; i < node->trie->len; i++) + row[i] = i+1; + + return 0; + } + + uprow = node->parent->data; + + distu = node->depth; /* up node */ + distul = node->parent->depth; /* up-left node */ + + for (i = 0; i < node->trie->len; i++) { + distl = uprow[i]; /* left node */ + + if (word[i] == node->id) + row[i] = distul; + else + row[i] = min ((distul + DISTANCE_EDIT), + min ((distu + DISTANCE_DEL), + (distl + DISTANCE_INS))); + + distu = row[i]; + distul = distl; + } + + return 0; +} + + +int +trienode_get_dist (trienode_t *node) +{ + int *row = NULL; + + row = node->data; + + return row[node->trie->len - 1]; +} + + +struct trienodevec_w { + struct trienodevec *vec; + const char *word; +}; + + +static void +trienodevec_clear (struct trienodevec *nodevec) +{ + memset(nodevec->nodes, 0, sizeof (*nodevec->nodes) * nodevec->cnt); +} + + +static int +collect_closest (trienode_t *node, void *data) +{ + struct trienodevec_w *nodevec_w = NULL; + struct trienodevec *nodevec = NULL; + int dist = 0; + int i = 0; + + nodevec_w = data; + nodevec = nodevec_w->vec; + + if (calc_dist (node, (void *)nodevec_w->word)) + return -1; + + if (!node->eow || !nodevec->cnt) + return 0; + + dist = trienode_get_dist (node); + + /* + * I thought that when descending further after some dictionary word dw, + * if we see that child's distance is bigger than it was for dw, then we + * can prune this branch, as it can contain only worse nodes. + * + * This conjecture fails, see eg: + * + * d("AB", "B") = 1; + * d("AB", "BA") = 2; + * d("AB", "BAB") = 1; + * + * -- if both "B" and "BAB" are in dict., then pruning at "BA" * would + * miss "BAB". + * + * (example courtesy of Richard Bann <richardbann at gmail.com>) + + if (node->parent->eow && dist > trienode_get_dist (node->parent)) + return 1; + + */ + + if (nodevec->nodes[0] && + dist < trienode_get_dist (nodevec->nodes[0])) { + /* improving over the findings so far */ + trienodevec_clear (nodevec); + nodevec->nodes[0] = node; + } else if (!nodevec->nodes[0] || + dist == trienode_get_dist (nodevec->nodes[0])) { + /* as good as the best so far, add if there is free space */ + for (i = 0; i < nodevec->cnt; i++) { + if (!nodevec->nodes[i]) { + nodevec->nodes[i] = node; + break; + } + } + } + + return 0; +} + + +int +trie_measure (trie_t *trie, const char *word, trienode_t **nodes, + int nodecnt) +{ + struct trienodevec nodevec = {0,}; + + nodevec.nodes = nodes; + nodevec.cnt = nodecnt; + + return trie_measure_vec (trie, word, &nodevec); +} + + +int +trie_measure_vec (trie_t *trie, const char *word, struct trienodevec *nodevec) +{ + struct trienodevec_w nodevec_w = {0,}; + int ret = 0; + + trie->len = strlen (word); + + trienodevec_clear (nodevec); + nodevec_w.vec = nodevec; + nodevec_w.word = word; + + ret = trie_walk (trie, collect_closest, &nodevec_w, 0); + if (ret > 0) + ret = 0; + + return ret; +} + + +static int +trienode_reset (trienode_t *node, void *data) +{ + GF_FREE (node->data); + + return 0; +} + + +void +trie_reset_search (trie_t *trie) +{ + trie->len = 0; + + trie_walk (trie, trienode_reset, NULL, 0); +} diff --git a/libglusterfs/src/trie.h b/libglusterfs/src/trie.h new file mode 100644 index 000000000..0356e6621 --- /dev/null +++ b/libglusterfs/src/trie.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _TRIE_H_ +#define _TRIE_H_ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +struct trienode; +typedef struct trienode trienode_t; + +struct trie; +typedef struct trie trie_t; + +struct trienodevec { + trienode_t **nodes; + unsigned cnt; +}; + + +trie_t *trie_new (); + +int trie_add (trie_t *trie, const char *word); + +void trie_destroy (trie_t *trie); + +void trie_destroy_bynode (trienode_t *node); + +int trie_measure (trie_t *trie, const char *word, trienode_t **nodes, + int nodecnt); + +int trie_measure_vec (trie_t *trie, const char *word, + struct trienodevec *nodevec); + +void trie_reset_search (trie_t *trie); + +int trienode_get_dist (trienode_t *node); + +int trienode_get_word (trienode_t *node, char **buf); + +#endif diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c index 879ddd76d..a277c58a8 100644 --- a/libglusterfs/src/xlator.c +++ b/libglusterfs/src/xlator.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -28,897 +19,438 @@ #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) + if (!xl->fops->fn) \ + xl->fops->fn = default_##fn; \ + } while (0) #define SET_DEFAULT_CBK(fn) do { \ - if (!xl->cbks->fn) \ - xl->cbks->fn = default_##fn; \ - } while (0) - + if (!xl->cbks->fn) \ + xl->cbks->fn = default_##fn; \ + } while (0) -#define GF_OPTION_LIST_EMPTY(_opt) (_opt->value[0] == NULL) static void fill_defaults (xlator_t *xl) { - if (xl == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return; - } + if (xl == NULL) { + gf_log_callingfn ("xlator", GF_LOG_WARNING, "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 (fsetxattr); - SET_DEFAULT_FOP (fgetxattr); - SET_DEFAULT_FOP (removexattr); - SET_DEFAULT_FOP (opendir); - SET_DEFAULT_FOP (readdir); - SET_DEFAULT_FOP (readdirp); - 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 (rchecksum); - SET_DEFAULT_FOP (xattrop); - SET_DEFAULT_FOP (fxattrop); - SET_DEFAULT_FOP (lock_notify); - SET_DEFAULT_FOP (lock_fnotify); + 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 (truncate); + 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 (fsetxattr); + SET_DEFAULT_FOP (fgetxattr); + SET_DEFAULT_FOP (removexattr); + SET_DEFAULT_FOP (fremovexattr); + SET_DEFAULT_FOP (opendir); + SET_DEFAULT_FOP (readdir); + SET_DEFAULT_FOP (readdirp); + 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 (rchecksum); + SET_DEFAULT_FOP (xattrop); + SET_DEFAULT_FOP (fxattrop); SET_DEFAULT_FOP (setattr); SET_DEFAULT_FOP (fsetattr); + SET_DEFAULT_FOP (fallocate); + SET_DEFAULT_FOP (discard); + SET_DEFAULT_FOP (zerofill); + + SET_DEFAULT_FOP (getspec); - SET_DEFAULT_MOP (log); - SET_DEFAULT_MOP (stats); + SET_DEFAULT_CBK (release); + SET_DEFAULT_CBK (releasedir); + SET_DEFAULT_CBK (forget); - SET_DEFAULT_CBK (release); - SET_DEFAULT_CBK (releasedir); - SET_DEFAULT_CBK (forget); + if (!xl->notify) + xl->notify = default_notify; - if (!xl->notify) - xl->notify = default_notify; + if (!xl->mem_acct_init) + xl->mem_acct_init = default_mem_acct_init; - return; + return; } -/* RFC 1123 & 952 */ -static char -valid_host_name (char *address, int length) + +int +xlator_set_type_virtual (xlator_t *xl, const char *type) { - int i = 0; - char ret = 1; + GF_VALIDATE_OR_GOTO ("xlator", xl, out); + GF_VALIDATE_OR_GOTO ("xlator", type, out); - if ((length > 75) || (length == 1)) { - ret = 0; - goto out; - } + xl->type = gf_strdup (type); - if (!isalnum (address[length - 1])) { - ret = 0; - goto out; - } - - for (i = 0; i < length; i++) { - if (!isalnum (address[i]) && (address[i] != '.') - && (address[i] != '-')) { - ret = 0; - goto out; - } - } + if (xl->type) + return 0; out: - return ret; + return -1; } -static char -valid_ipv4_address (char *address, int length) + +int +xlator_volopt_dynload (char *xlator_type, void **dl_handle, + volume_opt_list_t *opt_list) { - int octets = 0; - int value = 0; - char *tmp = NULL, *ptr = NULL, *prev = NULL, *endptr = NULL; - char ret = 1; - - prev = tmp = strdup (address); - prev = strtok_r (tmp, ".", &ptr); - - while (prev != NULL) - { - octets++; - value = strtol (prev, &endptr, 10); - if ((value > 255) || (value < 0) || (endptr != NULL)) { - ret = 0; - goto out; - } - - prev = strtok_r (NULL, ".", &ptr); - } + int ret = -1; + char *name = NULL; + void *handle = NULL; - if (octets != 4) { - ret = 0; + GF_VALIDATE_OR_GOTO ("xlator", xlator_type, out); + + ret = gf_asprintf (&name, "%s/%s.so", XLATORDIR, xlator_type); + if (-1 == ret) { + gf_log ("xlator", GF_LOG_ERROR, "asprintf failed"); + goto out; } -out: - FREE (tmp); - return ret; -} + ret = -1; -static char -valid_ipv6_address (char *address, int length) -{ - int hex_numbers = 0; - int value = 0; - char *tmp = NULL, *ptr = NULL, *prev = NULL, *endptr = NULL; - char ret = 1; - - tmp = strdup (address); - prev = strtok_r (tmp, ":", &ptr); - - while (prev != NULL) - { - hex_numbers++; - value = strtol (prev, &endptr, 16); - if ((value > 0xffff) || (value < 0) || (endptr != NULL)) { - ret = 0; - goto out; - } - - prev = strtok_r (NULL, ":", &ptr); + gf_log ("xlator", GF_LOG_TRACE, "attempt to load file %s", name); + + handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL); + if (!handle) { + gf_log ("xlator", GF_LOG_WARNING, "%s", dlerror ()); + goto out; } - - if (hex_numbers > 8) { - ret = 0; + + if (!(opt_list->given_opt = dlsym (handle, "options"))) { + dlerror (); + gf_log ("xlator", GF_LOG_ERROR, + "Failed to load xlator opt table"); + goto out; } -out: - FREE (tmp); + *dl_handle = handle; + + ret = 0; + out: + GF_FREE (name); + + gf_log ("xlator", GF_LOG_DEBUG, "Returning %d", ret); return ret; + } -static char -valid_internet_address (char *address) + +int +xlator_dynload (xlator_t *xl) { - char ret = 0; - int length = 0; + int ret = -1; + char *name = NULL; + void *handle = NULL; + volume_opt_list_t *vol_opt = NULL; + class_methods_t *vtbl = NULL; - if (address == NULL) { + GF_VALIDATE_OR_GOTO ("xlator", xl, out); + + INIT_LIST_HEAD (&xl->volume_options); + + ret = gf_asprintf (&name, "%s/%s.so", XLATORDIR, xl->type); + if (-1 == ret) { + gf_log ("xlator", GF_LOG_ERROR, "asprintf failed"); goto out; } - length = strlen (address); - if (length == 0) { + ret = -1; + + gf_log ("xlator", GF_LOG_TRACE, "attempt to load file %s", name); + + handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL); + if (!handle) { + gf_log ("xlator", GF_LOG_WARNING, "%s", dlerror ()); goto out; } + xl->dlhandle = handle; - if (valid_ipv4_address (address, length) - || valid_ipv6_address (address, length) - || valid_host_name (address, length)) { - ret = 1; + if (!(xl->fops = dlsym (handle, "fops"))) { + gf_log ("xlator", GF_LOG_WARNING, "dlsym(fops) on %s", + dlerror ()); + goto out; } -out: - return ret; -} + if (!(xl->cbks = dlsym (handle, "cbks"))) { + gf_log ("xlator", GF_LOG_WARNING, "dlsym(cbks) on %s", + dlerror ()); + goto out; + } -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: - { - if (strstr (pair->value->data, "../")) { - gf_log (xl->name, GF_LOG_ERROR, - "invalid path given '%s'", - pair->value->data); - ret = -1; + /* + * If class_methods exists, its contents override any definitions of + * init or fini for that translator. Otherwise, we fall back to the + * older method of looking for init and fini directly. + */ + vtbl = dlsym(handle,"class_methods"); + if (vtbl) { + xl->init = vtbl->init; + xl->fini = vtbl->fini; + xl->reconfigure = vtbl->reconfigure; + xl->notify = vtbl->notify; + } + else { + if (!(*VOID(&xl->init) = dlsym (handle, "init"))) { + gf_log ("xlator", GF_LOG_WARNING, "dlsym(init) on %s", + dlerror ()); goto out; } - /* 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 (GF_OPTION_LIST_EMPTY(opt)) { - ret = 0; + if (!(*VOID(&(xl->fini)) = dlsym (handle, "fini"))) { + gf_log ("xlator", GF_LOG_WARNING, "dlsym(fini) on %s", + dlerror ()); 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_PERCENT_OR_SIZET: - { - uint32_t percent = 0; - uint64_t input_size = 0; - - /* Check if the value is valid percentage */ - if (gf_string2percent (pair->value->data, - &percent) == 0) { - if (percent > 100) { - gf_log (xl->name, GF_LOG_DEBUG, - "value given was greater than 100, " - "assuming this is actually a size"); - if (gf_string2bytesize (pair->value->data, - &input_size) == 0) { - /* Check the range */ - 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); - // It is a size - ret = 0; - goto out; - } - 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); - } - // It is a size - ret = 0; - goto out; - } else { - // It's not a percent or size - gf_log (xl->name, GF_LOG_ERROR, - "invalid number format \"%s\" " - "in \"option %s\"", - pair->value->data, pair->key); - } - - } - // It is a percent - ret = 0; - goto out; - } else { - if (gf_string2bytesize (pair->value->data, - &input_size) == 0) { - /* Check the range */ - 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); - // It is a size - ret = 0; - goto out; - } - 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); - } - } else { - // It's not a percent or size - gf_log (xl->name, GF_LOG_ERROR, - "invalid number format \"%s\" " - "in \"option %s\"", - pair->value->data, pair->key); - } - //It is a size - ret = 0; - goto out; - } - - } - 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_DOUBLE: - { - double input_time = 0.0; - - /* Check if the value is valid double */ - if (gf_string2double (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 (input_time < 0.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; - } - ret = 0; - } - break; - case GF_OPTION_TYPE_INTERNET_ADDRESS: - { - if (valid_internet_address (pair->value->data)) { - ret = 0; + if (!(*VOID(&(xl->reconfigure)) = dlsym (handle, + "reconfigure"))) { + gf_log ("xlator", GF_LOG_TRACE, + "dlsym(reconfigure) on %s -- neglecting", + dlerror()); + } + if (!(*VOID(&(xl->notify)) = dlsym (handle, "notify"))) { + gf_log ("xlator", GF_LOG_TRACE, + "dlsym(notify) on %s -- neglecting", + dlerror ()); } - } - 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; -} + if (!(xl->dumpops = dlsym (handle, "dumpops"))) { + gf_log ("xlator", GF_LOG_TRACE, + "dlsym(dumpops) on %s -- neglecting", dlerror ()); + } -int32_t -xlator_set_type (xlator_t *xl, - const char *type) -{ - int ret = 0; - char *name = NULL; - void *handle = NULL; - volume_opt_list_t *vol_opt = NULL; - - if (xl == NULL || type == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return -1; - } + if (!(*VOID(&(xl->mem_acct_init)) = dlsym (handle, "mem_acct_init"))) { + gf_log (xl->name, GF_LOG_TRACE, + "dlsym(mem_acct_init) on %s -- neglecting", + dlerror ()); + } - xl->type = strdup (type); + vol_opt = GF_CALLOC (1, sizeof (volume_opt_list_t), + gf_common_mt_volume_opt_list_t); - ret = asprintf (&name, "%s/%s.so", XLATORDIR, type); - if (-1 == ret) { - gf_log ("xlator", GF_LOG_ERROR, "asprintf failed"); - return -1; + if (!vol_opt) { + goto out; } - gf_log ("xlator", GF_LOG_TRACE, "attempt to load file %s", name); + if (!(vol_opt->given_opt = dlsym (handle, "options"))) { + dlerror (); + gf_log (xl->name, GF_LOG_TRACE, + "Strict option validation not enforced -- neglecting"); + } + INIT_LIST_HEAD (&vol_opt->list); + list_add_tail (&vol_opt->list, &xl->volume_options); - handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL); - if (!handle) { - gf_log ("xlator", GF_LOG_DEBUG, "%s", dlerror ()); - return -1; - } + fill_defaults (xl); - if (!(xl->fops = dlsym (handle, "fops"))) { - gf_log ("xlator", GF_LOG_DEBUG, "dlsym(fops) on %s", - dlerror ()); - return -1; - } + ret = 0; - if (!(xl->mops = dlsym (handle, "mops"))) { - gf_log ("xlator", GF_LOG_DEBUG, "dlsym(mops) on %s", - dlerror ()); - return -1; - } +out: + GF_FREE (name); + return ret; +} - if (!(xl->cbks = dlsym (handle, "cbks"))) { - gf_log ("xlator", GF_LOG_DEBUG, "dlsym(cbks) on %s", - dlerror ()); - return -1; - } - if (!(xl->init = dlsym (handle, "init"))) { - gf_log ("xlator", GF_LOG_DEBUG, "dlsym(init) on %s", - dlerror ()); - return -1; - } +int +xlator_set_type (xlator_t *xl, const char *type) +{ + int ret = 0; - if (!(xl->fini = dlsym (handle, "fini"))) { - gf_log ("xlator", GF_LOG_DEBUG, "dlsym(fini) on %s", - dlerror ()); - return -1; - } + ret = xlator_set_type_virtual (xl, type); + if (!ret) + ret = xlator_dynload (xl); - if (!(xl->notify = dlsym (handle, "notify"))) { - gf_log ("xlator", GF_LOG_DEBUG, - "dlsym(notify) on %s -- neglecting", dlerror ()); - } + return ret; +} - if (!(xl->dumpops = dlsym (handle, "dumpops"))) { - gf_log ("xlator", GF_LOG_DEBUG, - "dlsym(dumpops) on %s -- neglecting", dlerror ()); - } - INIT_LIST_HEAD (&xl->volume_options); +void +xlator_foreach (xlator_t *this, + void (*fn)(xlator_t *each, + void *data), + void *data) +{ + xlator_t *first = NULL; + xlator_t *old_THIS = NULL; + + GF_VALIDATE_OR_GOTO ("xlator", this, out); + GF_VALIDATE_OR_GOTO ("xlator", fn, out); - vol_opt = CALLOC (1, sizeof (volume_opt_list_t)); + first = this; - 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); + while (first->prev) + first = first->prev; - fill_defaults (xl); + while (first) { + old_THIS = THIS; + THIS = first; - FREE (name); - return 0; + fn (first, data); + + THIS = old_THIS; + first = first->next; + } + +out: + return; } void -xlator_foreach (xlator_t *this, - void (*fn)(xlator_t *each, - void *data), - void *data) +xlator_foreach_depth_first (xlator_t *this, + void (*fn)(xlator_t *each, void *data), + void *data) { - xlator_t *first = NULL; + xlator_list_t *subv = NULL; - if (this == NULL || fn == NULL || data == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return; - } - - first = this; + subv = this->children; - while (first->prev) - first = first->prev; - - while (first) { - fn (first, data); - first = first->next; + while (subv) { + xlator_foreach_depth_first (subv->xlator, fn, data); + subv = subv->next; } + + fn (this, data); } xlator_t * xlator_search_by_name (xlator_t *any, const char *name) { - xlator_t *search = NULL; + xlator_t *search = NULL; - if (any == NULL || name == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return NULL; - } + GF_VALIDATE_OR_GOTO ("xlator", any, out); + GF_VALIDATE_OR_GOTO ("xlator", name, out); - search = any; + search = any; - while (search->prev) - search = search->prev; + while (search->prev) + search = search->prev; - while (search) { - if (!strcmp (search->name, name)) - break; - search = search->next; - } + while (search) { + if (!strcmp (search->name, name)) + break; + search = search->next; + } - return search; +out: + return search; } - -static int32_t -xlator_init_rec (xlator_t *xl) +static int +__xlator_init(xlator_t *xl) { - xlator_list_t *trav = NULL; - int32_t ret = 0; - - if (xl == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return 0; - } + xlator_t *old_THIS = NULL; + int ret = 0; - trav = xl->children; + old_THIS = THIS; + THIS = xl; - while (trav) { - ret = 0; - ret = xlator_init_rec (trav->xlator); - if (ret != 0) - break; - gf_log (trav->xlator->name, GF_LOG_TRACE, - "Initialization done"); - trav = trav->next; - } + ret = xl->init (xl); - if (!ret && !xl->ready) { - ret = -1; - if (xl->init) { - ret = xlator_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_DEBUG, "No init() found"); - } - /* This 'xl' is checked */ - xl->ready = 1; - } + THIS = old_THIS; - return ret; + return ret; } -int32_t -xlator_tree_init (xlator_t *xl) +int +xlator_init (xlator_t *xl) { - xlator_t *top = NULL; - int32_t ret = 0; + int32_t ret = -1; - if (xl == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return 0; - } + GF_VALIDATE_OR_GOTO ("xlator", xl, out); - top = xl; -/* - while (top->parents) - top = top->parents->xlator; -*/ - ret = xlator_init_rec (top); + if (xl->mem_acct_init) + xl->mem_acct_init (xl); - if (ret == 0 && top->notify) { - top->notify (top, GF_EVENT_PARENT_UP, NULL); - } + if (!xl->init) { + gf_log (xl->name, GF_LOG_WARNING, "No init() found"); + goto out; + } + + ret = __xlator_init (xl); + + if (ret) { + gf_log (xl->name, GF_LOG_ERROR, + "Initialization of volume '%s' failed," + " review your volfile again", + xl->name); + goto out; + } - return ret; + xl->init_succeeded = 1; + + ret = 0; +out: + return ret; } static void xlator_fini_rec (xlator_t *xl) { - xlator_list_t *trav = NULL; + xlator_list_t *trav = NULL; + xlator_t *old_THIS = NULL; - if (xl == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return; - } + GF_VALIDATE_OR_GOTO ("xlator", xl, out); - trav = xl->children; + trav = xl->children; - while (trav) { - if (!trav->xlator->init_succeeded) { - break; - } + 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; - } + 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_DEBUG, "No fini() found"); - } - xl->init_succeeded = 0; - } + if (xl->init_succeeded) { + if (xl->fini) { + old_THIS = THIS; + THIS = xl; + + xl->fini (xl); + + if (xl->local_pool) + mem_pool_destroy (xl->local_pool); + + THIS = old_THIS; + } else { + gf_log (xl->name, GF_LOG_DEBUG, "No fini() found"); + } + xl->init_succeeded = 0; + } + +out: + return; } @@ -940,57 +472,98 @@ xlator_notify (xlator_t *xl, int event, void *data, ...) int -xlator_init (xlator_t *xl) +xlator_mem_acct_init (xlator_t *xl, int num_types) { - xlator_t *old_THIS = NULL; - int ret = 0; + int i = 0; + int ret = 0; - old_THIS = THIS; - THIS = xl; + if (!xl) + return -1; - ret = xl->init (xl); + if (!xl->ctx->mem_acct_enable) + return 0; - THIS = old_THIS; + xl->mem_acct.num_types = num_types; - return ret; + xl->mem_acct.rec = CALLOC(num_types, sizeof(struct mem_acct_rec)); + + if (!xl->mem_acct.rec) { + return -1; + } + + for (i = 0; i < num_types; i++) { + ret = LOCK_INIT(&(xl->mem_acct.rec[i].lock)); + if (ret) { + fprintf(stderr, "Unable to lock..errno : %d",errno); + } + } + + return 0; } void xlator_tree_fini (xlator_t *xl) { - xlator_t *top = NULL; + xlator_t *top = NULL; - if (xl == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return; - } + GF_VALIDATE_OR_GOTO ("xlator", xl, out); - top = xl; - xlator_fini_rec (top); + top = xl; + xlator_fini_rec (top); + +out: + return; +} + +int +xlator_list_destroy (xlator_list_t *list) +{ + xlator_list_t *next = NULL; + + while (list) { + next = list->next; + GF_FREE (list); + list = next; + } + + return 0; } 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; + volume_opt_list_t *vol_opt = NULL; + volume_opt_list_t *tmp = NULL; + xlator_t *trav = tree; + xlator_t *prev = tree; + + if (!tree) { + gf_log ("parser", GF_LOG_ERROR, "Translator tree not found"); + return -1; + } + + while (prev) { + trav = prev->next; + if (prev->dlhandle) + dlclose (prev->dlhandle); + dict_unref (prev->options); + GF_FREE (prev->name); + GF_FREE (prev->type); + xlator_list_destroy (prev->children); + xlator_list_destroy (prev->parents); + + list_for_each_entry_safe (vol_opt, tmp, &prev->volume_options, + list) { + list_del_init (&vol_opt->list); + GF_FREE (vol_opt); + } + GF_FREE (prev); + prev = trav; + } + + return 0; } @@ -1002,40 +575,264 @@ loc_wipe (loc_t *loc) loc->inode = NULL; } if (loc->path) { - FREE (loc->path); + GF_FREE ((char *)loc->path); loc->path = NULL; } - + if (loc->parent) { inode_unref (loc->parent); loc->parent = NULL; } + + memset (loc, 0, sizeof (*loc)); +} + +int +loc_path (loc_t *loc, const char *bname) +{ + int ret = 0; + + if (loc->path) + goto out; + + ret = -1; + + if (bname && !strlen (bname)) + bname = NULL; + + if (!bname) + goto inode_path; + + if (loc->parent && !uuid_is_null (loc->parent->gfid)) { + ret = inode_path (loc->parent, bname, (char**)&loc->path); + } else if (!uuid_is_null (loc->pargfid)) { + ret = gf_asprintf ((char**)&loc->path, INODE_PATH_FMT"/%s", + uuid_utoa (loc->pargfid), bname); + } + + if (loc->path) + goto out; + +inode_path: + if (loc->inode && !uuid_is_null (loc->inode->gfid)) { + ret = inode_path (loc->inode, NULL, (char **)&loc->path); + } else if (!uuid_is_null (loc->gfid)) { + ret = gf_asprintf ((char**)&loc->path, INODE_PATH_FMT, + uuid_utoa (loc->gfid)); + } +out: + return ret; } +void +loc_gfid (loc_t *loc, uuid_t gfid) +{ + if (!gfid) + goto out; + uuid_clear (gfid); + + if (!loc) + goto out; + else if (!uuid_is_null (loc->gfid)) + uuid_copy (gfid, loc->gfid); + else if (loc->inode && (!uuid_is_null (loc->inode->gfid))) + uuid_copy (gfid, loc->inode->gfid); +out: + return; +} + +char* +loc_gfid_utoa (loc_t *loc) +{ + uuid_t gfid; + loc_gfid (loc, gfid); + return uuid_utoa (gfid); +} int loc_copy (loc_t *dst, loc_t *src) { - int ret = -1; + int ret = -1; + + GF_VALIDATE_OR_GOTO ("xlator", dst, err); + GF_VALIDATE_OR_GOTO ("xlator", src, err); + + uuid_copy (dst->gfid, src->gfid); + uuid_copy (dst->pargfid, src->pargfid); + uuid_copy (dst->gfid, src->gfid); + + if (src->inode) + dst->inode = inode_ref (src->inode); + + if (src->parent) + dst->parent = inode_ref (src->parent); + + if (src->path) { + dst->path = gf_strdup (src->path); + + if (!dst->path) + goto out; + + if (src->name) + dst->name = strrchr (dst->path, '/'); + if (dst->name) + dst->name++; + } + + ret = 0; +out: + if (ret == -1) + loc_wipe (dst); + +err: + return ret; +} + +gf_boolean_t +loc_is_root (loc_t *loc) +{ + if (loc && __is_root_gfid (loc->gfid)) { + return _gf_true; + } else if (loc && loc->inode && __is_root_gfid (loc->inode->gfid)) { + return _gf_true; + } + return _gf_false; +} + +int +xlator_destroy (xlator_t *xl) +{ + volume_opt_list_t *vol_opt = NULL; + volume_opt_list_t *tmp = NULL; + + if (!xl) + return 0; + + GF_FREE (xl->name); + GF_FREE (xl->type); + if (xl->dlhandle) + dlclose (xl->dlhandle); + if (xl->options) + dict_destroy (xl->options); + + xlator_list_destroy (xl->children); - dst->ino = src->ino; + xlator_list_destroy (xl->parents); - if (src->inode) - dst->inode = inode_ref (src->inode); + list_for_each_entry_safe (vol_opt, tmp, &xl->volume_options, list) { + list_del_init (&vol_opt->list); + GF_FREE (vol_opt); + } + + GF_FREE (xl); - if (src->parent) - dst->parent = inode_ref (src->parent); + return 0; +} - dst->path = strdup (src->path); - if (!dst->path) - goto out; +int +is_gf_log_command (xlator_t *this, const char *name, char *value) +{ + xlator_t *trav = NULL; + char key[1024] = {0,}; + int ret = -1; + int log_level = -1; + gf_boolean_t syslog_flag = 0; + glusterfs_ctx_t *ctx = NULL; + + if (!strcmp ("trusted.glusterfs.syslog", name)) { + ret = gf_string2boolean (value, &syslog_flag); + if (ret) { + ret = EOPNOTSUPP; + goto out; + } + if (syslog_flag) + gf_log_enable_syslog (); + else + gf_log_disable_syslog (); - dst->name = strrchr (dst->path, '/'); - if (dst->name) - dst->name++; + goto out; + } - ret = 0; + if (fnmatch ("trusted.glusterfs*set-log-level", name, FNM_NOESCAPE)) + goto out; + + log_level = glusterd_check_log_level (value); + if (log_level == -1) { + ret = EOPNOTSUPP; + goto out; + } + + /* Some crude way to change the log-level of process */ + if (!strcmp (name, "trusted.glusterfs.set-log-level")) { + /* */ + gf_log ("glusterfs", gf_log_get_loglevel(), + "setting log level to %d (old-value=%d)", + log_level, gf_log_get_loglevel()); + gf_log_set_loglevel (log_level); + ret = 0; + goto out; + } + + if (!strcmp (name, "trusted.glusterfs.fuse.set-log-level")) { + /* */ + gf_log (this->name, gf_log_get_xl_loglevel (this), + "setting log level to %d (old-value=%d)", + log_level, gf_log_get_xl_loglevel (this)); + gf_log_set_xl_loglevel (this, log_level); + ret = 0; + goto out; + } + + ctx = this->ctx; + if (!ctx) + goto out; + if (!ctx->active) + goto out; + trav = ctx->active->top; + + while (trav) { + snprintf (key, 1024, "trusted.glusterfs.%s.set-log-level", + trav->name); + if (fnmatch (name, key, FNM_NOESCAPE) == 0) { + gf_log (trav->name, gf_log_get_xl_loglevel (trav), + "setting log level to %d (old-value=%d)", + log_level, gf_log_get_xl_loglevel (trav)); + gf_log_set_xl_loglevel (trav, log_level); + ret = 0; + } + trav = trav->next; + } out: - return ret; + return ret; } + + +int +glusterd_check_log_level (const char *value) +{ + int log_level = -1; + + if (!strcasecmp (value, "CRITICAL")) { + log_level = GF_LOG_CRITICAL; + } else if (!strcasecmp (value, "ERROR")) { + log_level = GF_LOG_ERROR; + } else if (!strcasecmp (value, "WARNING")) { + log_level = GF_LOG_WARNING; + } else if (!strcasecmp (value, "INFO")) { + log_level = GF_LOG_INFO; + } else if (!strcasecmp (value, "DEBUG")) { + log_level = GF_LOG_DEBUG; + } else if (!strcasecmp (value, "TRACE")) { + log_level = GF_LOG_TRACE; + } else if (!strcasecmp (value, "NONE")) { + log_level = GF_LOG_NONE; + } + + if (log_level == -1) + gf_log (THIS->name, GF_LOG_ERROR, "Invalid log-level. possible values " + "are DEBUG|WARNING|ERROR|CRITICAL|NONE|TRACE"); + + return log_level; +} + diff --git a/libglusterfs/src/xlator.h b/libglusterfs/src/xlator.h index f71d5dea9..b57e5873e 100644 --- a/libglusterfs/src/xlator.h +++ b/libglusterfs/src/xlator.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.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 is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _XLATOR_H @@ -29,15 +20,13 @@ #include <stdint.h> #include <inttypes.h> - -#include "glusterfs.h" +#include "event-history.h" #include "logging.h" #include "common-utils.h" #include "dict.h" #include "compat.h" #include "list.h" - -#include <fuse/fuse_lowlevel.h> +#include "latency.h" #define FIRST_CHILD(xl) (xl->children->xlator) @@ -48,6 +37,13 @@ #define GF_SET_ATTR_ATIME 0x10 #define GF_SET_ATTR_MTIME 0x20 +#define gf_attr_mode_set(mode) ((mode) & GF_SET_ATTR_MODE) +#define gf_attr_uid_set(mode) ((mode) & GF_SET_ATTR_UID) +#define gf_attr_gid_set(mode) ((mode) & GF_SET_ATTR_GID) +#define gf_attr_size_set(mode) ((mode) & GF_SET_ATTR_SIZE) +#define gf_attr_atime_set(mode) ((mode) & GF_SET_ATTR_ATIME) +#define gf_attr_mtime_set(mode) ((mode) & GF_SET_ATTR_MTIME) + struct _xlator; typedef struct _xlator xlator_t; struct _dir_entry_t; @@ -58,10 +54,8 @@ struct _loc; typedef struct _loc loc_t; -typedef int32_t (*event_notify_fn_t) (xlator_t *this, - int32_t event, - void *data, - ...); +typedef int32_t (*event_notify_fn_t) (xlator_t *this, int32_t event, void *data, + ...); #include "list.h" #include "gf-dirent.h" @@ -70,54 +64,33 @@ typedef int32_t (*event_notify_fn_t) (xlator_t *this, #include "inode.h" #include "fd.h" #include "globals.h" - -struct _loc { - const char *path; - const char *name; - ino_t ino; - inode_t *inode; - inode_t *parent; -}; +#include "iatt.h" +#include "options.h" +#include "client_t.h" -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 */ +struct _loc { + const char *path; + const char *name; + inode_t *inode; + inode_t *parent; + /* Currently all location based operations are through 'gfid' of inode. + * But the 'inode->gfid' only gets set in higher most layer (as in, + * 'fuse', 'protocol/server', or 'nfs/server'). So if translators want + * to send fops on a inode before the 'inode->gfid' is set, they have to + * make use of below 'gfid' fields + */ + uuid_t gfid; + uuid_t pargfid; }; - -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 (*mop_log_cbk_t) (call_frame_t *frame, - void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno); - -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 (*fop_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_rchecksum_cbk_t) (call_frame_t *frame, void *cookie, @@ -125,505 +98,413 @@ typedef int32_t (*fop_rchecksum_cbk_t) (call_frame_t *frame, int32_t op_ret, int32_t op_errno, uint32_t weak_checksum, - uint8_t *strong_checksum); - -typedef int32_t (*mop_setvolume_t) (call_frame_t *frame, - xlator_t *this, - const char *volume); + uint8_t *strong_checksum, + dict_t *xdata); -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 (*mop_log_t) (call_frame_t *frame, - xlator_t *this, - const char *msg); - -typedef int32_t (*fop_checksum_t) (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t flag); +typedef int32_t (*fop_getspec_t) (call_frame_t *frame, + xlator_t *this, + const char *key, + int32_t flag); typedef int32_t (*fop_rchecksum_t) (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, - int32_t len); - -struct xlator_mops { - mop_stats_t stats; - mop_getspec_t getspec; - mop_log_t log; - - mop_log_cbk_t log_cbk; - mop_stats_cbk_t stats_cbk; - mop_getspec_cbk_t getspec_cbk; -}; + int32_t len, dict_t *xdata); 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, - struct stat *postparent); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct iatt *buf, + dict_t *xdata, + struct iatt *postparent); 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); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct iatt *buf, dict_t *xdata); 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); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct iatt *buf, dict_t *xdata); 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 *prebuf, - struct stat *postbuf); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); 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 *prebuf, - struct stat *postbuf); - -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); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); typedef int32_t (*fop_access_cbk_t) (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, dict_t *xdata); 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, - struct stat *buf); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + const char *path, + struct iatt *buf, dict_t *xdata); 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, - struct stat *preparent, - struct stat *postparent); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct iatt *buf, + struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); 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, - struct stat *preparent, - struct stat *postparent); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct iatt *buf, + struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); typedef int32_t (*fop_unlink_cbk_t) (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct stat *preparent, - struct stat *postparent); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); typedef int32_t (*fop_rmdir_cbk_t) (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct stat *preparent, - struct stat *postparent); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); 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, - struct stat *preparent, - struct stat *postparent); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct iatt *buf, + struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); 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, - struct stat *preoldparent, - struct stat *postoldparent, - struct stat *prenewparent, - struct stat *postnewparent); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct iatt *buf, + struct iatt *preoldparent, + struct iatt *postoldparent, + struct iatt *prenewparent, + struct iatt *postnewparent, dict_t *xdata); 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, - struct stat *preparent, - struct stat *postparent); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + inode_t *inode, + struct iatt *buf, + struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); 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, - struct stat *preparent, - struct stat *postparent); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + fd_t *fd, + inode_t *inode, + struct iatt *buf, + struct iatt *preparent, + struct iatt *postparent, dict_t *xdata); 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); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + fd_t *fd, dict_t *xdata); 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, - struct iobref *iobref); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct iovec *vector, + int32_t count, + struct iatt *stbuf, + struct iobref *iobref, dict_t *xdata); 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 *prebuf, - struct stat *postbuf); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); typedef int32_t (*fop_flush_cbk_t) (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, dict_t *xdata); typedef int32_t (*fop_fsync_cbk_t) (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - struct stat *prebuf, - struct stat *postbuf); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); 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); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + fd_t *fd, dict_t *xdata); typedef int32_t (*fop_fsyncdir_cbk_t) (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, dict_t *xdata); 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); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct statvfs *buf, dict_t *xdata); typedef int32_t (*fop_setxattr_cbk_t) (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, dict_t *xdata); 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); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + dict_t *dict, dict_t *xdata); typedef int32_t (*fop_fsetxattr_cbk_t) (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, - int32_t op_errno); + int32_t op_errno, dict_t *xdata); typedef int32_t (*fop_fgetxattr_cbk_t) (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, - dict_t *dict); + dict_t *dict, dict_t *xdata); typedef int32_t (*fop_removexattr_cbk_t) (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, dict_t *xdata); + +typedef int32_t (*fop_fremovexattr_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, dict_t *xdata); 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); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct gf_flock *flock, dict_t *xdata); typedef int32_t (*fop_inodelk_cbk_t) (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, dict_t *xdata); typedef int32_t (*fop_finodelk_cbk_t) (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, dict_t *xdata); typedef int32_t (*fop_entrylk_cbk_t) (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, dict_t *xdata); 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); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, dict_t *xdata); 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); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + gf_dirent_t *entries, dict_t *xdata); typedef int32_t (*fop_readdirp_cbk_t) (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - gf_dirent_t *entries); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + gf_dirent_t *entries, dict_t *xdata); 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); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + dict_t *xattr, dict_t *xdata); 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_lock_notify_cbk_t) (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + dict_t *xattr, dict_t *xdata); -typedef int32_t (*fop_lock_fnotify_cbk_t) (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno); typedef int32_t (*fop_setattr_cbk_t) (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, - struct stat *preop_stbuf, - struct stat *postop_stbuf); + struct iatt *preop_stbuf, + struct iatt *postop_stbuf, dict_t *xdata); typedef int32_t (*fop_fsetattr_cbk_t) (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, - struct stat *preop_stbuf, - struct stat *postop_stbuf); + struct iatt *preop_stbuf, + struct iatt *postop_stbuf, dict_t *xdata); + +typedef int32_t (*fop_fallocate_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct iatt *preop_stbuf, + struct iatt *postop_stbuf, dict_t *xdata); + +typedef int32_t (*fop_discard_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct iatt *preop_stbuf, + struct iatt *postop_stbuf, dict_t *xdata); + +typedef int32_t (*fop_zerofill_cbk_t) (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + struct iatt *preop_stbuf, + struct iatt *postop_stbuf, dict_t *xdata); typedef int32_t (*fop_lookup_t) (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - dict_t *xattr_req); + xlator_t *this, + loc_t *loc, + dict_t *xdata); typedef int32_t (*fop_stat_t) (call_frame_t *frame, - xlator_t *this, - loc_t *loc); + xlator_t *this, + loc_t *loc, dict_t *xdata); 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); + xlator_t *this, + fd_t *fd, dict_t *xdata); typedef int32_t (*fop_truncate_t) (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - off_t offset); + xlator_t *this, + loc_t *loc, + off_t offset, dict_t *xdata); 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]); + xlator_t *this, + fd_t *fd, + off_t offset, dict_t *xdata); typedef int32_t (*fop_access_t) (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t mask); + xlator_t *this, + loc_t *loc, + int32_t mask, dict_t *xdata); 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); + xlator_t *this, + loc_t *loc, + size_t size, dict_t *xdata); + +typedef int32_t (*fop_mknod_t) (call_frame_t *frame, xlator_t *this, + loc_t *loc, mode_t mode, dev_t rdev, + mode_t umask, dict_t *xdata); + +typedef int32_t (*fop_mkdir_t) (call_frame_t *frame, xlator_t *this, loc_t *loc, + mode_t mode, mode_t umask, dict_t *xdata); + +typedef int32_t (*fop_unlink_t) (call_frame_t *frame, xlator_t *this, + loc_t *loc, int xflags, dict_t *xdata); + +typedef int32_t (*fop_rmdir_t) (call_frame_t *frame, xlator_t *this, + loc_t *loc, int xflags, dict_t *xdata); + +typedef int32_t (*fop_symlink_t) (call_frame_t *frame, xlator_t *this, + const char *linkname, loc_t *loc, + mode_t umask, dict_t *xdata); typedef int32_t (*fop_rename_t) (call_frame_t *frame, - xlator_t *this, - loc_t *oldloc, - loc_t *newloc); + xlator_t *this, + loc_t *oldloc, + loc_t *newloc, dict_t *xdata); typedef int32_t (*fop_link_t) (call_frame_t *frame, - xlator_t *this, - loc_t *oldloc, - loc_t *newloc); + xlator_t *this, + loc_t *oldloc, + loc_t *newloc, dict_t *xdata); -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_create_t) (call_frame_t *frame, xlator_t *this, + loc_t *loc, int32_t flags, mode_t mode, + mode_t umask, fd_t *fd, dict_t *xdata); /* Tell subsequent writes on the fd_t to fsync after every writev fop without * requiring a fsync fop. @@ -634,283 +515,283 @@ typedef int32_t (*fop_create_t) (call_frame_t *frame, */ #define GF_OPEN_NOWB 0x02 -typedef int32_t (*fop_open_t) (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - int32_t flags, - fd_t *fd, - int32_t wbflags); +typedef int32_t (*fop_open_t) (call_frame_t *frame, xlator_t *this, + loc_t *loc, int32_t flags, + fd_t *fd, dict_t *xdata); typedef int32_t (*fop_readv_t) (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - size_t size, - off_t offset); + xlator_t *this, + fd_t *fd, + size_t size, + off_t offset, + uint32_t flags, dict_t *xdata); 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, - struct iobref *iobref); + xlator_t *this, + fd_t *fd, + struct iovec *vector, + int32_t count, + off_t offset, + uint32_t flags, + struct iobref *iobref, dict_t *xdata); typedef int32_t (*fop_flush_t) (call_frame_t *frame, - xlator_t *this, - fd_t *fd); + xlator_t *this, + fd_t *fd, dict_t *xdata); typedef int32_t (*fop_fsync_t) (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - int32_t datasync); + xlator_t *this, + fd_t *fd, + int32_t datasync, dict_t *xdata); 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); + xlator_t *this, + loc_t *loc, + fd_t *fd, dict_t *xdata); typedef int32_t (*fop_fsyncdir_t) (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - int32_t datasync); + xlator_t *this, + fd_t *fd, + int32_t datasync, dict_t *xdata); typedef int32_t (*fop_statfs_t) (call_frame_t *frame, - xlator_t *this, - loc_t *loc); + xlator_t *this, + loc_t *loc, dict_t *xdata); typedef int32_t (*fop_setxattr_t) (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - dict_t *dict, - int32_t flags); + xlator_t *this, + loc_t *loc, + dict_t *dict, + int32_t flags, dict_t *xdata); typedef int32_t (*fop_getxattr_t) (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - const char *name); + xlator_t *this, + loc_t *loc, + const char *name, dict_t *xdata); typedef int32_t (*fop_fsetxattr_t) (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, - int32_t flags); + int32_t flags, dict_t *xdata); typedef int32_t (*fop_fgetxattr_t) (call_frame_t *frame, xlator_t *this, fd_t *fd, - const char *name); + const char *name, dict_t *xdata); typedef int32_t (*fop_removexattr_t) (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - const char *name); + xlator_t *this, + loc_t *loc, + const char *name, dict_t *xdata); + +typedef int32_t (*fop_fremovexattr_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + const char *name, dict_t *xdata); typedef int32_t (*fop_lk_t) (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - int32_t cmd, - struct flock *flock); + xlator_t *this, + fd_t *fd, + int32_t cmd, + struct gf_flock *flock, dict_t *xdata); typedef int32_t (*fop_inodelk_t) (call_frame_t *frame, - xlator_t *this, + xlator_t *this, const char *volume, - loc_t *loc, - int32_t cmd, - struct flock *flock); + loc_t *loc, + int32_t cmd, + struct gf_flock *flock, dict_t *xdata); typedef int32_t (*fop_finodelk_t) (call_frame_t *frame, - xlator_t *this, + xlator_t *this, const char *volume, - fd_t *fd, - int32_t cmd, - struct flock *flock); + fd_t *fd, + int32_t cmd, + struct gf_flock *flock, dict_t *xdata); typedef int32_t (*fop_entrylk_t) (call_frame_t *frame, - xlator_t *this, + xlator_t *this, const char *volume, loc_t *loc, - const char *basename, entrylk_cmd cmd, - entrylk_type type); + const char *basename, entrylk_cmd cmd, + entrylk_type type, dict_t *xdata); typedef int32_t (*fop_fentrylk_t) (call_frame_t *frame, - xlator_t *this, + xlator_t *this, const char *volume, 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); + const char *basename, entrylk_cmd cmd, + entrylk_type type, dict_t *xdata); typedef int32_t (*fop_readdir_t) (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - size_t size, - off_t offset); + xlator_t *this, + fd_t *fd, + size_t size, + off_t offset, dict_t *xdata); typedef int32_t (*fop_readdirp_t) (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - size_t size, - off_t offset); + xlator_t *this, + fd_t *fd, + size_t size, + off_t offset, + dict_t *xdata); typedef int32_t (*fop_xattrop_t) (call_frame_t *frame, - xlator_t *this, - loc_t *loc, - gf_xattrop_flags_t optype, - dict_t *xattr); + xlator_t *this, + loc_t *loc, + gf_xattrop_flags_t optype, + dict_t *xattr, dict_t *xdata); typedef int32_t (*fop_fxattrop_t) (call_frame_t *frame, - xlator_t *this, - fd_t *fd, - gf_xattrop_flags_t optype, - dict_t *xattr); - -typedef int32_t (*fop_lock_notify_t) (call_frame_t *frame, - xlator_t *this, loc_t *loc, - int32_t timeout); - -typedef int32_t (*fop_lock_fnotify_t) (call_frame_t *frame, - xlator_t *this, fd_t *fd, - int32_t timeout); + xlator_t *this, + fd_t *fd, + gf_xattrop_flags_t optype, + dict_t *xattr, dict_t *xdata); typedef int32_t (*fop_setattr_t) (call_frame_t *frame, xlator_t *this, loc_t *loc, - struct stat *stbuf, - int32_t valid); + struct iatt *stbuf, + int32_t valid, dict_t *xdata); typedef int32_t (*fop_fsetattr_t) (call_frame_t *frame, xlator_t *this, fd_t *fd, - struct stat *stbuf, - int32_t valid); + struct iatt *stbuf, + int32_t valid, dict_t *xdata); +typedef int32_t (*fop_fallocate_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + int32_t keep_size, + off_t offset, + size_t len, + dict_t *xdata); + +typedef int32_t (*fop_discard_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + off_t offset, + size_t len, + dict_t *xdata); +typedef int32_t (*fop_zerofill_t) (call_frame_t *frame, + xlator_t *this, + fd_t *fd, + off_t offset, + size_t len, + dict_t *xdata); 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_readdirp_t readdirp; - fop_fsyncdir_t fsyncdir; - fop_statfs_t statfs; - fop_setxattr_t setxattr; - fop_getxattr_t getxattr; - fop_fsetxattr_t fsetxattr; - fop_fgetxattr_t fgetxattr; - 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_rchecksum_t rchecksum; - fop_xattrop_t xattrop; - fop_fxattrop_t fxattrop; - fop_lock_notify_t lock_notify; - fop_lock_fnotify_t lock_fnotify; + fop_lookup_t lookup; + fop_stat_t stat; + fop_fstat_t fstat; + fop_truncate_t truncate; + fop_ftruncate_t ftruncate; + 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_readdirp_t readdirp; + fop_fsyncdir_t fsyncdir; + fop_statfs_t statfs; + fop_setxattr_t setxattr; + fop_getxattr_t getxattr; + fop_fsetxattr_t fsetxattr; + fop_fgetxattr_t fgetxattr; + fop_removexattr_t removexattr; + fop_fremovexattr_t fremovexattr; + fop_lk_t lk; + fop_inodelk_t inodelk; + fop_finodelk_t finodelk; + fop_entrylk_t entrylk; + fop_fentrylk_t fentrylk; + fop_rchecksum_t rchecksum; + fop_xattrop_t xattrop; + fop_fxattrop_t fxattrop; fop_setattr_t setattr; fop_fsetattr_t fsetattr; - - /* 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_readdirp_cbk_t readdirp_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_fsetxattr_cbk_t fsetxattr_cbk; - fop_fgetxattr_cbk_t fgetxattr_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_rchecksum_cbk_t rchecksum_cbk; - fop_xattrop_cbk_t xattrop_cbk; - fop_fxattrop_cbk_t fxattrop_cbk; - fop_lock_notify_cbk_t lock_notify_cbk; - fop_lock_fnotify_cbk_t lock_fnotify_cbk; + fop_getspec_t getspec; + fop_fallocate_t fallocate; + fop_discard_t discard; + fop_zerofill_t zerofill; + + /* 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_truncate_cbk_t truncate_cbk; + fop_ftruncate_cbk_t ftruncate_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_readdirp_cbk_t readdirp_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_fsetxattr_cbk_t fsetxattr_cbk; + fop_fgetxattr_cbk_t fgetxattr_cbk; + fop_removexattr_cbk_t removexattr_cbk; + fop_fremovexattr_cbk_t fremovexattr_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_rchecksum_cbk_t rchecksum_cbk; + fop_xattrop_cbk_t xattrop_cbk; + fop_fxattrop_cbk_t fxattrop_cbk; fop_setattr_cbk_t setattr_cbk; fop_fsetattr_cbk_t fsetattr_cbk; + fop_getspec_cbk_t getspec_cbk; + fop_fallocate_cbk_t fallocate_cbk; + fop_discard_cbk_t discard_cbk; + fop_zerofill_cbk_t zerofill_cbk; }; typedef int32_t (*cbk_forget_t) (xlator_t *this, - inode_t *inode); + inode_t *inode); typedef int32_t (*cbk_release_t) (xlator_t *this, - fd_t *fd); + fd_t *fd); + +typedef int32_t (*cbk_invalidate_t)(xlator_t *this, inode_t *inode); + +typedef int32_t (*cbk_client_t)(xlator_t *this, client_t *client); struct xlator_cbks { - cbk_forget_t forget; - cbk_release_t release; - cbk_release_t releasedir; + cbk_forget_t forget; + cbk_release_t release; + cbk_release_t releasedir; + cbk_invalidate_t invalidate; + cbk_client_t client_destroy; + cbk_client_t client_disconnect; }; typedef int32_t (*dumpop_priv_t) (xlator_t *this); @@ -921,94 +802,120 @@ typedef int32_t (*dumpop_fd_t) (xlator_t *this); typedef int32_t (*dumpop_inodectx_t) (xlator_t *this, inode_t *ino); - +typedef int32_t (*dumpop_fdctx_t) (xlator_t *this, fd_t *fd); + +typedef int32_t (*dumpop_priv_to_dict_t) (xlator_t *this, dict_t *dict); + +typedef int32_t (*dumpop_inode_to_dict_t) (xlator_t *this, dict_t *dict); + +typedef int32_t (*dumpop_fd_to_dict_t) (xlator_t *this, dict_t *dict); + +typedef int32_t (*dumpop_inodectx_to_dict_t) (xlator_t *this, inode_t *ino, + dict_t *dict); + +typedef int32_t (*dumpop_fdctx_to_dict_t) (xlator_t *this, fd_t *fd, + dict_t *dict); + +typedef int32_t (*dumpop_eh_t) (xlator_t *this); + struct xlator_dumpops { - dumpop_priv_t priv; - dumpop_inode_t inode; - dumpop_fd_t fd; - dumpop_inodectx_t inodectx; + dumpop_priv_t priv; + dumpop_inode_t inode; + dumpop_fd_t fd; + dumpop_inodectx_t inodectx; + dumpop_fdctx_t fdctx; + dumpop_priv_to_dict_t priv_to_dict; + dumpop_inode_to_dict_t inode_to_dict; + dumpop_fd_to_dict_t fd_to_dict; + dumpop_inodectx_to_dict_t inodectx_to_dict; + dumpop_fdctx_to_dict_t fdctx_to_dict; + dumpop_eh_t history; }; typedef struct xlator_list { - xlator_t *xlator; - struct xlator_list *next; + 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_PERCENT_OR_SIZET, - GF_OPTION_TYPE_BOOL, - GF_OPTION_TYPE_XLATOR, - GF_OPTION_TYPE_PATH, - GF_OPTION_TYPE_TIME, - GF_OPTION_TYPE_DOUBLE, - GF_OPTION_TYPE_INTERNET_ADDRESS, -} 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 xlator_dumpops *dumpops; - struct list_head volume_options; /* list of volume_option_t */ - - void (*fini) (xlator_t *this); - int32_t (*init) (xlator_t *this); + /* 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() */ + void *dlhandle; + struct xlator_fops *fops; + struct xlator_cbks *cbks; + struct xlator_dumpops *dumpops; + struct list_head volume_options; /* list of volume_option_t */ + + void (*fini) (xlator_t *this); + int32_t (*init) (xlator_t *this); + int32_t (*reconfigure) (xlator_t *this, dict_t *options); + int32_t (*mem_acct_init) (xlator_t *this); event_notify_fn_t notify; - /* Misc */ - glusterfs_ctx_t *ctx; - inode_table_t *itable; - char ready; - char init_succeeded; - void *private; + gf_loglevel_t loglevel; /* Log level for translator */ + + /* for latency measurement */ + fop_latency_t latencies[GF_FOP_MAXVALUE]; + + /* Misc */ + eh_t *history; /* event history context */ + glusterfs_ctx_t *ctx; + glusterfs_graph_t *graph; /* not set for fuse */ + inode_table_t *itable; + char init_succeeded; + void *private; + struct mem_acct mem_acct; + uint64_t winds; + char switched; + + /* for the memory pool of 'frame->local' */ + struct mem_pool *local_pool; + gf_boolean_t is_autoloaded; }; -int validate_xlator_volume_options (xlator_t *xl, volume_option_t *opt); +typedef struct { + int32_t (*init) (xlator_t *this); + void (*fini) (xlator_t *this); + int32_t (*reconfigure) (xlator_t *this, + dict_t *options); + event_notify_fn_t notify; +} class_methods_t; + +#define xlator_has_parent(xl) (xl->parents != NULL) + +#define XLATOR_NOTIFY(_xl, params ...) \ + do { \ + xlator_t *_old_THIS = NULL; \ + \ + _old_THIS = THIS; \ + THIS = _xl; \ + \ + ret = _xl->notify (_xl, params);\ + \ + THIS = _old_THIS; \ + } while (0); + +int32_t xlator_set_type_virtual (xlator_t *xl, const char *type); int32_t xlator_set_type (xlator_t *xl, const char *type); +int32_t xlator_dynload (xlator_t *xl); + xlator_t *file_to_xlator_tree (glusterfs_ctx_t *ctx, - FILE *fp); + FILE *fp); int xlator_notify (xlator_t *this, int32_t event, void *data, ...); int xlator_init (xlator_t *this); +int xlator_destroy (xlator_t *xl); int32_t xlator_tree_init (xlator_t *xl); int32_t xlator_tree_free (xlator_t *xl); @@ -1016,9 +923,14 @@ 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); + void (*fn) (xlator_t *each, + void *data), + void *data); + +void xlator_foreach_depth_first (xlator_t *this, + void (*fn) (xlator_t *each, + void *data), + void *data); xlator_t *xlator_search_by_name (xlator_t *any, const char *name); @@ -1027,14 +939,22 @@ 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" - +int loc_path (loc_t *loc, const char *bname); +void loc_gfid (loc_t *loc, uuid_t gfid); +char* loc_gfid_utoa (loc_t *loc); +gf_boolean_t loc_is_root (loc_t *loc); +int xlator_mem_acct_init (xlator_t *xl, int num_types); +int is_gf_log_command (xlator_t *trans, const char *name, char *value); +int glusterd_check_log_level (const char *value); +int xlator_volopt_dynload (char *xlator_type, void **dl_handle, + volume_opt_list_t *vol_opt_handle); +enum gf_hdsk_event_notify_op { + GF_EN_DEFRAG_STATUS, + GF_EN_MAX, +}; +gf_boolean_t +is_graph_topology_equal (glusterfs_graph_t *graph1, glusterfs_graph_t *graph2); +int +glusterfs_volfile_reconfigure (int oldvollen, FILE *newvolfile_fp, + glusterfs_ctx_t *ctx, const char *oldvolfile); #endif /* _XLATOR_H */ - |
