diff options
Diffstat (limited to 'libglusterfs/src')
90 files changed, 25274 insertions, 13983 deletions
diff --git a/libglusterfs/src/Makefile.am b/libglusterfs/src/Makefile.am index 71a088d98..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\" -D$(GF_HOST_OS) -I$(CONTRIBDIR)/rbtree -DSCHEDULERDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/scheduler\" -I$(CONTRIBDIR)/md5 +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 graph.lex.c y.tab.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 $(CONTRIBDIR)/md5/md5.c $(CONTRIBDIR)/rbtree/rb.c rbthash.c latency.c graph.c $(CONTRIBDIR)/uuid/clear.c $(CONTRIBDIR)/uuid/copy.c $(CONTRIBDIR)/uuid/gen_uuid.c $(CONTRIBDIR)/uuid/pack.c $(CONTRIBDIR)/uuid/tst_uuid.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 - -noinst_HEADERS = common-utils.h defaults.h dict.h glusterfs.h hashfn.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 $(CONTRIBDIR)/md5/md5.h $(CONTRIBDIR)/rbtree/rb.h rbthash.h iatt.h latency.h mem-types.h $(CONTRIBDIR)/uuid/uuidd.h $(CONTRIBDIR)/uuid/uuid.h $(CONTRIBDIR)/uuid/uuidP.h $(CONTRIBDIR)/uuid/uuid_types.h syncop.h graph-utils.h graph-mem-types.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) -t $(srcdir)/graph.l > $@ + $(LEX) -Pgraphyy -t $(srcdir)/graph.l > $@ -y.tab.c y.tab.h: graph.y - $(YACC) -d $(srcdir)/graph.y +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/byte-order.h b/libglusterfs/src/byte-order.h index cabfcf4c6..4101db2c7 100644 --- a/libglusterfs/src/byte-order.h +++ b/libglusterfs/src/byte-order.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 d3b29a39a..ac79cf071 100644 --- a/libglusterfs/src/call-stub.c +++ b/libglusterfs/src/call-stub.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,3846 +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) + char wind, + glusterfs_fop_t fop) { - call_stub_t *new = NULL; + call_stub_t *new = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - new = mem_get0 (frame->this->ctx->stub_mem_pool); - GF_VALIDATE_OR_GOTO ("call-stub", new, out); + new = mem_get0 (frame->this->ctx->stub_mem_pool); + GF_VALIDATE_OR_GOTO ("call-stub", new, 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); + new->frame = frame; + new->wind = wind; + new->fop = fop; + new->stub_mem_pool = frame->this->ctx->stub_mem_pool; + INIT_LIST_HEAD (&new->list); + + INIT_LIST_HEAD (&new->args_cbk.entries); out: - return new; + return new; } call_stub_t * -fop_lookup_stub (call_frame_t *frame, - fop_lookup_t fn, - loc_t *loc, - dict_t *xattr_req) +fop_lookup_stub (call_frame_t *frame, fop_lookup_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", 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_LOOKUP); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub = stub_new (frame, 1, GF_FOP_LOOKUP); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.lookup.fn = fn; + stub->fn.lookup = fn; - if (xattr_req) - stub->args.lookup.xattr_req = dict_ref (xattr_req); + loc_copy (&stub->args.loc, loc); + if (xdata) + stub->args.xdata = dict_ref (xdata); - loc_copy (&stub->args.lookup.loc, loc); out: - return stub; + 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 iatt *buf, - dict_t *dict, - struct iatt *postparent) +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, 0, GF_FOP_LOOKUP); - 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.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); + 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.lookup_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_stat_stub (call_frame_t *frame, - fop_stat_t fn, - loc_t *loc) +fop_stat_stub (call_frame_t *frame, fop_stat_t fn, + loc_t *loc, dict_t *xdata) { - call_stub_t *stub = NULL; - - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - GF_VALIDATE_OR_GOTO ("call-stub", loc, out); + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", loc, out); - stub = stub_new (frame, 1, GF_FOP_STAT); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub = stub_new (frame, 1, GF_FOP_STAT); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.stat.fn = fn; - loc_copy (&stub->args.stat.loc, loc); + 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_stat_cbk_stub (call_frame_t *frame, - fop_stat_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct iatt *buf) +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; - - 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_STAT); - 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.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; + 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_fstat_stub (call_frame_t *frame, - fop_fstat_t fn, - fd_t *fd) +fop_fstat_stub (call_frame_t *frame, fop_fstat_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_FSTAT); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub = stub_new (frame, 1, GF_FOP_FSTAT); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.fstat.fn = fn; + stub->fn.fstat = fn; - if (fd) - stub->args.fstat.fd = fd_ref (fd); + 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_fstat_cbk_stub (call_frame_t *frame, - fop_fstat_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct iatt *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_FSTAT); - 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.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; + 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 iatt *prebuf, - struct iatt *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 iatt *prebuf, - struct iatt *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; + 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_FTRUNCATE); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub = stub_new (frame, 0, GF_FOP_FTRUNCATE); - 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.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; + return stub; } call_stub_t * -fop_access_stub (call_frame_t *frame, - fop_access_t fn, - loc_t *loc, - int32_t mask) +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", 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_ACCESS); - 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.access.fn = fn; - loc_copy (&stub->args.access.loc, loc); - stub->args.access.mask = mask; + 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_cbk_stub (call_frame_t *frame, - fop_access_cbk_t fn, - int32_t op_ret, - int32_t op_errno) +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", frame, out); - stub = stub_new (frame, 0, 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_cbk.fn = fn; - stub->args.access_cbk.op_ret = op_ret; - stub->args.access_cbk.op_errno = op_errno; + 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_readlink_stub (call_frame_t *frame, - fop_readlink_t fn, - loc_t *loc, - size_t size) +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; + 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 iatt *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 = gf_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, dict_t *params) +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; - if (params) - stub->args.mknod.params = dict_ref (params); + 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 iatt *buf, - struct iatt *preparent, - struct iatt *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, dict_t *params) + 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 (params) - stub->args.mkdir.params = dict_ref (params); + 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 iatt *buf, - struct iatt *preparent, - struct iatt *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 iatt *preparent, - struct iatt *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, int flags) + 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->args.rmdir.flags = flags; + 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 iatt *preparent, - struct iatt *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, dict_t *params) + 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 = gf_strdup (linkname); - loc_copy (&stub->args.symlink.loc, loc); - if (params) - stub->args.symlink.params = dict_ref (params); + 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 iatt *buf, - struct iatt *preparent, - struct iatt *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 iatt *buf, - struct iatt *preoldparent, - struct iatt *postoldparent, - struct iatt *prenewparent, - struct iatt *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 iatt *buf, - struct iatt *preparent, - struct iatt *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, dict_t *params) + 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); - if (params) - stub->args.create.params = dict_ref (params); + 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 iatt *buf, - struct iatt *preparent, - struct iatt *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; + 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_CREATE); - GF_VALIDATE_OR_GOTO ("call-stub", stub, 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; + 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->fn.readv = fn; + if (fd) + stub->args.fd = fd_ref (fd); + stub->args.size = size; + stub->args.offset = off; + stub->args.flags = flags; - stub->args.readv.fn = fn; - if (fd) - stub->args.readv.fd = fd_ref (fd); - stub->args.readv.size = size; - stub->args.readv.off = off; + 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 iatt *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; + 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_READ); - GF_VALIDATE_OR_GOTO ("call-stub", stub, 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); - } + 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 iatt *prebuf, - struct iatt *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 iatt *prebuf, - struct iatt *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_fsyncdir_stub (call_frame_t *frame, - fop_fsyncdir_t fn, - fd_t *fd, - int32_t datasync) +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_FSYNCDIR); - 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.fsyncdir.fn = fn; - if (fd) - stub->args.fsyncdir.fd = fd_ref (fd); - stub->args.fsyncdir.datasync = datasync; + 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_fsyncdir_cbk_stub (call_frame_t *frame, - fop_fsyncdir_cbk_t fn, - int32_t op_ret, - int32_t op_errno) - +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; + 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_FSYNCDIR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.fsyncdir_cbk.fn = fn; - stub->args.fsyncdir_cbk.op_ret = op_ret; - stub->args.fsyncdir_cbk.op_errno = op_errno; + 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_statfs_stub (call_frame_t *frame, - fop_statfs_t fn, - loc_t *loc) +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", 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_STATFS); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.statfs.fn = fn; - loc_copy (&stub->args.statfs.loc, loc); + 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_statfs_cbk_stub (call_frame_t *frame, - fop_statfs_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct statvfs *buf) - +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_STATFS); - 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.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.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_setxattr_stub (call_frame_t *frame, - fop_setxattr_t fn, - loc_t *loc, - dict_t *dict, - int32_t flags) +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_SETXATTR); - 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.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.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_setxattr_cbk_stub (call_frame_t *frame, - fop_setxattr_cbk_t fn, - int32_t op_ret, - int32_t op_errno) + 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_SETXATTR); - 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.setxattr_cbk.fn = fn; - stub->args.setxattr_cbk.op_ret = op_ret; - stub->args.setxattr_cbk.op_errno = op_errno; + 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_getxattr_stub (call_frame_t *frame, - fop_getxattr_t fn, - loc_t *loc, - const char *name) +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_GETXATTR); - 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.getxattr.fn = fn; - loc_copy (&stub->args.getxattr.loc, loc); + stub->fn.getxattr = fn; + loc_copy (&stub->args.loc, loc); - if (name) - stub->args.getxattr.name = gf_strdup (name); + 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_getxattr_cbk_stub (call_frame_t *frame, - fop_getxattr_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - dict_t *dict) +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_GETXATTR); - 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.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.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_fsetxattr_stub (call_frame_t *frame, - fop_fsetxattr_t fn, - fd_t *fd, - dict_t *dict, - int32_t flags) +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", 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_FSETXATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.fsetxattr.fn = fn; - stub->args.fsetxattr.fd = fd_ref (fd); + stub->fn.fsetxattr = fn; + stub->args.fd = fd_ref (fd); - /* TODO */ - if (dict) - stub->args.fsetxattr.dict = dict_ref (dict); - stub->args.fsetxattr.flags = flags; + 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_fsetxattr_cbk_stub (call_frame_t *frame, - fop_fsetxattr_cbk_t fn, - int32_t op_ret, - int32_t op_errno) +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_FSETXATTR); - 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.fsetxattr_cbk.fn = fn; - stub->args.fsetxattr_cbk.op_ret = op_ret; - stub->args.fsetxattr_cbk.op_errno = op_errno; + 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_fgetxattr_stub (call_frame_t *frame, - fop_fgetxattr_t fn, - fd_t *fd, - const char *name) +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_FGETXATTR); - 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.fgetxattr.fn = fn; - stub->args.fgetxattr.fd = fd_ref (fd); + stub->fn.fgetxattr = fn; + stub->args.fd = fd_ref (fd); - if (name) - stub->args.fgetxattr.name = gf_strdup (name); + 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_fgetxattr_cbk_stub (call_frame_t *frame, - fop_fgetxattr_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - dict_t *dict) +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_GETXATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.fgetxattr_cbk.fn = fn; - stub->args.fgetxattr_cbk.op_ret = op_ret; - stub->args.fgetxattr_cbk.op_errno = op_errno; + stub->fn_cbk.fgetxattr = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; - /* TODO */ - if (dict) - stub->args.fgetxattr_cbk.dict = dict_ref (dict); + 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_removexattr_stub (call_frame_t *frame, - fop_removexattr_t fn, - loc_t *loc, - 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; + 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", loc, out); + GF_VALIDATE_OR_GOTO ("call-stub", name, out); - stub = stub_new (frame, 1, GF_FOP_REMOVEXATTR); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub = stub_new (frame, 1, GF_FOP_REMOVEXATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.removexattr.fn = fn; - loc_copy (&stub->args.removexattr.loc, loc); - stub->args.removexattr.name = gf_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_removexattr_cbk_stub (call_frame_t *frame, - fop_removexattr_cbk_t fn, - int32_t op_ret, - int32_t op_errno) +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; + 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_REMOVEXATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.removexattr_cbk.fn = fn; - stub->args.removexattr_cbk.op_ret = op_ret; - stub->args.removexattr_cbk.op_errno = op_errno; + 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_lk_stub (call_frame_t *frame, - fop_lk_t fn, - fd_t *fd, - int32_t cmd, - struct gf_flock *lock) +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", fd, out); + GF_VALIDATE_OR_GOTO ("call-stub", name, out); - 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 = stub_new (frame, 1, GF_FOP_FREMOVEXATTR); + 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; + 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_lk_cbk_stub (call_frame_t *frame, - fop_lk_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct gf_flock *lock) +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; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_FREMOVEXATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + 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; +} + +call_stub_t * +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; + 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", lock, out); - stub = stub_new (frame, 0, GF_FOP_LK); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + stub = stub_new (frame, 1, 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.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_inodelk_stub (call_frame_t *frame, fop_inodelk_t fn, - const char *volume, loc_t *loc, int32_t cmd, struct gf_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; - if (!frame || !lock) - return NULL; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - stub = stub_new (frame, 1, GF_FOP_INODELK); - if (!stub) - return NULL; + stub = stub_new (frame, 0, GF_FOP_LK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.inodelk.fn = fn; + 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; +} - if (volume) - stub->args.inodelk.volume = gf_strdup (volume); - loc_copy (&stub->args.inodelk.loc, loc); - stub->args.inodelk.cmd = cmd; - stub->args.inodelk.lock = *lock; +call_stub_t * +fop_inodelk_stub (call_frame_t *frame, fop_inodelk_t fn, + const char *volume, loc_t *loc, int32_t cmd, + struct gf_flock *lock, dict_t *xdata) +{ + call_stub_t *stub = NULL; - return stub; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", lock, out); + + stub = stub_new (frame, 1, GF_FOP_INODELK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->fn.inodelk = fn; + + if (volume) + stub->args.volume = gf_strdup (volume); + + 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 gf_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 = gf_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; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - if (!frame) - return NULL; + stub = stub_new (frame, 1, GF_FOP_ENTRYLK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub = stub_new (frame, 1, GF_FOP_ENTRYLK); - if (!stub) - return NULL; + stub->fn.entrylk = fn; - stub->args.entrylk.fn = fn; + if (volume) + stub->args.volume = gf_strdup (volume); - if (volume) - stub->args.entrylk.volume = gf_strdup (volume); + loc_copy (&stub->args.loc, loc); - loc_copy (&stub->args.entrylk.loc, loc); + stub->args.entrylkcmd = cmd; + stub->args.entrylktype = type; - stub->args.entrylk.cmd = cmd; - stub->args.entrylk.type = type; - if (name) - stub->args.entrylk.name = gf_strdup (name); + 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_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 = gf_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 = gf_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; + call_stub_t *stub = NULL; - if (!frame) - return NULL; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - stub = stub_new (frame, 0, GF_FOP_FENTRYLK); - if (!stub) - return NULL; + stub = stub_new (frame, 0, GF_FOP_FENTRYLK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.fentrylk_cbk.fn = fn; - stub->args.fentrylk_cbk.op_ret = op_ret; - stub->args.fentrylk_cbk.op_errno = op_errno; + stub->fn_cbk.fentrylk = 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_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; + call_stub_t *stub = NULL; + gf_dirent_t *stub_entry = NULL, *entry = NULL; - GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + 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 = 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); + stub->fn_cbk.readdirp = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; - /* 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; + 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 (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; - list_add_tail (&stub_entry->list, - &stub->args.readdirp_cbk.entries.list); - } - } + 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; + call_stub_t *stub = NULL; + gf_dirent_t *stub_entry = NULL, *entry = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - 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 = 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); + stub->fn_cbk.readdir = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; - /* 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; + 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 (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_off = entry->d_off; + stub_entry->d_ino = entry->d_ino; - list_add_tail (&stub_entry->list, - &stub->args.readdir_cbk.entries.list); - } - } + 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_stub (call_frame_t *frame, - fop_readdir_t fn, - fd_t *fd, - size_t size, - off_t off) +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; - 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, 1, GF_FOP_READDIR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - return stub; + stub->fn.readdir = 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; } + call_stub_t * -fop_readdirp_stub (call_frame_t *frame, - fop_readdirp_t fn, - fd_t *fd, - size_t size, - off_t off) +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; + call_stub_t *stub = NULL; - 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; + stub = stub_new (frame, 1, GF_FOP_READDIRP); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - return stub; + 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; } + 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); - - stub = stub_new (frame, 0, GF_FOP_XATTROP); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - stub->args.xattrop_cbk.fn = fn; - stub->args.xattrop_cbk.op_ret = op_ret; - stub->args.xattrop_cbk.op_errno = op_errno; + stub = stub_new (frame, 0, GF_FOP_XATTROP); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + 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, 0, 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_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) +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; - if (frame == NULL) - goto out; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - stub = stub_new (frame, 0, GF_FOP_SETATTR); - if (stub == NULL) - goto out; + stub = stub_new (frame, 0, GF_FOP_SETATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.setattr_cbk.fn = fn; + stub->fn_cbk.setattr = 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 iatt *statpre, - struct iatt *statpost) +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; - if (frame == NULL) - goto out; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - stub = stub_new (frame, 0, GF_FOP_FSETATTR); - if (stub == NULL) - goto out; + stub = stub_new (frame, 0, GF_FOP_FSETATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.fsetattr_cbk.fn = fn; + stub->fn_cbk.fsetattr = fn; - stub->args.fsetattr_cbk.op_ret = op_ret; - stub->args.fsetattr_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.fsetattr_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_setattr_stub (call_frame_t *frame, - fop_setattr_t fn, - loc_t *loc, - struct iatt *stbuf, - int32_t valid) +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; - if (frame == NULL) - goto out; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fn, out); - if (fn == NULL) - goto out; + stub = stub_new (frame, 1, GF_FOP_SETATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub = stub_new (frame, 1, GF_FOP_SETATTR); - if (stub == NULL) - goto out; + stub->fn.setattr = fn; - stub->args.setattr.fn = fn; - - loc_copy (&stub->args.setattr.loc, loc); + loc_copy (&stub->args.loc, loc); if (stbuf) - stub->args.setattr.stbuf = *stbuf; + stub->args.stat = *stbuf; - stub->args.setattr.valid = valid; + stub->args.valid = valid; + if (xdata) + stub->args.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 iatt *stbuf, - int32_t valid) +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; - if (frame == NULL) - goto out; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fn, out); - if (fn == NULL) - goto out; + stub = stub_new (frame, 1, GF_FOP_FSETATTR); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub = stub_new (frame, 1, GF_FOP_FSETATTR); - if (stub == NULL) - goto out; - - stub->args.fsetattr.fn = fn; + stub->fn.fsetattr = 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.stat = *stbuf; - stub->args.fsetattr.valid = valid; + stub->args.valid = valid; + 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_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) { - 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, - stub->args.create.params); - 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, - stub->args.mknod.params); - } - break; - - case GF_FOP_MKDIR: - { - stub->args.mkdir.fn (stub->frame, stub->frame->this, - &stub->args.mkdir.loc, - stub->args.mkdir.mode, - stub->args.mkdir.params); - } - 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, - stub->args.rmdir.flags); - } - break; - - case GF_FOP_SYMLINK: - { - stub->args.symlink.fn (stub->frame, - stub->frame->this, - stub->args.symlink.linkname, - &stub->args.symlink.loc, - stub->args.symlink.params); - } - 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_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_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; - } - - 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_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_FALLOCATE); + 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.fallocate = fn; - 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_ERROR, "Invalid value of FOP (%d)", - stub->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; } +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 *stub = NULL; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fn, out); -static void -call_resume_unwind (call_stub_t *stub) -{ - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - - switch (stub->fop) { - case GF_FOP_OPEN: - { - if (!stub->args.open_cbk.fn) - STACK_UNWIND (stub->frame, - stub->args.open_cbk.op_ret, - stub->args.open_cbk.op_errno, - stub->args.open_cbk.fd); - else - stub->args.open_cbk.fn (stub->frame, - stub->frame->cookie, - stub->frame->this, - stub->args.open_cbk.op_ret, - stub->args.open_cbk.op_errno, - stub->args.open_cbk.fd); - break; - } - - case GF_FOP_CREATE: - { - if (!stub->args.create_cbk.fn) - STACK_UNWIND (stub->frame, - stub->args.create_cbk.op_ret, - stub->args.create_cbk.op_errno, - stub->args.create_cbk.fd, - stub->args.create_cbk.inode, - &stub->args.create_cbk.buf, - &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); + stub = stub_new (frame, 1, GF_FOP_FALLOCATE); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - 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); + stub->fn.fallocate = fn; - 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); + if (fd) + stub->args.fd = fd_ref (fd); - 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.rmdir_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_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->args.flags = mode; + stub->args.offset = offset; + stub->args.size = len; - 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); + if (xdata) + stub->args.xdata = dict_ref (xdata); +out: + return stub; - 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); +} - 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_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); +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 *stub = NULL; - 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_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); + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - 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) - { - GF_FREE (stub->args.rchecksum_cbk.strong_checksum); - } + stub = stub_new (frame, 0, GF_FOP_DISCARD); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - 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); + stub->fn_cbk.discard = fn; - break; - } + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; - 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); + 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; +} - 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); +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 *stub = NULL; - 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); + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fn, out); - 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); - 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); - break; - } - default: - { - gf_log ("call-stub", GF_LOG_ERROR, "Invalid value of FOP (%d)", - stub->fop); - break; - } - } + stub = stub_new (frame, 1, GF_FOP_DISCARD); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->fn.discard = fn; + + if (fd) + stub->args.fd = fd_ref (fd); + + stub->args.offset = offset; + stub->args.size = len; + + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return; + return 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) +{ + call_stub_t *stub = NULL; -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); - if (stub->args.create.params) - dict_unref (stub->args.create.params); - 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); - if (stub->args.mknod.params) - dict_unref (stub->args.mknod.params); - } - break; - - case GF_FOP_MKDIR: - { - loc_wipe (&stub->args.mkdir.loc); - if (stub->args.mkdir.params) - dict_unref (stub->args.mkdir.params); - } - 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: - { - GF_FREE ((char *)stub->args.symlink.linkname); - loc_wipe (&stub->args.symlink.loc); - if (stub->args.symlink.params) - dict_unref (stub->args.symlink.params); - } - 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_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); - GF_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; - } + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - 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) - GF_FREE ((char *)stub->args.getxattr.name); - loc_wipe (&stub->args.getxattr.loc); - break; - } + stub = stub_new (frame, 0, GF_FOP_ZEROFILL); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - case GF_FOP_FSETXATTR: - { - fd_unref (stub->args.fsetxattr.fd); - if (stub->args.fsetxattr.dict) - dict_unref (stub->args.fsetxattr.dict); - break; - } + stub->fn_cbk.zerofill = fn; - case GF_FOP_FGETXATTR: - { - if (stub->args.fgetxattr.name) - GF_FREE ((char *)stub->args.fgetxattr.name); - fd_unref (stub->args.fgetxattr.fd); - break; - } + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; - case GF_FOP_REMOVEXATTR: - { - loc_wipe (&stub->args.removexattr.loc); - GF_FREE ((char *)stub->args.removexattr.name); - break; - } + 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; +} - case GF_FOP_OPENDIR: - { - loc_wipe (&stub->args.opendir.loc); - if (stub->args.opendir.fd) - fd_unref (stub->args.opendir.fd); - break; - } +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 *stub = NULL; - 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; - } + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fn, out); - case GF_FOP_INODELK: - { - if (stub->args.inodelk.volume) - GF_FREE ((char *)stub->args.inodelk.volume); + stub = stub_new (frame, 1, GF_FOP_ZEROFILL); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - loc_wipe (&stub->args.inodelk.loc); - break; - } - case GF_FOP_FINODELK: - { - if (stub->args.finodelk.volume) - GF_FREE ((char *)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) - GF_FREE ((char *)stub->args.entrylk.volume); - - if (stub->args.entrylk.name) - GF_FREE ((char *)stub->args.entrylk.name); - loc_wipe (&stub->args.entrylk.loc); - break; - } - case GF_FOP_FENTRYLK: - { - if (stub->args.fentrylk.volume) - GF_FREE ((char *)stub->args.fentrylk.volume); + stub->fn.zerofill = fn; - if (stub->args.fentrylk.name) - GF_FREE ((char *)stub->args.fentrylk.name); + if (fd) + stub->args.fd = fd_ref (fd); - if (stub->args.fentrylk.fd) - fd_unref (stub->args.fentrylk.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; - } + stub->args.offset = offset; + stub->args.size = len; - case GF_FOP_RCHECKSUM: - { - if (stub->args.rchecksum.fd) - fd_unref (stub->args.rchecksum.fd); - break; - } + if (xdata) + stub->args.xdata = dict_ref (xdata); +out: + return stub; - case GF_FOP_READDIR: - { - if (stub->args.readdir.fd) - fd_unref (stub->args.readdir.fd); - 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.fxattrop.xattr); - break; - } +static void +call_resume_wind (call_stub_t *stub) +{ + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + switch (stub->fop) { + case GF_FOP_OPEN: + stub->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: + 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: - { - loc_wipe (&stub->args.setattr.loc); + 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.fd) - fd_unref (stub->args.fsetattr.fd); + 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 ("call-stub", GF_LOG_ERROR, "Invalid value of FOP (%d)", - stub->fop); + gf_log_callingfn ("call-stub", GF_LOG_ERROR, + "Invalid value of FOP (%d)", + stub->fop); break; - } - } + } +out: + return; } +#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) + + static void -call_stub_destroy_unwind (call_stub_t *stub) -{ - switch (stub->fop) { - case GF_FOP_OPEN: - { - if (stub->args.open_cbk.fd) - fd_unref (stub->args.open_cbk.fd); - } - break; - - case GF_FOP_CREATE: - { - if (stub->args.create_cbk.fd) - fd_unref (stub->args.create_cbk.fd); - - if (stub->args.create_cbk.inode) - inode_unref (stub->args.create_cbk.inode); - } - break; - - case GF_FOP_STAT: - break; +call_resume_unwind (call_stub_t *stub) +{ + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - case GF_FOP_READLINK: - { - if (stub->args.readlink_cbk.buf) - GF_FREE ((char *)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: + 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_RMDIR: + 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_SYMLINK: - { - if (stub->args.symlink_cbk.inode) - inode_unref (stub->args.symlink_cbk.inode); - } - break; - - case GF_FOP_RENAME: + 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_LINK: - { - if (stub->args.link_cbk.inode) - inode_unref (stub->args.link_cbk.inode); - } - break; - - case GF_FOP_TRUNCATE: + case GF_FOP_READDIR: + STUB_UNWIND (stub, readdir, &stub->args_cbk.entries, + stub->args_cbk.xdata); break; - - case GF_FOP_READ: - { - if (stub->args.readv_cbk.op_ret >= 0) { - struct iobref *iobref = stub->args.readv_cbk.iobref; - GF_FREE (stub->args.readv_cbk.vector); - - if (iobref) { - iobref_unref (iobref); - } - } - } - break; - - case GF_FOP_WRITE: + case GF_FOP_READDIRP: + 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_STATFS: + case GF_FOP_FXATTROP: + STUB_UNWIND (stub, fxattrop, stub->args_cbk.xattr, + stub->args_cbk.xdata); break; - - case GF_FOP_FLUSH: + case GF_FOP_SETATTR: + STUB_UNWIND (stub, setattr, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); + break; + case GF_FOP_FSETATTR: + STUB_UNWIND (stub, fsetattr, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); + break; + case GF_FOP_FALLOCATE: + STUB_UNWIND(stub, fallocate, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); break; - - case GF_FOP_FSYNC: + 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; - 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; + default: + gf_log_callingfn ("call-stub", GF_LOG_ERROR, + "Invalid value of FOP (%d)", + stub->fop); + break; + } +out: + return; +} - case GF_FOP_FGETXATTR: - { - if (stub->args.fgetxattr_cbk.dict) - dict_unref (stub->args.fgetxattr_cbk.dict); - } - break; - case GF_FOP_REMOVEXATTR: - break; +static void +call_stub_wipe_args (call_stub_t *stub) +{ + loc_wipe (&stub->args.loc); - case GF_FOP_OPENDIR: - { - if (stub->args.opendir_cbk.fd) - fd_unref (stub->args.opendir_cbk.fd); - } - break; + loc_wipe (&stub->args.loc2); - 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; + if (stub->args.fd) + fd_unref (stub->args.fd); - case GF_FOP_INODELK: - break; + GF_FREE ((char *)stub->args.linkname); - case GF_FOP_FINODELK: - break; + GF_FREE (stub->args.vector); - case GF_FOP_ENTRYLK: - break; + if (stub->args.iobref) + iobref_unref (stub->args.iobref); - case GF_FOP_FENTRYLK: - break; + if (stub->args.xattr) + dict_unref (stub->args.xattr); - 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_RCHECKSUM: - { - if (stub->args.rchecksum_cbk.op_ret >= 0) { - GF_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; + GF_FREE ((char *)stub->args.name); - 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; - } + GF_FREE ((char *)stub->args.volume); - case GF_FOP_FSETATTR: - { - break; - } + if (stub->args.xdata) + dict_unref (stub->args.xdata); +} - default: - { - gf_log ("call-stub", GF_LOG_ERROR, "Invalid value of FOP (%d)", - stub->fop); - break; - } - } + +static void +call_stub_wipe_args_cbk (call_stub_t *stub) +{ + if (stub->args_cbk.inode) + inode_unref (stub->args_cbk.inode); + + GF_FREE ((char *)stub->args_cbk.buf); + + GF_FREE (stub->args_cbk.vector); + + if (stub->args_cbk.iobref) + iobref_unref (stub->args_cbk.iobref); + + if (stub->args_cbk.fd) + fd_unref (stub->args_cbk.fd); + + if (stub->args_cbk.xattr) + dict_unref (stub->args_cbk.xattr); + + GF_FREE (stub->args_cbk.strong_checksum); + + if (stub->args_cbk.xdata) + dict_unref (stub->args_cbk.xdata); + + if (!list_empty (&stub->args_cbk.entries.list)) + gf_dirent_free (&stub->args_cbk.entries); } - + void call_stub_destroy (call_stub_t *stub) { - struct mem_pool *tmp_pool = NULL; + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + if (stub->wind) + call_stub_wipe_args (stub); + else + call_stub_wipe_args_cbk (stub); - tmp_pool = stub->stub_mem_pool; - - if (stub->wind) { - call_stub_destroy_wind (stub); - } else { - call_stub_destroy_unwind (stub); - } + stub->stub_mem_pool = NULL; - stub->stub_mem_pool = NULL; - mem_put (tmp_pool, stub); + mem_put (stub); out: - tmp_pool = NULL; - - 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; @@ -3873,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 0d34b3d2e..45bef8044 100644 --- a/libglusterfs/src/call-stub.h +++ b/libglusterfs/src/call-stub.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,561 +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 glusterfs ctx */ + 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 iatt buf; - dict_t *dict; - struct iatt 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 iatt 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 iatt buf; - } fstat_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 iatt prebuf; - struct iatt 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 iatt prebuf; - struct iatt postbuf; - } ftruncate_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 iatt sbuf; - } readlink_cbk; - - /* mknod */ - struct { - fop_mknod_t fn; - loc_t loc; - mode_t mode; - dev_t rdev; - dict_t *params; - } mknod; - struct { - fop_mknod_cbk_t fn; - int32_t op_ret, op_errno; - inode_t *inode; - struct iatt buf; - struct iatt preparent; - struct iatt postparent; - } mknod_cbk; - - /* mkdir */ - struct { - fop_mkdir_t fn; - loc_t loc; - mode_t mode; - dict_t *params; - } mkdir; - struct { - fop_mkdir_cbk_t fn; - int32_t op_ret, op_errno; - inode_t *inode; - struct iatt buf; - struct iatt preparent; - struct iatt 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 iatt preparent; - struct iatt postparent; - } unlink_cbk; - - /* rmdir */ - struct { - fop_rmdir_t fn; - loc_t loc; - int flags; - } rmdir; - struct { - fop_rmdir_cbk_t fn; - int32_t op_ret, op_errno; - struct iatt preparent; - struct iatt postparent; - } rmdir_cbk; - - /* symlink */ - struct { - fop_symlink_t fn; - const char *linkname; - loc_t loc; - dict_t *params; - } symlink; - struct { - fop_symlink_cbk_t fn; - int32_t op_ret, op_errno; - inode_t *inode; - struct iatt buf; - struct iatt preparent; - struct iatt 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 iatt buf; - struct iatt preoldparent; - struct iatt postoldparent; - struct iatt prenewparent; - struct iatt 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 iatt buf; - struct iatt preparent; - struct iatt postparent; - } link_cbk; - - /* create */ - struct { - fop_create_t fn; - loc_t loc; - int32_t flags; - mode_t mode; - fd_t *fd; - dict_t *params; - } create; - struct { - fop_create_cbk_t fn; - int32_t op_ret, op_errno; - fd_t *fd; - inode_t *inode; - struct iatt buf; - struct iatt preparent; - struct iatt 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 iatt 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 iatt prebuf; - struct iatt 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 iatt prebuf; - struct iatt 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; - - - /* 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 gf_flock lock; - } lk; - struct { - fop_lk_cbk_t fn; - int32_t op_ret, op_errno; - struct gf_flock lock; - } lk_cbk; - - /* inodelk */ - struct { - fop_inodelk_t fn; - const char *volume; - loc_t loc; - int32_t cmd; - struct gf_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 gf_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; - - /* 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; - - /* setattr */ - struct { - fop_setattr_t fn; - loc_t loc; - struct iatt stbuf; - int32_t valid; - } setattr; - struct { - fop_setattr_cbk_t fn; - int32_t op_ret; - int32_t op_errno; - struct iatt statpre; - struct iatt statpost; - } setattr_cbk; - - /* fsetattr */ - struct { - fop_fsetattr_t fn; - fd_t *fd; - struct iatt stbuf; - int32_t valid; - } fsetattr; - struct { - fop_fsetattr_cbk_t fn; - int32_t op_ret; - int32_t op_errno; - struct iatt statpre; - struct iatt 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, @@ -597,34 +191,34 @@ fop_lookup_cbk_stub (call_frame_t *frame, int32_t op_errno, inode_t *inode, struct iatt *buf, - dict_t *dict, + 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 iatt *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 iatt *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, @@ -632,13 +226,13 @@ fop_truncate_cbk_stub (call_frame_t *frame, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf); + 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, @@ -646,25 +240,25 @@ fop_ftruncate_cbk_stub (call_frame_t *frame, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf); + 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, @@ -672,11 +266,11 @@ fop_readlink_cbk_stub (call_frame_t *frame, int32_t op_ret, int32_t op_errno, const char *path, - struct iatt *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, dict_t *params); +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, @@ -686,11 +280,11 @@ fop_mknod_cbk_stub (call_frame_t *frame, inode_t *inode, struct iatt *buf, struct iatt *preparent, - struct iatt *postparent); + 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, dict_t *params); +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, @@ -700,12 +294,11 @@ fop_mkdir_cbk_stub (call_frame_t *frame, inode_t *inode, struct iatt *buf, struct iatt *preparent, - struct iatt *postparent); + 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, @@ -713,11 +306,11 @@ fop_unlink_cbk_stub (call_frame_t *frame, int32_t op_ret, int32_t op_errno, struct iatt *preparent, - struct iatt *postparent); + struct iatt *postparent, dict_t *xdata); call_stub_t * fop_rmdir_stub (call_frame_t *frame, fop_rmdir_t fn, - loc_t *loc, int flags); + loc_t *loc, int flags, dict_t *xdata); call_stub_t * fop_rmdir_cbk_stub (call_frame_t *frame, @@ -725,11 +318,11 @@ fop_rmdir_cbk_stub (call_frame_t *frame, int32_t op_ret, int32_t op_errno, struct iatt *preparent, - struct iatt *postparent); + 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, dict_t *params); + const char *linkname, loc_t *loc, mode_t umask, dict_t *xdata); call_stub_t * fop_symlink_cbk_stub (call_frame_t *frame, @@ -739,13 +332,13 @@ fop_symlink_cbk_stub (call_frame_t *frame, inode_t *inode, struct iatt *buf, struct iatt *preparent, - struct iatt *postparent); + 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, @@ -756,13 +349,13 @@ fop_rename_cbk_stub (call_frame_t *frame, struct iatt *preoldparent, struct iatt *postoldparent, struct iatt *prenewparent, - struct iatt *postnewparent); + 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, @@ -772,12 +365,12 @@ fop_link_cbk_stub (call_frame_t *frame, inode_t *inode, struct iatt *buf, struct iatt *preparent, - struct iatt *postparent); + 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, dict_t *params); + mode_t umask, fd_t *fd, dict_t *xdata); call_stub_t * fop_create_cbk_stub (call_frame_t *frame, @@ -788,7 +381,7 @@ fop_create_cbk_stub (call_frame_t *frame, inode_t *inode, struct iatt *buf, struct iatt *preparent, - struct iatt *postparent); + struct iatt *postparent, dict_t *xdata); call_stub_t * fop_open_stub (call_frame_t *frame, @@ -796,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, @@ -820,7 +413,7 @@ fop_readv_cbk_stub (call_frame_t *frame, struct iovec *vector, int32_t count, struct iatt *stbuf, - struct iobref *iobref); + struct iobref *iobref, dict_t *xdata); call_stub_t * fop_writev_stub (call_frame_t *frame, @@ -828,8 +421,8 @@ 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, @@ -837,24 +430,24 @@ fop_writev_cbk_stub (call_frame_t *frame, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf); + 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, @@ -862,190 +455,205 @@ fop_fsync_cbk_stub (call_frame_t *frame, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf); + 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); + 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 gf_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 gf_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 gf_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 gf_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); + 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, @@ -1053,40 +661,40 @@ 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); + 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 iatt *stbuf, - int32_t valid); + int32_t valid, dict_t *xdata); call_stub_t * fop_setattr_cbk_stub (call_frame_t *frame, @@ -1094,14 +702,14 @@ fop_setattr_cbk_stub (call_frame_t *frame, int32_t op_ret, int32_t op_errno, struct iatt *statpre, - struct iatt *statpost); + struct iatt *statpost, dict_t *xdata); call_stub_t * fop_fsetattr_stub (call_frame_t *frame, fop_fsetattr_t fn, fd_t *fd, struct iatt *stbuf, - int32_t valid); + int32_t valid, dict_t *xdata); call_stub_t * fop_fsetattr_cbk_stub (call_frame_t *frame, @@ -1109,8 +717,51 @@ fop_fsetattr_cbk_stub (call_frame_t *frame, int32_t op_ret, int32_t op_errno, struct iatt *statpre, - struct iatt *statpost); + 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 de86adc9a..e14a3044c 100644 --- a/libglusterfs/src/checksum.c +++ b/libglusterfs/src/checksum.c @@ -1,28 +1,17 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 592e99fcb..bf7eeede8 100644 --- a/libglusterfs/src/checksum.h +++ b/libglusterfs/src/checksum.h @@ -1,29 +1,20 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 e4c7e2c31..827475282 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 @@ -40,22 +31,127 @@ #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); - struct dnscache6 { - struct addrinfo *first; - struct addrinfo *next; + struct addrinfo *first; + struct addrinfo *next; }; +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]); +} + +/* 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,}; + + 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) @@ -73,138 +169,211 @@ log_base2 (unsigned long x) 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; - } + 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 (!*dnscache) { - *dnscache = GF_CALLOC (1, sizeof (struct dnscache6), - gf_common_mt_dnscache6); + if (!*dnscache) { + *dnscache = GF_CALLOC (1, sizeof (struct dnscache6), + gf_common_mt_dnscache6); if (!*dnscache) return -1; - } - - cache = *dnscache; - if (cache->first && !cache->next) { - freeaddrinfo(cache->first); - cache->first = cache->next = NULL; - gf_log ("resolver", GF_LOG_TRACE, - "flushing DNS cache"); - } + } - if (!cache->first) { - char *port_str = NULL; - gf_log ("resolver", GF_LOG_TRACE, - "DNS cache not present, freshly probing hostname: %s", - hostname); + cache = *dnscache; + if (cache->first && !cache->next) { + freeaddrinfo(cache->first); + cache->first = cache->next = NULL; + gf_log ("resolver", GF_LOG_TRACE, + "flushing DNS cache"); + } - memset(&hints, 0, sizeof(hints)); - hints.ai_family = family; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_ADDRCONFIG; + 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); + 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)); - - GF_FREE (*dnscache); - *dnscache = NULL; - GF_FREE (port_str); - return -1; - } - GF_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->first; + } + + if (cache->next) { + ret = getnameinfo((struct sockaddr *)cache->next->ai_addr, + cache->next->ai_addrlen, + host, sizeof (host), + service, sizeof (service), + NI_NUMERICHOST); + if (ret != 0) { + gf_log ("resolver", GF_LOG_ERROR, + "getnameinfo failed (%s)", gai_strerror (ret)); + goto err; + } + + gf_log ("resolver", GF_LOG_DEBUG, + "returning ip-%s (port-%s) for hostname: %s and port: %d", + host, service, hostname, port); + + *addr_info = cache->next; + } 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_TRACE, - "next DNS query will return: ip-%s port-%s", host, service); - } + 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; + } - return 0; + 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; - GF_FREE (cache); - *dnscache = NULL; - return -1; + freeaddrinfo (cache->first); + cache->first = cache->next = NULL; + GF_FREE (cache); + *dnscache = NULL; + return -1; +} + + +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; +} + + +static int +xldump_options (dict_t *this, char *key, data_t *value, void *d) +{ + nprintf (d, " option %s %s", key, value->data); + return 0; +} + + +static void +xldump_subvolumes (xlator_t *this, void *d) +{ + 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); +} + + +static void +xldump (xlator_t *each, void *d) +{ + 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, ""); } void -gf_log_volume_file (FILE *specfp) +gf_log_dump_graph (FILE *specfp, glusterfs_graph_t *graph) { - extern FILE *gf_log_logfile; - int lcount = 0; - char data[GF_UNIT_KB]; + glusterfs_ctx_t *ctx; + struct xldump xld = {0, }; - 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); + 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 @@ -212,201 +381,223 @@ gf_dump_config_flags (int fd) { int ret = 0; - 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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)); + { + char msg[128]; + sprintf (msg, "package-string: %s\n", PACKAGE_STRING); + ret = write (fd, msg, strlen (msg)); if (ret == -1) goto out; - } + } #endif out: - return; + 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); - { - glusterfs_ctx_t *ctx = glusterfs_ctx_get (); - 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]); - if (tmp->root->type == GF_OP_TYPE_MGMT) - sprintf (msg,"frame : type(%d) op(%s)\n", - tmp->root->type, - gf_mgmt_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 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 @@ -418,97 +609,90 @@ trap (void) char * gf_trim (char *string) { - register char *s, *t; + register char *s, *t; - if (string == NULL) - { - return NULL; - } + if (string == NULL) { + return NULL; + } - for (s = string; isspace (*s); s++) - ; + for (s = string; isspace (*s); s++) + ; - if (*s == 0) - return s; + if (*s == 0) + return s; - t = s + strlen (s) - 1; - while (t > s && isspace (*t)) - t--; - *++t = '\0'; + t = s + strlen (s) - 1; + while (t > s && isspace (*t)) + t--; + *++t = '\0'; - return s; + 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; - } + 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; + if (_running == NULL) + return -1; - while ((token = strsep (&running, delim)) != NULL) - { - if (token[0] != '\0') - count++; - } - GF_FREE (_running); + 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 (_running == NULL) + return -1; - if ((token_list = GF_CALLOC (count, sizeof (char *), - gf_common_mt_char)) == NULL) - { - GF_FREE (_running); - return -1; - } + running = _running; - while ((token = strsep (&running, delim)) != NULL) - { - if (token[0] == '\0') - continue; + 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; + if (token_list[i] == NULL) + goto free_exit; i++; - } + } - GF_FREE (_running); + GF_FREE (_running); - *tokens = token_list; - *token_count = count; - return 0; + *tokens = token_list; + *token_count = count; + return 0; free_exit: - GF_FREE (_running); - for (j = 0; j < i; j++) - { - GF_FREE (token_list[j]); - } - GF_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 @@ -523,9 +707,10 @@ gf_strstr (const char *str, const char *delim, const char *match) 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; - } + goto out; + } tmp = strtok_r (tmp_str, delim, &save_ptr); @@ -540,8 +725,7 @@ gf_strstr (const char *str, const char *delim, const char *match) } out: - if (tmp_str) - free (tmp_str); + free (tmp_str); return ret; @@ -550,870 +734,882 @@ out: int gf_volume_name_validate (const char *volume_name) { - const char *vname = NULL; + const char *vname = NULL; - if (volume_name == NULL) - { - return -1; - } + if (volume_name == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); + return -1; + } - if (!isalpha (volume_name[0])) - { - return 1; - } + if (!isalpha (volume_name[0])) + return 1; - for (vname = &volume_name[1]; *vname != '\0'; vname++) - { - if (!(isalnum (*vname) || *vname == '_')) - return 1; - } + for (vname = &volume_name[1]; *vname != '\0'; vname++) { + if (!(isalnum (*vname) || *vname == '_')) + return 1; + } - return 0; + return 0; } int gf_string2time (const char *str, uint32_t *n) { - unsigned long value = 0; - char *tail = NULL; - int old_errno = 0; - const char *s = NULL; - - if (str == NULL || n == NULL) - { - errno = EINVAL; - return -1; - } + 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; - } + 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); + old_errno = errno; + errno = 0; + value = strtol (str, &tail, 0); + if (str == tail) + errno = EINVAL; - if (errno == ERANGE || errno == EINVAL) - { - return -1; - } + if (errno == ERANGE || errno == EINVAL) + return -1; - if (errno == 0) - { - errno = old_errno; - } + 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; - } + 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; + *n = value; - return 0; + return 0; } - int -gf_string2percent (const char *str, uint32_t *n) +gf_string2percent (const char *str, double *n) { - unsigned long value = 0; - char *tail = NULL; - int old_errno = 0; - const char *s = NULL; + 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; + } - if (str == NULL || n == NULL) - { - errno = EINVAL; - return -1; - } + for (s = str; *s != '\0'; s++) { + if (isspace (*s)) + continue; + if (*s == '-') + return -1; + break; + } - 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; - old_errno = errno; - errno = 0; - value = strtol (str, &tail, 0); + if (errno == ERANGE || errno == EINVAL) + return -1; - if (errno == ERANGE || errno == EINVAL) - { - return -1; - } + if (errno == 0) + errno = old_errno; - if (errno == 0) - { - errno = old_errno; - } - - if (!((tail[0] == '\0') || - ((tail[0] == '%') && (tail[1] == '\0')))) - { - return -1; - } + if (!((tail[0] == '\0') || + ((tail[0] == '%') && (tail[1] == '\0')))) + return -1; - *n = value; + *n = value; - return 0; + return 0; } static int _gf_string2long (const char *str, long *n, int base) { - long value = 0; - char *tail = NULL; - int old_errno = 0; - - if (str == NULL || n == NULL) - { - errno = EINVAL; - return -1; - } + 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 = strtol (str, &tail, base); + old_errno = errno; + errno = 0; + value = strtol (str, &tail, base); + if (str == tail) + errno = EINVAL; - if (errno == ERANGE || errno == EINVAL) - { - return -1; - } + if (errno == ERANGE || errno == EINVAL) + return -1; - if (errno == 0) - { - errno = old_errno; - } + if (errno == 0) + errno = old_errno; - if (tail[0] != '\0') - { - /* bala: invalid integer format */ - return -1; - } + if (tail[0] != '\0') + return -1; - *n = value; + *n = value; - return 0; + return 0; } static int _gf_string2ulong (const char *str, unsigned long *n, int base) { - unsigned long value = 0; - char *tail = NULL; - int old_errno = 0; - const char *s = NULL; - - if (str == NULL || n == NULL) - { - errno = EINVAL; - return -1; - } + 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 == '-') - { - /* bala: we do not support suffixed (-) sign and - invalid integer format */ - return -1; - } - break; - } + 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); + old_errno = errno; + errno = 0; + value = strtoul (str, &tail, base); + if (str == tail) + errno = EINVAL; - if (errno == ERANGE || errno == EINVAL) - { - return -1; - } + if (errno == ERANGE || errno == EINVAL) + return -1; - if (errno == 0) - { - errno = old_errno; - } + if (errno == 0) + errno = old_errno; - if (tail[0] != '\0') - { - /* bala: invalid integer format */ - return -1; - } + if (tail[0] != '\0') + return -1; - *n = value; + *n = value; - return 0; + return 0; } static int _gf_string2uint (const char *str, unsigned int *n, int base) { - unsigned long value = 0; - char *tail = NULL; - int old_errno = 0; - const char *s = NULL; - - if (str == NULL || n == NULL) - { - errno = EINVAL; - return -1; - } + 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 == '-') - { - /* bala: we do not support suffixed (-) sign and - invalid integer format */ - return -1; - } - break; - } + 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); + old_errno = errno; + errno = 0; + value = strtoul (str, &tail, base); + if (str == tail) + errno = EINVAL; - if (errno == ERANGE || errno == EINVAL) - { - return -1; - } + if (errno == ERANGE || errno == EINVAL) + return -1; - if (errno == 0) - { - errno = old_errno; - } + if (errno == 0) + errno = old_errno; - if (tail[0] != '\0') - { - /* bala: invalid integer format */ - return -1; - } + if (tail[0] != '\0') + return -1; - *n = (unsigned int)value; + *n = (unsigned int)value; - return 0; + return 0; } 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; - } + 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); + old_errno = errno; + errno = 0; + value = strtod (str, &tail); + if (str == tail) + errno = EINVAL; - if (errno == ERANGE || errno == EINVAL) { - return -1; - } + if (errno == ERANGE || errno == EINVAL) + return -1; - if (errno == 0) { - errno = old_errno; - } + if (errno == 0) + errno = old_errno; - if (tail[0] != '\0') { - return -1; - } + if (tail[0] != '\0') + return -1; - *n = value; + *n = value; - return 0; + return 0; } static int _gf_string2longlong (const char *str, long long *n, int base) { - long long value = 0; - char *tail = NULL; - int old_errno = 0; - - if (str == NULL || n == NULL) - { - errno = EINVAL; - return -1; - } + 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); + old_errno = errno; + errno = 0; + value = strtoll (str, &tail, base); + if (str == tail) + errno = EINVAL; - if (errno == ERANGE || errno == EINVAL) - { - return -1; - } + if (errno == ERANGE || errno == EINVAL) + return -1; - if (errno == 0) - { - errno = old_errno; - } + if (errno == 0) + errno = old_errno; - if (tail[0] != '\0') - { - /* bala: invalid integer format */ - return -1; - } + if (tail[0] != '\0') + return -1; - *n = value; + *n = value; - return 0; + return 0; } static int _gf_string2ulonglong (const char *str, unsigned long long *n, int base) { - unsigned long long value = 0; - char *tail = NULL; - int old_errno = 0; - const char *s = NULL; - - if (str == NULL || n == NULL) - { - errno = EINVAL; - return -1; - } + 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 == '-') - { - /* bala: we do not support suffixed (-) sign and - invalid integer format */ - return -1; - } - break; - } + 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); + old_errno = errno; + errno = 0; + value = strtoull (str, &tail, base); + if (str == tail) + errno = EINVAL; - if (errno == ERANGE || errno == EINVAL) - { - return -1; - } + if (errno == ERANGE || errno == EINVAL) + return -1; - if (errno == 0) - { - errno = old_errno; - } + if (errno == 0) + errno = old_errno; - if (tail[0] != '\0') - { - /* bala: invalid integer format */ - return -1; - } + if (tail[0] != '\0') + return -1; - *n = value; + *n = value; - return 0; + return 0; } int gf_string2long (const char *str, long *n) { - return _gf_string2long (str, n, 0); + return _gf_string2long (str, n, 0); } int gf_string2ulong (const char *str, unsigned long *n) { - return _gf_string2ulong (str, n, 0); + return _gf_string2ulong (str, n, 0); } 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 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 gf_string2longlong (const char *str, long long *n) { - return _gf_string2longlong (str, n, 0); + return _gf_string2longlong (str, n, 0); } int gf_string2ulonglong (const char *str, unsigned long long *n) { - return _gf_string2ulonglong (str, n, 0); + return _gf_string2ulonglong (str, n, 0); } int gf_string2int8 (const char *str, int8_t *n) { - long l = 0L; - int rv = 0; + long l = 0L; + int rv = 0; - rv = _gf_string2long (str, &l, 0); - if (rv != 0) - return rv; + rv = _gf_string2long (str, &l, 0); + if (rv != 0) + return rv; - if (l >= INT8_MIN && l <= INT8_MAX) - { - *n = (int8_t) l; - return 0; - } + if ((l >= INT8_MIN) && (l <= INT8_MAX)) { + *n = (int8_t) l; + return 0; + } - errno = ERANGE; - return -1; + errno = ERANGE; + return -1; } int gf_string2int16 (const char *str, int16_t *n) { - long l = 0L; - int rv = 0; + long l = 0L; + int rv = 0; - rv = _gf_string2long (str, &l, 0); - if (rv != 0) - return rv; + rv = _gf_string2long (str, &l, 0); + if (rv != 0) + return rv; - if (l >= INT16_MIN && l <= INT16_MAX) - { - *n = (int16_t) l; - return 0; - } + if ((l >= INT16_MIN) && (l <= INT16_MAX)) { + *n = (int16_t) l; + return 0; + } - errno = ERANGE; - return -1; + errno = ERANGE; + return -1; } int gf_string2int32 (const char *str, int32_t *n) { - long l = 0L; - int rv = 0; + long l = 0L; + int rv = 0; - rv = _gf_string2long (str, &l, 0); - if (rv != 0) - return rv; + rv = _gf_string2long (str, &l, 0); + if (rv != 0) + return rv; - if (l >= INT32_MIN && l <= INT32_MAX) - { - *n = (int32_t) l; - return 0; - } + if ((l >= INT32_MIN) && (l <= INT32_MAX)) { + *n = (int32_t) l; + return 0; + } - errno = ERANGE; - return -1; + errno = ERANGE; + return -1; } int gf_string2int64 (const char *str, int64_t *n) { - long long l = 0LL; - int rv = 0; + long long l = 0LL; + int rv = 0; - rv = _gf_string2longlong (str, &l, 0); - if (rv != 0) - return rv; + rv = _gf_string2longlong (str, &l, 0); + if (rv != 0) + return rv; - if (l >= INT64_MIN && l <= INT64_MAX) - { - *n = (int64_t) l; - return 0; - } + if ((l >= INT64_MIN) && (l <= INT64_MAX)) { + *n = (int64_t) l; + return 0; + } - errno = ERANGE; - return -1; + errno = ERANGE; + return -1; } int gf_string2uint8 (const char *str, uint8_t *n) { - unsigned long l = 0L; - int rv = 0; + unsigned long l = 0L; + int rv = 0; - rv = _gf_string2ulong (str, &l, 0); - if (rv != 0) - return rv; + rv = _gf_string2ulong (str, &l, 0); + if (rv != 0) + return rv; - if (l >= 0 && l <= UINT8_MAX) - { - *n = (uint8_t) l; - return 0; - } + if (l >= 0 && l <= UINT8_MAX) { + *n = (uint8_t) l; + return 0; + } - errno = ERANGE; - return -1; + errno = ERANGE; + return -1; } int gf_string2uint16 (const char *str, uint16_t *n) { - unsigned long l = 0L; - int rv = 0; + unsigned long l = 0L; + int rv = 0; - rv = _gf_string2ulong (str, &l, 0); - if (rv != 0) - return rv; + rv = _gf_string2ulong (str, &l, 0); + if (rv != 0) + return rv; - if (l >= 0 && l <= UINT16_MAX) - { - *n = (uint16_t) l; - return 0; - } + if (l >= 0 && l <= UINT16_MAX) { + *n = (uint16_t) l; + return 0; + } - errno = ERANGE; - return -1; + errno = ERANGE; + return -1; } int gf_string2uint32 (const char *str, uint32_t *n) { - unsigned long l = 0L; - int rv = 0; + unsigned long l = 0L; + int rv = 0; - rv = _gf_string2ulong (str, &l, 0); - if (rv != 0) - return rv; + rv = _gf_string2ulong (str, &l, 0); + if (rv != 0) + return rv; - if (l >= 0 && l <= UINT32_MAX) - { - *n = (uint32_t) l; - return 0; - } + if (l >= 0 && l <= UINT32_MAX) { + *n = (uint32_t) l; + return 0; + } - errno = ERANGE; - return -1; + errno = ERANGE; + return -1; } int gf_string2uint64 (const char *str, uint64_t *n) { - unsigned long long l = 0ULL; - int rv = 0; + unsigned long long l = 0ULL; + int rv = 0; - rv = _gf_string2ulonglong (str, &l, 0); - if (rv != 0) - return rv; + rv = _gf_string2ulonglong (str, &l, 0); + if (rv != 0) + return rv; - if (l >= 0 && l <= UINT64_MAX) - { - *n = (uint64_t) l; - return 0; - } + if (l >= 0 && l <= UINT64_MAX) { + *n = (uint64_t) l; + return 0; + } - errno = ERANGE; - return -1; + errno = ERANGE; + return -1; } int gf_string2ulong_base10 (const char *str, unsigned long *n) { - return _gf_string2ulong (str, n, 10); + return _gf_string2ulong (str, n, 10); } int gf_string2uint_base10 (const char *str, unsigned int *n) { - return _gf_string2uint (str, n, 10); + return _gf_string2uint (str, n, 10); } int gf_string2uint8_base10 (const char *str, uint8_t *n) { - unsigned long l = 0L; - int rv = 0; + unsigned long l = 0L; + int rv = 0; - rv = _gf_string2ulong (str, &l, 10); - if (rv != 0) - return rv; + rv = _gf_string2ulong (str, &l, 10); + if (rv != 0) + return rv; - if (l >= 0 && l <= UINT8_MAX) - { - *n = (uint8_t) l; - return 0; - } + if (l >= 0 && l <= UINT8_MAX) { + *n = (uint8_t) l; + return 0; + } - errno = ERANGE; - return -1; + errno = ERANGE; + return -1; } int gf_string2uint16_base10 (const char *str, uint16_t *n) { - unsigned long l = 0L; - int rv = 0; + unsigned long l = 0L; + int rv = 0; - rv = _gf_string2ulong (str, &l, 10); - if (rv != 0) - return rv; + rv = _gf_string2ulong (str, &l, 10); + if (rv != 0) + return rv; - if (l >= 0 && l <= UINT16_MAX) - { - *n = (uint16_t) l; - return 0; - } + if (l >= 0 && l <= UINT16_MAX) { + *n = (uint16_t) l; + return 0; + } - errno = ERANGE; - return -1; + errno = ERANGE; + return -1; } int gf_string2uint32_base10 (const char *str, uint32_t *n) { - unsigned long l = 0L; - int rv = 0; + unsigned long l = 0L; + int rv = 0; - rv = _gf_string2ulong (str, &l, 10); - if (rv != 0) - return rv; + rv = _gf_string2ulong (str, &l, 10); + if (rv != 0) + return rv; - if (l >= 0 && l <= UINT32_MAX) - { - *n = (uint32_t) l; - return 0; - } + if (l >= 0 && l <= UINT32_MAX) { + *n = (uint32_t) l; + return 0; + } - errno = ERANGE; - return -1; + errno = ERANGE; + return -1; } int gf_string2uint64_base10 (const char *str, uint64_t *n) { - unsigned long long l = 0ULL; - int rv = 0; + unsigned long long l = 0ULL; + int rv = 0; - rv = _gf_string2ulonglong (str, &l, 10); - if (rv != 0) - return rv; + rv = _gf_string2ulonglong (str, &l, 10); + if (rv != 0) + return rv; - if (l >= 0 && l <= UINT64_MAX) - { - *n = (uint64_t) l; - return 0; - } + if (l >= 0 && l <= UINT64_MAX) { + *n = (uint64_t) l; + return 0; + } - errno = ERANGE; - return -1; + 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 gf_string2bytesize (const char *str, uint64_t *n) { - uint64_t value = 0ULL; - char *tail = NULL; - int old_errno = 0; - const char *s = NULL; + 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; + } - if (str == NULL || n == NULL) - { - errno = EINVAL; - return -1; - } + for (s = str; *s != '\0'; s++) { + if (isspace (*s)) + continue; + if (*s == '-') + return -1; + break; + } - 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 = strtod (str, &tail); + if (str == tail) + errno = EINVAL; - old_errno = errno; - errno = 0; - value = strtoull (str, &tail, 10); + if (errno == ERANGE || errno == EINVAL) + return -1; - if (errno == ERANGE || errno == EINVAL) - { - return -1; - } + if (errno == 0) + errno = old_errno; - 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 (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; - } - } + if ((UINT64_MAX - value) < 0) { + errno = ERANGE; + return -1; + } - *n = value; + *n = (uint64_t) value; - return 0; + 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 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 gf_string2boolean (const char *str, gf_boolean_t *b) { - if (str == NULL) { - 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, "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; - } + 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; + return -1; } int gf_lockfd (int fd) { - struct gf_flock fl; + struct gf_flock fl; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; - return fcntl (fd, F_SETLK, &fl); + return fcntl (fd, F_SETLK, &fl); } int gf_unlockfd (int fd) { - struct gf_flock fl; + struct gf_flock fl; - fl.l_type = F_UNLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; + fl.l_type = F_UNLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; - return fcntl (fd, F_SETLK, &fl); + return fcntl (fd, F_SETLK, &fl); } static void @@ -1469,65 +1665,6 @@ get_checksum_for_file (int fd, uint32_t *checksum) } -/* One should pass the command here with command with full path, - otherwise, execv will fail */ -int -gf_system (const char *command) -{ - int ret = -1; - pid_t pid = 0; - int status = 0; - int idx = 0; - char *dupcmd = NULL; - char *arg = NULL; - char *tmp = NULL; - char *argv[100] = { NULL, }; - - dupcmd = gf_strdup (command); - if (!dupcmd) - goto out; - - pid = fork (); - if (pid < 0) { - /* failure */ - goto out; - } - if (pid == 0) { - /* Child process */ - /* Step 0: Prepare the argv */ - arg = strtok_r (dupcmd, " ", &tmp); - while (arg) { - argv[idx] = arg; - arg = strtok_r (NULL, " ", &tmp); - idx++; - } - /* Step 1: Close all 'fd' */ - for (idx = 3; idx < 65536; idx++) { - close (idx); - } - /* Step 2: execv (); */ - ret = execvp (argv[0], argv); - - /* Code will not come here at all */ - gf_log ("", GF_LOG_ERROR, "execv of (%s) failed", command); - - kill (getpid(), SIGKILL); - } - if (pid > 0) { - /* Current, ie, parent process */ - pid = waitpid (pid, &status, 0); - if (WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS) - ret = 0; - else - ret = -1; - } -out: - if (dupcmd) - GF_FREE (dupcmd); - - return ret; -} - int get_checksum_for_path (char *path, uint32_t *checksum) { @@ -1540,7 +1677,7 @@ get_checksum_for_path (char *path, uint32_t *checksum) fd = open (path, O_RDWR); if (fd == -1) { - gf_log ("", GF_LOG_ERROR, "Unable to open %s, errno: %d", + gf_log (THIS->name, GF_LOG_ERROR, "Unable to open %s, errno: %d", path, errno); goto out; } @@ -1566,3 +1703,1206 @@ strtail (char *str, const char *pattern) 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 4371888d0..3c99a4212 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,77 +61,185 @@ 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" -enum _gf_boolean +#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")) + +/* 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 { - _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); 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_mgmt_list[GF_MGMT_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); + } 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(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 (name, GF_LOG_ERROR, \ - "invalid argument: " #arg); \ + gf_log_callingfn (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_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) -#define GF_ASSERT(x) \ - do { \ - if (!(x)) { \ - gf_log_callingfn ("", GF_LOG_ERROR, \ - "Assertion failed: " #x); \ - } \ - } while (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) @@ -165,7 +267,7 @@ 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; @@ -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) { @@ -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); @@ -323,9 +530,11 @@ 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); @@ -334,9 +543,52 @@ int gf_unlockfd (int fd); int get_checksum_for_file (int fd, uint32_t *checksum); int log_base2 (unsigned long x); -int gf_system (const char *command); int get_checksum_for_path (char *path, uint32_t *checksum); char *strtail (char *str, const char *pattern); -#endif /* _COMMON_UTILS_H */ +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 7b39b0a8d..fd5cc49ce 100644 --- a/libglusterfs/src/compat-errno.c +++ b/libglusterfs/src/compat-errno.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 bdd8becfd..65e52081d 100644 --- a/libglusterfs/src/compat-errno.h +++ b/libglusterfs/src/compat-errno.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 081869e4b..eb6d8d4b7 100644 --- a/libglusterfs/src/compat.c +++ b/libglusterfs/src/compat.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,275 +26,422 @@ #include "compat.h" #include "common-utils.h" +#include "iatt.h" +#include "inode.h" #ifdef GF_SOLARIS_HOST_OS +int +solaris_fsetxattr(int fd, const char* key, const char *value, size_t size, + int flags) +{ + int attrfd = -1; + int ret = 0; + + attrfd = openat (fd, key, flags|O_CREAT|O_WRONLY|O_XATTR, 0777); + if (attrfd >= 0) { + ftruncate (attrfd, 0); + ret = write (attrfd, value, size); + close (attrfd); + } else { + if (errno != ENOENT) + gf_log ("libglusterfs", GF_LOG_ERROR, + "Couldn't set extended attribute for %d (%d)", + fd, errno); + return -1; + } + + return 0; +} -int -solaris_fsetxattr(int fd, - 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 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 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. +*/ -int -solaris_fgetxattr(int fd, - const char* key, - char *value, - size_t size) +int +make_export_path (const char *real_path, char **path) { - 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 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; } +int +solaris_xattr_resolve_path (const char *real_path, char **path) +{ + 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); -int -solaris_setxattr(const char *path, - const char* key, - const char *value, - size_t size, - int flags) + 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; +} + +int +solaris_setxattr(const char *path, const char* key, const char *value, + size_t size, int flags) { - int attrfd = -1; - int ret = 0; - - attrfd = attropen (path, key, flags|O_CREAT|O_WRONLY, 0777); - if (attrfd >= 0) { - ftruncate (attrfd, 0); - ret = write (attrfd, value, size); - close (attrfd); - } else { - if (errno != ENOENT) - gf_log ("libglusterfs", GF_LOG_ERROR, - "Couldn't set extended attribute for %s (%d)", - path, errno); - return -1; - } - - return 0; + int 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; } int -solaris_listxattr(const char *path, - char *list, - size_t size) +solaris_listxattr(const char *path, char *list, size_t size) { - int attrdirfd = -1; - ssize_t len = 0; - DIR *dirptr = NULL; - struct dirent *dent = NULL; - int newfd = -1; - - attrdirfd = attropen (path, ".", O_RDONLY, 0); - if (attrdirfd >= 0) { - newfd = dup(attrdirfd); - dirptr = fdopendir(newfd); - if (dirptr) { - while ((dent = readdir(dirptr))) { - size_t listlen = strlen(dent->d_name); - if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) { - /* we don't want "." and ".." here */ - continue; - } - if (size == 0) { - /* return the current size of the list of extended attribute names*/ - len += listlen + 1; - } else { - /* check size and copy entrie + nul into list. */ - if ((len + listlen + 1) > size) { - errno = ERANGE; - len = -1; - break; - } else { - strncpy(list + len, dent->d_name, listlen); - len += listlen; - list[len] = '\0'; - ++len; - } - } - } - - if (closedir(dirptr) == -1) { - close (attrdirfd); - return -1; - } - } else { - close (attrdirfd); - return -1; - } - close (attrdirfd); - } - return len; + int 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; } int -solaris_flistxattr(int fd, - char *list, - size_t size) +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 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 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; } -int -solaris_removexattr(const char *path, - const char* key) +int +solaris_removexattr(const char *path, const char* key) { - int ret = -1; - int attrfd = attropen (path, ".", O_RDONLY, 0); - if (attrfd >= 0) { - ret = unlinkat (attrfd, key, 0); - close (attrfd); - } else { - if (errno == ENOENT) - errno = ENODATA; - return -1; - } - - return ret; + int 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_getxattr(const char *path, - 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 = attropen (path, key, O_RDONLY, 0); - if (attrfd >= 0) { - if (size == 0) { - struct stat buf; - fstat (attrfd, &buf); - ret = buf.st_size; - } else { - ret = read (attrfd, value, size); - } - close (attrfd); - } else { - if (errno == ENOENT) - errno = ENODATA; - if (errno != ENOENT) - gf_log ("libglusterfs", GF_LOG_DEBUG, - "Couldn't read extended attribute for the file %s (%d)", - path, errno); - return -1; - } - return ret; + int 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; } char* strsep(char** str, const char* delims) { - char* token; - - if (*str==NULL) { - /* No more tokens */ - return NULL; - } - - token=*str; - while (**str!='\0') { - if (strchr(delims,**str)!=NULL) { - **str='\0'; - (*str)++; - return token; - } - (*str)++; - } - /* There is no other token */ - *str=NULL; - return token; + 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 */ @@ -311,116 +449,97 @@ char* strsep(char** str, const char* delims) int vasprintf (char **result, const char *format, va_list args) { - const char *p = format; - /* Add one to make sure that it is never zero, which might cause malloc - to return NULL. */ - int total_width = strlen (format) + 1; - va_list ap; - - /* vasprintf does not work on Solaris when memcpy is called on va_list pointers. - * Replacing it with va_copy which works on Solaris - */ - va_copy (ap, args); - - while (*p != '\0') - { - if (*p++ == '%') - { - while (strchr ("-+ #0", *p)) - ++p; - if (*p == '*') - { - ++p; - total_width += abs (va_arg (ap, int)); - } - else - { - char *endp; - total_width += strtoul (p, &endp, 10); - p = endp; - } - if (*p == '.') - { - ++p; - if (*p == '*') - { - ++p; - total_width += abs (va_arg (ap, int)); - } - else - { - char *endp; - total_width += strtoul (p, &endp, 10); - p = endp; - } - } - while (strchr ("hlL", *p)) - ++p; - /* Should be big enough for any format specifier except %s - and floats. */ - total_width += 30; - switch (*p) - { - case 'd': - case 'i': - case 'o': - case 'u': - case 'x': - case 'X': - case 'c': - (void) va_arg (ap, int); - break; - case 'f': - case 'e': - case 'E': - case 'g': - case 'G': - (void) va_arg (ap, double); - /* Since an ieee double can have an exponent of 307, we'll - make the buffer wide enough to cover the gross case. */ - total_width += 307; - - case 's': - total_width += strlen (va_arg (ap, char *)); - break; - case 'p': - case 'n': - (void) va_arg (ap, char *); - break; - } - } - } - - va_end (ap); - - *result = malloc (total_width); - if (*result != NULL) - return vsprintf (*result, format, args); - else - return 0; + return gf_vasprintf(result, format, args); } int asprintf (char **buf, const char *fmt, ...) { - int status; - va_list ap; + int status; + va_list ap; + + va_start (ap, fmt); + status = vasprintf (buf, fmt, ap); + va_end (ap); + return status; +} + +int solaris_unlink (const char *path) +{ + 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_rename (const char *old_path, const char *new_path) +{ + char *mapped_path = NULL; + int ret = -1; + + ret = solaris_xattr_resolve_path (new_path, &mapped_path); + + + 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 *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; - va_start (ap, fmt); - status = vasprintf (buf, fmt, ap); - va_end (ap); - return status; +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 2f83054fa..2bd982541 100644 --- a/libglusterfs/src/compat.h +++ b/libglusterfs/src/compat.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 @@ -177,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> @@ -189,7 +191,7 @@ 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 { @@ -208,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 @@ -264,22 +266,32 @@ enum { #define FTW_CONTINUE 0 #endif -int asprintf(char **string_ptr, const char *format, ...); +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 @@ -289,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 @@ -301,7 +313,7 @@ size_t strnlen(const char *string, size_t maxlen); char *__new = (char *) __builtin_alloca (__len); \ (char *) memcpy (__new, __old, __len); \ })) -#endif +#endif #define GF_DIR_ALIGN(x) (((x) + sizeof (uint64_t) - 1) & ~(sizeof (uint64_t) - 1)) @@ -311,20 +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 GF_DIR_ALIGN (24 /* FIX MEEEE!!! */ + entry->d_namlen); + size = GF_DIR_ALIGN (24 /* FIX MEEEE!!! */ + entry->d_namlen); #endif #ifdef GF_DARWIN_HOST_OS - return GF_DIR_ALIGN (24 /* FIX MEEEE!!! */ + entry->d_namlen); + size = GF_DIR_ALIGN (24 /* FIX MEEEE!!! */ + entry->d_namlen); #endif #ifdef GF_LINUX_HOST_OS - return GF_DIR_ALIGN (24 /* FIX MEEEE!!! */ + entry->d_reclen); + size = GF_DIR_ALIGN (24 /* FIX MEEEE!!! */ + entry->d_reclen); #endif #ifdef GF_SOLARIS_HOST_OS - return GF_DIR_ALIGN (24 /* FIX MEEEE!!! */ + entry->d_reclen); + size = GF_DIR_ALIGN (24 /* FIX MEEEE!!! */ + entry->d_reclen); #endif + return size; } +#ifdef THREAD_UNSAFE_BASENAME +char *basename_r(const char *); +#define basename(path) basename_r(path) +#endif /* THREAD_UNSAFE_BASENAME */ + +#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 */ @@ -351,4 +378,25 @@ dirent_size (struct dirent *entry) #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 718afeb9a..2ebb25150 100644 --- a/libglusterfs/src/defaults.c +++ b/libglusterfs/src/defaults.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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: @@ -41,18 +32,19 @@ 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 *dict, struct iatt *postparent) + struct iatt *buf, dict_t *xdata, struct iatt *postparent) { STACK_UNWIND_STRICT (lookup, frame, op_ret, op_errno, inode, buf, - dict, postparent); + xdata, postparent); return 0; } 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) + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *xdata) { - STACK_UNWIND_STRICT (stat, frame, op_ret, op_errno, buf); + STACK_UNWIND_STRICT (stat, frame, op_ret, op_errno, buf, xdata); return 0; } @@ -60,37 +52,41 @@ default_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, 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) + struct iatt *postbuf, + dict_t *xdata) { STACK_UNWIND_STRICT (truncate, frame, op_ret, op_errno, prebuf, - postbuf); + postbuf, xdata); return 0; } 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) + struct iatt *postbuf, + dict_t *xdata) { STACK_UNWIND_STRICT (ftruncate, frame, op_ret, op_errno, prebuf, - postbuf); + postbuf, xdata); return 0; } int32_t default_access_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_UNWIND_STRICT (access, frame, op_ret, op_errno); + STACK_UNWIND_STRICT (access, frame, op_ret, op_errno, xdata); return 0; } 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) + struct iatt *buf, dict_t *xdata) { - STACK_UNWIND_STRICT (readlink, frame, op_ret, op_errno, path, buf); + STACK_UNWIND_STRICT (readlink, frame, op_ret, op_errno, path, buf, + xdata); return 0; } @@ -99,10 +95,10 @@ 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) + struct iatt *postparent, dict_t *xdata) { STACK_UNWIND_STRICT (mknod, frame, op_ret, op_errno, inode, - buf, preparent, postparent); + buf, preparent, postparent, xdata); return 0; } @@ -110,30 +106,31 @@ 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) + struct iatt *postparent, dict_t *xdata) { STACK_UNWIND_STRICT (mkdir, frame, op_ret, op_errno, inode, - buf, preparent, postparent); + buf, preparent, postparent, xdata); return 0; } 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) + struct iatt *postparent, dict_t *xdata) { STACK_UNWIND_STRICT (unlink, frame, op_ret, op_errno, preparent, - postparent); + postparent, xdata); return 0; } 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) + struct iatt *postparent, + dict_t *xdata) { STACK_UNWIND_STRICT (rmdir, frame, op_ret, op_errno, preparent, - postparent); + postparent, xdata); return 0; } @@ -142,10 +139,10 @@ 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) + struct iatt *postparent, dict_t *xdata) { STACK_UNWIND_STRICT (symlink, frame, op_ret, op_errno, inode, buf, - preparent, postparent); + preparent, postparent, xdata); return 0; } @@ -154,10 +151,11 @@ 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) + struct iatt *prenewparent, struct iatt *postnewparent, + dict_t *xdata) { STACK_UNWIND_STRICT (rename, frame, op_ret, op_errno, buf, preoldparent, - postoldparent, prenewparent, postnewparent); + postoldparent, prenewparent, postnewparent, xdata); return 0; } @@ -166,10 +164,11 @@ 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) + struct iatt *postparent, + dict_t *xdata) { STACK_UNWIND_STRICT (link, frame, op_ret, op_errno, inode, buf, - preparent, postparent); + preparent, postparent, xdata); return 0; } @@ -178,28 +177,31 @@ 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) + struct iatt *postparent, + dict_t *xdata) { STACK_UNWIND_STRICT (create, frame, op_ret, op_errno, fd, inode, buf, - preparent, postparent); + preparent, postparent, xdata); 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) + int32_t op_ret, int32_t op_errno, fd_t *fd, + dict_t *xdata) { - STACK_UNWIND_STRICT (open, frame, op_ret, op_errno, fd); + STACK_UNWIND_STRICT (open, frame, op_ret, op_errno, fd, xdata); return 0; } 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) + int32_t count, struct iatt *stbuf, struct iobref *iobref, + dict_t *xdata) { STACK_UNWIND_STRICT (readv, frame, op_ret, op_errno, vector, count, - stbuf, iobref); + stbuf, iobref, xdata); return 0; } @@ -207,18 +209,20 @@ default_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this, 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) + struct iatt *postbuf, + dict_t *xdata) { - STACK_UNWIND_STRICT (writev, frame, op_ret, op_errno, prebuf, postbuf); + STACK_UNWIND_STRICT (writev, frame, op_ret, op_errno, prebuf, postbuf, xdata); return 0; } int32_t default_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_UNWIND_STRICT (flush, frame, op_ret, op_errno); + STACK_UNWIND_STRICT (flush, frame, op_ret, op_errno, xdata); return 0; } @@ -227,59 +231,67 @@ default_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this, 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) + struct iatt *postbuf, + dict_t *xdata) { - STACK_UNWIND_STRICT (fsync, frame, op_ret, op_errno, prebuf, postbuf); + 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) + int32_t op_ret, int32_t op_errno, struct iatt *buf, + dict_t *xdata) { - STACK_UNWIND_STRICT (fstat, frame, op_ret, op_errno, buf); + STACK_UNWIND_STRICT (fstat, frame, op_ret, op_errno, buf, xdata); return 0; } 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 op_ret, int32_t op_errno, fd_t *fd, + dict_t *xdata) { - STACK_UNWIND_STRICT (opendir, frame, op_ret, op_errno, fd); + STACK_UNWIND_STRICT (opendir, frame, op_ret, op_errno, fd, xdata); return 0; } int32_t default_fsyncdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_UNWIND_STRICT (fsyncdir, frame, op_ret, op_errno); + STACK_UNWIND_STRICT (fsyncdir, frame, op_ret, op_errno, xdata); return 0; } 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) + int32_t op_ret, int32_t op_errno, struct statvfs *buf, + dict_t *xdata) { - STACK_UNWIND_STRICT (statfs, frame, op_ret, op_errno, buf); + STACK_UNWIND_STRICT (statfs, frame, op_ret, op_errno, buf, xdata); return 0; } int32_t default_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno); + STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno, xdata); return 0; } int32_t default_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_UNWIND_STRICT (fsetxattr, frame, op_ret, op_errno); + STACK_UNWIND_STRICT (fsetxattr, frame, op_ret, op_errno, xdata); return 0; } @@ -287,84 +299,104 @@ default_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, 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 op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) { - STACK_UNWIND_STRICT (fgetxattr, frame, op_ret, op_errno, dict); + STACK_UNWIND_STRICT (fgetxattr, frame, op_ret, op_errno, dict, xdata); return 0; } 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 op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) { - STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict); + STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict, 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) + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) { - STACK_UNWIND_STRICT (xattrop, frame, op_ret, op_errno, dict); + STACK_UNWIND_STRICT (xattrop, frame, op_ret, op_errno, dict, 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) + int32_t op_ret, int32_t op_errno, dict_t *dict, + dict_t *xdata) { - STACK_UNWIND_STRICT (fxattrop, frame, op_ret, op_errno, dict); + STACK_UNWIND_STRICT (fxattrop, frame, op_ret, op_errno, dict, xdata); return 0; } int32_t default_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, + dict_t *xdata) +{ + STACK_UNWIND_STRICT (removexattr, frame, op_ret, op_errno, xdata); + return 0; +} + + +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) { - STACK_UNWIND_STRICT (removexattr, frame, op_ret, op_errno); + STACK_UNWIND_STRICT (fremovexattr, frame, op_ret, op_errno, xdata); 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) + 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); + STACK_UNWIND_STRICT (lk, frame, op_ret, op_errno, lock, xdata); return 0; } int32_t default_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_UNWIND_STRICT (inodelk, frame, op_ret, op_errno); + STACK_UNWIND_STRICT (inodelk, frame, op_ret, op_errno, xdata); return 0; } int32_t default_finodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_UNWIND_STRICT (finodelk, frame, op_ret, op_errno); + STACK_UNWIND_STRICT (finodelk, frame, op_ret, op_errno, xdata); return 0; } int32_t default_entrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_UNWIND_STRICT (entrylk, frame, op_ret, op_errno); + STACK_UNWIND_STRICT (entrylk, frame, op_ret, op_errno, xdata); return 0; } int32_t default_fentrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_UNWIND_STRICT (fentrylk, frame, op_ret, op_errno); + STACK_UNWIND_STRICT (fentrylk, frame, op_ret, op_errno, xdata); return 0; } @@ -372,52 +404,86 @@ default_fentrylk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, 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) + uint8_t *strong_checksum, + dict_t *xdata) { STACK_UNWIND_STRICT (rchecksum, frame, op_ret, op_errno, weak_checksum, - strong_checksum); + strong_checksum, 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) + int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, + dict_t *xdata) { - STACK_UNWIND_STRICT (readdir, frame, op_ret, op_errno, entries); + STACK_UNWIND_STRICT (readdir, frame, op_ret, op_errno, entries, 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) + int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, + dict_t *xdata) { - STACK_UNWIND_STRICT (readdirp, frame, op_ret, op_errno, entries); + STACK_UNWIND_STRICT (readdirp, frame, op_ret, op_errno, entries, 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 iatt *statpre, - struct iatt *statpost) + struct iatt *statpost, + dict_t *xdata) { STACK_UNWIND_STRICT (setattr, frame, op_ret, op_errno, statpre, - statpost); + statpost, xdata); 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 iatt *statpre, - struct iatt *statpost) + struct iatt *statpost, + dict_t *xdata) { STACK_UNWIND_STRICT (fsetattr, frame, op_ret, op_errno, statpre, - statpost); + statpost, xdata); return 0; } 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_STRICT(fallocate, frame, op_ret, op_errno, pre, post, xdata); + return 0; +} + +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) +{ + STACK_UNWIND_STRICT(discard, frame, op_ret, op_errno, pre, post, xdata); + 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_getspec_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, char *spec_data) { @@ -429,257 +495,271 @@ default_getspec_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t default_fgetxattr_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, - const char *name) + const char *name, dict_t *xdata) { STACK_WIND (frame, default_fgetxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fgetxattr, fd, name); + FIRST_CHILD(this)->fops->fgetxattr, fd, name, xdata); return 0; } int32_t default_fsetxattr_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, - dict_t *dict, int32_t flags) + 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); + FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags, xdata); return 0; } int32_t default_setxattr_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - dict_t *dict, int32_t flags) + dict_t *dict, int32_t flags, dict_t *xdata) { STACK_WIND (frame, default_setxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->setxattr, loc, dict, flags); + FIRST_CHILD(this)->fops->setxattr, loc, dict, flags, xdata); return 0; } int32_t -default_statfs_resume (call_frame_t *frame, xlator_t *this, loc_t *loc) +default_statfs_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { STACK_WIND (frame, default_statfs_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->statfs, loc); + 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) + int32_t flags, dict_t *xdata) { STACK_WIND (frame, default_fsyncdir_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsyncdir, fd, flags); + FIRST_CHILD(this)->fops->fsyncdir, fd, flags, xdata); return 0; } int32_t default_opendir_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - fd_t *fd) + fd_t *fd, dict_t *xdata) { STACK_WIND (frame, default_opendir_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->opendir, loc, fd); + FIRST_CHILD(this)->fops->opendir, loc, fd, xdata); return 0; } int32_t -default_fstat_resume (call_frame_t *frame, xlator_t *this, fd_t *fd) +default_fstat_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); + FIRST_CHILD(this)->fops->fstat, fd, xdata); return 0; } int32_t default_fsync_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, - int32_t flags) + int32_t flags, dict_t *xdata) { STACK_WIND (frame, default_fsync_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsync, fd, flags); + FIRST_CHILD(this)->fops->fsync, fd, flags, xdata); return 0; } int32_t -default_flush_resume (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_flush_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->flush, fd); + FIRST_CHILD(this)->fops->flush, fd, xdata); return 0; } int32_t default_writev_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, int32_t count, off_t off, - struct iobref *iobref) + uint32_t flags, struct iobref *iobref, dict_t *xdata) { STACK_WIND (frame, default_writev_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->writev, fd, vector, count, off, - iobref); + flags, iobref, xdata); return 0; } int32_t default_readv_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, - size_t size, off_t offset) + size_t size, off_t offset, uint32_t flags, dict_t *xdata) { STACK_WIND (frame, default_readv_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readv, fd, size, offset); + FIRST_CHILD(this)->fops->readv, fd, size, offset, flags, xdata); return 0; } int32_t default_open_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - int32_t flags, fd_t *fd, int32_t wbflags) + int32_t flags, fd_t *fd, dict_t *xdata) { STACK_WIND (frame, default_open_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->open, loc, flags, fd, wbflags); + FIRST_CHILD(this)->fops->open, loc, flags, fd, xdata); return 0; } int32_t default_create_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - int32_t flags, mode_t mode, fd_t *fd, dict_t *params) + int32_t flags, mode_t mode, mode_t umask, fd_t *fd, + dict_t *xdata) { STACK_WIND (frame, default_create_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->create, loc, flags, mode, fd, - params); + FIRST_CHILD(this)->fops->create, loc, flags, mode, umask, + fd, xdata); return 0; } int32_t default_link_resume (call_frame_t *frame, xlator_t *this, loc_t *oldloc, - loc_t *newloc) + loc_t *newloc, dict_t *xdata) { STACK_WIND (frame, default_link_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->link, oldloc, newloc); + FIRST_CHILD(this)->fops->link, oldloc, newloc, xdata); return 0; } int32_t default_rename_resume (call_frame_t *frame, xlator_t *this, loc_t *oldloc, - loc_t *newloc) + loc_t *newloc, dict_t *xdata) { STACK_WIND (frame, default_rename_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rename, oldloc, newloc); + FIRST_CHILD(this)->fops->rename, oldloc, newloc, xdata); return 0; } int default_symlink_resume (call_frame_t *frame, xlator_t *this, - const char *linkpath, loc_t *loc, dict_t *params) + const char *linkpath, loc_t *loc, mode_t umask, + dict_t *xdata) { STACK_WIND (frame, default_symlink_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->symlink, linkpath, loc, params); + FIRST_CHILD(this)->fops->symlink, linkpath, loc, umask, + xdata); return 0; } int32_t default_rmdir_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - int flags) + int flags, dict_t *xdata) { STACK_WIND (frame, default_rmdir_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rmdir, loc, flags); + 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) +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); + 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, dict_t *params) + 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, params); + FIRST_CHILD(this)->fops->mkdir, loc, mode, umask, xdata); return 0; } int default_mknod_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - mode_t mode, dev_t rdev, dict_t *parms) + mode_t mode, dev_t rdev, mode_t umask, dict_t *xdata) { STACK_WIND (frame, default_mknod_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, parms); + FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, umask, + xdata); return 0; } int32_t default_readlink_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - size_t size) + size_t size, dict_t *xdata) { STACK_WIND (frame, default_readlink_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readlink, loc, size); + FIRST_CHILD(this)->fops->readlink, loc, size, xdata); return 0; } int32_t default_access_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - int32_t mask) + int32_t mask, dict_t *xdata) { STACK_WIND (frame, default_access_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->access, loc, mask); + FIRST_CHILD(this)->fops->access, loc, mask, xdata); return 0; } int32_t default_ftruncate_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, - off_t offset) + off_t offset, dict_t *xdata) { STACK_WIND (frame, default_ftruncate_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->ftruncate, fd, offset); + FIRST_CHILD(this)->fops->ftruncate, fd, offset, xdata); return 0; } int32_t default_getxattr_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - const char *name) + const char *name, dict_t *xdata) { STACK_WIND (frame, default_getxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->getxattr, loc, name); + FIRST_CHILD(this)->fops->getxattr, loc, name, xdata); return 0; } int32_t default_xattrop_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - gf_xattrop_flags_t flags, dict_t *dict) + gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata) { STACK_WIND (frame, default_xattrop_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->xattrop, loc, flags, dict); + 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) + 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); + FIRST_CHILD(this)->fops->fxattrop, fd, flags, dict, xdata); return 0; } int32_t default_removexattr_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - const char *name) + const char *name, dict_t *xdata) { STACK_WIND (frame, default_removexattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->removexattr, loc, name); + 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_lk_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, - int32_t cmd, struct gf_flock *lock) + int32_t cmd, struct gf_flock *lock, dict_t *xdata) { STACK_WIND (frame, default_lk_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->lk, fd, cmd, lock); + FIRST_CHILD(this)->fops->lk, fd, cmd, lock, xdata); return 0; } @@ -687,367 +767,431 @@ default_lk_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, 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) + struct gf_flock *lock, + dict_t *xdata) { STACK_WIND (frame, default_inodelk_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->inodelk, - volume, loc, cmd, lock); + volume, loc, cmd, lock, xdata); return 0; } int32_t default_finodelk_resume (call_frame_t *frame, xlator_t *this, const char *volume, fd_t *fd, int32_t cmd, - struct gf_flock *lock) + struct gf_flock *lock, + dict_t *xdata) { STACK_WIND (frame, default_finodelk_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->finodelk, - volume, fd, cmd, lock); + volume, fd, cmd, lock, xdata); return 0; } 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) + entrylk_cmd cmd, entrylk_type type, + dict_t *xdata) { STACK_WIND (frame, default_entrylk_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->entrylk, - volume, loc, basename, cmd, type); + volume, loc, basename, cmd, type, xdata); return 0; } 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) + entrylk_cmd cmd, entrylk_type type, + dict_t *xdata) { STACK_WIND (frame, default_fentrylk_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->fentrylk, - volume, fd, basename, cmd, type); + volume, fd, basename, cmd, type, xdata); return 0; } int32_t default_rchecksum_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, - off_t offset, int32_t len) + off_t offset, int32_t len, + dict_t *xdata) { STACK_WIND (frame, default_rchecksum_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rchecksum, fd, offset, len); + FIRST_CHILD(this)->fops->rchecksum, fd, offset, len, xdata); return 0; } int32_t default_readdir_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, - size_t size, off_t off) + size_t size, off_t off, + dict_t *xdata) { STACK_WIND (frame, default_readdir_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readdir, fd, size, off); + FIRST_CHILD(this)->fops->readdir, fd, size, off, xdata); return 0; } int32_t default_readdirp_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, - size_t size, off_t off) + size_t size, off_t off, dict_t *xdata) { STACK_WIND (frame, default_readdirp_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readdirp, fd, size, off); + FIRST_CHILD(this)->fops->readdirp, fd, size, off, xdata); return 0; } int32_t default_setattr_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - struct iatt *stbuf, int32_t valid) + struct iatt *stbuf, int32_t valid, + dict_t *xdata) { STACK_WIND (frame, default_setattr_cbk, FIRST_CHILD (this), - FIRST_CHILD (this)->fops->setattr, loc, stbuf, valid); + FIRST_CHILD (this)->fops->setattr, loc, stbuf, valid, xdata); return 0; } int32_t default_truncate_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - off_t offset) + off_t offset, + dict_t *xdata) { STACK_WIND (frame, default_truncate_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->truncate, loc, offset); + FIRST_CHILD(this)->fops->truncate, loc, offset, xdata); return 0; } int32_t -default_stat_resume (call_frame_t *frame, xlator_t *this, loc_t *loc) +default_stat_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata) { STACK_WIND (frame, default_stat_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->stat, loc); + 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 *xattr_req) + dict_t *xdata) { STACK_WIND (frame, default_lookup_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->lookup, loc, xattr_req); + FIRST_CHILD(this)->fops->lookup, loc, xdata); return 0; } int32_t default_fsetattr_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, - struct iatt *stbuf, int32_t valid) + 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); + 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_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_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; +} + + /* FOPS */ int32_t default_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, - const char *name) + const char *name, dict_t *xdata) { - STACK_WIND (frame, default_fgetxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fgetxattr, fd, name); + 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) + int32_t flags, dict_t *xdata) { - STACK_WIND (frame, default_fsetxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags, + xdata); return 0; } int32_t default_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, - int32_t flags) + int32_t flags, dict_t *xdata) { - STACK_WIND (frame, default_setxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->setxattr, loc, dict, flags); + 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) +default_statfs (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { - STACK_WIND (frame, default_statfs_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->statfs, loc); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->statfs, loc, xdata); return 0; } int32_t -default_fsyncdir (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags) +default_fsyncdir (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); + 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) +default_opendir (call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, dict_t *xdata) { - STACK_WIND (frame, default_opendir_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->opendir, loc, fd); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->opendir, loc, fd, xdata); return 0; } int32_t -default_fstat (call_frame_t *frame, xlator_t *this, fd_t *fd) +default_fstat (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); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fstat, fd, xdata); return 0; } int32_t -default_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags) +default_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, dict_t *xdata) { - STACK_WIND (frame, default_fsync_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsync, fd, flags); + 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) +default_flush (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) { - STACK_WIND (frame, default_flush_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->flush, fd); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->flush, fd, 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) + struct iovec *vector, int32_t count, off_t off, uint32_t flags, + struct iobref *iobref, dict_t *xdata) { - STACK_WIND (frame, default_writev_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->writev, fd, vector, count, off, - iobref); + 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) + off_t offset, uint32_t flags, dict_t *xdata) { - STACK_WIND (frame, default_readv_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readv, fd, size, offset); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readv, fd, size, offset, + flags, 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) + fd_t *fd, dict_t *xdata) { - STACK_WIND (frame, default_open_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->open, loc, flags, fd, wbflags); + 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, fd_t *fd, dict_t *params) + mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata) { - STACK_WIND (frame, default_create_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->create, loc, flags, mode, fd, - params); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->create, loc, flags, mode, + umask, fd, xdata); return 0; } int32_t -default_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc) +default_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, + dict_t *xdata) { - STACK_WIND (frame, default_link_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->link, oldloc, newloc); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->link, oldloc, newloc, xdata); return 0; } int32_t default_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, - loc_t *newloc) + loc_t *newloc, dict_t *xdata) { - STACK_WIND (frame, default_rename_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rename, oldloc, newloc); + 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, dict_t *params) + loc_t *loc, mode_t umask, dict_t *xdata) { - STACK_WIND (frame, default_symlink_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->symlink, linkpath, loc, params); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->symlink, linkpath, loc, + umask, xdata); return 0; } int32_t -default_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags) +default_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags, + dict_t *xdata) { - STACK_WIND (frame, default_rmdir_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rmdir, loc, flags); + 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) +default_unlink (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); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->unlink, loc, xflag, xdata); return 0; } int default_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, - dict_t *params) + mode_t umask, dict_t *xdata) { - STACK_WIND (frame, default_mkdir_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->mkdir, loc, mode, params); + 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, dict_t *parms) + dev_t rdev, mode_t umask, dict_t *xdata) { - STACK_WIND (frame, default_mknod_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, parms); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, + umask, xdata); return 0; } int32_t -default_readlink (call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size) +default_readlink (call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size, dict_t *xdata) { - STACK_WIND (frame, default_readlink_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readlink, loc, size); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readlink, loc, size, xdata); return 0; } int32_t -default_access (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t mask) +default_access (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t mask, dict_t *xdata) { - STACK_WIND (frame, default_access_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->access, loc, mask); + 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) +default_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, dict_t *xdata) { - STACK_WIND (frame, default_ftruncate_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->ftruncate, fd, offset); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->ftruncate, fd, offset, xdata); return 0; } int32_t default_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, - const char *name) + const char *name, dict_t *xdata) { - STACK_WIND (frame, default_getxattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->getxattr, loc, name); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getxattr, loc, name, 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) + gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata) { - STACK_WIND (frame, default_xattrop_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->xattrop, loc, flags, dict); + 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) + 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); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fxattrop, fd, flags, dict, + xdata); return 0; } int32_t default_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, - const char *name) + const char *name, dict_t *xdata) { - STACK_WIND (frame, default_removexattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->removexattr, loc, name); + 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_lk (call_frame_t *frame, xlator_t *this, fd_t *fd, - int32_t cmd, struct gf_flock *lock) + int32_t cmd, struct gf_flock *lock, dict_t *xdata) { - STACK_WIND (frame, default_lk_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->lk, fd, cmd, lock); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lk, fd, cmd, lock, xdata); return 0; } @@ -1055,115 +1199,160 @@ default_lk (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t default_inodelk (call_frame_t *frame, xlator_t *this, const char *volume, loc_t *loc, int32_t cmd, - struct gf_flock *lock) + struct gf_flock *lock, + dict_t *xdata) { - STACK_WIND (frame, default_inodelk_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->inodelk, - volume, loc, cmd, lock); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->inodelk, volume, loc, cmd, + lock, xdata); return 0; } int32_t default_finodelk (call_frame_t *frame, xlator_t *this, - const char *volume, fd_t *fd, int32_t cmd, struct gf_flock *lock) + const char *volume, fd_t *fd, int32_t cmd, struct gf_flock *lock, + dict_t *xdata) { - STACK_WIND (frame, default_finodelk_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->finodelk, - volume, fd, cmd, lock); + 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) + entrylk_cmd cmd, entrylk_type type, + dict_t *xdata) { - STACK_WIND (frame, default_entrylk_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->entrylk, - volume, loc, basename, cmd, type); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->entrylk, volume, loc, + basename, cmd, type, 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) + entrylk_cmd cmd, entrylk_type type, + dict_t *xdata) { - STACK_WIND (frame, default_fentrylk_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fentrylk, - volume, fd, basename, cmd, type); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fentrylk, volume, fd, + basename, cmd, type, xdata); return 0; } 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) { - STACK_WIND (frame, default_rchecksum_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->rchecksum, fd, offset, len); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->rchecksum, fd, offset, len, + xdata); return 0; } int32_t default_readdir (call_frame_t *frame, xlator_t *this, fd_t *fd, - size_t size, off_t off) + size_t size, off_t off, + dict_t *xdata) { - STACK_WIND (frame, default_readdir_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readdir, fd, size, off); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readdir, fd, size, off, + xdata); return 0; } int32_t default_readdirp (call_frame_t *frame, xlator_t *this, fd_t *fd, - size_t size, off_t off) + size_t size, off_t off, dict_t *xdata) { - STACK_WIND (frame, default_readdirp_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->readdirp, fd, size, off); + 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) + struct iatt *stbuf, int32_t valid, + dict_t *xdata) { - STACK_WIND (frame, default_setattr_cbk, FIRST_CHILD (this), - FIRST_CHILD (this)->fops->setattr, loc, stbuf, valid); + STACK_WIND_TAIL (frame, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->setattr, loc, stbuf, valid, + xdata); return 0; } int32_t -default_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset) +default_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, + dict_t *xdata) { - STACK_WIND (frame, default_truncate_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->truncate, loc, offset); + 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) +default_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, + dict_t *xdata) { - STACK_WIND (frame, default_stat_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->stat, loc); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->stat, loc, xdata); return 0; } int32_t default_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, - dict_t *xattr_req) + dict_t *xdata) { - STACK_WIND (frame, default_lookup_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->lookup, loc, xattr_req); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lookup, loc, xdata); return 0; } int32_t default_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, - struct iatt *stbuf, int32_t valid) + 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); + STACK_WIND_TAIL (frame, FIRST_CHILD (this), + FIRST_CHILD (this)->fops->fsetattr, fd, stbuf, valid, + xdata); + return 0; +} + +int32_t +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_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_zerofill(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->zerofill, fd, offset, len, + xdata); return 0; } @@ -1171,6 +1360,8 @@ default_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t default_forget (xlator_t *this, inode_t *inode) { + gf_log_callingfn (this->name, GF_LOG_WARNING, "xlator does not " + "implement forget_cbk"); return 0; } @@ -1178,12 +1369,16 @@ default_forget (xlator_t *this, inode_t *inode) int32_t default_releasedir (xlator_t *this, fd_t *fd) { + gf_log_callingfn (this->name, GF_LOG_WARNING, "xlator does not " + "implement releasedir_cbk"); return 0; } int32_t default_release (xlator_t *this, fd_t *fd) { + gf_log_callingfn (this->name, GF_LOG_WARNING, "xlator does not " + "implement release_cbk"); return 0; } @@ -1196,8 +1391,8 @@ int32_t default_getspec (call_frame_t *frame, xlator_t *this, const char *key, int32_t flags) { - STACK_WIND (frame, default_getspec_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->getspec, key, flags); + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getspec, key, flags); return 0; } @@ -1208,6 +1403,7 @@ 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; @@ -1218,10 +1414,13 @@ default_notify (xlator_t *this, int32_t event, void *data, ...) } 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 the case of CHILD_UP specially, send it to fuse */ + /* 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); @@ -1233,7 +1432,6 @@ default_notify (xlator_t *this, int32_t event, void *data, ...) } } break; - case GF_EVENT_CHILD_DOWN: default: { xlator_list_t *parent = this->parents; diff --git a/libglusterfs/src/defaults.h b/libglusterfs/src/defaults.h index 6e451602b..0747027bc 100644 --- a/libglusterfs/src/defaults.h +++ b/libglusterfs/src/defaults.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,6 +22,18 @@ #include "xlator.h" +int32_t default_notify (xlator_t *this, + int32_t event, + void *data, + ...); + +int32_t default_forget (xlator_t *this, inode_t *inode); + +int32_t default_release (xlator_t *this, fd_t *fd); + +int32_t default_releasedir (xlator_t *this, fd_t *fd); + + /* Management Operations */ int32_t default_getspec (call_frame_t *frame, @@ -41,83 +44,85 @@ int32_t default_getspec (call_frame_t *frame, 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); + dict_t *xdata); int32_t default_stat (call_frame_t *frame, xlator_t *this, - loc_t *loc); + loc_t *loc, dict_t *xdata); int32_t default_fstat (call_frame_t *frame, xlator_t *this, - fd_t *fd); + fd_t *fd, dict_t *xdata); int32_t default_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, - off_t offset); + off_t offset, dict_t *xdata); int32_t default_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, - off_t offset); + off_t offset, dict_t *xdata); int32_t default_access (call_frame_t *frame, xlator_t *this, loc_t *loc, - int32_t mask); + int32_t mask, dict_t *xdata); int32_t default_readlink (call_frame_t *frame, xlator_t *this, loc_t *loc, - size_t size); + 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, dict_t *params); +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, dict_t *params); + 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); + loc_t *loc, int xflag, dict_t *xdata); int32_t default_rmdir (call_frame_t *frame, xlator_t *this, - loc_t *loc, int flags); + 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, dict_t *params); + 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); + loc_t *newloc, dict_t *xdata); int32_t default_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, - loc_t *newloc); + 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, dict_t *params); + 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); + dict_t *xdata); int32_t default_readv (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, - off_t offset); + off_t offset, + uint32_t flags, dict_t *xdata); int32_t default_writev (call_frame_t *frame, xlator_t *this, @@ -125,550 +130,588 @@ int32_t default_writev (call_frame_t *frame, struct iovec *vector, int32_t count, off_t offset, - struct iobref *iobref); + uint32_t flags, + struct iobref *iobref, dict_t *xdata); int32_t default_flush (call_frame_t *frame, xlator_t *this, - fd_t *fd); + fd_t *fd, dict_t *xdata); int32_t default_fsync (call_frame_t *frame, xlator_t *this, fd_t *fd, - int32_t datasync); + int32_t datasync, dict_t *xdata); int32_t default_opendir (call_frame_t *frame, xlator_t *this, - loc_t *loc, fd_t *fd); + 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); + int32_t datasync, dict_t *xdata); int32_t default_statfs (call_frame_t *frame, xlator_t *this, - loc_t *loc); + 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); + int32_t flags, dict_t *xdata); int32_t default_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, - const char *name); + 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); + 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 gf_flock *flock); + 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 gf_flock *flock); + 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 gf_flock *flock); + 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); + 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); + 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); + 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); + 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); + 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); - -int32_t default_notify (xlator_t *this, - int32_t event, - void *data, - ...); - -int32_t default_forget (xlator_t *this, - inode_t *inode); - -int32_t default_release (xlator_t *this, - fd_t *fd); - -int32_t default_releasedir (xlator_t *this, - fd_t *fd); + 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); + 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); + int32_t valid, dict_t *xdata); + +int32_t 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); + +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_zerofill(call_frame_t *frame, + xlator_t *this, + fd_t *fd, + off_t offset, + size_t len, dict_t *xdata); + /* Resume */ -int32_t default_getspec (call_frame_t *frame, - xlator_t *this, - const char *key, - int32_t flag); +int32_t default_getspec_resume (call_frame_t *frame, + xlator_t *this, + const char *key, + int32_t flag); -int32_t default_rchecksum (call_frame_t *frame, +int32_t default_rchecksum_resume (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_resume (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_resume (call_frame_t *frame, xlator_t *this, - loc_t *loc); + loc_t *loc, dict_t *xdata); int32_t default_fstat_resume (call_frame_t *frame, xlator_t *this, - fd_t *fd); + fd_t *fd, dict_t *xdata); int32_t default_truncate_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - off_t offset); + off_t offset, dict_t *xdata); int32_t default_ftruncate_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, - off_t offset); + off_t offset, dict_t *xdata); int32_t default_access_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - int32_t mask); + int32_t mask, dict_t *xdata); int32_t default_readlink_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - size_t size); + 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, dict_t *params); +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, dict_t *params); +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); + 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 flags); + 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, dict_t *params); + 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); + loc_t *newloc, dict_t *xdata); int32_t default_link_resume (call_frame_t *frame, xlator_t *this, loc_t *oldloc, - loc_t *newloc); + 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, - fd_t *fd, dict_t *params); + 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, - int32_t wbflags); + 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); + 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, - 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_resume (call_frame_t *frame, xlator_t *this, - fd_t *fd); + fd_t *fd, dict_t *xdata); int32_t default_fsync_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, - int32_t datasync); + int32_t datasync, dict_t *xdata); int32_t default_opendir_resume (call_frame_t *frame, xlator_t *this, - loc_t *loc, fd_t *fd); + 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); + int32_t datasync, dict_t *xdata); int32_t default_statfs_resume (call_frame_t *frame, xlator_t *this, - loc_t *loc); + 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); + int32_t flags, dict_t *xdata); int32_t default_getxattr_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - const char *name); + 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); + int32_t flags, dict_t *xdata); int32_t default_fgetxattr_resume (call_frame_t *frame, xlator_t *this, fd_t *fd, - const char *name); + const char *name, dict_t *xdata); int32_t default_removexattr_resume (call_frame_t *frame, xlator_t *this, loc_t *loc, - const char *name); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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, gf_xattrop_flags_t flags, - dict_t *dict); + dict_t *dict, dict_t *xdata); 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 *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); - -int32_t default_notify (xlator_t *this, - int32_t event, - void *data, - ...); - -int32_t default_forget (xlator_t *this, - inode_t *inode); - -int32_t default_release (xlator_t *this, - fd_t *fd); - -int32_t default_releasedir (xlator_t *this, - fd_t *fd); + 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); + 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); + 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 *dict, struct iatt *postparent); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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, @@ -676,4 +719,5 @@ default_getspec_cbk (call_frame_t *frame, void *cookie, xlator_t *this, 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 bbd14fc86..3b7ddce5e 100644 --- a/libglusterfs/src/dict.c +++ b/libglusterfs/src/dict.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,872 +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 *) GF_CALLOC (1, sizeof (data_pair_t), - gf_common_mt_data_pair_t); - if (!data_pair_ptr) - gf_log ("dict", GF_LOG_ERROR, "memory alloc failed"); - - return data_pair_ptr; -} +#include "globals.h" data_t * get_new_data () { - data_t *data = NULL; + data_t *data = NULL; - data = (data_t *) GF_CALLOC (1, sizeof (data_t), gf_common_mt_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 = GF_CALLOC (1, sizeof (dict_t), gf_common_mt_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 = GF_CALLOC (size_hint, sizeof (data_pair_t *), - gf_common_mt_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) { + if (!data->is_static) { + if (data->data) { if (data->is_stdalloc) free (data->data); - else + else GF_FREE (data->data); } - if (data->vec) - GF_FREE (data->vec); - } + } - data->len = 0xbabababa; - if (!data->is_const) - GF_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; - } - - data_t *newdata = (data_t *) GF_CALLOC (1, sizeof (*newdata), - gf_common_mt_data_t); + if (!old) { + gf_log_callingfn ("dict", GF_LOG_WARNING, + "old is NULL"); + return NULL; + } - if (!newdata) { - gf_log ("dict", GF_LOG_CRITICAL, - "@newdata - NULL returned by CALLOC"); - return NULL; - } + data_t *newdata = mem_get0 (THIS->ctx->dict_data_pool); + if (!newdata) { + 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->vec) { - newdata->vec = memdup (old->vec, old->len * (sizeof (void *) + - sizeof (size_t))); - if (!newdata->vec) - goto err_out; - } - } + if (old) { + newdata->len = old->len; + if (old->data) { + newdata->data = memdup (old->data, old->len); + if (!newdata->data) + goto err_out; + } + } - return newdata; + LOCK_INIT (&newdata->lock); + return newdata; - err_out: +err_out: - if (newdata->data) - FREE (newdata->data); - if (newdata->vec) - FREE (newdata->vec); - FREE (newdata); + FREE (newdata->data); + mem_put (newdata); - gf_log ("dict", GF_LOG_CRITICAL, - "@newdata->data || @newdata->vec got NULL from CALLOC()"); - return NULL; + 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 = gf_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) - GF_FREE (key); - /* Indicates duplicate key */ - return 0; - } - pair = (data_pair_t *) GF_CALLOC (1, sizeof (*pair), - gf_common_mt_data_pair_t); - 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 *) GF_CALLOC (1, strlen (key) + 1, - gf_common_mt_char); - if (!pair->key) { - gf_log ("dict", GF_LOG_CRITICAL, - "@pair->key - NULL returned by CALLOC"); - FREE (pair); + 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) - GF_FREE (key); - return -1; - } + 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; - 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) - GF_FREE (key); - return 0; + 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) + 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_ERROR, - "@this=%p @value=%p, key=%s", this, value, key); - 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_callingfn ("dict", GF_LOG_DEBUG, - "@this=%p key=%s", this, (key) ? 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; - - GF_FREE (pair->key); - GF_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 = this->members_list; - data_pair_t *prev = this->members_list; + data_pair_t *pair; - 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); - GF_FREE (prev->key); - GF_FREE (prev); - prev = pair; - } + LOCK (&this->lock); - GF_FREE (this->members); + pair = _dict_lookup (this, key); - if (this->extra_free) - GF_FREE (this->extra_free); - if (this->extra_stdfree) - free (this->extra_stdfree); + UNLOCK (&this->lock); - if (!this->is_static) - GF_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 || !key) { + gf_log_callingfn ("dict", GF_LOG_WARNING, + "!this || key=%s", key); + return; + } - if (!this) { - gf_log ("dict", GF_LOG_DEBUG, - "@this=%p", this); - return; - } + 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; - this->refcount--; - ref = this->refcount; + while (pair) { + if (strcmp (pair->key, key) == 0) { + if (prev) + prev->hash_next = pair->hash_next; + else + this->members[hashval] = pair->hash_next; - UNLOCK (&this->lock); + data_unref (pair->value); - if (!ref) - dict_destroy (this); -} + if (pair->prev) + pair->prev->next = pair->next; + else + this->members_list = pair->next; -dict_t * -dict_ref (dict_t *this) -{ - if (!this) { - gf_log ("dict", GF_LOG_DEBUG, - "@this=%p", this); - return NULL; - } + if (pair->next) + pair->next->prev = pair->prev; - LOCK (&this->lock); + 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 || !(*fill)) { - gf_log ("dict", GF_LOG_ERROR, - "@buf=%p @fill=%p @*fill=%p", - buf, fill, (fill) ? (*fill) : NULL); - 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: - GF_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 = gf_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 = gf_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 = gf_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 = gf_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 = gf_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 = gf_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 = gf_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; } @@ -908,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 = gf_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; } @@ -931,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 = gf_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 * @@ -977,326 +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 ("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; data->is_stdalloc = 1; - return data; + return data; } data_t * data_from_dynptr (void *value, int32_t len) { - data_t *data = get_new_data (); + data_t *data = get_new_data (); - data->len = len; - data->data = value; + if (!data) + return NULL; + + 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); + char *str = alloca (data->len + 1); if (!str) return -1; - 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); + char *str = alloca (data->len + 1); if (!str) return -1; - memcpy (str, data->data, data->len); - str[data->len] = '\0'; + memcpy (str, data->data, data->len); + str[data->len] = '\0'; - return strtoul (str, NULL, 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); + char *str = alloca (data->len + 1); if (!str) return -1; - memcpy (str, data->data, data->len); - str[data->len] = '\0'; + 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; - char *str = alloca (data->len + 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; - memcpy (str, data->data, data->len); - str[data->len] = '\0'; + memcpy (str, data->data, data->len); + str[data->len] = '\0'; + + errno = 0; + value = strtol (str, NULL, 0); - return (int8_t)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); + if (!data) + return -1; + char *str = alloca (data->len + 1); if (!str) return -1; - memcpy (str, data->data, data->len); - str[data->len] = '\0'; + 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); + char *str = alloca (data->len + 1); if (!str) return -1; - 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; - char *str = alloca (data->len + 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; - 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); + 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_WARNING, - "@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 || !dict) { - gf_log_callingfn ("dict", GF_LOG_CRITICAL, - "@data=%p, @dict=%p", data, dict); - 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; - data_pair_t *next = NULL; + int ret = -1; + data_pair_t *pairs = NULL; + data_pair_t *next = NULL; + pairs = dict->members_list; while (pairs) { next = pairs->next; - fn (dict, pairs->key, pairs->value, data); + 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; } /* @@ -1305,7 +1272,7 @@ fail: /** * Common cleaned up interface: - * + * * Return value: 0 success * -val error, val = errno */ @@ -1314,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; } @@ -1821,355 +1790,385 @@ 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); + + 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; -err: - if (data) - data_unref (data); + ret = _data_to_ptr (data, ptr); + if (ret != 0) { + goto err; + } - return ret; +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); + ret = dict_set (this, key, data); err: - return ret; + return ret; } /* - for malloced strings we should do a free instead of GF_FREE + 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_t * data = NULL; + int ret = 0; - data = data_from_dynmstr (str); - if (!data) { - ret = -EINVAL; - goto err; - } + 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; + data->data = ptr; + data->len = size; + data->is_static = 1; - ret = dict_set (this, key, data); + ret = dict_set (this, key, data); err: - return ret; + return ret; } @@ -2257,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 @@ -2341,78 +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; - int32_t netword = 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; - netword = hton32 (count); - memcpy (buf, &netword, sizeof(netword)); - 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); - netword = hton32 (keylen); - memcpy (buf, &netword, sizeof(netword)); - 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; - netword = hton32 (vallen); - memcpy (buf, &netword, sizeof(netword)); - 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'; - ret = 0; + if (!pair->value->data) { + gf_log ("dict", GF_LOG_ERROR, + "pair->value->data is null!"); + goto out; + } + memcpy (buf, pair->value->data, vallen); + buf += vallen; + + pair = pair->next; + count--; + } + + ret = 0; out: - return ret; + return ret; } @@ -2427,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); @@ -2441,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 @@ -2458,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); { @@ -2477,7 +2458,7 @@ dict_serialize (dict_t *this, char *buf) } UNLOCK (&this->lock); out: - return ret; + return ret; } @@ -2487,7 +2468,7 @@ out: * @buf: buf containing serialized dict * @size: size of the @buf * @fill: dict to fill in - * + * * @return: success: 0 * failure: -errno */ @@ -2495,116 +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; + 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; + data_t * value = NULL; + char * key = NULL; + int32_t keylen = 0; + int32_t vallen = 0; + int32_t hostord = 0; - buf = orig_buf; + buf = orig_buf; - if (!buf) { - gf_log ("dict", GF_LOG_ERROR, - "buf is null!"); - goto out; - } + if (!buf) { + gf_log_callingfn ("dict", GF_LOG_WARNING, "buf is null!"); + goto out; + } - if (size == 0) { - gf_log ("dict", GF_LOG_ERROR, - "size is 0!"); - goto out; - } + if (size == 0) { + gf_log_callingfn ("dict", GF_LOG_ERROR, + "size is 0!"); + goto out; + } - if (!fill) { - gf_log ("dict", GF_LOG_ERROR, - "fill is null!"); - goto out; - } + if (!fill) { + gf_log_callingfn ("dict", GF_LOG_ERROR, + "fill is null!"); + goto out; + } - if (!*fill) { - gf_log ("dict", GF_LOG_ERROR, - "*fill is null!"); - goto out; - } + if (!*fill) { + gf_log_callingfn ("dict", GF_LOG_ERROR, + "*fill is null!"); + goto out; + } - if ((buf + DICT_HDR_LEN) > (orig_buf + size)) { - gf_log ("dict", GF_LOG_ERROR, - "undersized buffer passed"); - goto out; - } + 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; + } - memcpy (&hostord, buf, sizeof(hostord)); - count = ntoh32 (hostord); - buf += DICT_HDR_LEN; + memcpy (&hostord, buf, sizeof(hostord)); + count = ntoh32 (hostord); + buf += DICT_HDR_LEN; - 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; + } - /* count will be set by the dict_set's below */ - (*fill)->count = 0; - - for (i = 0; i < count; i++) { - if ((buf + DICT_DATA_HDR_KEY_LEN) > (orig_buf + size)) { - gf_log ("dict", GF_LOG_DEBUG, - "No room for keylen (size %d).", - DICT_DATA_HDR_KEY_LEN); - gf_log ("dict", GF_LOG_ERROR, - "undersized buffer passed"); - 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 ("dict", GF_LOG_DEBUG, - "No room for vallen (size %d).", - DICT_DATA_HDR_VAL_LEN); - gf_log ("dict", GF_LOG_ERROR, - "undersized buffer passed"); - goto out; - } - memcpy (&hostord, buf, sizeof(hostord)); - vallen = ntoh32 (hostord); - buf += DICT_DATA_HDR_VAL_LEN; - - if ((buf + keylen) > (orig_buf + size)) { - gf_log ("dict", GF_LOG_DEBUG, - "No room for key (size %d).", keylen); - gf_log ("dict", GF_LOG_ERROR, - "undersized buffer passed"); - goto out; - } - key = buf; - buf += keylen + 1; /* for '\0' */ - - if ((buf + vallen) > (orig_buf + size)) { - gf_log ("dict", GF_LOG_DEBUG, - "No room for value (size %d).", vallen); - gf_log ("dict", GF_LOG_ERROR, - "undersized buffer passed"); - 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; } @@ -2613,31 +2598,26 @@ 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; @@ -2647,7 +2627,6 @@ dict_allocate_and_serialize (dict_t *this, char **buf, size_t *length) *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; } @@ -2665,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 417967051..9b41b5a7d 100644 --- a/libglusterfs/src/dict.h +++ b/libglusterfs/src/dict.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,62 +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; - unsigned char is_stdalloc: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; - char *extra_stdfree; - 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); @@ -109,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); @@ -127,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); @@ -173,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); @@ -186,4 +230,8 @@ 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 cb6abd418..0197e7948 100644 --- a/libglusterfs/src/event.c +++ b/libglusterfs/src/event.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,960 +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 = 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_log ("poll", GF_LOG_CRITICAL, - "failed to allocate event registry"); - 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; - - 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 = 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); - - 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; - - 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) - 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; - - - 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 = 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_log ("epoll", GF_LOG_CRITICAL, - "event registry allocation failed"); - GF_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)); - GF_FREE (event_pool->reg); - GF_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 = 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); - - 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; - - 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) - 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); - - 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); - } - } - - 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 25396325c..7ed182492 100644 --- a/libglusterfs/src/event.h +++ b/libglusterfs/src/event.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 e4e75d804..36cc4d056 100644 --- a/libglusterfs/src/fd.c +++ b/libglusterfs/src/fd.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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" @@ -35,30 +26,7 @@ gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr); 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 int -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_ref (fd_t *fd); static int gf_fd_chain_fd_entries (fdentry_t *entries, uint32_t startidx, @@ -66,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. @@ -85,35 +55,35 @@ gf_fd_chain_fd_entries (fdentry_t *entries, uint32_t startidx, static int gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr) { - fdentry_t *oldfds = NULL; - uint32_t oldmax_fds = -1; + fdentry_t *oldfds = NULL; + uint32_t oldmax_fds = -1; int ret = -1; - if (fdtable == NULL || nr < 0) { - gf_log ("fd", GF_LOG_ERROR, "invalid argument"); + 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_power_of_two (nr + 1); - nr *= (1024 / sizeof (fdentry_t)); + 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; + oldfds = fdtable->fdentries; + oldmax_fds = fdtable->max_fds; - fdtable->fdentries = GF_CALLOC (nr, sizeof (fdentry_t), + fdtable->fdentries = GF_CALLOC (nr, sizeof (fdentry_t), gf_common_mt_fdentry_t); - if (!fdtable->fdentries) { + if (!fdtable->fdentries) { ret = ENOMEM; goto out; } - fdtable->max_fds = nr; + fdtable->max_fds = nr; - if (oldfds) { - uint32_t cpy = oldmax_fds * sizeof (fdentry_t); - memcpy (fdtable->fdentries, oldfds, cpy); - } + 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); @@ -123,40 +93,41 @@ gf_fd_fdtable_expand (fdtable_t *fdtable, uint32_t nr) * using the expanded table. */ fdtable->first_free = oldmax_fds; - GF_FREE (oldfds); + GF_FREE (oldfds); ret = 0; out: - return ret; + return ret; } fdtable_t * gf_fd_fdtable_alloc (void) { - fdtable_t *fdtable = NULL; + fdtable_t *fdtable = NULL; - fdtable = GF_CALLOC (1, sizeof (*fdtable), gf_common_mt_fdtable_t); - 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; } @@ -188,6 +159,53 @@ gf_fd_fdtable_get_all_fds (fdtable_t *fdtable, uint32_t *count) } +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) { @@ -199,15 +217,17 @@ gf_fd_fdtable_destroy (fdtable_t *fdtable) 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); - GF_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++) { @@ -218,53 +238,52 @@ gf_fd_fdtable_destroy (fdtable_t *fdtable) } GF_FREE (fdentries); - pthread_mutex_destroy (&fdtable->lock); - GF_FREE (fdtable); - } + pthread_mutex_destroy (&fdtable->lock); + GF_FREE (fdtable); + } } 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; - } + 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: + 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 @@ -273,39 +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 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 == -2) + /* anonymous fd */ + return; - if (!(fd < fdtable->max_fds)) { - gf_log ("fd", GF_LOG_ERROR, "invalid argument"); - 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); - { + 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) @@ -314,85 +337,133 @@ 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); + pthread_mutex_unlock (&fdtable->lock); - if (fdptr) { - fd_unref (fdptr); - } + 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); + + if ((fd != NULL) && (fde != NULL)) { + fd_unref (fd); + } } fd_t * gf_fd_fdptr_get (fdtable_t *fdtable, int64_t fd) { - fd_t *fdptr = NULL; + fd_t *fdptr = NULL; - if (fdtable == NULL || fd < 0) { - gf_log ("fd", GF_LOG_ERROR, "invalid argument"); - errno = EINVAL; - return 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 ("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); + pthread_mutex_lock (&fdtable->lock); + { + fdptr = fdtable->fdentries[fd].fd; + if (fdptr) { + fd_ref (fdptr); + } + } + pthread_mutex_unlock (&fdtable->lock); - return fdptr; + return fdptr; } fd_t * -_fd_ref (fd_t *fd) +__fd_ref (fd_t *fd) { - ++fd->refcount; + ++fd->refcount; - return fd; + 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) { - GF_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; } @@ -400,55 +471,57 @@ static void fd_destroy (fd_t *fd) { xlator_t *xl = NULL; - int i = 0; + int i = 0; xlator_t *old_THIS = NULL; - struct mem_pool *tmp_pool = 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; - - tmp_pool = fd->inode->table->fd_mem_pool; + 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; + 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); + if (xl->cbks->releasedir) + xl->cbks->releasedir (xl, fd); THIS = old_THIS; - } - } + } + } } else { - for (i = 0; i < fd->xl_count; i++) { - if (fd->_ctx[i].key) { - xl = fd->_ctx[i].xl_key; + 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); + if (xl->cbks->release) + xl->cbks->release (xl, fd); THIS = old_THIS; - } - } + } + } } LOCK_DESTROY (&fd->lock); - GF_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; - mem_put (tmp_pool,fd); - tmp_pool = NULL; + fd_lk_ctx_unref (fd->lk_ctx); + mem_put (fd); out: return; } @@ -460,13 +533,13 @@ 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); @@ -480,56 +553,41 @@ fd_unref (fd_t *fd) fd_t * -fd_bind (fd_t *fd) +__fd_bind (fd_t *fd) { - inode_t *inode = NULL; - - if (!fd || !fd->inode) { - gf_log_callingfn ("fd", GF_LOG_ERROR, "!fd || !fd->inode"); - return NULL; - } - inode = fd->inode; - - LOCK (&inode->lock); - { - list_add (&fd->inode_list, &inode->fd_list); - } - UNLOCK (&inode->lock); + list_del_init (&fd->inode_list); + list_add (&fd->inode_list, &fd->inode->fd_list); + fd->inode->fd_count++; return fd; } -void -fd_unref_unbind (fd_t *fd) +fd_t * +fd_bind (fd_t *fd) { - GF_ASSERT (fd->refcount); + if (!fd || !fd->inode) { + gf_log_callingfn ("fd", GF_LOG_ERROR, "!fd || !fd->inode"); + return NULL; + } LOCK (&fd->inode->lock); { - --fd->refcount; - /* Better know what you're doing with this function - * because it does not do what fd_destroy does when - * refcount goes to 0. - * Make sure you only call this when you know there are - * pending refs on the fd. - */ - GF_ASSERT (fd->refcount); - list_del_init (&fd->inode_list); + fd = __fd_bind (fd); } UNLOCK (&fd->inode->lock); - return; + 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; } @@ -541,60 +599,211 @@ fd_create (inode_t *inode, pid_t pid) fd->_ctx = GF_CALLOC (1, (sizeof (struct _fd_ctx) * fd->xl_count), gf_common_mt_fd_ctx); - if (!fd->_ctx) { - GF_FREE (fd); - fd = NULL; - goto out; - } + 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); -out: + 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) + 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) @@ -614,9 +823,12 @@ fd_list_empty (inode_t *inode) 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; @@ -635,15 +847,40 @@ __fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value) } 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].xl_key = xlator; fd->_ctx[set_idx].value1 = value; out: - return ret; + return ret; } @@ -652,8 +889,10 @@ 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); { @@ -668,11 +907,11 @@ fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value) int __fd_ctx_get (fd_t *fd, xlator_t *xlator, uint64_t *value) { - int index = 0; + int index = 0; int ret = 0; - if (!fd || !xlator) - return -1; + if (!fd || !xlator) + return -1; for (index = 0; index < fd->xl_count; index++) { if (fd->_ctx[index].xl_key == xlator) @@ -688,7 +927,7 @@ __fd_ctx_get (fd_t *fd, xlator_t *xlator, uint64_t *value) *value = fd->_ctx[index].value1; out: - return ret; + return ret; } @@ -697,8 +936,8 @@ 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); { @@ -713,11 +952,11 @@ 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) { - int index = 0; + int index = 0; int ret = 0; - if (!fd || !xlator) - return -1; + if (!fd || !xlator) + return -1; for (index = 0; index < fd->xl_count; index++) { if (fd->_ctx[index].xl_key == xlator) @@ -736,7 +975,7 @@ __fd_ctx_del (fd_t *fd, xlator_t *xlator, uint64_t *value) fd->_ctx[index].value1 = 0; out: - return ret; + return ret; } @@ -745,8 +984,8 @@ 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); { @@ -767,16 +1006,16 @@ fd_dump (fd_t *fd, char *prefix) 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); } + } @@ -804,12 +1043,10 @@ fdtable_dump (fdtable_t *fdtable, char *prefix) if (!fdtable) return; - ret = pthread_mutex_trylock (&fdtable->lock); + ret = pthread_mutex_trylock (&fdtable->lock); - if (ret) { - gf_log ("fd", GF_LOG_WARNING, "Unable to acquire lock"); - return; - } + if (ret) + goto out; memset(key, 0, sizeof(key)); gf_proc_dump_build_key(key, prefix, "refcount"); @@ -821,7 +1058,7 @@ fdtable_dump (fdtable_t *fdtable, char *prefix) for ( i = 0 ; i < fdtable->max_fds; i++) { if (GF_FDENTRY_ALLOCATED == - fdtable->fdentries[i].next_free) { + 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); @@ -829,6 +1066,12 @@ 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; } @@ -838,7 +1081,7 @@ 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; @@ -847,28 +1090,25 @@ fd_ctx_dump (fd_t *fd, char *prefix) LOCK (&fd->lock); { if (fd->_ctx != NULL) { - fd_ctx = GF_CALLOC (fd->inode->table->xl->graph->xl_count, - sizeof (*fd_ctx), + fd_ctx = GF_CALLOC (fd->xl_count, sizeof (*fd_ctx), gf_common_mt_fd_ctx); if (fd_ctx == NULL) { - gf_log ("fd", GF_LOG_ERROR, "out of memory"); goto unlock; } - for (i = 0; i < fd->inode->table->xl->graph->xl_count; - i++) { + 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->inode->table->xl->graph->xl_count; i++) { + 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) @@ -877,9 +1117,99 @@ unlock: } out: - if (fd_ctx != NULL) { - GF_FREE (fd_ctx); + 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 f8bfe58d2..c1b9157d8 100644 --- a/libglusterfs/src/fd.h +++ b/libglusterfs/src/fd.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,9 +21,14 @@ #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 { union { @@ -45,21 +41,18 @@ struct _fd_ctx { }; }; -/* 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; @@ -93,7 +86,7 @@ typedef struct _fdtable fdtable_t; #include "xlator.h" -inline void +void gf_fd_put (fdtable_t *fdtable, int32_t fd); @@ -118,6 +111,10 @@ gf_fd_fdtable_destroy (fdtable_t *fdtable); fd_t * +__fd_ref (fd_t *fd); + + +fd_t * fd_ref (fd_t *fd); @@ -128,10 +125,25 @@ 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); @@ -152,6 +164,9 @@ 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); +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); @@ -161,15 +176,14 @@ 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); -fd_t * -_fd_ref (fd_t *fd); void -fd_ctx_dump (fd_t *fd, char *prefix); +gf_fdptr_put (fdtable_t *fdtable, fd_t *fd); -extern void -fd_unref_unbind (fd_t *fd); #endif /* _FD_H */ diff --git a/libglusterfs/src/gf-dirent.c b/libglusterfs/src/gf-dirent.c index af09cb06c..bb028c967 100644 --- a/libglusterfs/src/gf-dirent.c +++ b/libglusterfs/src/gf-dirent.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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. */ @@ -31,53 +22,33 @@ #include "xlator.h" gf_dirent_t * -gf_dirent_for_namelen (int len) -{ - gf_dirent_t *gf_dirent = NULL; - - /* TODO: use mem-pool */ - gf_dirent = CALLOC (len, sizeof(char)); - if (!gf_dirent) - return NULL; - - INIT_LIST_HEAD (&gf_dirent->list); - - gf_dirent->d_off = 0; - gf_dirent->d_ino = -1; - gf_dirent->d_type = 0; - - return gf_dirent; -} - - -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 = GF_CALLOC (gf_dirent_size (name), 1, - gf_common_mt_gf_dirent_t); - 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; @@ -85,10 +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); - GF_FREE (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); + 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_link_inodes_from_dirent (xlator_t *this, inode_t *parent, + gf_dirent_t *entries) +{ + 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 8a6533fc3..588d522db 100644 --- a/libglusterfs/src/gf-dirent.h +++ b/libglusterfs/src/gf-dirent.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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. */ @@ -27,6 +18,7 @@ #endif #include "iatt.h" +#include "inode.h" #define gf_dirent_size(name) (sizeof (gf_dirent_t) + strlen (name) + 1) @@ -51,12 +43,16 @@ struct _gf_dirent_t { uint32_t d_len; uint32_t d_type; struct iatt d_stat; - char d_name[0]; + 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); -gf_dirent_t * gf_dirent_for_namelen (int len); +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 979f84e32..259c5c885 100644 --- a/libglusterfs/src/globals.c +++ b/libglusterfs/src/globals.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 @@ -28,112 +19,74 @@ #include "globals.h" #include "xlator.h" #include "mem-pool.h" - - -/* gf_*_list[] */ - -char *gf_fop_list[GF_FOP_MAXVALUE]; -char *gf_mgmt_list[GF_MGMT_MAXVALUE]; - - -void -gf_op_list_init() -{ - gf_fop_list[GF_FOP_NULL] = "NULL"; - gf_fop_list[GF_FOP_STAT] = "STAT"; - gf_fop_list[GF_FOP_READLINK] = "READLINK"; - gf_fop_list[GF_FOP_MKNOD] = "MKNOD"; - gf_fop_list[GF_FOP_MKDIR] = "MKDIR"; - gf_fop_list[GF_FOP_UNLINK] = "UNLINK"; - gf_fop_list[GF_FOP_RMDIR] = "RMDIR"; - 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_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"; - 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"; - gf_fop_list[GF_FOP_REMOVEXATTR] = "REMOVEXATTR"; - gf_fop_list[GF_FOP_OPENDIR] = "OPENDIR"; - gf_fop_list[GF_FOP_FSYNCDIR] = "FSYNCDIR"; - 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"; - gf_fop_list[GF_FOP_LOOKUP] = "LOOKUP"; - 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"; - gf_fop_list[GF_FOP_XATTROP] = "XATTROP"; - gf_fop_list[GF_FOP_FXATTROP] = "FXATTROP"; - 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_fop_list[GF_FOP_GETSPEC] = "GETSPEC"; - gf_fop_list[GF_FOP_FORGET] = "FORGET"; - gf_fop_list[GF_FOP_RELEASE] = "RELEASE"; - gf_fop_list[GF_FOP_RELEASEDIR] = "RELEASEDIR"; - - gf_fop_list[GF_MGMT_NULL] = "NULL"; - return; -} - - -/* 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; - } - - INIT_LIST_HEAD (&glusterfs_ctx->graphs); - ret = pthread_mutex_init (&glusterfs_ctx->lock, NULL); - -out: - return ret; -} - - -glusterfs_ctx_t * -glusterfs_ctx_get () -{ - return glusterfs_ctx; - -} - - +#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); } @@ -144,12 +97,14 @@ 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"; - global_xlator.ctx = glusterfs_ctx; + + INIT_LIST_HEAD (&global_xlator.volume_options); return ret; } @@ -211,68 +166,56 @@ glusterfs_this_set (xlator_t *this) return 0; } +/* SYNCOPCTX */ +static pthread_key_t syncopctx_key; -/* IS_CENTRAL_LOG */ - -static pthread_key_t central_log_flag_key; - -void -glusterfs_central_log_flag_destroy (void *ptr) -{ - if (ptr) - FREE (ptr); -} - - -int -glusterfs_central_log_flag_init () +static void +syncopctx_key_destroy (void *ptr) { - int ret = 0; + struct syncopctx *opctx = ptr; - ret = pthread_key_create (¢ral_log_flag_key, - glusterfs_central_log_flag_destroy); - - if (ret != 0) { - return ret; - } + if (opctx) { + if (opctx->groups) + GF_FREE (opctx->groups); - pthread_setspecific (central_log_flag_key, (void *) 0); + GF_FREE (opctx); + } - return ret; + return; } - -void -glusterfs_central_log_flag_set () +void * +syncopctx_getctx () { - pthread_setspecific (central_log_flag_key, (void *) 1); -} + void *opctx = NULL; + opctx = pthread_getspecific (syncopctx_key); -long -glusterfs_central_log_flag_get () + return opctx; +} + +int +syncopctx_setctx (void *ctx) { - long flag = 0; + int ret = 0; - flag = (long) pthread_getspecific (central_log_flag_key); + ret = pthread_setspecific (syncopctx_key, ctx); - return flag; + return ret; } - -void -glusterfs_central_log_flag_unset () +static int +syncopctx_init (void) { - pthread_setspecific (central_log_flag_key, (void *) 0); -} + int ret; + ret = pthread_key_create (&syncopctx_key, syncopctx_key_destroy); + return ret; +} /* SYNCTASK */ -static pthread_key_t synctask_key; - - int synctask_init () { @@ -283,7 +226,6 @@ synctask_init () return ret; } - void * synctask_get () { @@ -305,55 +247,115 @@ synctask_set (void *synctask) return ret; } +//UUID_BUFFER + +void +glusterfs_uuid_buf_destroy (void *ptr) +{ + FREE (ptr); +} int -glusterfs_globals_init () +glusterfs_uuid_buf_init () { int ret = 0; - gf_op_list_init (); + ret = pthread_key_create (&uuid_buf_key, + glusterfs_uuid_buf_destroy); + return ret; +} - ret = glusterfs_ctx_init (); - if (ret) - goto out; +char * +glusterfs_uuid_buf_get () +{ + char *buf; + int ret = 0; + + 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_lkowner_buf_destroy (void *ptr) +{ + 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_ctx_t *ctx) +{ + int ret = 0; + + 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_central_log_flag_init (); - if (ret) + ret = glusterfs_uuid_buf_init (); + if(ret) { + gf_log ("", GF_LOG_CRITICAL, + "ERROR: glusterfs uuid buffer init failed"); goto out; + } - gf_mem_acct_enable_set (); + 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) + 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; } - - -char eventstring[GF_EVENT_MAXVAL][64] = { - "Invalid event", - "Parent Up", - "Poll In", - "Poll Out", - "Poll Err", - "Child Up", - "Child Down", - "Child Connecting", - "Transport Cleanup", - "Transport Connected", - "Volfile Modified", -}; - -/* Copy the string ptr contents if needed for yourself */ -char * -glusterfs_strevent (glusterfs_event_t ev) -{ - return eventstring[ev]; -} - diff --git a/libglusterfs/src/globals.h b/libglusterfs/src/globals.h index 96a113623..3085db21c 100644 --- a/libglusterfs/src/globals.h +++ b/libglusterfs/src/globals.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 @@ -22,18 +13,24 @@ #define GF_DEFAULT_BASE_PORT 24007 -/* This corresponds to the max 16 number of group IDs that are sent through an - * RPC request. Since NFS is the only one going to set this, we can be safe - * in keeping this size hardcoded. +#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 GF_REQUEST_MAXGROUPS 16 - -#include "glusterfs.h" - -/* CTX */ -#define CTX (glusterfs_ctx_get()) - -glusterfs_ctx_t *glusterfs_ctx_get (); +#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 */ #include "xlator.h" @@ -44,17 +41,22 @@ xlator_t **__glusterfs_this_location (); xlator_t *glusterfs_this_get (); int glusterfs_this_set (xlator_t *); -/* central log */ - -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 bf37f4fa5..2f1e12ee7 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,17 +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 @@ -64,26 +61,111 @@ #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)) + +#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 -/* TODO: Should we use PATH-MAX? On some systems it may save space */ -#define ZR_PATH_MAX 4096 +#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 { @@ -118,8 +200,8 @@ typedef enum { GF_FOP_READDIR, GF_FOP_INODELK, GF_FOP_FINODELK, - GF_FOP_ENTRYLK, - GF_FOP_FENTRYLK, + GF_FOP_ENTRYLK, + GF_FOP_FENTRYLK, GF_FOP_XATTROP, GF_FOP_FXATTROP, GF_FOP_FGETXATTR, @@ -132,6 +214,10 @@ typedef enum { 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; @@ -148,15 +234,6 @@ typedef enum { GF_OP_TYPE_MAX, } gf_op_type_t; -struct gf_flock { - short l_type; - short l_whence; - off_t l_start; - off_t l_len; - pid_t l_pid; - uint64_t l_owner; -}; - /* NOTE: all the miscellaneous flags used by GlusterFS should be listed here */ typedef enum { GF_LK_GETLK = 0, @@ -190,20 +267,23 @@ typedef enum { 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_XATTROP_ADD_ARRAY, + GF_XATTROP_ADD_ARRAY, + GF_XATTROP_ADD_ARRAY64, + GF_XATTROP_OR_ARRAY, + GF_XATTROP_AND_ARRAY } gf_xattrop_flags_t; @@ -212,65 +292,84 @@ typedef enum { #define GF_SET_DIR_ONLY 0x4 #define GF_SET_EPOCH_TIME 0x8 /* used by afr dir lookup selfheal */ -/* Directory into which replicate self-heal will move deleted files and - directories into. The storage/posix janitor thread will periodically - clean up this directory */ - -#define GF_REPLICATE_TRASH_DIR ".landfill" - /* 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 *volfile; - 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; + 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; - struct list_head xlator_options; /* list of xlator_option_t */ - - /* fuse options */ - int fuse_direct_io_mode; + 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 fuse_nodev; - int fuse_nosuid; - char *dump_fuse; - - /* 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; @@ -282,39 +381,68 @@ struct _glusterfs_graph { 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; - void *pool; - void *event_pool; + 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; + 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); -/* If you edit this structure then, make a corresponding change in - * globals.c in the eventstring. - */ typedef enum { GF_EVENT_PARENT_UP = 1, GF_EVENT_POLLIN, @@ -323,17 +451,37 @@ typedef enum { 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; -extern char * -glusterfs_strevent (glusterfs_event_t ev); +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); diff --git a/libglusterfs/src/graph-mem-types.h b/libglusterfs/src/graph-mem-types.h deleted file mode 100644 index d5a939eb9..000000000 --- a/libglusterfs/src/graph-mem-types.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. -*/ - -#ifndef __GRAPH_MEM_TYPES_H__ -#define __GRAPH_MEM_TYPES_H__ - -#include "mem-types.h" - -#define GF_MEM_TYPE_START (gf_common_mt_end + 1) - -enum gfd_mem_types_ { - gf_graph_mt_buf = GF_MEM_TYPE_START, - gfd_mt_end -}; -#endif - diff --git a/libglusterfs/src/graph-print.c b/libglusterfs/src/graph-print.c index 53d8643ee..d860d63b3 100644 --- a/libglusterfs/src/graph-print.c +++ b/libglusterfs/src/graph-print.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 @@ -26,7 +17,6 @@ #include "common-utils.h" #include "xlator.h" -#include "graph-mem-types.h" #include "graph-utils.h" @@ -34,6 +24,7 @@ struct gf_printer { ssize_t (*write) (struct gf_printer *gp, char *buf, size_t len); void *priv; + int len; }; static ssize_t @@ -90,19 +81,31 @@ gpprintf (struct gf_printer *gp, const char *format, ...) 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 -glusterfs_graph_print (struct gf_printer *gp, glusterfs_graph_t *graph) +_print_volume_options (dict_t *d, char *k, data_t *v, + void *tmp) { -#define GPPRINTF(gp, fmt, ...) do { \ - ret = gpprintf (gp, fmt, ## __VA_ARGS__); \ - if (ret == -1) \ - goto out; \ - else \ - len += ret; \ -} while (0) + 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; - data_pair_t *pair = NULL; xlator_list_t *xch = NULL; int ret = 0; ssize_t len = 0; @@ -115,11 +118,9 @@ glusterfs_graph_print (struct gf_printer *gp, glusterfs_graph_t *graph) GPPRINTF (gp, "volume %s\n type %s\n", trav->name, trav->type); - for (pair = trav->options->members_list; pair && pair->next; - pair = pair->next); - for (; pair; pair = pair->prev) - GPPRINTF (gp, " option %s %s\n", pair->key, - pair->value->data); + ret = dict_foreach (trav->options, _print_volume_options, gp); + if (ret) + goto out; if (trav->children) { GPPRINTF (gp, " subvolumes"); @@ -135,7 +136,8 @@ glusterfs_graph_print (struct gf_printer *gp, glusterfs_graph_t *graph) GPPRINTF (gp, "\n"); } - out: +out: + len = gp->len; if (ret == -1) { gf_log ("graph-print", GF_LOG_ERROR, "printing failed"); @@ -152,7 +154,7 @@ 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); } @@ -166,7 +168,7 @@ glusterfs_graph_print_buf (glusterfs_graph_t *graph) char *buf = NULL; struct gf_printer gp = { .write = gp_write_buf, .priv = &iov - }; + }; f = fopen ("/dev/null", "a"); if (!f) { @@ -180,10 +182,8 @@ glusterfs_graph_print_buf (glusterfs_graph_t *graph) if (len == -1) return NULL; - buf = GF_CALLOC (1, len + 1, gf_graph_mt_buf); + buf = GF_CALLOC (1, len + 1, gf_common_mt_graph_buf); if (!buf) { - gf_log ("graph-print", GF_LOG_ERROR, "Out of memory"); - return NULL; } iov.iov_base = buf; diff --git a/libglusterfs/src/graph-utils.h b/libglusterfs/src/graph-utils.h index a6c1ccd5a..207664fdb 100644 --- a/libglusterfs/src/graph-utils.h +++ b/libglusterfs/src/graph-utils.h @@ -1,30 +1,19 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 _GRAPH_H_ #define _GRAPH_H_ -int -glusterfs_graph_print_file (FILE *file, glusterfs_graph_t *graph); +int glusterfs_graph_print_file (FILE *file, glusterfs_graph_t *graph); -char * -glusterfs_graph_print_buf (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); diff --git a/libglusterfs/src/graph.c b/libglusterfs/src/graph.c index a2d03fa0b..e76df1ca5 100644 --- a/libglusterfs/src/graph.c +++ b/libglusterfs/src/graph.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 @@ -29,28 +20,23 @@ #include "defaults.h" - - #if 0 static void _gf_dump_details (int argc, char **argv) { extern FILE *gf_log_logfile; int i = 0; - char timestr[256]; + char timestr[64]; time_t utime = 0; - struct tm *tm = NULL; pid_t mypid = 0; struct utsname uname_buf = {{0, }, }; int uname_ret = -1; - utime = time (NULL); - tm = localtime (&utime); mypid = getpid (); uname_ret = uname (&uname_buf); - /* Which git? What time? */ - strftime (timestr, 256, "%Y-%m-%d %H:%M:%S", tm); + utime = time (NULL); + gf_time_fmt (timestr, sizeof timestr, utime, gf_timefmt_FT); fprintf (gf_log_logfile, "========================================" "========================================\n"); @@ -84,44 +70,6 @@ _gf_dump_details (int argc, char **argv) #endif -static int -_log_if_option_is_invalid (xlator_t *xl, data_pair_t *pair) -{ - volume_opt_list_t *vol_opt = NULL; - volume_option_t *opt = NULL; - int i = 0; - int index = 0; - int found = 0; - - /* Get the first volume_option */ - list_for_each_entry (vol_opt, &xl->volume_options, list) { - /* Warn for extra option */ - if (!vol_opt->given_opt) - break; - - opt = vol_opt->given_opt; - for (index = 0; - ((index < ZR_OPTION_MAX_ARRAY_SIZE) && - (opt[index].key && opt[index].key[0])); index++) - for (i = 0; (i < ZR_VOLUME_MAX_NUM_KEY) && - opt[index].key[i]; i++) { - if (fnmatch (opt[index].key[i], - pair->key, - FNM_NOESCAPE) == 0) { - found = 1; - break; - } - } - } - - if (!found) { - gf_log (xl->name, GF_LOG_WARNING, - "option '%s' is not recognized", - pair->key); - } - return 0; -} - int glusterfs_xlator_link (xlator_t *pxl, xlator_t *cxl) @@ -169,7 +117,8 @@ glusterfs_graph_set_first (glusterfs_graph_t *graph, xlator_t *xl) int glusterfs_graph_insert (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx, - const char *type, const char *name) + const char *type, const char *name, + gf_boolean_t autoload) { xlator_t *ixl = NULL; @@ -195,6 +144,8 @@ glusterfs_graph_insert (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx, 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", @@ -213,23 +164,37 @@ err: return -1; } - int -glusterfs_graph_readonly (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) +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->read_only) + if (!cmd_args->acl) return 0; - ret = glusterfs_graph_insert (graph, ctx, "features/read-only", - "readonly-autoload"); + 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) @@ -243,11 +208,26 @@ glusterfs_graph_mac_compat (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) return 0; ret = glusterfs_graph_insert (graph, ctx, "features/mac-compat", - "mac-compat-autoload"); + "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) @@ -267,7 +247,7 @@ gf_add_cmdline_options (glusterfs_graph_t *graph, cmd_args_t *cmd_args) cmd_option->key, cmd_option->value); if (ret == 0) { - gf_log (trav->name, GF_LOG_WARNING, + gf_log (trav->name, GF_LOG_INFO, "adding option '%s' for " "volume '%s' with value '%s'", cmd_option->key, trav->name, @@ -289,9 +269,9 @@ gf_add_cmdline_options (glusterfs_graph_t *graph, cmd_args_t *cmd_args) int glusterfs_graph_validate_options (glusterfs_graph_t *graph) { - volume_opt_list_t *vol_opt = NULL; xlator_t *trav = NULL; int ret = -1; + char *errstr = NULL; trav = graph->first; @@ -299,14 +279,10 @@ glusterfs_graph_validate_options (glusterfs_graph_t *graph) if (list_empty (&trav->volume_options)) continue; - vol_opt = list_entry (trav->volume_options.next, - volume_opt_list_t, list); - - ret = validate_xlator_volume_options (trav, - vol_opt->given_opt); + ret = xlator_options_validate (trav, trav->options, &errstr); if (ret) { gf_log (trav->name, GF_LOG_ERROR, - "validating translator failed"); + "validation failed: %s", errstr); return ret; } trav = trav->next; @@ -338,35 +314,46 @@ glusterfs_graph_init (glusterfs_graph_t *graph) } -int -glusterfs_graph_unknown_options (glusterfs_graph_t *graph) +static int +_log_if_unknown_option (dict_t *dict, char *key, data_t *value, void *data) { - data_pair_t *pair = NULL; - xlator_t *trav = NULL; + volume_option_t *found = NULL; + xlator_t *xl = NULL; - trav = graph->first; + xl = data; - /* Validate again phase */ - while (trav) { - pair = trav->options->members_list; - while (pair) { - _log_if_option_is_invalid (trav, pair); - pair = pair->next; - } - trav = trav->next; + 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,}; - struct tm now = {0, }; - char now_str[32]; + char now_str[64]; if (gettimeofday (&tv, NULL) == -1) { gf_log ("graph", GF_LOG_ERROR, @@ -380,8 +367,7 @@ fill_uuid (char *uuid, int size) strerror (errno)); } - localtime_r (&tv.tv_sec, &now); - strftime (now_str, 32, "%Y/%m/%d-%H:%M:%S", &now); + 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); @@ -446,18 +432,37 @@ glusterfs_graph_prepare (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) /* XXX: attach to -n volname */ ret = glusterfs_graph_settop (graph, ctx); - if (ret) + if (ret) { + gf_log ("graph", GF_LOG_ERROR, "glusterfs graph settop failed"); return -1; + } - /* XXX: RO VOLUME */ - ret = glusterfs_graph_readonly (graph, ctx); - if (ret) + /* 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) + 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) { @@ -469,6 +474,8 @@ glusterfs_graph_prepare (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) fill_uuid (graph->graph_uuid, 128); + graph->id = ctx->graph_id++; + /* XXX: --xlator-option additions */ gf_add_cmdline_options (graph, &ctx->cmd_args); @@ -484,17 +491,23 @@ glusterfs_graph_activate (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) /* XXX: all xlator options validation */ ret = glusterfs_graph_validate_options (graph); - if (ret) + if (ret) { + gf_log ("graph", GF_LOG_ERROR, "validate options failed"); return ret; + } /* XXX: perform init () */ ret = glusterfs_graph_init (graph); - if (ret) + if (ret) { + gf_log ("graph", GF_LOG_ERROR, "init failed"); return ret; + } ret = glusterfs_graph_unknown_options (graph); - if (ret) + if (ret) { + gf_log ("graph", GF_LOG_ERROR, "unknown options failed"); return ret; + } /* XXX: log full graph (_gf_dump_details) */ @@ -502,32 +515,224 @@ glusterfs_graph_activate (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) ctx->active = graph; /* XXX: attach to master and set active pointer */ - if (ctx->master) + if (ctx->master) { ret = xlator_notify (ctx->master, GF_EVENT_GRAPH_NEW, graph); - if (ret) - return ret; + 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) + 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; + 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); } @@ -535,7 +740,12 @@ glusterfs_graph_reconfigure (glusterfs_graph_t *oldgraph, int glusterfs_graph_destroy (glusterfs_graph_t *graph) { - return 0; -} + 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 index 08f7d5367..e4eba9cbe 100644 --- a/libglusterfs/src/graph.l +++ b/libglusterfs/src/graph.l @@ -1,23 +1,13 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.com> + Copyright (c) 2006-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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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. */ - %x STRING %option yylineno %option noinput @@ -80,10 +70,10 @@ TYPE [t][y][p][e] yyunput (0, NULL); } BEGIN (INITIAL); - yylval = text; + graphyylval = text; return STRING_TOK; } } -[^ \t\r\n\"\\]+ { yylval = gf_strdup (yytext) ; return ID; } +[^ \t\r\n\"\\]+ { graphyylval = gf_strdup (yytext) ; return ID; } [ \t\r\n]+ ; %% diff --git a/libglusterfs/src/graph.y b/libglusterfs/src/graph.y index 52e15940a..a220abeb9 100644 --- a/libglusterfs/src/graph.y +++ b/libglusterfs/src/graph.y @@ -1,23 +1,13 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.com> + Copyright (c) 2006-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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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. */ - %token VOLUME_BEGIN VOLUME_END OPTION NEWLINE SUBVOLUME ID WHITESPACE COMMENT TYPE STRING_TOK %{ @@ -28,6 +18,9 @@ #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" @@ -45,8 +38,8 @@ static void option_error (void); #define YYSTYPE char * #define GF_CMD_BUFFER_LEN (8 * GF_UNIT_KB) -int yyerror (const char *); -int yylex (); +int graphyyerror (const char *); +int graphyylex (); %} @@ -86,11 +79,11 @@ glusterfs_graph_t *construct; static void type_error (void) { - extern int yylineno; + extern int graphyylineno; gf_log ("parser", GF_LOG_ERROR, "Volume %s, before line %d: Please specify volume type", - curr->name, yylineno); + curr->name, graphyylineno); return; } @@ -98,11 +91,11 @@ type_error (void) static void sub_error (void) { - extern int yylineno; + extern int graphyylineno; gf_log ("parser", GF_LOG_ERROR, "Volume %s, before line %d: Please specify subvolumes", - curr->name, yylineno); + curr->name, graphyylineno); return; } @@ -110,12 +103,12 @@ sub_error (void) static void option_error (void) { - extern int yylineno; + extern int graphyylineno; gf_log ("parser", GF_LOG_ERROR, "Volume %s, before line %d: Please specify " "option <key> <value>", - curr->name, yylineno); + curr->name, graphyylineno); return; } @@ -123,7 +116,7 @@ option_error (void) static int new_volume (char *name) { - extern int yylineno; + extern int graphyylineno; xlator_t *trav = NULL; int ret = 0; @@ -137,7 +130,7 @@ new_volume (char *name) if (curr) { gf_log ("parser", GF_LOG_ERROR, "new volume (%s) defintion in line %d unexpected", - name, yylineno); + name, graphyylineno); ret = -1; goto out; } @@ -157,7 +150,7 @@ new_volume (char *name) if (!strcmp (name, trav->name)) { gf_log ("parser", GF_LOG_ERROR, "Line %d: volume '%s' defined again", - yylineno, name); + graphyylineno, name); ret = -1; goto out; } @@ -202,7 +195,7 @@ out: static int volume_type (char *type) { - extern int yylineno; + extern int graphyylineno; int32_t ret = 0; if (!type) { @@ -216,7 +209,7 @@ volume_type (char *type) gf_log ("parser", GF_LOG_ERROR, "Volume '%s', line %d: type '%s' is not valid or " "not found on this machine", - curr->name, yylineno, type); + curr->name, graphyylineno, type); ret = -1; goto out; } @@ -233,7 +226,7 @@ out: static int volume_option (char *key, char *value) { - extern int yylineno; + extern int graphyylineno; int ret = 0; char *set_value = NULL; @@ -250,7 +243,7 @@ volume_option (char *key, char *value) gf_log ("parser", GF_LOG_ERROR, "Volume '%s', line %d: duplicate entry " "('option %s') present", - curr->name, yylineno, key); + curr->name, graphyylineno, key); ret = -1; goto out; } @@ -269,7 +262,7 @@ out: static int volume_sub (char *sub) { - extern int yylineno; + extern int graphyylineno; xlator_t *trav = NULL; int ret = 0; @@ -291,7 +284,7 @@ volume_sub (char *sub) gf_log ("parser", GF_LOG_ERROR, "Volume '%s', line %d: subvolume '%s' is not defined " "prior to usage", - curr->name, yylineno, sub); + curr->name, graphyylineno, sub); ret = -1; goto out; } @@ -299,7 +292,7 @@ volume_sub (char *sub) if (trav == curr) { gf_log ("parser", GF_LOG_ERROR, "Volume '%s', line %d: has '%s' itself as subvolume", - curr->name, yylineno, sub); + curr->name, graphyylineno, sub); ret = -1; goto out; } @@ -336,46 +329,46 @@ volume_end (void) int -yywrap () +graphyywrap () { return 1; } int -yyerror (const char *str) +graphyyerror (const char *str) { - extern char *yytext; - extern int yylineno; + extern char *graphyytext; + extern int graphyylineno; - if (curr && curr->name && yytext) { - if (!strcmp (yytext, "volume")) { + 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 (yytext, "type")) { + } else if (!strcmp (graphyytext, "type")) { gf_log ("parser", GF_LOG_ERROR, "line %d: duplicate 'type' defined for " "volume '%s'", - yylineno, curr->name); - } else if (!strcmp (yytext, "subvolumes")) { + graphyylineno, curr->name); + } else if (!strcmp (graphyytext, "subvolumes")) { gf_log ("parser", GF_LOG_ERROR, "line %d: duplicate 'subvolumes' defined for " "volume '%s'", - yylineno, curr->name); + 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'()", - yylineno, curr->name, - yytext); + graphyylineno, curr->name, + graphyytext); } else { gf_log ("parser", GF_LOG_ERROR, "syntax error: line %d (just after volume " "'%s'): \"%s\"\n(%s)", - yylineno, curr->name, - yytext, + graphyylineno, curr->name, + graphyytext, "allowed tokens are 'volume', 'type', " "'subvolumes', 'option', 'end-volume'"); } @@ -384,7 +377,7 @@ yyerror (const char *str) "syntax error in line %d: \"%s\" \n" "(allowed tokens are 'volume', 'type', " "'subvolumes', 'option', 'end-volume')\n", - yylineno, yytext); + graphyylineno, graphyytext); } return -1; @@ -443,8 +436,6 @@ preprocess (FILE *srcfp, FILE *dstfp) char in_backtick = 0; int line = 1; int column = 0; - int backtick_line = 0; - int backtick_column = 0; int character = 0; @@ -482,9 +473,6 @@ preprocess (FILE *srcfp, FILE *dstfp) } else { i = 0; cmd[i] = '\0'; - - backtick_column = column; - backtick_line = line; } in_backtick = !in_backtick; @@ -494,6 +482,7 @@ preprocess (FILE *srcfp, FILE *dstfp) cmd_buf_size *= 2; cmd = GF_REALLOC (cmd, cmd_buf_size); if (cmd == NULL) { + GF_FREE (result); return -1; } @@ -535,6 +524,7 @@ preprocess (FILE *srcfp, FILE *dstfp) out: fseek (srcfp, 0L, SEEK_SET); fseek (dstfp, 0L, SEEK_SET); + GF_FREE (cmd); GF_FREE (result); @@ -542,7 +532,7 @@ out: } -extern FILE *yyin; +extern FILE *graphyyin; glusterfs_graph_t * glusterfs_graph_new () @@ -566,52 +556,65 @@ glusterfs_graph_t * glusterfs_graph_construct (FILE *fp) { int ret = 0; + int tmp_fd = -1; glusterfs_graph_t *graph = NULL; - FILE *tmp_file = 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) - return NULL; + goto err; - tmp_file = tmpfile (); + strcpy (template, "/tmp/tmp.XXXXXX"); + tmp_fd = mkstemp (template); + if (-1 == tmp_fd) + goto err; - if (tmp_file == NULL) { - gf_log ("parser", GF_LOG_ERROR, - "cannot create temparory file"); + ret = unlink (template); + if (ret < 0) { + gf_log ("parser", GF_LOG_WARNING, "Unable to delete file: %s", + template); + } - glusterfs_graph_destroy (graph); - return NULL; - } + 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"); + ret = preprocess (fp, tmp_file); + if (ret < 0) { + gf_log ("parser", GF_LOG_ERROR, "parsing of backticks failed"); + goto err; + } - glusterfs_graph_destroy (graph); - fclose (tmp_file); - return NULL; + pthread_mutex_lock (&graph_mutex); + { + graphyyin = tmp_file; + construct = graph; + ret = yyparse (); + construct = NULL; } - - yyin = tmp_file; - - construct = graph; - - ret = yyparse (); - - construct = NULL; - - fclose (tmp_file); + pthread_mutex_unlock (&graph_mutex); if (ret == 1) { gf_log ("parser", GF_LOG_DEBUG, - "parsing of volfile failed, please review it " - "once more"); - - glusterfs_graph_destroy (graph); - return NULL; + "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 98f741885..f79165b22 100644 --- a/libglusterfs/src/hashfn.c +++ b/libglusterfs/src/hashfn.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 8261e4c78..06ae37e79 100644 --- a/libglusterfs/src/hashfn.h +++ b/libglusterfs/src/hashfn.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 index a17e0e7a4..60ae59047 100644 --- a/libglusterfs/src/iatt.h +++ b/libglusterfs/src/iatt.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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. */ @@ -103,6 +94,8 @@ struct iatt { #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) { @@ -120,7 +113,7 @@ ia_minor (uint64_t ia_dev) static inline uint64_t ia_makedev (uint32_t ia_maj, uint32_t ia_min) { - return ((((uint64_t) ia_maj) << 32) & ia_min); + return ((((uint64_t) ia_maj) << 32) | ia_min); } @@ -272,6 +265,24 @@ iatt_from_stat (struct iatt *iatt, struct stat *stat) 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); diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c index 04e4560ed..15e0ccf78 100644 --- a/libglusterfs/src/inode.c +++ b/libglusterfs/src/inode.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 @@ -37,13 +28,13 @@ move latest accessed dentry to list_head of inode */ -#define INODE_DUMP_LIST(head, key_buf, key_prefix, list_type) \ +#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_build_key(key_buf, key_prefix, \ + "%s.%d",list_type, i++); \ gf_proc_dump_add_section(key_buf); \ inode_dump(inode, key); \ } \ @@ -93,8 +84,10 @@ __dentry_hash (dentry_t *dentry) inode_table_t *table = NULL; int hash = 0; - if (!dentry) + if (!dentry) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found"); return; + } table = dentry->inode->table; hash = hash_dentry (dentry->parent, dentry->name, @@ -108,8 +101,10 @@ __dentry_hash (dentry_t *dentry) static int __is_dentry_hashed (dentry_t *dentry) { - if (!dentry) + if (!dentry) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found"); return 0; + } return !list_empty (&dentry->hash); } @@ -118,8 +113,10 @@ __is_dentry_hashed (dentry_t *dentry) static void __dentry_unhash (dentry_t *dentry) { - if (!dentry) + if (!dentry) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found"); return; + } list_del_init (&dentry->hash); } @@ -128,36 +125,109 @@ __dentry_unhash (dentry_t *dentry) static void __dentry_unset (dentry_t *dentry) { - struct mem_pool *tmp_pool = NULL; - - if (!dentry) + if (!dentry) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "dentry not found"); return; + } - tmp_pool = dentry->inode->table->dentry_pool; __dentry_unhash (dentry); list_del_init (&dentry->inode_list); - if (dentry->name) - GF_FREE (dentry->name); + GF_FREE (dentry->name); if (dentry->parent) { __inode_unref (dentry->parent); dentry->parent = NULL; } - mem_put (tmp_pool, dentry); - tmp_pool = NULL; + mem_put (dentry); +} + + +static int +__foreach_ancestor_dentry (dentry_t *dentry, + int (per_dentry_fn) (dentry_t *dentry, + void *data), + void *data) +{ + 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; + } + + 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 int +__check_cycle (dentry_t *a_dentry, void *data) +{ + inode_t *link_inode = NULL; + + link_inode = data; + + if (a_dentry->parent == link_inode) + return 1; + + return 0; +} + + +static int +__is_dentry_cyclic (dentry_t *dentry) +{ + int ret = 0; + inode_t *inode = NULL; + char *name = "<nul>"; + + ret = __foreach_ancestor_dentry (dentry, __check_cycle, + dentry->inode); + if (ret) { + inode = dentry->inode; + + 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 ret; +} + static void __inode_unhash (inode_t *inode) { - if (!inode) + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); return; + } list_del_init (&inode->hash); } @@ -166,8 +236,10 @@ __inode_unhash (inode_t *inode) static int __is_inode_hashed (inode_t *inode) { - if (!inode) + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); return 0; + } return !list_empty (&inode->hash); } @@ -179,8 +251,10 @@ __inode_hash (inode_t *inode) inode_table_t *table = NULL; int hash = 0; - if (!inode) + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); return; + } table = inode->table; hash = hash_gfid (inode->gfid, 65536); @@ -191,16 +265,25 @@ __inode_hash (inode_t *inode) static dentry_t * -__dentry_search_for_inode (inode_t *inode, ino_t par, const char *name) +__dentry_search_for_inode (inode_t *inode, uuid_t pargfid, const char *name) { dentry_t *dentry = NULL; dentry_t *tmp = NULL; - if (!inode || !name) + if (!inode || !name) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode || name not found"); + return NULL; + } + + /* 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 (tmp->parent->ino == par && !strcmp (tmp->name, name)) { + if ((uuid_compare (tmp->parent->gfid, pargfid) == 0) && + !strcmp (tmp->name, name)) { dentry = tmp; break; } @@ -216,17 +299,18 @@ __inode_destroy (inode_t *inode) int index = 0; xlator_t *xl = NULL; xlator_t *old_THIS = NULL; - struct mem_pool *tmp_pool = NULL; - if (!inode) + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); return; + } - if (!inode->_ctx) + if (!inode->_ctx) { + gf_log (THIS->name, GF_LOG_WARNING, "_ctx not found"); goto noctx; + } - tmp_pool = inode->table->inode_pool; - - for (index = 0; index < inode->table->xl->graph->xl_count; index++) { + 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; @@ -241,9 +325,7 @@ __inode_destroy (inode_t *inode) noctx: LOCK_DESTROY (&inode->lock); // memset (inode, 0xb, sizeof (*inode)); - mem_put (tmp_pool, inode); - tmp_pool = NULL; - + mem_put (inode); } @@ -264,8 +346,10 @@ __inode_passivate (inode_t *inode) dentry_t *dentry = NULL; dentry_t *t = NULL; - if (!inode) + 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++; @@ -283,8 +367,10 @@ __inode_retire (inode_t *inode) dentry_t *dentry = NULL; dentry_t *t = NULL; - if (!inode) + 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++; @@ -303,7 +389,7 @@ __inode_unref (inode_t *inode) if (!inode) return NULL; - if (inode->ino == 1) + if (__is_root_gfid(inode->gfid)) return inode; GF_ASSERT (inode->ref); @@ -386,13 +472,14 @@ __dentry_create (inode_t *inode, inode_t *parent, const char *name) { dentry_t *newd = NULL; - if (!inode || !parent || !name) + 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) { - gf_log ("inode", GF_LOG_ERROR, "out of memory"); goto out; } @@ -401,8 +488,7 @@ __dentry_create (inode_t *inode, inode_t *parent, const char *name) newd->name = gf_strdup (name); if (newd->name == NULL) { - gf_log ("inode", GF_LOG_ERROR, "out of memory"); - mem_put (parent->table->dentry_pool, newd); + mem_put (newd); newd = NULL; goto out; } @@ -423,12 +509,13 @@ __inode_create (inode_table_t *table) { inode_t *newi = NULL; - if (!table) + if (!table) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "table not found"); return NULL; + } newi = mem_get0 (table->inode_pool); if (!newi) { - gf_log ("inode", GF_LOG_ERROR, "out of memory"); goto out; } @@ -441,14 +528,12 @@ __inode_create (inode_table_t *table) INIT_LIST_HEAD (&newi->hash); INIT_LIST_HEAD (&newi->dentry_list); - newi->_ctx = GF_CALLOC (1, (sizeof (struct _inode_ctx) * - table->xl->graph->xl_count), - gf_common_mt_inode_ctx); - + newi->_ctx = GF_CALLOC (1, + (sizeof (struct _inode_ctx) * table->ctxcount), + gf_common_mt_inode_ctx); if (newi->_ctx == NULL) { - gf_log ("inode", GF_LOG_ERROR, "out of memory"); LOCK_DESTROY (&newi->lock); - mem_put (table->inode_pool, newi); + mem_put (newi); newi = NULL; goto out; } @@ -467,8 +552,10 @@ inode_new (inode_table_t *table) { inode_t *inode = NULL; - if (!table) + if (!table) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); return NULL; + } pthread_mutex_lock (&table->lock); { @@ -541,8 +628,11 @@ inode_grep (inode_table_t *table, inode_t *parent, const char *name) inode_t *inode = NULL; dentry_t *dentry = NULL; - if (!table || !parent || !name) + if (!table || !parent || !name) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, + "table || parent || name not found"); return NULL; + } pthread_mutex_lock (&table->lock); { @@ -561,24 +651,94 @@ inode_grep (inode_table_t *table, inode_t *parent, const char *name) inode_t * -inode_get (inode_table_t *table, ino_t ino, uint64_t gen) +inode_resolve (inode_table_t *table, char *path) { - return NULL; + char *tmp = NULL, *bname = NULL, *str = NULL, *saveptr = NULL; + inode_t *inode = NULL, *parent = NULL; + + if ((path == NULL) || (table == NULL)) { + goto out; + } + + parent = inode_ref (table->root); + str = tmp = gf_strdup (path); + + while (1) { + bname = strtok_r (str, "/", &saveptr); + if (bname == NULL) { + break; + } + + 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 int +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 = 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; + } + + 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); + + return ret; +} + + +/* return 1 if gfid is of root, 0 if not */ +gf_boolean_t __is_root_gfid (uuid_t gfid) { uuid_t root; - int ret; memset (root, 0, 16); root[15] = 1; - ret = uuid_compare (gfid, root); + if (uuid_compare (gfid, root) == 0) + return _gf_true; - return ret; + return _gf_false; } @@ -589,10 +749,12 @@ __inode_find (inode_table_t *table, uuid_t gfid) inode_t *tmp = NULL; int hash = 0; - if (!table) + if (!table) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "table not found"); goto out; + } - if (__is_root_gfid (gfid) == 0) + if (__is_root_gfid (gfid)) return table->root; hash = hash_gfid (gfid, 65536); @@ -614,8 +776,10 @@ inode_find (inode_table_t *table, uuid_t gfid) { inode_t *inode = NULL; - if (!table) + if (!table) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "table not found"); return NULL; + } pthread_mutex_lock (&table->lock); { @@ -646,6 +810,15 @@ __inode_link (inode_t *inode, inode_t *parent, const char *name, 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 (!__is_inode_hashed (inode)) { @@ -655,25 +828,40 @@ __inode_link (inode_t *inode, inode_t *parent, const char *name, if (uuid_is_null (iatt->ia_gfid)) return NULL; - uuid_copy (inode->gfid, iatt->ia_gfid); - inode->ino = iatt->ia_ino; - inode->ia_type = iatt->ia_type; - - old_inode = __inode_find (table, inode->gfid); + old_inode = __inode_find (table, iatt->ia_gfid); if (old_inode) { link_inode = old_inode; } else { + uuid_copy (inode->gfid, iatt->ia_gfid); + inode->ia_type = iatt->ia_type; __inode_hash (inode); } } + if (name) { + if (!strcmp(name, ".") || !strcmp(name, "..")) + return link_inode; + } + /* use only link_inode beyond this point */ if (parent) { 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); if (old_dentry) @@ -692,8 +880,10 @@ inode_link (inode_t *inode, inode_t *parent, const char *name, inode_table_t *table = NULL; inode_t *linked_inode = NULL; - if (!inode) + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); return NULL; + } table = inode->table; @@ -717,8 +907,10 @@ inode_lookup (inode_t *inode) { inode_table_t *table = NULL; - if (!inode) + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); return -1; + } table = inode->table; @@ -737,8 +929,10 @@ inode_forget (inode_t *inode, uint64_t nlookup) { inode_table_t *table = NULL; - if (!inode) + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); return -1; + } table = inode->table; @@ -753,6 +947,54 @@ 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) @@ -762,7 +1004,7 @@ __inode_unlink (inode_t *inode, inode_t *parent, const char *name) if (!inode || !parent || !name) return; - dentry = __dentry_search_for_inode (inode, parent->ino, name); + dentry = __dentry_search_for_inode (inode, parent->gfid, name); /* dentry NULL for corrupted backend */ if (dentry) @@ -775,8 +1017,10 @@ inode_unlink (inode_t *inode, inode_t *parent, const char *name) { inode_table_t *table = NULL; - if (!inode) + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); return; + } table = inode->table; @@ -795,8 +1039,10 @@ inode_rename (inode_table_t *table, inode_t *srcdir, const char *srcname, inode_t *dstdir, const char *dstname, inode_t *inode, struct iatt *iatt) { - if (!inode) + if (!inode) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); return -1; + } table = inode->table; @@ -841,21 +1087,23 @@ __dentry_search_arbit (inode_t *inode) 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) + 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); } @@ -873,99 +1121,124 @@ inode_parent (inode_t *inode, ino_t par, const char *name) int -inode_path (inode_t *inode, const char *name, char **bufp) +__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; - - if (!inode) + 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 (table->name, GF_LOG_CRITICAL, - "possible infinite loop detected, " - "forcing break. name=(%s)", name); - ret = -ENOENT; - goto unlock; - } - } - - if ((inode->ino != 1) && - (i == 0)) { - gf_log (table->name, GF_LOG_DEBUG, - "no dentry for non-root inode %"PRId64, - inode->ino); + 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 unlock; + goto out; } + } - if (name) { - i++; - i += strlen (name); - } + if (!__is_root_gfid (itrav->gfid)) { + /* "<gfid:00000000-0000-0000-0000-000000000000>"/path */ + i += GFID_STR_PFX_LEN; + } - ret = i; - size = i + 1; - buf = GF_CALLOC (size, sizeof (char), gf_common_mt_char); - if (buf) { + if (name) { + i++; + i += strlen (name); + } - buf[size - 1] = 0; + ret = i; + size = i + 1; + buf = GF_CALLOC (size, sizeof (char), gf_common_mt_char); + if (buf) { - if (name) { - len = strlen (name); - strncpy (buf + (i - len), name, len); - buf[i-len-1] = '/'; - i -= (len + 1); - } + buf[size - 1] = 0; - for (trav = __dentry_search_arbit (inode); trav; - trav = __dentry_search_arbit (trav->parent)) { - len = strlen (trav->name); - strncpy (buf + (i - len), trav->name, len); - buf[i-len-1] = '/'; - i -= (len + 1); - } - *bufp = buf; - } else { - gf_log (table->name, GF_LOG_ERROR, - "out of memory"); - ret = -ENOMEM; + if (name) { + len = strlen (name); + strncpy (buf + (i - len), name, len); + buf[i-len-1] = '/'; + i -= (len + 1); } + + 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); + } + + 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] = '>'; + } + + *bufp = buf; + } else { + ret = -ENOMEM; } -unlock: - pthread_mutex_unlock (&table->lock); - if (inode->ino == 1 && !name) { +out: + if (__is_root_gfid (inode->gfid) && !name) { ret = 1; - if (buf) { - GF_FREE (buf); - } + 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; } } + 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) { @@ -1025,8 +1298,8 @@ __inode_table_init_root (inode_table_t *table) iatt.ia_ino = 1; iatt.ia_type = IA_IFDIR; - table->root = root; __inode_link (root, NULL, NULL, &iatt); + table->root = root; } @@ -1034,7 +1307,7 @@ 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 *)GF_CALLOC(1, sizeof (*new), gf_common_mt_inode_table_t); @@ -1042,48 +1315,44 @@ inode_table_new (size_t lru_limit, xlator_t *xl) 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_pool = mem_pool_new (inode_t, 204654); + /* In case FUSE is initing the inode table. */ + if (lru_limit == 0) + lru_limit = DEFAULT_INODE_MEMPOOL_ENTRIES; - if (!new->inode_pool) { - GF_FREE (new); - return NULL; - } + new->inode_pool = mem_pool_new (inode_t, lru_limit); + + if (!new->inode_pool) + goto out; - new->dentry_pool = mem_pool_new (dentry_t, 204654); + new->dentry_pool = mem_pool_new (dentry_t, lru_limit); - if (!new->dentry_pool) { - GF_FREE (new); - return NULL; - } + 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) { - GF_FREE (new); - return NULL; - } + 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) { - GF_FREE (new->inode_hash); - GF_FREE (new); - return NULL; - } + if (!new->name_hash) + goto out; - new->fd_mem_pool = mem_pool_new (fd_t, 16384); + /* 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) { - GF_FREE (new->inode_hash); - GF_FREE (new); - } + if (!new->fd_mem_pool) + goto out; for (i = 0; i < 65536; i++) { INIT_LIST_HEAD (&new->inode_hash[i]); @@ -1108,6 +1377,21 @@ inode_table_new (size_t lru_limit, xlator_t *xl) 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; } @@ -1129,7 +1413,6 @@ inode_from_path (inode_table_t *itable, const char *path) /* top-down approach */ pathname = gf_strdup (path); if (pathname == NULL) { - gf_log ("inode", GF_LOG_ERROR, "out of memory"); goto out; } @@ -1165,8 +1448,7 @@ inode_from_path (inode_table_t *itable, const char *path) if (parent) inode_unref (parent); - if (pathname) - GF_FREE (pathname); + GF_FREE (pathname); out: return inode; @@ -1174,45 +1456,59 @@ out: int -__inode_ctx_put2 (inode_t *inode, xlator_t *xlator, uint64_t value1, - uint64_t value2) +__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->graph->xl_count; index++) { + for (index = 0; index < inode->table->ctxcount; index++) { if (!inode->_ctx[index].xl_key) { - if (put_idx == -1) - put_idx = index; + if (set_idx == -1) + set_idx = index; /* dont break, to check if key already exists further on */ } if (inode->_ctx[index].xl_key == xlator) { - put_idx = index; + set_idx = index; break; } } - if (put_idx == -1) { + if (set_idx == -1) { ret = -1; goto out;; } - inode->_ctx[put_idx].xl_key = xlator; - inode->_ctx[put_idx].value1 = value1; - inode->_ctx[put_idx].value2 = value2; + 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_set0 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p) +{ + return __inode_ctx_set2 (inode, xlator, value1_p, NULL); +} int -inode_ctx_put2 (inode_t *inode, xlator_t *xlator, uint64_t value1, - uint64_t value2) +__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; @@ -1221,7 +1517,40 @@ inode_ctx_put2 (inode_t *inode, xlator_t *xlator, uint64_t value1, LOCK (&inode->lock); { - ret = __inode_ctx_put2 (inode, xlator, value1, value2); + ret = __inode_ctx_set2 (inode, xlator, value1_p, value2_p); + } + UNLOCK (&inode->lock); + + return ret; +} + +int +inode_ctx_set1 (inode_t *inode, xlator_t *xlator, uint64_t *value2_p) +{ + int ret = 0; + + 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); @@ -1234,28 +1563,58 @@ __inode_ctx_get2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, uint64_t *value2) { int index = 0; - int ret = 0; + int ret = -1; if (!inode || !xlator) - return -1; + goto out; - for (index = 0; index < xlator->graph->xl_count; index++) { + for (index = 0; index < inode->table->ctxcount; index++) { if (inode->_ctx[index].xl_key == xlator) break; } - if (index == xlator->graph->xl_count) { - ret = -1; + 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; +} - if (value1) - *value1 = inode->_ctx[index].value1; - if (value2) - *value2 = inode->_ctx[index].value2; -out: +int +__inode_ctx_get0 (inode_t *inode, xlator_t *xlator, uint64_t *value1) +{ + uint64_t tmp_value = 0; + int ret = 0; + + 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; } @@ -1278,6 +1637,40 @@ inode_ctx_get2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, 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); + + return ret; +} + +int +inode_ctx_get0 (inode_t *inode, xlator_t *xlator, uint64_t *value1) +{ + int ret = 0; + + 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, @@ -1291,19 +1684,20 @@ inode_ctx_del2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, LOCK (&inode->lock); { - for (index = 0; index < xlator->graph->xl_count; index++) { + for (index = 0; index < inode->table->ctxcount; + index++) { if (inode->_ctx[index].xl_key == xlator) break; } - if (index == xlator->graph->xl_count) { + if (index == inode->table->ctxcount) { ret = -1; goto unlock; } - if (value1) + if (inode->_ctx[index].value1 && value1) *value1 = inode->_ctx[index].value1; - if (value2) + if (inode->_ctx[index].value2 && value2) *value2 = inode->_ctx[index].value2; inode->_ctx[index].key = 0; @@ -1316,56 +1710,106 @@ unlock: return ret; } - -int -__inode_ctx_put (inode_t *inode, xlator_t *key, uint64_t value) +/* 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) { - return __inode_ctx_put2 (inode, key, value, 0); -} + int index = 0; + int ret = 0; + if (!inode || !xlator) + return -1; -int -inode_ctx_put (inode_t *inode, xlator_t *key, uint64_t value) -{ - return inode_ctx_put2 (inode, key, value, 0); -} + 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_get (inode_t *inode, xlator_t *key, uint64_t *value) +inode_ctx_reset2 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p, + uint64_t *value2_p) { - return __inode_ctx_get2 (inode, key, value, 0); -} + 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_get (inode_t *inode, xlator_t *key, uint64_t *value) +inode_ctx_reset1 (inode_t *inode, xlator_t *xlator, uint64_t *value2_p) { - return inode_ctx_get2 (inode, key, value, 0); -} + 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_del (inode_t *inode, xlator_t *key, uint64_t *value) +inode_ctx_reset0 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p) { - return inode_ctx_del2 (inode, key, value, 0); + 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; - char uuidbuf[256]; fd_t *fd = NULL; struct _inode_ctx *inode_ctx = NULL; - struct fd_wrapper { - fd_t *fd; - struct list_head next; - } *fd_wrapper, *tmp; struct list_head fd_list; if (!inode) @@ -1374,62 +1818,43 @@ inode_dump (inode_t *inode, char *prefix) 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; } { - uuid_unparse (inode->gfid, uuidbuf); - gf_proc_dump_build_key(key, prefix, "gfid"); - gf_proc_dump_write(key, "%s", uuidbuf); - gf_proc_dump_build_key(key, prefix, "nlookup"); - gf_proc_dump_write(key, "%ld", inode->nlookup); - 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, "ia_type"); - gf_proc_dump_write(key, "%d", inode->ia_type); + 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->xl->graph->xl_count, + inode_ctx = GF_CALLOC (inode->table->ctxcount, sizeof (*inode_ctx), gf_common_mt_inode_ctx); if (inode_ctx == NULL) { - gf_log ("", GF_LOG_ERROR, "out of memory"); goto unlock; } - for (i = 0; i < inode->table->xl->graph->xl_count; i++) { + for (i = 0; i < inode->table->ctxcount; + i++) { inode_ctx[i] = inode->_ctx[i]; } } - if (list_empty (&inode->fd_list)) { - goto unlock; - } - - list_for_each_entry (fd, &inode->fd_list, inode_list) { - fd_wrapper = GF_CALLOC (1, sizeof (*fd_wrapper), - gf_common_mt_char); - if (fd_wrapper == NULL) { - gf_log ("", GF_LOG_ERROR, "out of memory"); - goto unlock; - } + if (dump_options.xl_options.dump_fdctx != _gf_true) + goto unlock; - INIT_LIST_HEAD (&fd_wrapper->next); - list_add_tail (&fd_wrapper->next, &fd_list); - fd_wrapper->fd = _fd_ref (fd); + 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->xl->graph->xl_count; i++) { + 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) @@ -1438,21 +1863,7 @@ unlock: } } - if (!list_empty (&fd_list) - && (dump_options.xl_options.dump_fdctx == _gf_true)) { - list_for_each_entry_safe (fd_wrapper, tmp, &fd_list, - next) { - list_del (&fd_wrapper->next); - fd_ctx_dump (fd_wrapper->fd, prefix); - - fd_unref (fd_wrapper->fd); - GF_FREE (fd_wrapper); - } - } - - if (inode_ctx != NULL) { - GF_FREE (inode_ctx); - } + GF_FREE (inode_ctx); return; } @@ -1471,8 +1882,6 @@ inode_table_dump (inode_table_t *itable, char *prefix) ret = pthread_mutex_trylock(&itable->lock); if (ret != 0) { - gf_log("", GF_LOG_WARNING, "Unable to dump inode table" - " errno: %d", errno); return; } @@ -1496,3 +1905,99 @@ 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 de423d888..a88976265 100644 --- a/libglusterfs/src/inode.h +++ b/libglusterfs/src/inode.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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; @@ -63,6 +56,7 @@ struct _inode_table { 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 */ }; @@ -79,10 +73,12 @@ struct _inode_ctx { 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; @@ -94,8 +90,8 @@ struct _inode { 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 */ - ino_t ino; /* inode number in the storage (persistent) */ 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 */ @@ -106,6 +102,10 @@ struct _inode { }; +#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); @@ -120,7 +120,7 @@ void inode_unlink (inode_t *inode, inode_t *parent, const char *name); inode_t * -inode_parent (inode_t *inode, ino_t par, const char *name); +inode_parent (inode_t *inode, uuid_t pargfid, const char *name); inode_t * inode_ref (inode_t *inode); @@ -135,6 +135,9 @@ int inode_forget (inode_t *inode, uint64_t nlookup); int +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); @@ -142,8 +145,9 @@ inode_rename (inode_table_t *table, inode_t *olddir, const char *oldname, inode_t * inode_grep (inode_table_t *table, inode_t *parent, const char *name); -inode_t * -inode_get (inode_table_t *table, ino_t ino, uint64_t gen); +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_find (inode_table_t *table, uuid_t gfid); @@ -151,34 +155,97 @@ inode_find (inode_table_t *table, uuid_t gfid); int inode_path (inode_t *inode, const char *name, char **bufp); +int +__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_put (inode_t *inode, xlator_t *xlator, uint64_t value); +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_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_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_get (inode_t *inode, xlator_t *xlator, uint64_t *value); +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_del (inode_t *inode, xlator_t *xlator, uint64_t *value); +inode_ctx_set0 (inode_t *inode, xlator_t *xlator, uint64_t *value1); int -inode_ctx_put2 (inode_t *inode, xlator_t *xlator, uint64_t value1, - uint64_t value2); +__inode_ctx_set0 (inode_t *inode, xlator_t *xlator, uint64_t *value1); int -inode_ctx_get2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, - uint64_t *value2); +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_del2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, - uint64_t *value2); +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) + +#define inode_ctx_del(i,x,v) inode_ctx_del2(i,x,v,0) + +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 a8bd192cf..a89e96267 100644 --- a/libglusterfs/src/iobuf.c +++ b/libglusterfs/src/iobuf.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,22 +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_cnt = iobuf_arena->page_count; iobuf_arena->iobufs = GF_CALLOC (sizeof (*iobuf), iobuf_cnt, - gf_common_mt_iobuf); + gf_common_mt_iobuf); if (!iobuf_arena->iobufs) return; @@ -58,27 +97,30 @@ __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++) { @@ -89,37 +131,40 @@ __iobuf_arena_destroy_iobufs (struct iobuf_arena *iobuf_arena) } 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); 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; + + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out); iobuf_arena = GF_CALLOC (sizeof (*iobuf_arena), 1, - gf_common_mt_iobuf_arena); + gf_common_mt_iobuf_arena); if (!iobuf_arena) goto err; @@ -128,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++; @@ -144,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); + + 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.list, list) { + 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; } @@ -202,92 +289,167 @@ void iobuf_pool_destroy (struct iobuf_pool *iobuf_pool) { struct iobuf_arena *iobuf_arena = NULL; - struct iobuf_arena *tmp = NULL; - - if (!iobuf_pool) - return; + struct iobuf_arena *tmp = NULL; + int i = 0; - list_for_each_entry_safe (iobuf_arena, tmp, &iobuf_pool->arenas.list, - list) { + GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out); - 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; - - if (arena_size < page_size) - return NULL; + int i = 0; + size_t page_size = 0; + size_t arena_size = 0; + int32_t num_pages = 0; 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; + + 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); + 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; @@ -295,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; } @@ -320,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; @@ -338,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); @@ -393,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; } @@ -404,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); { @@ -421,7 +720,8 @@ iobuf_put (struct iobuf *iobuf) } pthread_mutex_unlock (&iobuf_pool->mutex); - iobuf_pool_prune (iobuf_pool); +out: + return; } @@ -430,8 +730,7 @@ iobuf_unref (struct iobuf *iobuf) { int ref = 0; - if (!iobuf) - return; + GF_VALIDATE_OR_GOTO ("iobuf", iobuf, out); LOCK (&iobuf->lock); { @@ -442,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); { @@ -457,6 +758,7 @@ iobuf_ref (struct iobuf *iobuf) } UNLOCK (&iobuf->lock); +out: return iobuf; } @@ -482,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); { @@ -491,6 +792,7 @@ iobref_ref (struct iobref *iobref) } UNLOCK (&iobref->lock); +out: return iobref; } @@ -501,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; @@ -513,6 +814,9 @@ iobref_destroy (struct iobref *iobref) } GF_FREE (iobref); + +out: + return; } @@ -521,8 +825,7 @@ iobref_unref (struct iobref *iobref) { int ref = 0; - if (!iobref) - return; + GF_VALIDATE_OR_GOTO ("iobuf", iobref, out); LOCK (&iobref->lock); { @@ -532,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; } @@ -541,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; @@ -549,6 +881,7 @@ __iobref_add (struct iobref *iobref, struct iobuf *iobuf) } } +out: return ret; } @@ -556,13 +889,10 @@ __iobref_add (struct iobref *iobref, struct iobuf *iobuf) int iobref_add (struct iobref *iobref, struct iobuf *iobuf) { - int ret = 0; + int ret = -EINVAL; - if (!iobref) - return -EINVAL; - - if (!iobuf) - return -EINVAL; + GF_VALIDATE_OR_GOTO ("iobuf", iobref, out); + GF_VALIDATE_OR_GOTO ("iobuf", iobuf, out); LOCK (&iobref->lock); { @@ -570,6 +900,7 @@ iobref_add (struct iobref *iobref, struct iobuf *iobuf) } UNLOCK (&iobref->lock); +out: return ret; } @@ -578,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) @@ -597,6 +931,7 @@ iobref_merge (struct iobref *to, struct iobref *from) } UNLOCK (&from->lock); +out: return ret; } @@ -606,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; } @@ -627,113 +965,136 @@ 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); } +out: + return; } void iobuf_stats_dump (struct iobuf_pool *iobuf_pool) { - char msg[1024]; 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; } @@ -741,7 +1102,12 @@ iobuf_stats_dump (struct iobuf_pool *iobuf_pool) 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 fc8ff623a..5595309e1 100644 --- a/libglusterfs/src/iobuf.h +++ b/libglusterfs/src/iobuf.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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_ @@ -26,6 +17,9 @@ #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 * now deprecated MAP_ANON flag. @@ -37,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; @@ -49,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 { @@ -64,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 */ }; @@ -75,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; @@ -86,25 +99,34 @@ 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); @@ -113,14 +135,14 @@ 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_pagesize(iobpool) ((iobpool)->page_size) -#define iobuf_pagesize(iob) (iobpool_pagesize((iob)->iobuf_arena->iobuf_pool)) +#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 (); @@ -128,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 index bc2409138..b22f72950 100644 --- a/libglusterfs/src/latency.c +++ b/libglusterfs/src/latency.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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. */ @@ -35,87 +26,87 @@ gf_set_fop_from_fn_pointer (call_frame_t *frame, struct xlator_fops *fops, void { glusterfs_fop_t fop = -1; - if (fops->stat == fn) + if (fops->stat == *(fop_stat_t *)&fn) fop = GF_FOP_STAT; - else if (fops->readlink == fn) + else if (fops->readlink == *(fop_readlink_t *)&fn) fop = GF_FOP_READLINK; - else if (fops->mknod == fn) + else if (fops->mknod == *(fop_mknod_t *)&fn) fop = GF_FOP_MKNOD; - else if (fops->mkdir == fn) + else if (fops->mkdir == *(fop_mkdir_t *)&fn) fop = GF_FOP_MKDIR; - else if (fops->unlink == fn) + else if (fops->unlink == *(fop_unlink_t *)&fn) fop = GF_FOP_UNLINK; - else if (fops->rmdir == fn) + else if (fops->rmdir == *(fop_rmdir_t *)&fn) fop = GF_FOP_RMDIR; - else if (fops->symlink == fn) + else if (fops->symlink == *(fop_symlink_t *)&fn) fop = GF_FOP_SYMLINK; - else if (fops->rename == fn) + else if (fops->rename == *(fop_rename_t *)&fn) fop = GF_FOP_RENAME; - else if (fops->link == fn) + else if (fops->link == *(fop_link_t *)&fn) fop = GF_FOP_LINK; - else if (fops->truncate == fn) + else if (fops->truncate == *(fop_truncate_t *)&fn) fop = GF_FOP_TRUNCATE; - else if (fops->open == fn) + else if (fops->open == *(fop_open_t *)&fn) fop = GF_FOP_OPEN; - else if (fops->readv == fn) + else if (fops->readv == *(fop_readv_t *)&fn) fop = GF_FOP_READ; - else if (fops->writev == fn) + else if (fops->writev == *(fop_writev_t *)&fn) fop = GF_FOP_WRITE; - else if (fops->statfs == fn) + else if (fops->statfs == *(fop_statfs_t *)&fn) fop = GF_FOP_STATFS; - else if (fops->flush == fn) + else if (fops->flush == *(fop_flush_t *)&fn) fop = GF_FOP_FLUSH; - else if (fops->fsync == fn) + else if (fops->fsync == *(fop_fsync_t *)&fn) fop = GF_FOP_FSYNC; - else if (fops->setxattr == fn) + else if (fops->setxattr == *(fop_setxattr_t *)&fn) fop = GF_FOP_SETXATTR; - else if (fops->getxattr == fn) + else if (fops->getxattr == *(fop_getxattr_t *)&fn) fop = GF_FOP_GETXATTR; - else if (fops->removexattr == fn) + else if (fops->removexattr == *(fop_removexattr_t *)&fn) fop = GF_FOP_REMOVEXATTR; - else if (fops->opendir == fn) + else if (fops->opendir == *(fop_opendir_t *)&fn) fop = GF_FOP_OPENDIR; - else if (fops->fsyncdir == fn) + else if (fops->fsyncdir == *(fop_fsyncdir_t *)&fn) fop = GF_FOP_FSYNCDIR; - else if (fops->access == fn) + else if (fops->access == *(fop_access_t *)&fn) fop = GF_FOP_ACCESS; - else if (fops->create == fn) + else if (fops->create == *(fop_create_t *)&fn) fop = GF_FOP_CREATE; - else if (fops->ftruncate == fn) + else if (fops->ftruncate == *(fop_ftruncate_t *)&fn) fop = GF_FOP_FTRUNCATE; - else if (fops->fstat == fn) + else if (fops->fstat == *(fop_fstat_t *)&fn) fop = GF_FOP_FSTAT; - else if (fops->lk == fn) + else if (fops->lk == *(fop_lk_t *)&fn) fop = GF_FOP_LK; - else if (fops->lookup == fn) + else if (fops->lookup == *(fop_lookup_t *)&fn) fop = GF_FOP_LOOKUP; - else if (fops->readdir == fn) + else if (fops->readdir == *(fop_readdir_t *)&fn) fop = GF_FOP_READDIR; - else if (fops->inodelk == fn) + else if (fops->inodelk == *(fop_inodelk_t *)&fn) fop = GF_FOP_INODELK; - else if (fops->finodelk == fn) + else if (fops->finodelk == *(fop_finodelk_t *)&fn) fop = GF_FOP_FINODELK; - else if (fops->entrylk == fn) + else if (fops->entrylk == *(fop_entrylk_t *)&fn) fop = GF_FOP_ENTRYLK; - else if (fops->fentrylk == fn) + else if (fops->fentrylk == *(fop_fentrylk_t *)&fn) fop = GF_FOP_FENTRYLK; - else if (fops->xattrop == fn) + else if (fops->xattrop == *(fop_xattrop_t *)&fn) fop = GF_FOP_XATTROP; - else if (fops->fxattrop == fn) + else if (fops->fxattrop == *(fop_fxattrop_t *)&fn) fop = GF_FOP_FXATTROP; - else if (fops->fgetxattr == fn) + else if (fops->fgetxattr == *(fop_fgetxattr_t *)&fn) fop = GF_FOP_FGETXATTR; - else if (fops->fsetxattr == fn) + else if (fops->fsetxattr == *(fop_fsetxattr_t *)&fn) fop = GF_FOP_FSETXATTR; - else if (fops->rchecksum == fn) + else if (fops->rchecksum == *(fop_rchecksum_t *)&fn) fop = GF_FOP_RCHECKSUM; - else if (fops->setattr == fn) + else if (fops->setattr == *(fop_setattr_t *)&fn) fop = GF_FOP_SETATTR; - else if (fops->fsetattr == fn) + else if (fops->fsetattr == *(fop_fsetattr_t *)&fn) fop = GF_FOP_FSETATTR; - else if (fops->readdirp == fn) + else if (fops->readdirp == *(fop_readdirp_t *)&fn) fop = GF_FOP_READDIRP; - else if (fops->getspec == fn) + else if (fops->getspec == *(fop_getspec_t *)&fn) fop = GF_FOP_GETSPEC; else fop = -1; @@ -140,11 +131,27 @@ gf_update_latency (call_frame_t *frame) lat = &frame->this->latencies[frame->op]; - lat->total += elapsed; + 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) @@ -157,26 +164,25 @@ gf_proc_dump_latency_info (xlator_t *xl) gf_proc_dump_add_section (key_prefix); for (i = 0; i < GF_FOP_MAXVALUE; i++) { - gf_proc_dump_build_key (key, key_prefix, gf_fop_list[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); + xl->latencies[i].total); } + + memset (xl->latencies, 0, sizeof (xl->latencies)); } void -gf_latency_toggle (int signum) +gf_latency_toggle (int signum, glusterfs_ctx_t *ctx) { - glusterfs_ctx_t *ctx = NULL; - - ctx = glusterfs_ctx_get (); - if (ctx) { ctx->measure_latency = !ctx->measure_latency; - gf_log ("[core]", GF_LOG_NORMAL, + 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 index 610f12550..81acbf484 100644 --- a/libglusterfs/src/latency.h +++ b/libglusterfs/src/latency.h @@ -1,25 +1,17 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 __LATENCY_H__ #define __LATENCY_H__ +#include "glusterfs.h" typedef struct fop_latency { uint64_t min; /* min time for the call (microseconds) */ @@ -31,6 +23,6 @@ typedef struct fop_latency { } fop_latency_t; void -gf_latency_toggle (int signum); +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 d4851dfec..392c22ceb 100644 --- a/libglusterfs/src/list.h +++ b/libglusterfs/src/list.h @@ -1,26 +1,16 @@ /* - Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 c5043aa14..79c6992af 100644 --- a/libglusterfs/src/locking.h +++ b/libglusterfs/src/locking.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 5b89aafb4..5deb90cda 100644 --- a/libglusterfs/src/logging.c +++ b/libglusterfs/src/logging.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,9 +22,22 @@ #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" #ifdef GF_LINUX_HOST_OS #include <syslog.h> @@ -43,49 +47,44 @@ #include <execinfo.h> #endif +/* Ideally this should get moved to logging.h */ +struct _msg_queue { + struct list_head msgs; +}; -static pthread_mutex_t logfile_mutex; -static char *filename = NULL; -static uint8_t logrotate = 0; -static FILE *logfile = NULL; -static gf_loglevel_t loglevel = GF_LOG_MAX; -static int gf_log_syslog = 0; - -char gf_log_xl_log_set; -gf_loglevel_t gf_log_loglevel; /* extern'd */ -FILE *gf_log_logfile; - -static char *cmd_log_filename = NULL; -static FILE *cmdlogfile = NULL; +struct _log_msg { + const char *msg; + struct list_head queue; +}; void gf_log_logrotate (int signum) { - logrotate = 1; + THIS->ctx->log.logrotate = 1; } void gf_log_enable_syslog (void) { - gf_log_syslog = 1; + THIS->ctx->log.gf_log_syslog = 1; } void gf_log_disable_syslog (void) { - gf_log_syslog = 0; + THIS->ctx->log.gf_log_syslog = 0; } gf_loglevel_t gf_log_get_loglevel (void) { - return loglevel; + return THIS->ctx->log.loglevel; } void gf_log_set_loglevel (gf_loglevel_t level) { - gf_log_loglevel = loglevel = level; + THIS->ctx->log.loglevel = level; } @@ -104,151 +103,506 @@ gf_log_set_xl_loglevel (void *this, gf_loglevel_t level) xlator_t *xl = this; if (!xl) return; - gf_log_xl_log_set = 1; + xl->ctx->log.gf_log_xl_log_set = 1; xl->loglevel = level; } void gf_log_fini (void) { - pthread_mutex_destroy (&logfile_mutex); + pthread_mutex_destroy (&THIS->ctx->log.logfile_mutex); } -int -gf_log_init (const char *file) +#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); +} + + +/** + * 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) { - if (!file){ - fprintf (stderr, "gf_log_init: no filename specified\n"); - return -1; - } - - pthread_mutex_init (&logfile_mutex, NULL); - - filename = gf_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; - } + int _option = option; + int _facility = facility; -#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 + if (-1 == _option) { + _option = LOG_PID | LOG_NDELAY; + } + if (-1 == _facility) { + _facility = LOG_LOCAL1; + } - gf_log_logfile = logfile; + setlocale(LC_ALL, ""); + bindtextdomain("gluster", "/usr/share/locale"); + textdomain("gluster"); - return 0; + openlog(ident, _option, _facility); } -/* - * Initialize logging to a central server. - * If successful, log messages will be written both to - * the local file and to the remote server. +/** + * _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" + * */ +char * +_json_escape(const char *str, char *buf, size_t len) +{ + 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; + } -static int __central_log_enabled = 0; - -struct _msg_queue { - struct list_head msgs; -}; + for (p = (unsigned char *)str; + *p && (pos + 1) < len; + p++) + { + if (json_exceptions[*p] == 0) { + buf[pos++] = *p; + continue; + } -struct _log_msg { - const char *msg; - struct list_head queue; -}; + if ((pos + 2) >= len) { + break; + } + 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; + } + } + buf[pos] = '\0'; + return (char *)p; +} -void -gf_log_lock (void) +/** + * 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, ...) { - pthread_mutex_lock (&logfile_mutex); + 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 */ - -void -gf_log_unlock (void) +void +gf_log_globals_init (void *data) { - pthread_mutex_unlock (&logfile_mutex); + glusterfs_ctx_t *ctx = data; + + pthread_mutex_init (&ctx->log.logfile_mutex, NULL); + + 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 } +int +gf_log_init (void *data, const char *file, const char *ident) +{ + glusterfs_ctx_t *ctx = NULL; + int fd = -1; + + ctx = data; + +#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; + } + + if (strcmp (file, "-") == 0) { + ctx->log.gf_log_logfile = stderr; + ctx->log.logfile = stderr; + return 0; + } + + 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); + + 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; + } + + ctx->log.gf_log_logfile = ctx->log.logfile; + + return 0; +} void -gf_log_cleanup (void) +set_sys_log_level (gf_loglevel_t level) { - pthread_mutex_destroy (&logfile_mutex); + THIS->ctx->log.sys_log_level = level; } int +_gf_log_nomem (const char *domain, const char *file, + const char *function, int line, gf_loglevel_t level, + size_t size) +{ + 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; + + 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) { + 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; + } + 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; + } + + 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_callingfn (const char *domain, const char *file, const char *function, int line, gf_loglevel_t level, const char *fmt, ...) { - const char *basename = NULL; - struct tm *tm = NULL; + 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,}; + char timestr[256] = {0,}; + char callstr[4096] = {0,}; struct timeval tv = {0,}; size_t len = 0; int ret = 0; - gf_loglevel_t xlator_loglevel = 0; - va_list ap; - - if (!logfile) - return -1; + va_list ap; + glusterfs_ctx_t *ctx = NULL; this = THIS; + ctx = this->ctx; - xlator_loglevel = this->loglevel; - if (xlator_loglevel == 0) - xlator_loglevel = loglevel; - - if (level > xlator_loglevel) + 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 */ + static char *level_strings[] = {"", /* NONE */ "M", /* EMERGENCY */ "A", /* ALERT */ - "C", /* CRITICAL */ - "E", /* ERROR */ - "W", /* WARNING */ - "N", /* NOTICE */ - "I", /* INFO/NORMAL */ - "D", /* DEBUG */ + "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 (!domain || !file || !function || !fmt) { + 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]; + /* Print 'calling function' */ + do { + void *array[5]; char **callingfn = NULL; - size_t size = 0; + size_t size = 0; - size = backtrace (array, 5); + size = backtrace (array, 5); if (size) callingfn = backtrace_symbols (&array[2], size-2); if (!callingfn) @@ -264,322 +618,355 @@ _gf_log_callingfn (const char *domain, const char *file, const char *function, snprintf (callstr, 4096, "(-->%s)", callingfn[0]); free (callingfn); - } while (0); + } 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; + } + + 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); + + 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); - tm = localtime (&tv.tv_sec); + 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; + } - pthread_mutex_lock (&logfile_mutex); - { - va_start (ap, fmt); + ret = vasprintf (&str2, fmt, ap); + if (-1 == ret) { + goto out; + } - strftime (timestr, 256, "%Y-%m-%d %H:%M:%S", tm); - snprintf (timestr + strlen (timestr), 256 - strlen (timestr), - ".%"GF_PRI_SUSECONDS, tv.tv_usec); + va_end (ap); - basename = strrchr (file, '/'); - if (basename) - basename++; - else - basename = file; + len = strlen (str1); + msg = GF_MALLOC (len + strlen (str2) + 1, gf_common_mt_char); - ret = gf_asprintf (&str1, "[%s] %s [%s:%d:%s] %s %s: ", - timestr, level_strings[level], - basename, line, function, callstr, - domain); - if (-1 == ret) { - goto unlock; - } + strcpy (msg, str1); + strcpy (msg + len, str2); - ret = vasprintf (&str2, fmt, ap); - if (-1 == ret) { - goto unlock; + pthread_mutex_lock (&ctx->log.logfile_mutex); + { + if (ctx->log.logfile) { + fprintf (ctx->log.logfile, "%s\n", msg); + } else { + fprintf (stderr, "%s\n", msg); } - va_end (ap); - - len = strlen (str1); - msg = GF_MALLOC (len + strlen (str2) + 1, gf_common_mt_char); - - strcpy (msg, str1); - strcpy (msg + len, str2); - - fprintf (logfile, "%s\n", msg); - fflush (logfile); - #ifdef GF_LINUX_HOST_OS /* We want only serious log in 'syslog', not our debug and trace logs */ - if (gf_log_syslog && level && (level <= GF_LOG_ERROR)) + if (ctx->log.gf_log_syslog && level && + (level <= ctx->log.sys_log_level)) syslog ((level-1), "%s\n", msg); #endif - } + } -unlock: - pthread_mutex_unlock (&logfile_mutex); + pthread_mutex_unlock (&ctx->log.logfile_mutex); - if (msg) { - GF_FREE (msg); - } +out: + GF_FREE (msg); - if (str1) - GF_FREE (str1); + GF_FREE (str1); - if (str2) - FREE (str2); + FREE (str2); -out: 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; - struct tm *tm = NULL; - char timestr[256]; + 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; - xlator_t *this = NULL; - gf_loglevel_t xlator_loglevel = 0; - - if (!logfile) - return -1; + 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; - xlator_loglevel = this->loglevel; - if (xlator_loglevel == 0) - xlator_loglevel = loglevel; - - if (level > xlator_loglevel) + 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 */ + static char *level_strings[] = {"", /* NONE */ "M", /* EMERGENCY */ "A", /* ALERT */ - "C", /* CRITICAL */ - "E", /* ERROR */ - "W", /* WARNING */ - "N", /* NOTICE */ - "I", /* INFO/NORMAL */ - "D", /* DEBUG */ + "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 (!domain || !file || !function || !fmt) { + 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 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; + } - if (logrotate) { - logrotate = 0; + va_start (ap, fmt); + vasprintf (&str2, fmt, ap); + va_end (ap); - 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; - } + 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 */ + + if (ctx->log.logrotate) { + ctx->log.logrotate = 0; + + 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; + } - fclose (logfile); - gf_log_logfile = logfile = new_logfile; - } + pthread_mutex_lock (&ctx->log.logfile_mutex); + { + if (ctx->log.logfile) + fclose (ctx->log.logfile); + + ctx->log.gf_log_logfile = ctx->log.logfile = new_logfile; + } + pthread_mutex_unlock (&ctx->log.logfile_mutex); + + } 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); - tm = localtime (&tv.tv_sec); - - pthread_mutex_lock (&logfile_mutex); - { - va_start (ap, fmt); - - strftime (timestr, 256, "%Y-%m-%d %H:%M:%S", tm); - snprintf (timestr + strlen (timestr), 256 - strlen (timestr), - ".%"GF_PRI_SUSECONDS, tv.tv_usec); - - basename = strrchr (file, '/'); - if (basename) - basename++; - else - basename = file; + 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; + } - ret = gf_asprintf (&str1, "[%s] %s [%s:%d:%s] %s: ", - timestr, level_strings[level], - basename, line, function, - domain); - if (-1 == ret) { - goto unlock; - } + ret = vasprintf (&str2, fmt, ap); + if (-1 == ret) { + goto err; + } - ret = vasprintf (&str2, fmt, ap); - if (-1 == ret) { - goto unlock; - } + va_end (ap); - va_end (ap); + len = strlen (str1); + msg = GF_MALLOC (len + strlen (str2) + 1, gf_common_mt_char); - len = strlen (str1); - msg = GF_MALLOC (len + strlen (str2) + 1, gf_common_mt_char); + strcpy (msg, str1); + strcpy (msg + len, str2); - strcpy (msg, str1); - strcpy (msg + len, str2); + pthread_mutex_lock (&ctx->log.logfile_mutex); + { - fprintf (logfile, "%s\n", msg); - fflush (logfile); + 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 (gf_log_syslog && level && (level <= GF_LOG_ERROR)) + if (ctx->log.gf_log_syslog && level && + (level <= ctx->log.sys_log_level)) syslog ((level-1), "%s\n", msg); #endif - } + } -unlock: - pthread_mutex_unlock (&logfile_mutex); + pthread_mutex_unlock (&ctx->log.logfile_mutex); - if (msg) { - if ((ret != -1) && __central_log_enabled && - ((glusterfs_central_log_flag_get ()) == 0)) { +err: + GF_FREE (msg); - glusterfs_central_log_flag_set (); - { - //gf_log_central (msg); - } - glusterfs_central_log_flag_unset (); - } - GF_FREE (msg); - } + GF_FREE (str1); - if (str1) - GF_FREE (str1); - - if (str2) - FREE (str2); + FREE (str2); out: - return (0); + return (0); } - -struct _client_log { - char *identifier; - FILE *file; - struct list_head list; -}; - -struct _client_log *client_logs = NULL; - - -static void -client_log_init (struct _client_log *cl, char *identifier) +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; - cl->identifier = identifier; + this = THIS; - ret = gf_asprintf (&path, "%s.client-%s", filename, identifier); + ret = gf_asprintf (&str1, "[%d] %s: ", + ((this->graph)?this->graph->id:0), + function); if (-1 == ret) { - return; + goto out; } - cl->file = fopen (path, "a"); - GF_FREE (path); - - INIT_LIST_HEAD (&cl->list); -} + va_start (ap, fmt); -static FILE * -__logfile_for_client (char *identifier) -{ - struct _client_log *client = NULL; - - if (!client_logs) { - client = GF_CALLOC (1, sizeof (*client), - gf_common_mt_client_log); - if (!client) - return NULL; + ret = vasprintf (&str2, fmt, ap); + if (-1 == ret) { + goto out; + } - client_log_init (client, identifier); + va_end (ap); - client_logs = client; + msg = GF_MALLOC (strlen (str1) + strlen (str2) + 1, gf_common_mt_char); + if (!msg) { + ret = -1; + goto out; } - list_for_each_entry (client, &client_logs->list, list) { - if (!strcmp (client->identifier, identifier)) - break; - } + strcpy (msg, str1); + strcat (msg, str2); - if (!client) { - client = GF_CALLOC (1, sizeof (*client), - gf_common_mt_client_log); - if (!client) - return NULL; + ret = eh_save_history (this->history, msg); - client_log_init (client, identifier); +out: + GF_FREE (str1); - list_add_tail (&client->list, &client_logs->list); - } + /* Use FREE instead of GF_FREE since str2 was allocated by vasprintf */ + if (str2) + FREE (str2); - return client->file; + return ret; } - int -gf_log_from_client (const char *msg, char *identifier) +gf_cmd_log_init (const char *filename) { - FILE *client_log = NULL; - - client_log = __logfile_for_client (identifier); + int fd = -1; + xlator_t *this = NULL; + glusterfs_ctx_t *ctx = NULL; - fprintf (client_log, "%s\n", msg); - fflush (client_log); - - return 0; -} + this = THIS; + ctx = this->ctx; -int -gf_cmd_log_init (const char *filename) -{ if (!filename){ - gf_log ("glusterd",GF_LOG_CRITICAL, "gf_cmd_log_init: no " + gf_log (this->name, GF_LOG_CRITICAL, "gf_cmd_log_init: no " "filename specified\n"); return -1; } - cmd_log_filename = gf_strdup (filename); - if (!filename) { - gf_log ("glusterd",GF_LOG_CRITICAL, "gf_cmd_log_init: strdup" - " error\n"); + 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; + } - cmdlogfile = fopen (cmd_log_filename, "a"); - if (!cmdlogfile){ - gf_log ("glusterd", GF_LOG_CRITICAL, - "gf_cmd_log_init: failed to open logfile \"%s\" " - "(%s)\n", cmd_log_filename, strerror (errno)); + 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; @@ -588,46 +975,44 @@ gf_cmd_log_init (const char *filename) int gf_cmd_log (const char *domain, const char *fmt, ...) { - va_list ap; - struct tm *tm = NULL; - char timestr[256]; + 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; - - if (!cmdlogfile) + 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"); + "logging: invalid argument\n"); return -1; } ret = gettimeofday (&tv, NULL); if (ret == -1) goto out; - - tm = localtime (&tv.tv_sec); - va_start (ap, fmt); - strftime (timestr, 256, "%Y-%m-%d %H:%M:%S", tm); + 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); + timestr, domain); if (ret == -1) { - goto out; + goto out; } ret = vasprintf (&str2, fmt, ap); if (ret == -1) { - goto out; + goto out; } va_end (ap); @@ -638,20 +1023,15 @@ gf_cmd_log (const char *domain, const char *fmt, ...) strcpy (msg, str1); strcpy (msg + len, str2); - fprintf (cmdlogfile, "%s\n", msg); - fflush (cmdlogfile); + fprintf (ctx->log.cmdlogfile, "%s\n", msg); + fflush (ctx->log.cmdlogfile); out: - if (msg) { - GF_FREE (msg); - } + GF_FREE (msg); - if (str1) - GF_FREE (str1); + GF_FREE (str1); - if (str2) - FREE (str2); + FREE (str2); return (0); - } diff --git a/libglusterfs/src/logging.h b/libglusterfs/src/logging.h index 39fdff155..cc806a767 100644 --- a/libglusterfs/src/logging.h +++ b/libglusterfs/src/logging.h @@ -1,22 +1,12 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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__ @@ -29,21 +19,23 @@ #include <stdint.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 PRId32 +#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 "ld" +#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 */ @@ -57,62 +49,95 @@ #endif typedef enum { - GF_LOG_NONE, + 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_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 */ -#define GF_LOG_NORMAL GF_LOG_INFO - GF_LOG_DEBUG, /* internal errors */ + GF_LOG_INFO, /* Normal information */ + GF_LOG_DEBUG, /* internal errors */ GF_LOG_TRACE, /* full trace of operation */ } gf_loglevel_t; -#define GF_LOG_MAX GF_LOG_DEBUG +#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); + +void gf_log_cleanup (void); + +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))); + +int _gf_log_nomem (const char *domain, const char *file, + const char *function, int line, gf_loglevel_t level, + size_t size); -extern gf_loglevel_t gf_log_loglevel; -extern char gf_log_xl_log_set; +int _gf_log_eh (const char *function, const char *fmt, ...); -#define gf_log(dom, levl, fmt...) do { \ - if ((levl > gf_log_loglevel) && !gf_log_xl_log_set) \ - break; \ + + +#define FMT_WARN(fmt...) do { if (0) printf (fmt); } while (0) + +#define gf_log(dom, levl, fmt...) do { \ + FMT_WARN (fmt); \ _gf_log (dom, __FILE__, __FUNCTION__, __LINE__, \ levl, ##fmt); \ } while (0) +#define gf_log_eh(fmt...) do { \ + FMT_WARN (fmt); \ + _gf_log_eh (__FUNCTION__, ##fmt); \ + } while (0) + #define gf_log_callingfn(dom, levl, fmt...) do { \ - if ((levl > gf_log_loglevel) && !gf_log_xl_log_set) \ - break; \ + FMT_WARN (fmt); \ _gf_log_callingfn (dom, __FILE__, __FUNCTION__, __LINE__, \ levl, ##fmt); \ } while (0) -/* Log once in GF_UNIVERSAL_ANSWER times */ -#define GF_LOG_OCCASIONALLY(var, args...) if (!(var++%GF_UNIVERSAL_ANSWER)) { \ - gf_log (args); \ - } - - -void -gf_log_logrotate (int signum); - -int gf_log_init (const char *filename); -void gf_log_cleanup (void); -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_callingfn (const char *domain, const char *file, const char *function, - int32_t line, gf_loglevel_t level, const char *fmt, ...); +/* 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) -int -gf_log_from_client (const char *msg, char *identifier); -void gf_log_lock (void); -void gf_log_unlock (void); +/* Log once in GF_UNIVERSAL_ANSWER times */ +#define GF_LOG_OCCASIONALLY(var, args...) if (!(var++%GF_UNIVERSAL_ANSWER)) { \ + gf_log (args); \ + } void gf_log_disable_syslog (void); void gf_log_enable_syslog (void); @@ -121,18 +146,20 @@ 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); -#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) +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_cmd_log (const char *domain, const char *fmt, ...); +#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) -int -gf_cmd_log_init (const char *filename); #endif /* __LOGGING_H__ */ diff --git a/libglusterfs/src/mem-pool.c b/libglusterfs/src/mem-pool.c index 17d2e0dd2..b901dd7a8 100644 --- a/libglusterfs/src/mem-pool.c +++ b/libglusterfs/src/mem-pool.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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" @@ -24,45 +15,33 @@ #include <stdarg.h> #define GF_MEM_POOL_LIST_BOUNDARY (sizeof(struct list_head)) -#define GF_MEM_POOL_PAD_BOUNDARY (GF_MEM_POOL_LIST_BOUNDARY + sizeof(int)) +#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) -#define GF_MEM_TRAILER_SIZE 4 +#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" -static int gf_mem_acct_enable = 1; - -int -gf_mem_acct_is_enabled () -{ - return gf_mem_acct_enable; -} - void -gf_mem_acct_enable_set () +gf_mem_acct_enable_set (void *data) { - char *opt = NULL; - long val = -1; + glusterfs_ctx_t *ctx = NULL; - opt = getenv (GLUSTERFS_ENV_MEM_ACCT_STR); - - if (!opt) - return; + ctx = data; - val = strtol (opt, NULL, 0); + GF_ASSERT (ctx); - if (val) - gf_mem_acct_enable = 0; - else - gf_mem_acct_enable = 1; + ctx->mem_acct_enable = 1; + return; } void @@ -77,28 +56,23 @@ gf_mem_set_acct_info (xlator_t *xl, char **alloc_ptr, ptr = (char *) (*alloc_ptr); - if (!xl) { - GF_ASSERT (0); - } + GF_ASSERT (xl != NULL); - if (!(xl->mem_acct.rec)) { - GF_ASSERT (0); - } + GF_ASSERT (xl->mem_acct.rec != NULL); - if (type > xl->mem_acct.num_types) { - GF_ASSERT (0); - } + 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); + 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); + max (xl->mem_acct.rec[type].max_num_allocs, + xl->mem_acct.rec[type].num_allocs); } UNLOCK(&xl->mem_acct.rec[type].lock); @@ -110,6 +84,7 @@ gf_mem_set_acct_info (xlator_t *xl, char **alloc_ptr, 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; @@ -125,7 +100,7 @@ __gf_calloc (size_t nmemb, size_t size, uint32_t type) char *ptr = NULL; xlator_t *xl = NULL; - if (!gf_mem_acct_enable) + if (!THIS->ctx->mem_acct_enable) return CALLOC (nmemb, size); xl = THIS; @@ -135,9 +110,10 @@ __gf_calloc (size_t nmemb, size_t size, uint32_t type) ptr = calloc (1, tot_size); - if (!ptr) + 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; @@ -150,7 +126,7 @@ __gf_malloc (size_t size, uint32_t type) char *ptr = NULL; xlator_t *xl = NULL; - if (!gf_mem_acct_enable) + if (!THIS->ctx->mem_acct_enable) return MALLOC (size); xl = THIS; @@ -158,9 +134,10 @@ __gf_malloc (size_t size, uint32_t type) tot_size = size + GF_MEM_HEADER_SIZE + GF_MEM_TRAILER_SIZE; ptr = malloc (tot_size); - if (!ptr) + if (!ptr) { + gf_log_nomem ("", GF_LOG_ALERT, tot_size); return NULL; - + } gf_mem_set_acct_info (xl, &ptr, size, type); return (void *)ptr; @@ -174,10 +151,12 @@ __gf_realloc (void *ptr, size_t size) 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 - 4; + orig_ptr = (char *)ptr - 8 - 4; GF_ASSERT (*(uint32_t *)orig_ptr == GF_MEM_HEADER_MAGIC); @@ -188,8 +167,10 @@ __gf_realloc (void *ptr, size_t size) type = *(uint32_t *)orig_ptr; ptr = realloc (orig_ptr, tot_size); - if (!ptr) + if (!ptr) { + gf_log_nomem ("", GF_LOG_ALERT, tot_size); return NULL; + } gf_mem_set_acct_info (xl, (char **)&ptr, size, type); @@ -200,44 +181,39 @@ 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; + char *str = NULL; + int size = 0; + int rv = 0; - if (!string_ptr || !format) - return -1; + 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) { - /* - * 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_save); - - *string_ptr = str; - return (rv); + 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_list arg; + int rv = 0; - va_start (arg, format); - rv = gf_vasprintf (string_ptr, format, arg); - va_end (arg); + va_start (arg, format); + rv = gf_vasprintf (string_ptr, format, arg); + va_end (arg); - return rv; + return rv; } void @@ -248,7 +224,7 @@ __gf_free (void *free_ptr) uint32_t type = 0; xlator_t *xl = NULL; - if (!gf_mem_acct_enable) { + if (!THIS->ctx->mem_acct_enable) { FREE (free_ptr); return; } @@ -256,23 +232,18 @@ __gf_free (void *free_ptr) if (!free_ptr) return; + ptr = (char *)free_ptr - 8 - 4; - ptr = (char *)free_ptr - 4; - - if (GF_MEM_HEADER_MAGIC != *(uint32_t *)ptr) { - //Possible corruption, assert here - GF_ASSERT (0); - } + //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 *)); - if (!xl) { - //gf_free expects xl to be available - GF_ASSERT (0); - } + //gf_free expects xl to be available + GF_ASSERT (xl != NULL); if (!xl->mem_acct.rec) { ptr = (char *)free_ptr - GF_MEM_HEADER_SIZE; @@ -285,11 +256,10 @@ __gf_free (void *free_ptr) ptr = ptr - 4; type = *(uint32_t *)ptr; - if (GF_MEM_TRAILER_MAGIC != *(uint32_t *) - ((char *)free_ptr + req_size)) { - // This points to a memory overrun - GF_ASSERT (0); - } + // 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); @@ -306,47 +276,68 @@ free: 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 = GF_CALLOC (sizeof (*mem_pool), 1, gf_common_mt_mem_pool); - if (!mem_pool) - return NULL; + 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); + 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 = GF_CALLOC (count, padded_sizeof_type, gf_common_mt_long); - if (!pool) { + if (!pool) { + GF_FREE (mem_pool->name); GF_FREE (mem_pool); - return NULL; + 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)); - 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; - return mem_pool; + list_add (&mem_pool->global_list, &ctx->mempool_list); + +out: + return mem_pool; } void* @@ -355,7 +346,7 @@ mem_get0 (struct mem_pool *mem_pool) void *ptr = NULL; if (!mem_pool) { - gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument"); + gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument"); return NULL; } @@ -370,35 +361,41 @@ mem_get0 (struct mem_pool *mem_pool) void * mem_get (struct mem_pool *mem_pool) { - struct list_head *list = NULL; - void *ptr = NULL; + struct list_head *list = NULL; + void *ptr = NULL; int *in_use = NULL; + struct mem_pool **pool_ptr = NULL; - if (!mem_pool) { - gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument"); - return NULL; - } + if (!mem_pool) { + gf_log_callingfn ("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); + 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--; + mem_pool->hot_count++; + mem_pool->cold_count--; - ptr = list; - in_use = (ptr + GF_MEM_POOL_LIST_BOUNDARY); + 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. @@ -415,83 +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 (!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 (ptr < pool->pool || ptr >= pool->pool_end) + return 0; - if ((mem_pool_ptr2chunkhead (ptr) - pool->pool) - % pool->padded_sizeof_type) - return -1; + if ((mem_pool_ptr2chunkhead (ptr) - pool->pool) + % pool->padded_sizeof_type) + return -1; - return 1; + return 1; } void -mem_put (struct mem_pool *pool, void *ptr) +mem_put (void *ptr) { - struct list_head *list = NULL; - int *in_use = NULL; - void *head = 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 = head = mem_pool_ptr2chunkhead (ptr); - in_use = (head + GF_MEM_POOL_LIST_BOUNDARY); - 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: + 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 @@ -500,24 +518,30 @@ 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); + GF_FREE (pool->name); GF_FREE (pool->pool); GF_FREE (pool); diff --git a/libglusterfs/src/mem-pool.h b/libglusterfs/src/mem-pool.h index 6b09d6221..31f49f75c 100644 --- a/libglusterfs/src/mem-pool.h +++ b/libglusterfs/src/mem-pool.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,6 +13,7 @@ #include "list.h" #include "locking.h" +#include "logging.h" #include "mem-types.h" #include <stdlib.h> #include <inttypes.h> @@ -29,15 +21,6 @@ #include <stdarg.h> -#define MALLOC(size) malloc(size) -#define CALLOC(cnt,size) calloc(cnt,size) - -#define FREE(ptr) \ - if (ptr != NULL) { \ - free ((void *)ptr); \ - ptr = (void *)0xeeeeeeee; \ - } - struct mem_acct { uint32_t num_types; struct mem_acct_rec *rec; @@ -47,6 +30,7 @@ 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; }; @@ -67,17 +51,82 @@ 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); + + return ptr; +} + +#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) -void -__gf_free (void *ptr); +#define GF_FREE(free_ptr) __gf_free (free_ptr) +static inline +char *gf_strndup (const char *src, size_t len) +{ + char *dup_str = NULL; -#define GF_FREE(free_ptr) __gf_free (free_ptr); + 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) @@ -98,31 +147,50 @@ char * gf_strdup (const char *src) 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); -int gf_mem_acct_is_enabled (); -void gf_mem_acct_enable_set (); +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 index 9e857901b..666bd120a 100644 --- a/libglusterfs/src/mem-types.h +++ b/libglusterfs/src/mem-types.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 __MEM_TYPES_H__ @@ -22,81 +13,113 @@ 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_end = 75 + 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/rbthash.c b/libglusterfs/src/rbthash.c index 3a45d9fb6..0d7b9e521 100644 --- a/libglusterfs/src/rbthash.c +++ b/libglusterfs/src/rbthash.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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. */ @@ -124,7 +115,6 @@ rbthash_table_init (int buckets, rbt_hasher_t hfunc, newtab->buckets = GF_CALLOC (buckets, sizeof (struct rbthash_bucket), gf_common_mt_rbthash_bucket); if (!newtab->buckets) { - gf_log (GF_RBTHASH, GF_LOG_ERROR, "Failed to allocate memory"); goto free_newtab; } @@ -142,6 +132,7 @@ rbthash_table_init (int buckets, rbt_hasher_t hfunc, } LOCK_INIT (&newtab->tablelock); + INIT_LIST_HEAD (&newtab->list); newtab->numbuckets = buckets; ret = __rbthash_init_buckets (newtab, buckets); @@ -189,10 +180,10 @@ rbthash_init_entry (rbthash_table_t *tbl, void *data, void *key, int keylen) entry->data = data; entry->key = GF_CALLOC (keylen, sizeof (char), gf_common_mt_char); if (!entry->key) { - gf_log (GF_RBTHASH, GF_LOG_ERROR, "Memory allocation failed"); goto free_entry; } + INIT_LIST_HEAD (&entry->list); memcpy (entry->key, key, keylen); entry->keylen = keylen; entry->keyhash = tbl->hashfunc (entry->key, entry->keylen); @@ -201,7 +192,7 @@ rbthash_init_entry (rbthash_table_t *tbl, void *data, void *key, int keylen) ret = 0; free_entry: if (ret == -1) { - mem_put (tbl->entrypool, entry); + mem_put (entry); entry = NULL; } @@ -217,20 +208,26 @@ rbthash_deinit_entry (rbthash_table_t *tbl, rbthash_entry_t *entry) if (!entry) return; - if (entry->key) - GF_FREE (entry->key); + GF_FREE (entry->key); if (tbl) { if ((entry->data) && (tbl->dfunc)) tbl->dfunc (entry->data); - mem_put (tbl->entrypool, entry); + + LOCK (&tbl->tablelock); + { + list_del_init (&entry->list); + } + UNLOCK (&tbl->tablelock); + + mem_put (entry); } return; } -inline struct rbthash_bucket * +static inline struct rbthash_bucket * rbthash_entry_bucket (rbthash_table_t *tbl, rbthash_entry_t * entry) { int nbucket = 0; @@ -294,11 +291,17 @@ rbthash_insert (rbthash_table_t *tbl, void *data, void *key, int keylen) rbthash_deinit_entry (tbl, entry); } + LOCK (&tbl->tablelock); + { + list_add_tail (&entry->list, &tbl->list); + } + UNLOCK (&tbl->tablelock); + err: return ret; } -inline struct rbthash_bucket * +static inline struct rbthash_bucket * rbthash_key_bucket (rbthash_table_t *tbl, void *key, int keylen) { uint32_t keyhash = 0; @@ -378,7 +381,14 @@ rbthash_remove (rbthash_table_t *tbl, void *key, int keylen) GF_FREE (entry->key); dataref = entry->data; - mem_put (tbl->entrypool, entry); + + LOCK (&tbl->tablelock); + { + list_del_init (&entry->list); + } + UNLOCK (&tbl->tablelock); + + mem_put (entry); return dataref; } @@ -424,3 +434,25 @@ rbthash_table_destroy (rbthash_table_t *tbl) 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 index 73b5b8e30..b093ce998 100644 --- a/libglusterfs/src/rbthash.h +++ b/libglusterfs/src/rbthash.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 __RBTHASH_TABLE_H_ @@ -24,6 +15,7 @@ #include "mem-pool.h" #include "logging.h" #include "common-utils.h" +#include "list.h" #include <pthread.h> @@ -38,12 +30,14 @@ struct rbthash_bucket { typedef struct rbthash_entry { void *data; void *key; - int keylen; - uint32_t keyhash; + 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; @@ -54,6 +48,7 @@ typedef struct rbthash_table { 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 * @@ -75,4 +70,8 @@ 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/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 dc49d22d2..000000000 --- a/libglusterfs/src/scheduler.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 = gf_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 ()); - GF_FREE(sched_file); - return NULL; - } - - tmp_sched = dlsym (handle, "sched"); - if (!tmp_sched) { - gf_log ("scheduler", GF_LOG_ERROR, - "dlsym(sched) on %s", dlerror ()); - GF_FREE(sched_file); - return NULL; - } - - vol_opt = GF_CALLOC (1, sizeof (volume_opt_list_t), - gf_common_mt_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"); - GF_FREE(sched_file); - return NULL; - } - } - GF_FREE(sched_file); - GF_FREE (vol_opt); - - return tmp_sched; -} diff --git a/libglusterfs/src/scheduler.h b/libglusterfs/src/scheduler.h deleted file mode 100644 index 556cdae15..000000000 --- a/libglusterfs/src/scheduler.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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); - int32_t (*mem_acct_init) (xlator_t *this); -}; - -extern struct sched_ops *get_scheduler (xlator_t *xl, const char *name); - -#endif /* _SCHEDULER_H */ diff --git a/libglusterfs/src/stack.c b/libglusterfs/src/stack.c index b2659c57f..37b338f51 100644 --- a/libglusterfs/src/stack.c +++ b/libglusterfs/src/stack.c @@ -1,27 +1,18 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,15 +26,53 @@ 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; @@ -53,28 +82,49 @@ gf_proc_dump_call_frame (call_frame_t *call_frame, const char *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,7 +136,7 @@ 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; @@ -97,28 +147,32 @@ gf_proc_dump_call_stack (call_stack_t *call_stack, const char *key_buf,...) 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); + 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)); - gf_proc_dump_build_key(key, prefix,"op"); if (call_stack->type == GF_OP_TYPE_FOP) - gf_proc_dump_write(key, "%s", gf_fop_list[call_stack->op]); - else if (call_stack->type == GF_OP_TYPE_MGMT) - gf_proc_dump_write(key, "%s", gf_mgmt_list[call_stack->op]); + gf_proc_dump_write("op", "%s", + (char *)gf_fop_list[call_stack->op]); + else + gf_proc_dump_write("op", "stack"); - 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); + gf_proc_dump_write("type", "%d", call_stack->type); + gf_proc_dump_write("cnt", "%d", cnt); trav = &call_stack->frames; @@ -126,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; } } } @@ -134,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) { @@ -160,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 b06470bf5..f2d2ef950 100644 --- a/libglusterfs/src/stack.h +++ b/libglusterfs/src/stack.h @@ -1,20 +1,11 @@ -/* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,8 +25,8 @@ 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> @@ -44,109 +35,124 @@ typedef struct _call_pool_t call_pool_t; #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; - struct mem_pool *frame_mem_pool; - struct mem_pool *stack_mem_pool; + 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; - - glusterfs_fop_t op; + 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; - uint32_t ngrps; - uint32_t groups[GF_REQUEST_MAXGROUPS]; - uint64_t lk_owner; - - 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); \ +#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_set_fop_from_fn_pointer (call_frame_t *frame, struct xlator_fops *fops, - void *fn); +gf_latency_begin (call_frame_t *frame, void *fn); void -gf_update_latency (call_frame_t *frame); +gf_latency_end (call_frame_t *frame); static inline void FRAME_DESTROY (call_frame_t *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->root->pool->frame_mem_pool, frame); - - if (local) - GF_FREE (local); + 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); } @@ -155,101 +161,171 @@ STACK_DESTROY (call_stack_t *stack) { void *local = NULL; - LOCK (&stack->pool->lock); - { - list_del_init (&stack->all_frames); - stack->pool->cnt--; - } - UNLOCK (&stack->pool->lock); + LOCK (&stack->pool->lock); + { + list_del_init (&stack->all_frames); + stack->pool->cnt--; + } + UNLOCK (&stack->pool->lock); - if (stack->frames.local) { - local = stack->frames.local; - stack->frames.local = NULL; - } + 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); - } - mem_put (stack->pool->stack_mem_pool, stack); + while (stack->frames.next) { + FRAME_DESTROY (stack->frames.next); + } + + GF_FREE (stack->groups_large); - if (local) - GF_FREE (local); + 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 = mem_get0 (frame->root->pool->frame_mem_pool); \ + _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->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++; \ + 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; \ - fn (_new, obj, params); \ + if (frame->this->ctx->measure_latency) \ + gf_latency_begin (_new, fn); \ + fn (_new, obj, params); \ THIS = old_THIS; \ - } while (0) + } 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 (frame, obj, params); \ + THIS = old_THIS; \ + } 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 = mem_get0 (frame->root->pool->frame_mem_pool); \ + _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->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; \ + 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"); \ @@ -257,20 +333,27 @@ STACK_DESTROY (call_stack_t *stack) } \ 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) { \ @@ -279,88 +362,101 @@ STACK_DESTROY (call_stack_t *stack) } \ 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 int +call_stack_alloc_groups (call_stack_t *stack, int ngrps) +{ + 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; + } + stack->ngrps = ngrps; + + return 0; +} static inline call_frame_t * copy_frame (call_frame_t *frame) { - call_stack_t *newstack = NULL; - call_stack_t *oldstack = NULL; + call_stack_t *newstack = NULL; + call_stack_t *oldstack = NULL; - if (!frame) { - return NULL; - } + if (!frame) { + return NULL; + } - newstack = mem_get0 (frame->root->pool->stack_mem_pool); + newstack = mem_get0 (frame->root->pool->stack_mem_pool); if (newstack == NULL) { return NULL; } - oldstack = frame->root; + oldstack = frame->root; - newstack->uid = oldstack->uid; - newstack->gid = oldstack->gid; - newstack->pid = oldstack->pid; + newstack->uid = oldstack->uid; + newstack->gid = oldstack->gid; + newstack->pid = oldstack->pid; newstack->ngrps = oldstack->ngrps; - memcpy (newstack->groups, oldstack->groups, - sizeof (uint32_t) * GF_REQUEST_MAXGROUPS); - newstack->unique = oldstack->unique; - - newstack->frames.this = frame->this; - newstack->frames.root = newstack; - newstack->pool = oldstack->pool; - newstack->lk_owner = oldstack->lk_owner; - - LOCK_INIT (&newstack->frames.lock); - - LOCK (&oldstack->pool->lock); - { - list_add (&newstack->all_frames, &oldstack->all_frames); - newstack->pool->cnt++; - } - UNLOCK (&oldstack->pool->lock); - - return &newstack->frames; -} - - -static inline call_frame_t * -create_frame (xlator_t *xl, call_pool_t *pool) -{ - call_stack_t *stack = NULL; - - if (!xl || !pool) { + newstack->op = oldstack->op; + newstack->type = oldstack->type; + if (call_stack_alloc_groups (newstack, oldstack->ngrps) != 0) { + mem_put (newstack); return NULL; } + memcpy (newstack->groups, oldstack->groups, + sizeof (gid_t) * oldstack->ngrps); + newstack->unique = oldstack->unique; - stack = mem_get0 (pool->stack_mem_pool); - if (!stack) - return NULL; - - stack->pool = pool; - stack->frames.root = stack; - stack->frames.this = xl; + 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 (&pool->lock); - { - list_add (&stack->all_frames, &pool->all_frames); - pool->cnt++; - } - UNLOCK (&pool->lock); + LOCK_INIT (&newstack->frames.lock); + LOCK_INIT (&newstack->stack_lock); - LOCK_INIT (&stack->frames.lock); + LOCK (&oldstack->pool->lock); + { + list_add (&newstack->all_frames, &oldstack->all_frames); + newstack->pool->cnt++; + } + UNLOCK (&oldstack->pool->lock); - return &stack->frames; + return &newstack->frames; } -void -gf_proc_dump_pending_frames(call_pool_t *call_pool); - +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 d3e1272c5..8175faba4 100644 --- a/libglusterfs/src/statedump.c +++ b/libglusterfs/src/statedump.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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> @@ -23,16 +14,23 @@ #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) \ +#define GF_PROC_DUMP_IS_OPTION_ENABLED(opt) \ (dump_options.dump_##opt == _gf_true) -#define GF_PROC_DUMP_IS_XL_OPTION_ENABLED(opt)\ +#define GF_PROC_DUMP_IS_XL_OPTION_ENABLED(opt) \ (dump_options.xl_options.dump_##opt == _gf_true) extern xlator_t global_xlator; @@ -45,35 +43,29 @@ gf_dump_options_t dump_options; static void gf_proc_dump_lock (void) { - pthread_mutex_lock (&gf_proc_dump_mutex); + pthread_mutex_lock (&gf_proc_dump_mutex); } 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) + 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) { @@ -81,16 +73,54 @@ gf_proc_dump_close (void) gf_dump_fd = -1; } +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; -void + 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; - GF_ASSERT(key); + GF_ASSERT(key); memset (buf, 0, sizeof(buf)); snprintf (buf, GF_DUMP_MAX_BUF_LEN, "\n["); @@ -100,20 +130,19 @@ gf_proc_dump_add_section (char *key, ...) va_end (ap); snprintf (buf + strlen(buf), GF_DUMP_MAX_BUF_LEN - strlen (buf), "]\n"); - ret = write (gf_dump_fd, buf, strlen (buf)); + return write (gf_dump_fd, buf, strlen (buf)); } -void +int gf_proc_dump_write (char *key, char *value,...) { char buf[GF_DUMP_MAX_BUF_LEN]; int offset = 0; - va_list ap; - int ret; + va_list ap; - GF_ASSERT (key); + GF_ASSERT (key); offset = strlen (key); @@ -127,14 +156,12 @@ gf_proc_dump_write (char *key, char *value,...) offset = strlen (buf); snprintf (buf + offset, GF_DUMP_MAX_BUF_LEN - offset, "\n"); - ret = write (gf_dump_fd, buf, strlen (buf)); + return write (gf_dump_fd, buf, strlen (buf)); } static void gf_proc_dump_xlator_mem_info (xlator_t *xl) { - char key[GF_DUMP_MAX_BUF_LEN]; - char prefix[GF_DUMP_MAX_BUF_LEN]; int i = 0; struct mem_acct rec = {0,}; @@ -144,26 +171,61 @@ gf_proc_dump_xlator_mem_info (xlator_t *xl) if (!xl->mem_acct.rec) return; - gf_proc_dump_add_section ("%s.%s - Memory usage", xl->type,xl->name); + 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", xl->type, - xl->name,i); - gf_proc_dump_build_key (prefix, "memusage", "%s.%s.type.%d", - xl->type, xl->name, i); - gf_proc_dump_build_key (key, prefix, "size"); - gf_proc_dump_write (key, "%u", xl->mem_acct.rec[i].size); - gf_proc_dump_build_key (key, prefix, "num_allocs"); - gf_proc_dump_write (key, "%u", xl->mem_acct.rec[i].num_allocs); - gf_proc_dump_build_key (key, prefix, "max_size"); - gf_proc_dump_write (key, "%u", xl->mem_acct.rec[i].max_size); - gf_proc_dump_build_key (key, prefix, "max_num_allocs"); - gf_proc_dump_write (key, "%u", xl->mem_acct.rec[i].max_num_allocs); + 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; @@ -197,124 +259,242 @@ gf_proc_dump_mem_info () } -void gf_proc_dump_latency_info (xlator_t *xl); +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_xlator_info (xlator_t *this_xl) +gf_proc_dump_mempool_info_to_dict (glusterfs_ctx_t *ctx, dict_t *dict) { - glusterfs_ctx_t *ctx = NULL; - xlator_t *fuse_xlator, *this_xlator; - - if (!this_xl) + struct mem_pool *pool = NULL; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + int count = 0; + int ret = -1; + + if (!ctx || !dict) return; - - ctx = glusterfs_ctx_get (); - if (!ctx) - return; - if (ctx->master){ + 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); - fuse_xlator = (xlator_t *) ctx->master; + return; +} - if (!fuse_xlator->dumpops) - return; +void gf_proc_dump_latency_info (xlator_t *xl); - if (fuse_xlator->dumpops->priv && - GF_PROC_DUMP_IS_XL_OPTION_ENABLED (priv)) - fuse_xlator->dumpops->priv (fuse_xlator); - - if (fuse_xlator->dumpops->inode && - GF_PROC_DUMP_IS_XL_OPTION_ENABLED (inode)) { - - if (!ctx->active) - return; - this_xlator = (xlator_t *) ctx->active->top; - - if (this_xlator && this_xlator->itable) - inode_table_dump (this_xlator->itable, - "xlator.mount.fuse.itable"); - else - return; - } - - if (fuse_xlator->dumpops->fd && - GF_PROC_DUMP_IS_XL_OPTION_ENABLED (fd)) - fuse_xlator->dumpops->fd (fuse_xlator); - } - +void +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; - while (this_xl) { - - if (ctx->measure_latency) - gf_proc_dump_latency_info (this_xl); + trav = top; + while (trav) { - gf_proc_dump_xlator_mem_info(this_xl); + 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 (!this_xl->dumpops) { - this_xl = this_xl->next; + if (!trav->dumpops) { + trav = trav->next; continue; } - if (this_xl->dumpops->priv && + if (trav->dumpops->priv && GF_PROC_DUMP_IS_XL_OPTION_ENABLED (priv)) - this_xl->dumpops->priv (this_xl); - - if (this_xl->dumpops->inode && - GF_PROC_DUMP_IS_XL_OPTION_ENABLED (inode)) - this_xl->dumpops->inode (this_xl); - - - if (this_xl->dumpops->fd && + 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)) - this_xl->dumpops->fd (this_xl); - - this_xl = this_xl->next; + 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 int -gf_proc_dump_parse_set_option (char *key, char *value) + +static void +gf_proc_dump_oldgraph_xlator_info (xlator_t *top) { - gf_boolean_t *opt_key = NULL; - gf_boolean_t opt_value = _gf_false; - char buf[GF_DUMP_MAX_BUF_LEN]; + xlator_t *trav = NULL; - if (!strncasecmp (key, "mem", 3)) { - opt_key = &dump_options.dump_mem; - } else if (!strncasecmp (key, "iobuf", 5)) { - opt_key = &dump_options.dump_iobuf; - } else if (!strncasecmp (key, "callpool", 8)) { - opt_key = &dump_options.dump_callpool; - } else if (!strncasecmp (key, "priv", 4)) { - opt_key = &dump_options.xl_options.dump_priv; - } else if (!strncasecmp (key, "fd", 2)) { - opt_key = &dump_options.xl_options.dump_fd; - } else if (!strncasecmp (key, "inode", 5)) { - opt_key = &dump_options.xl_options.dump_inode; - } else if (!strncasecmp (key, "inodectx", strlen ("inodectx"))) { - opt_key = &dump_options.xl_options.dump_inodectx; - } else if (!strncasecmp (key, "fdctx", strlen ("fdctx"))) { - opt_key = &dump_options.xl_options.dump_fdctx; - } + if (!top) + return; - 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); - write (gf_dump_fd, buf, strlen (buf)); + trav = top; + while (trav) { + gf_proc_dump_xlator_mem_info_only_in_use (trav); - return -1; - } + 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 + */ + } - opt_value = (strncasecmp (value, "yes", 3) ? - _gf_false: _gf_true); + if (!trav->dumpops) { + trav = trav->next; + continue; + } - GF_PROC_DUMP_SET_OPTION (*opt_key, opt_value); + if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED (inode) && + (trav->dumpops->inode)) + trav->dumpops->inode (trav); - return 0; -} + 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 () @@ -329,6 +509,46 @@ gf_proc_dump_enable_all_options () 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; } @@ -342,40 +562,113 @@ gf_proc_dump_disable_all_options () 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_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 dumpbuf[GF_DUMP_MAX_BUF_LEN]; char *key = NULL, *value = NULL; char *saveptr = NULL; - - - fp = fopen (GF_DUMP_OPTIONFILE, "r"); - + 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) { - //ENOENT, return success - (void) gf_proc_dump_enable_all_options (); - return 0; + 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); @@ -389,49 +682,128 @@ gf_proc_dump_options_init () continue; } - snprintf (dumpbuf, sizeof (dumpbuf), "[Debug]:key=%s, value=%s\n",key,value); - write (gf_dump_fd, dumpbuf, strlen (dumpbuf)); - 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) +gf_proc_dump_info (int signum, glusterfs_ctx_t *ctx) { - int ret = -1; - glusterfs_ctx_t *ctx = NULL; + 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 (); - ret = gf_proc_dump_open (); - if (ret < 0) + + 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; - if (GF_PROC_DUMP_IS_OPTION_ENABLED (mem)) + 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); - ctx = glusterfs_ctx_get (); - - if (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); - gf_proc_dump_xlator_info (ctx->active->top); + 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); } - gf_proc_dump_close (); + snprintf (sign_string, sizeof (sign_string), "\nDUMP-END-TIME: %s", + timestr); + ret = write (gf_dump_fd, sign_string, strlen (sign_string)); + out: + 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; @@ -441,23 +813,21 @@ out: 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 5e106d897..8342b120a 100644 --- a/libglusterfs/src/statedump.h +++ b/libglusterfs/src/statedump.h @@ -1,42 +1,29 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 - -#define GF_DUMP_OPTIONFILE "/tmp/glusterdump.input" - 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_ { @@ -44,6 +31,7 @@ typedef struct gf_dump_options_ { 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; @@ -58,43 +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 -void -gf_proc_dump_init(); +#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_fini(void); +int gf_proc_dump_write(char *key, char *value,...); -void -gf_proc_dump_cleanup(void); +void inode_table_dump(inode_table_t *itable, char *prefix); -void -gf_proc_dump_info(int signum); +void inode_table_dump_to_dict (inode_table_t *itable, char *prefix, dict_t *dict); -void -gf_proc_dump_add_section(char *key,...); +void fdtable_dump(fdtable_t *fdtable, char *prefix); -void -gf_proc_dump_write(char *key, char *value,...); +void fdtable_dump_to_dict (fdtable_t *fdtable, char *prefix, dict_t *dict); -void -inode_table_dump(inode_table_t *itable, char *prefix); +void inode_dump(inode_t *inode, char *prefix); -void -fdtable_dump(fdtable_t *fdtable, char *prefix); +void gf_proc_dump_mem_info_to_dict (dict_t *dict); -void -inode_dump(inode_t *inode, char *prefix); +void gf_proc_dump_mempool_info_to_dict (glusterfs_ctx_t *ctx, dict_t *dict); -void -glusterd_init (int sig); +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 index 6b46a14d3..c1620bb70 100644 --- a/libglusterfs/src/syncop.c +++ b/libglusterfs/src/syncop.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + 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 @@ -24,57 +15,250 @@ #include "syncop.h" -call_frame_t * -syncop_create_frame () +int +syncopctx_setfsuid (void *uid) { - struct synctask *task = NULL; - struct call_frame_t *frame = NULL; - - task = synctask_get (); + 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; +} - if (task) { - frame = task->opaque; - } +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; +} - return (call_frame_t *)frame; +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; } -void -synctask_yield (struct synctask *task) +static void +__run (struct synctask *task) { - struct syncenv *env = NULL; + struct syncenv *env = NULL; env = task->env; - if (swapcontext (&task->ctx, &env->sched) < 0) { - gf_log ("syncop", GF_LOG_ERROR, - "swapcontext failed (%s)", strerror (errno)); + 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; } -void -synctask_yawn (struct synctask *task) +static void +__wait (struct synctask *task) { - struct syncenv *env = NULL; + struct syncenv *env = NULL; - env = task->env; + env = task->env; - pthread_mutex_lock (&env->mutex); - { - list_del_init (&task->all_tasks); - list_add (&task->all_tasks, &env->waitq); + 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; } - pthread_mutex_unlock (&env->mutex); + + list_add_tail (&task->all_tasks, &env->waitq); + env->waitcount++; + task->state = SYNCTASK_WAIT; } void -synctask_zzzz (struct synctask *task) +synctask_yield (struct synctask *task) { - synctask_yawn (task); + xlator_t *oldTHIS = THIS; - synctask_yield (task); +#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; } @@ -87,28 +271,30 @@ synctask_wake (struct synctask *task) pthread_mutex_lock (&env->mutex); { - list_del_init (&task->all_tasks); - list_add_tail (&task->all_tasks, &env->runq); + task->woken = 1; + + if (task->slept) + __run (task); + + pthread_cond_broadcast (&env->cond); } pthread_mutex_unlock (&env->mutex); - - pthread_cond_broadcast (&env->cond); } - void -synctask_wrap (struct synctask *task) +synctask_wrap (struct synctask *old_task) { - int ret; + struct synctask *task = NULL; - ret = task->syncfn (task->opaque); - task->synccbk (ret, task->opaque); + /* Do not trust the pointer received. It may be + wrong and can lead to crashes. */ - /* cannot destroy @task right here as we are - in the execution stack of @task itself - */ - task->complete = 1; - synctask_wake (task); + 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); } @@ -120,29 +306,88 @@ synctask_destroy (struct synctask *task) if (!task) return; - if (task->stack) - FREE (task->stack); + 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_new (struct syncenv *env, synctask_fn_t fn, synctask_cbk_t cbk, - void *opaque) +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 -ENOMEM; + 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->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, @@ -161,35 +406,114 @@ synctask_new (struct syncenv *env, synctask_fn_t fn, synctask_cbk_t cbk, newtask->ctx.uc_stack.ss_sp = newtask->stack; newtask->ctx.uc_stack.ss_size = env->stacksize; - makecontext (&newtask->ctx, (void *) synctask_wrap, 2, newtask); + 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 0; + return newtask; err: if (newtask) { - if (newtask->stack) - FREE (newtask->stack); + FREE (newtask->stack); + if (newtask->opframe) + STACK_DESTROY (newtask->opframe->root); FREE (newtask); } - return -1; + + 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 syncenv *env) +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)) - pthread_cond_wait (&env->cond, &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; @@ -206,30 +530,51 @@ synctask_switchto (struct synctask *task) synctask_set (task); THIS = task->xl; - if (swapcontext (&env->sched, &task->ctx) < 0) { +#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; - env = thdata; + proc = thdata; + env = proc->env; for (;;) { - task = syncenv_task (env); - - if (task->complete) { - synctask_destroy (task); - continue; - } + task = syncenv_task (proc); + if (!task) + break; synctask_switchto (task); + + syncenv_scale (env); } return NULL; @@ -237,6 +582,45 @@ syncenv_processor (void *thdata) 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) { @@ -244,10 +628,19 @@ syncenv_destroy (struct syncenv *env) struct syncenv * -syncenv_new (size_t stacksize) +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)); @@ -263,9 +656,17 @@ syncenv_new (size_t stacksize) newenv->stacksize = SYNCENV_DEFAULT_STACKSIZE; if (stacksize) newenv->stacksize = stacksize; - - ret = pthread_create (&newenv->processor, NULL, - syncenv_processor, newenv); + 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); @@ -274,13 +675,275 @@ syncenv_new (size_t stacksize) } +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 *xattr, struct iatt *parent) + struct iatt *iatt, dict_t *xdata, struct iatt *parent) { struct syncargs *args = NULL; @@ -291,8 +954,9 @@ syncop_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (op_ret == 0) { args->iatt1 = *iatt; - args->xattr = xattr; args->iatt2 = *parent; + if (xdata) + args->xdata = dict_ref (xdata); } __wake (args); @@ -302,20 +966,22 @@ syncop_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int -syncop_lookup (xlator_t *subvol, loc_t *loc, dict_t *xattr_req, - struct iatt *iatt, dict_t **xattr_rsp, struct iatt *parent) +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, xattr_req); + loc, xdata_req); if (iatt) *iatt = args.iatt1; - if (xattr_rsp) - *xattr_rsp = args.xattr; 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; @@ -331,17 +997,20 @@ entry_copy (gf_dirent_t *source) 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) + 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; @@ -375,18 +1044,79 @@ syncop_readdirp_cbk (call_frame_t *frame, int syncop_readdirp (xlator_t *subvol, - fd_t *fd, - size_t size, - off_t off, + 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); + 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; @@ -399,7 +1129,7 @@ syncop_opendir_cbk (call_frame_t *frame, xlator_t *this, int32_t op_ret, int32_t op_errno, - fd_t *fd) + fd_t *fd, dict_t *xdata) { struct syncargs *args = NULL; @@ -421,17 +1151,100 @@ syncop_opendir (xlator_t *subvol, struct syncargs args = {0, }; SYNCOP (subvol, (&args), syncop_opendir_cbk, subvol->fops->opendir, - loc, fd); + 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) + int op_ret, int op_errno, dict_t *xdata) { struct syncargs *args = NULL; @@ -452,7 +1265,105 @@ 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); + 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; @@ -460,8 +1371,8 @@ syncop_setxattr (xlator_t *subvol, loc_t *loc, dict_t *dict, int32_t flags) int syncop_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, - struct statvfs *buf) + int32_t op_ret, int32_t op_errno, + struct statvfs *buf, dict_t *xdata) { struct syncargs *args = NULL; @@ -488,7 +1399,7 @@ 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); + loc, NULL); if (buf) *buf = args.statvfs_buf; @@ -500,7 +1411,7 @@ syncop_statfs (xlator_t *subvol, loc_t *loc, struct statvfs *buf) 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) + struct iatt *preop, struct iatt *postop, dict_t *xdata) { struct syncargs *args = NULL; @@ -527,7 +1438,26 @@ syncop_setattr (xlator_t *subvol, loc_t *loc, struct iatt *iatt, int valid, struct syncargs args = {0, }; SYNCOP (subvol, (&args), syncop_setattr_cbk, subvol->fops->setattr, - loc, iatt, valid); + 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; @@ -538,3 +1468,770 @@ syncop_setattr (xlator_t *subvol, loc_t *loc, struct iatt *iatt, int valid, 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 index 12d97010a..f790981f0 100644 --- a/libglusterfs/src/syncop.h +++ b/libglusterfs/src/syncop.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 _SYNCOP_H @@ -30,46 +21,112 @@ #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, void *opaque); +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 complete; + 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 */ }; -/* hosts the scheduler thread and framework for executing synctasks */ -struct syncenv { + +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; - ucontext_t sched; 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; @@ -78,104 +135,278 @@ struct syncargs { 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; - char complete; pthread_cond_t cond; - struct synctask *task; + 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 { \ - struct synctask *task = NULL; \ - \ - task = synctask_get (); \ - if (task) { \ - args->task = task; \ - synctask_yawn (task); \ - } else { \ - pthread_mutex_init (&args->mutex, NULL); \ - pthread_cond_init (&args->cond, NULL); \ - } \ -} while (0) - - -#define __yield(args) do { \ - if (args->task) { \ - synctask_yield (args->task); \ - } else { \ - pthread_mutex_lock (&args->mutex); \ - { \ - while (!args->complete) \ - 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 __wake(args) do { \ - if (args->task) { \ - synctask_wake (args->task); \ - } else { \ - pthread_mutex_lock (&args->mutex); \ - { \ - args->complete = 1; \ - pthread_cond_broadcast (&args->cond); \ - } \ - pthread_mutex_unlock (&args->mutex); \ - } \ -} while (0) +#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 { \ - call_frame_t *frame = NULL; \ + 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); \ \ - frame = syncop_create_frame (); \ + STACK_WIND_COOKIE (frame, cbk, (void *)stb, subvol, \ + op, params); \ \ - __yawn (stb); \ - STACK_WIND_COOKIE (frame, cbk, (void *)stb, subvol, op, params);\ - __yield (stb); \ -} while (0) + __yield (stb); \ + if (task) \ + STACK_RESET (frame->root); \ + else \ + STACK_DESTROY (frame->root); \ + } while (0) -#define SYNCENV_DEFAULT_STACKSIZE (16 * 1024) +#define SYNCENV_DEFAULT_STACKSIZE (2 * 1024 * 1024) -struct syncenv * syncenv_new (); +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, void *); -void synctask_zzzz (struct synctask *task); -void synctask_yawn (struct synctask *task); +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_opendir (xlator_t *subvol, - loc_t *loc, - fd_t *fd); +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_statfs (xlator_t *subvol, loc_t *loc, struct statvfs *buf); +int syncop_fsetattr (xlator_t *subvol, fd_t *fd, struct iatt *iatt, int valid, + /* out */ + struct iatt *preop, struct iatt *postop); -int -syncop_setxattr (xlator_t *subvol, loc_t *loc, dict_t *dict, int32_t flags); +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 c0855f1d1..e8954cc23 100644 --- a/libglusterfs/src/syscall.c +++ b/libglusterfs/src/syscall.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 @@ -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 de1044cdb..f1c9f58c3 100644 --- a/libglusterfs/src/syscall.h +++ b/libglusterfs/src/syscall.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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__ @@ -140,9 +131,14 @@ int sys_lremovexattr (const char *path, const char *name); int +sys_fremovexattr (int filedes, const char *name); + +int sys_access (const char *pathname, int mode); 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 b926644ff..a059cc212 100644 --- a/libglusterfs/src/timer.c +++ b/libglusterfs/src/timer.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 @@ -26,42 +17,38 @@ #include "logging.h" #include "common-utils.h" #include "globals.h" - -#define TS(tv) ((((unsigned long long) tv.tv_sec) * 1000000) + (tv.tv_usec)) +#include "timespec.h" gf_timer_t * gf_timer_call_after (glusterfs_ctx_t *ctx, - struct timeval delta, + 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 = 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->callbk = callbk; event->data = data; @@ -89,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; @@ -108,13 +95,13 @@ 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"); @@ -137,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"); @@ -151,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); @@ -179,7 +167,7 @@ gf_timer_proc (void *ctx) else break; } - usleep (1000000); + nanosleep (&sleepts, NULL); } pthread_mutex_lock (®->lock); @@ -203,7 +191,7 @@ gf_timer_registry_t * gf_timer_registry_init (glusterfs_ctx_t *ctx) { if (ctx == NULL) { - gf_log ("timer", GF_LOG_ERROR, "invalid argument"); + gf_log_callingfn ("timer", GF_LOG_ERROR, "invalid argument"); return NULL; } @@ -222,7 +210,7 @@ gf_timer_registry_init (glusterfs_ctx_t *ctx) reg->stale.prev = ®->stale; ctx->timer = reg; - pthread_create (®->th, NULL, gf_timer_proc, ctx); + 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 4598029dc..2f963adbf 100644 --- a/libglusterfs/src/timer.h +++ b/libglusterfs/src/timer.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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 @@ -33,19 +24,19 @@ typedef void (*gf_timer_cbk_t) (void *); struct _gf_timer { - struct _gf_timer *next, *prev; - struct timeval at; - gf_timer_cbk_t callbk; - void *data; - xlator_t *xl; + 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; @@ -53,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/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 d5883f316..a277c58a8 100644 --- a/libglusterfs/src/xlator.c +++ b/libglusterfs/src/xlator.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,774 +19,264 @@ #include <fnmatch.h> #include "defaults.h" - #define SET_DEFAULT_FOP(fn) do { \ - if (!xl->fops->fn) \ - xl->fops->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; - } - - 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 (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); + 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 (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_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 i = 0; - char ret = 1; - if ((length > 75) || (length == 1)) { - ret = 0; - goto out; - } +int +xlator_set_type_virtual (xlator_t *xl, const char *type) +{ + GF_VALIDATE_OR_GOTO ("xlator", xl, out); + GF_VALIDATE_OR_GOTO ("xlator", type, out); - if (!isalnum (address[length - 1])) { - ret = 0; - goto out; - } + xl->type = gf_strdup (type); - 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 octets = 0; - int value = 0; - char *tmp = NULL, *ptr = NULL, *prev = NULL, *endptr = NULL; - char ret = 1; - - tmp = gf_strdup (address); - prev = tmp; - 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); - } - if (octets != 4) { - ret = 0; - } +int +xlator_volopt_dynload (char *xlator_type, void **dl_handle, + volume_opt_list_t *opt_list) +{ + int ret = -1; + char *name = NULL; + void *handle = NULL; -out: - GF_FREE (tmp); - return ret; -} + GF_VALIDATE_OR_GOTO ("xlator", xlator_type, out); -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 = gf_strdup (address); - prev = strtok_r (tmp, ":", &ptr); - - while (prev != NULL) - { - hex_numbers++; - 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) { - ret = 0; + ret = gf_asprintf (&name, "%s/%s.so", XLATORDIR, xlator_type); + if (-1 == ret) { + gf_log ("xlator", GF_LOG_ERROR, "asprintf failed"); + goto out; } -out: - GF_FREE (tmp); - return ret; -} + ret = -1; -static char -valid_internet_address (char *address) -{ - char ret = 0; - int length = 0; + gf_log ("xlator", GF_LOG_TRACE, "attempt to load file %s", name); - if (address == NULL) { + handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL); + if (!handle) { + gf_log ("xlator", GF_LOG_WARNING, "%s", dlerror ()); goto out; } - length = strlen (address); - if (length == 0) { + if (!(opt_list->given_opt = dlsym (handle, "options"))) { + dlerror (); + gf_log ("xlator", GF_LOG_ERROR, + "Failed to load xlator opt table"); goto out; } - if (valid_ipv4_address (address, length) - || valid_ipv6_address (address, length) - || valid_host_name (address, length)) { - ret = 1; - } - -out: - return ret; -} - -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; - 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_WARNING, - "'%"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; - goto out; - } - - for (i = 0; (i < ZR_OPTION_MAX_ARRAY_SIZE) && - opt->value[i]; i++) { - if (fnmatch (opt->value[i], pair->value->data, - FNM_EXTMATCH) == 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; - } + *dl_handle = handle; - } - 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; - } else { - gf_log (xl->name, GF_LOG_ERROR, "internet address '%s'" - " does not conform to standards.", - pair->value->data); - goto out; - } - } - 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 = gf_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; + ret = 0; out: - return ret; -} - -int32_t -xlator_set_type_virtual (xlator_t *xl, const char *type) -{ - if (xl == NULL || type == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return -1; - } + GF_FREE (name); - xl->type = gf_strdup (type); + gf_log ("xlator", GF_LOG_DEBUG, "Returning %d", ret); + return ret; - if (xl->type) - return 0; - else - return -1; } -int32_t +int xlator_dynload (xlator_t *xl) { - int ret = 0; - char *name = NULL; - void *handle = NULL; - volume_opt_list_t *vol_opt = NULL; + int ret = -1; + char *name = NULL; + void *handle = NULL; + volume_opt_list_t *vol_opt = NULL; + class_methods_t *vtbl = NULL; + + GF_VALIDATE_OR_GOTO ("xlator", xl, out); - ret = gf_asprintf (&name, "%s/%s.so", XLATORDIR, xl->type); + 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"); - return -1; + goto out; } - gf_log ("xlator", GF_LOG_TRACE, "attempt to load file %s", name); + ret = -1; - handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL); - if (!handle) { - gf_log ("xlator", GF_LOG_DEBUG, "%s", dlerror ()); - GF_FREE (name); - return -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 (!(xl->fops = dlsym (handle, "fops"))) { - gf_log ("xlator", GF_LOG_DEBUG, "dlsym(fops) on %s", - dlerror ()); - GF_FREE (name); - return -1; - } + if (!(xl->fops = dlsym (handle, "fops"))) { + gf_log ("xlator", GF_LOG_WARNING, "dlsym(fops) on %s", + dlerror ()); + goto out; + } - if (!(xl->cbks = dlsym (handle, "cbks"))) { - gf_log ("xlator", GF_LOG_DEBUG, "dlsym(cbks) on %s", - dlerror ()); - GF_FREE (name); - return -1; - } + if (!(xl->cbks = dlsym (handle, "cbks"))) { + gf_log ("xlator", GF_LOG_WARNING, "dlsym(cbks) on %s", + dlerror ()); + goto out; + } - if (!(xl->init = dlsym (handle, "init"))) { - gf_log ("xlator", GF_LOG_DEBUG, "dlsym(init) on %s", - dlerror ()); - GF_FREE (name); - return -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; + } - if (!(xl->fini = dlsym (handle, "fini"))) { - gf_log ("xlator", GF_LOG_DEBUG, "dlsym(fini) on %s", - dlerror ()); - GF_FREE (name); - return -1; - } + if (!(*VOID(&(xl->fini)) = dlsym (handle, "fini"))) { + gf_log ("xlator", GF_LOG_WARNING, "dlsym(fini) on %s", + dlerror ()); + goto out; + } + 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 ()); + } - if (!(xl->notify = dlsym (handle, "notify"))) { - gf_log ("xlator", GF_LOG_DEBUG, - "dlsym(notify) on %s -- neglecting", dlerror ()); - } + } - if (!(xl->dumpops = dlsym (handle, "dumpops"))) { - gf_log ("xlator", GF_LOG_DEBUG, - "dlsym(dumpops) on %s -- neglecting", dlerror ()); - } + if (!(xl->dumpops = dlsym (handle, "dumpops"))) { + gf_log ("xlator", GF_LOG_TRACE, + "dlsym(dumpops) on %s -- neglecting", dlerror ()); + } - if (!(xl->mem_acct_init = dlsym (handle, "mem_acct_init"))) { - gf_log (xl->name, GF_LOG_DEBUG, + 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 ()); } - if (!(xl->reconfigure = dlsym (handle, "reconfigure"))) { - gf_log ("xlator", GF_LOG_DEBUG, - "dlsym(reconfigure) on %s -- neglecting", - dlerror()); - } - - if (!(xl->validate_options = dlsym (handle, "validate_options"))) { - gf_log ("xlator", GF_LOG_DEBUG, - "dlsym(validate_options) on %s -- neglecting", - dlerror()); - } - - - INIT_LIST_HEAD (&xl->volume_options); - - vol_opt = GF_CALLOC (1, sizeof (volume_opt_list_t), + vol_opt = GF_CALLOC (1, sizeof (volume_opt_list_t), gf_common_mt_volume_opt_list_t); if (!vol_opt) { - GF_FREE (name); - return -1; + goto out; } - 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); + 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); + + fill_defaults (xl); - fill_defaults (xl); + ret = 0; - GF_FREE (name); - return 0; +out: + GF_FREE (name); + return ret; } -int32_t +int xlator_set_type (xlator_t *xl, const char *type) { int ret = 0; @@ -810,54 +291,77 @@ xlator_set_type (xlator_t *xl, const char *type) void xlator_foreach (xlator_t *this, - void (*fn)(xlator_t *each, - void *data), - void *data) + void (*fn)(xlator_t *each, + void *data), + void *data) { - xlator_t *first = NULL; + xlator_t *first = NULL; + xlator_t *old_THIS = NULL; - if (this == NULL || fn == NULL || data == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return; - } + GF_VALIDATE_OR_GOTO ("xlator", this, out); + GF_VALIDATE_OR_GOTO ("xlator", fn, out); - first = this; + first = this; - while (first->prev) - first = first->prev; + while (first->prev) + first = first->prev; - while (first) { - fn (first, data); - first = first->next; + while (first) { + old_THIS = THIS; + THIS = first; + + fn (first, data); + + THIS = old_THIS; + first = first->next; + } + +out: + return; +} + + +void +xlator_foreach_depth_first (xlator_t *this, + void (*fn)(xlator_t *each, void *data), + void *data) +{ + xlator_list_t *subv = NULL; + + subv = this->children; + + 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 int __xlator_init(xlator_t *xl) { @@ -878,20 +382,15 @@ __xlator_init(xlator_t *xl) int xlator_init (xlator_t *xl) { - int32_t ret = 0; + int32_t ret = -1; - if (xl == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return 0; - } - - ret = -1; + GF_VALIDATE_OR_GOTO ("xlator", xl, out); if (xl->mem_acct_init) xl->mem_acct_init (xl); if (!xl->init) { - gf_log (xl->name, GF_LOG_DEBUG, "No init() found"); + gf_log (xl->name, GF_LOG_WARNING, "No init() found"); goto out; } @@ -909,133 +408,52 @@ xlator_init (xlator_t *xl) ret = 0; out: - return ret; + return ret; } static void xlator_fini_rec (xlator_t *xl) { - xlator_list_t *trav = NULL; - - if (xl == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return; - } - - trav = xl->children; - - while (trav) { - if (!trav->xlator->init_succeeded) { - break; - } - - xlator_fini_rec (trav->xlator); - gf_log (trav->xlator->name, GF_LOG_DEBUG, "fini done"); - trav = trav->next; - } - - if (xl->init_succeeded) { - if (xl->fini) { - xl->fini (xl); - } else { - gf_log (xl->name, GF_LOG_DEBUG, "No fini() found"); - } - xl->init_succeeded = 0; - } -} - -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 = 0; - - if (old_xl == NULL || new_xl == NULL) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return -1; - } + xlator_list_t *trav = NULL; + xlator_t *old_THIS = NULL; - trav1 = old_xl->children; - trav2 = new_xl->children; + GF_VALIDATE_OR_GOTO ("xlator", xl, out); - while (trav1 && trav2) { - ret = xlator_reconfigure_rec (trav1->xlator, trav2->xlator); + trav = xl->children; - if (ret) - goto out; - - gf_log (trav1->xlator->name, GF_LOG_DEBUG, "reconfigured"); - - trav1 = trav1->next; - trav2 = trav2->next; - } + while (trav) { + if (!trav->xlator->init_succeeded) { + break; + } - if (old_xl->reconfigure) { - ret = old_xl->reconfigure (old_xl, new_xl->options); - if (ret) - goto out; + xlator_fini_rec (trav->xlator); + gf_log (trav->xlator->name, GF_LOG_DEBUG, "fini done"); + trav = trav->next; } - else - gf_log (old_xl->name, GF_LOG_DEBUG, "No reconfigure() found"); - -out: - return ret; -} -int -xlator_validate_rec (xlator_t *xlator, char **op_errstr) -{ - xlator_list_t *trav = NULL; - - if (xlator == NULL ) { - gf_log ("xlator", GF_LOG_DEBUG, "invalid argument"); - return -1; - } + if (xl->init_succeeded) { + if (xl->fini) { + old_THIS = THIS; + THIS = xl; - trav = xlator->children; + xl->fini (xl); - while (trav) { - if (xlator_validate_rec (trav->xlator, op_errstr) ) - return -1; + if (xl->local_pool) + mem_pool_destroy (xl->local_pool); - trav = trav->next; - } - - if (xlator_dynload (xlator)) - gf_log ("", GF_LOG_DEBUG, "Did not load the symbols"); - - if (xlator->validate_options) { - if (xlator->validate_options (xlator, xlator->options, - op_errstr)) { - gf_log ("", GF_LOG_DEBUG, *op_errstr); - return -1; + THIS = old_THIS; + } else { + gf_log (xl->name, GF_LOG_DEBUG, "No fini() found"); } - gf_log (xlator->name, GF_LOG_DEBUG, "Validated option"); - + xl->init_succeeded = 0; } - - gf_log (xlator->name, GF_LOG_DEBUG, "No validate_options() found"); - return 0; +out: + return; } -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; -} int xlator_notify (xlator_t *xl, int event, void *data, ...) { @@ -1059,18 +477,17 @@ xlator_mem_acct_init (xlator_t *xl, int num_types) int i = 0; int ret = 0; - if (!gf_mem_acct_is_enabled()) - return 0; - if (!xl) return -1; + if (!xl->ctx->mem_acct_enable) + return 0; + xl->mem_acct.num_types = num_types; - xl->mem_acct.rec = calloc(num_types, sizeof(struct mem_acct_rec)); + xl->mem_acct.rec = CALLOC(num_types, sizeof(struct mem_acct_rec)); if (!xl->mem_acct.rec) { - gf_log("xlator", GF_LOG_ERROR, "Out of Memory"); return -1; } @@ -1081,62 +498,72 @@ xlator_mem_acct_init (xlator_t *xl, int num_types) } } - gf_log(xl->name, GF_LOG_DEBUG, "Allocated mem_acct_rec for %d types", - num_types); - 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_tree_reconfigure (xlator_t *old_xl, xlator_t *new_xl) +xlator_list_destroy (xlator_list_t *list) { - xlator_t *new_top = NULL; - xlator_t *old_top = NULL; - - GF_ASSERT (old_xl); - GF_ASSERT (new_xl); + xlator_list_t *next = NULL; - old_top = old_xl; - new_top = new_xl; + while (list) { + next = list->next; + GF_FREE (list); + list = next; + } - return xlator_reconfigure_rec (old_top, new_top); + 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); - GF_FREE (prev->name); - GF_FREE (prev->type); - GF_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; } @@ -1151,56 +578,126 @@ loc_wipe (loc_t *loc) 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_copy (loc_t *dst, loc_t *src) +loc_path (loc_t *loc, const char *bname) { - int ret = -1; + int ret = 0; - dst->ino = src->ino; + if (loc->path) + goto out; - if (src->inode) - dst->inode = inode_ref (src->inode); + ret = -1; - if (src->parent) - dst->parent = inode_ref (src->parent); + if (bname && !strlen (bname)) + bname = NULL; - dst->path = gf_strdup (src->path); + if (!bname) + goto inode_path; - if (!dst->path) - goto out; + 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); + } - dst->name = strrchr (dst->path, '/'); - if (dst->name) - dst->name++; + if (loc->path) + goto out; - ret = 0; +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; + 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 -xlator_list_destroy (xlator_list_t *list) +loc_copy (loc_t *dst, loc_t *src) { - xlator_list_t *next = NULL; + int ret = -1; - while (list) { - next = list->next; - GF_FREE (list); - list = next; + 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++; } - return 0; + 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) @@ -1211,10 +708,8 @@ xlator_destroy (xlator_t *xl) if (!xl) return 0; - if (xl->name) - GF_FREE (xl->name); - if (xl->type) - GF_FREE (xl->type); + GF_FREE (xl->name); + GF_FREE (xl->type); if (xl->dlhandle) dlclose (xl->dlhandle); if (xl->options) @@ -1233,6 +728,8 @@ xlator_destroy (xlator_t *xl) return 0; } + + int is_gf_log_command (xlator_t *this, const char *name, char *value) { @@ -1276,6 +773,7 @@ is_gf_log_command (xlator_t *this, const char *name, char *value) ret = 0; goto out; } + if (!strcmp (name, "trusted.glusterfs.fuse.set-log-level")) { /* */ gf_log (this->name, gf_log_get_xl_loglevel (this), @@ -1286,7 +784,7 @@ is_gf_log_command (xlator_t *this, const char *name, char *value) goto out; } - ctx = glusterfs_ctx_get(); + ctx = this->ctx; if (!ctx) goto out; if (!ctx->active) @@ -1309,6 +807,7 @@ out: return ret; } + int glusterd_check_log_level (const char *value) { @@ -1331,8 +830,9 @@ glusterd_check_log_level (const char *value) } if (log_level == -1) - gf_log ("", GF_LOG_ERROR, "Invalid log-level. possible values " + 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 e583e8c13..b57e5873e 100644 --- a/libglusterfs/src/xlator.h +++ b/libglusterfs/src/xlator.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2010 Gluster, Inc. <http://www.gluster.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 Affero 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 - Affero General Public License for more details. - - You should have received a copy of the GNU Affero 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,7 +20,7 @@ #include <stdint.h> #include <inttypes.h> - +#include "event-history.h" #include "logging.h" #include "common-utils.h" #include "dict.h" @@ -64,7 +55,7 @@ typedef struct _loc loc_t; typedef int32_t (*event_notify_fn_t) (xlator_t *this, int32_t event, void *data, - ...); + ...); #include "list.h" #include "gf-dirent.h" @@ -74,22 +65,32 @@ typedef int32_t (*event_notify_fn_t) (xlator_t *this, int32_t event, void *data, #include "fd.h" #include "globals.h" #include "iatt.h" +#include "options.h" +#include "client_t.h" + struct _loc { - const char *path; - const char *name; - ino_t ino; - inode_t *inode; - inode_t *parent; + 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 (*fop_getspec_cbk_t) (call_frame_t *frame, - void *cookie, - xlator_t *this, - int32_t op_ret, - int32_t op_errno, - char *spec_data); + 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, @@ -97,301 +98,308 @@ 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); + uint8_t *strong_checksum, + dict_t *xdata); typedef int32_t (*fop_getspec_t) (call_frame_t *frame, - xlator_t *this, - const char *key, - int32_t flag); + 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); + 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 iatt *buf, - dict_t *xattr, + 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 iatt *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 iatt *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 iatt *prebuf, - struct iatt *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 iatt *prebuf, - struct iatt *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_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 iatt *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, + 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); + 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, + 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); + 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, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, struct iatt *preparent, - struct iatt *postparent); + 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, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, struct iatt *preparent, - struct iatt *postparent); + 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, + 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); + 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 iatt *buf, + 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); + 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, + 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); + 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 iatt *buf, + 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); + 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 iatt *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 iatt *prebuf, - struct iatt *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, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf); + 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); + 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 gf_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); + 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); + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + dict_t *xattr, dict_t *xdata); typedef int32_t (*fop_setattr_cbk_t) (call_frame_t *frame, @@ -400,7 +408,7 @@ typedef int32_t (*fop_setattr_cbk_t) (call_frame_t *frame, int32_t op_ret, int32_t op_errno, struct iatt *preop_stbuf, - struct iatt *postop_stbuf); + struct iatt *postop_stbuf, dict_t *xdata); typedef int32_t (*fop_fsetattr_cbk_t) (call_frame_t *frame, void *cookie, @@ -408,72 +416,95 @@ typedef int32_t (*fop_fsetattr_cbk_t) (call_frame_t *frame, int32_t op_ret, int32_t op_errno, struct iatt *preop_stbuf, - struct iatt *postop_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); + 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); + 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); + 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, - dict_t *params); + 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, dict_t *params); +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); +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 flags); + 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, - dict_t *params); + 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, dict_t *params); + 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. @@ -484,243 +515,283 @@ typedef int32_t (*fop_create_t) (call_frame_t *frame, xlator_t *this, */ #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); + 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 gf_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 gf_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 gf_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); + 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); + 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 iatt *stbuf, - int32_t valid); + int32_t valid, dict_t *xdata); typedef int32_t (*fop_fsetattr_t) (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iatt *stbuf, - int32_t valid); + 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_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_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_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; fop_getspec_t getspec; - - /* 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_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_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); @@ -733,82 +804,61 @@ 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_fdctx_t fdctx; + 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() */ + /* 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 */ + 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); + 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); - int32_t (*validate_options) (xlator_t *this, dict_t *options, - char **op_errstr); event_notify_fn_t notify; gf_loglevel_t loglevel; /* Log level for translator */ @@ -816,18 +866,43 @@ struct _xlator { /* for latency measurement */ fop_latency_t latencies[GF_FOP_MAXVALUE]; - /* Misc */ - glusterfs_ctx_t *ctx; - glusterfs_graph_t *graph; /* not set for fuse */ - inode_table_t *itable; - char init_succeeded; - void *private; + /* 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; }; +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) -int validate_xlator_volume_options (xlator_t *xl, volume_option_t *opt); +#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); @@ -836,7 +911,7 @@ 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); @@ -848,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); @@ -859,19 +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); +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 xlator_tree_reconfigure (xlator_t *old_xl, xlator_t *new_xl); int is_gf_log_command (xlator_t *trans, const char *name, char *value); -int xlator_validate_rec (xlator_t *xlator, char **op_errstr); -int graph_reconf_validateopt (glusterfs_graph_t *graph, char **op_errstr); int glusterd_check_log_level (const char *value); - -#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 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 */ |
