diff options
Diffstat (limited to 'libglusterfs')
89 files changed, 13579 insertions, 7652 deletions
diff --git a/libglusterfs/src/Makefile.am b/libglusterfs/src/Makefile.am index 34543f622..907399ae6 100644 --- a/libglusterfs/src/Makefile.am +++ b/libglusterfs/src/Makefile.am @@ -1,11 +1,10 @@ -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@ @@ -16,36 +15,42 @@ 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 \ - $(CONTRIBDIR)/md5/md5.c $(CONTRIBDIR)/rbtree/rb.c rbthash.c latency.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 + 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 + +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 \ +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)/md5/md5.h $(CONTRIBDIR)/rbtree/rb.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 + $(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 y.tab.h: graph.y - $(YACC) -d $(srcdir)/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 e325e522d..4101db2c7 100644 --- a/libglusterfs/src/byte-order.h +++ b/libglusterfs/src/byte-order.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _BYTE_ORDER_H diff --git a/libglusterfs/src/call-stub.c b/libglusterfs/src/call-stub.c index cdae9df25..ac79cf071 100644 --- a/libglusterfs/src/call-stub.c +++ b/libglusterfs/src/call-stub.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -22,9 +13,9 @@ #include "config.h" #endif +#include <openssl/md5.h> #include <inttypes.h> -#include "md5.h" #include "call-stub.h" #include "mem-types.h" @@ -46,16 +37,16 @@ stub_new (call_frame_t *frame, 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; } 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; @@ -65,26 +56,22 @@ fop_lookup_stub (call_frame_t *frame, 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; } 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; @@ -93,27 +80,25 @@ fop_lookup_cbk_stub (call_frame_t *frame, 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; + stub->fn_cbk.lookup = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (inode) - stub->args.lookup_cbk.inode = inode_ref (inode); + stub->args_cbk.inode = inode_ref (inode); if (buf) - stub->args.lookup_cbk.buf = *buf; - if (dict) - stub->args.lookup_cbk.dict = dict_ref (dict); + 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; } - 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; @@ -123,19 +108,19 @@ fop_stat_stub (call_frame_t *frame, 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; } 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; @@ -144,20 +129,21 @@ fop_stat_cbk_stub (call_frame_t *frame, 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; + 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.stat_cbk.buf = *buf; + stub->args_cbk.stat = *buf; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: 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; @@ -166,21 +152,21 @@ fop_fstat_stub (call_frame_t *frame, 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); + stub->args.fd = fd_ref (fd); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: return stub; } call_stub_t * -fop_fstat_cbk_stub (call_frame_t *frame, - fop_fstat_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - struct 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; @@ -189,23 +175,21 @@ fop_fstat_cbk_stub (call_frame_t *frame, 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; + stub->fn_cbk.fstat = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (buf) - stub->args.fstat_cbk.buf = *buf; + stub->args_cbk.stat = *buf; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: 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; @@ -215,21 +199,20 @@ fop_truncate_stub (call_frame_t *frame, 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; } 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; @@ -238,23 +221,23 @@ fop_truncate_cbk_stub (call_frame_t *frame, 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; + stub->fn_cbk.truncate = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (prebuf) - stub->args.truncate_cbk.prebuf = *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; } 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; @@ -263,23 +246,22 @@ fop_ftruncate_stub (call_frame_t *frame, stub = stub_new (frame, 1, GF_FOP_FTRUNCATE); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.ftruncate.fn = fn; + stub->fn.ftruncate = fn; if (fd) - stub->args.ftruncate.fd = fd_ref (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; } 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; @@ -288,23 +270,24 @@ fop_ftruncate_cbk_stub (call_frame_t *frame, stub = stub_new (frame, 0, GF_FOP_FTRUNCATE); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.ftruncate_cbk.fn = fn; - stub->args.ftruncate_cbk.op_ret = op_ret; - stub->args.ftruncate_cbk.op_errno = op_errno; + stub->fn_cbk.ftruncate = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (prebuf) - stub->args.ftruncate_cbk.prebuf = *prebuf; + stub->args_cbk.prestat = *prebuf; if (postbuf) - stub->args.ftruncate_cbk.postbuf = *postbuf; + stub->args_cbk.poststat = *postbuf; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); + out: 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; @@ -314,19 +297,19 @@ fop_access_stub (call_frame_t *frame, 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; } 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; @@ -335,19 +318,19 @@ fop_access_cbk_stub (call_frame_t *frame, 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; } 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; @@ -357,21 +340,20 @@ fop_readlink_stub (call_frame_t *frame, 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; } 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; @@ -380,21 +362,23 @@ fop_readlink_cbk_stub (call_frame_t *frame, 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; + stub->fn_cbk.readlink = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (path) - stub->args.readlink_cbk.buf = gf_strdup (path); - if (sbuf) - stub->args.readlink_cbk.sbuf = *sbuf; + 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; } 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; @@ -404,26 +388,23 @@ fop_mknod_stub (call_frame_t *frame, fop_mknod_t fn, 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; } 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; @@ -432,17 +413,20 @@ fop_mknod_cbk_stub (call_frame_t *frame, 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; + stub->fn_cbk.mknod = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (inode) - stub->args.mknod_cbk.inode = inode_ref (inode); + stub->args_cbk.inode = inode_ref (inode); if (buf) - stub->args.mknod_cbk.buf = *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; } @@ -450,7 +434,7 @@ out: 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; @@ -460,25 +444,23 @@ fop_mkdir_stub (call_frame_t *frame, fop_mkdir_t fn, stub = stub_new (frame, 1, GF_FOP_MKDIR); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.mkdir.fn = fn; - loc_copy (&stub->args.mkdir.loc, loc); - stub->args.mkdir.mode = mode; - if (params) - stub->args.mkdir.params = dict_ref (params); + stub->fn.mkdir = fn; + loc_copy (&stub->args.loc, loc); + stub->args.mode = mode; + stub->args.umask = umask; + + if (xdata) + stub->args.xdata = dict_ref (xdata); out: return stub; } call_stub_t * -fop_mkdir_cbk_stub (call_frame_t *frame, - fop_mkdir_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - inode_t *inode, - struct 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; @@ -487,26 +469,27 @@ fop_mkdir_cbk_stub (call_frame_t *frame, 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; + stub->fn_cbk.mkdir = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (inode) - stub->args.mkdir_cbk.inode = inode_ref (inode); + stub->args_cbk.inode = inode_ref (inode); if (buf) - stub->args.mkdir_cbk.buf = *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; } 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; @@ -516,20 +499,21 @@ fop_unlink_stub (call_frame_t *frame, 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; } 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; @@ -538,13 +522,15 @@ fop_unlink_cbk_stub (call_frame_t *frame, 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; } @@ -553,7 +539,7 @@ out: 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; @@ -563,21 +549,21 @@ fop_rmdir_stub (call_frame_t *frame, fop_rmdir_t fn, 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; } 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; @@ -586,13 +572,15 @@ fop_rmdir_cbk_stub (call_frame_t *frame, 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; } @@ -600,7 +588,7 @@ out: 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; @@ -611,25 +599,23 @@ fop_symlink_stub (call_frame_t *frame, fop_symlink_t fn, 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; } 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; @@ -638,27 +624,27 @@ fop_symlink_cbk_stub (call_frame_t *frame, 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; + stub->fn_cbk.symlink = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (inode) - stub->args.symlink_cbk.inode = inode_ref (inode); + stub->args_cbk.inode = inode_ref (inode); if (buf) - stub->args.symlink_cbk.buf = *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; } 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; @@ -669,24 +655,22 @@ fop_rename_stub (call_frame_t *frame, 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; } 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; @@ -695,29 +679,29 @@ fop_rename_cbk_stub (call_frame_t *frame, 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; + stub->fn_cbk.rename = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (buf) - stub->args.rename_cbk.buf = *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; } 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; @@ -728,24 +712,23 @@ fop_link_stub (call_frame_t *frame, 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; } 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; @@ -754,17 +737,19 @@ fop_link_cbk_stub (call_frame_t *frame, 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; + stub->fn_cbk.link = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (inode) - stub->args.link_cbk.inode = inode_ref (inode); + stub->args_cbk.inode = inode_ref (inode); if (buf) - stub->args.link_cbk.buf = *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; } @@ -773,7 +758,7 @@ out: 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 *stub = NULL; @@ -783,29 +768,26 @@ fop_create_stub (call_frame_t *frame, fop_create_t fn, 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; + 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.create.fd = fd_ref (fd); - if (params) - stub->args.create.params = dict_ref (params); + stub->args.fd = fd_ref (fd); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: return stub; } call_stub_t * -fop_create_cbk_stub (call_frame_t *frame, - fop_create_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - fd_t *fd, - inode_t *inode, - struct 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; @@ -814,30 +796,29 @@ fop_create_cbk_stub (call_frame_t *frame, 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; + stub->fn_cbk.create = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (fd) - stub->args.create_cbk.fd = fd_ref (fd); + stub->args_cbk.fd = fd_ref (fd); if (inode) - stub->args.create_cbk.inode = inode_ref (inode); + stub->args_cbk.inode = inode_ref (inode); if (buf) - stub->args.create_cbk.buf = *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; } 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; @@ -847,24 +828,22 @@ fop_open_stub (call_frame_t *frame, 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; + stub->fn.open = fn; + loc_copy (&stub->args.loc, loc); + stub->args.flags = flags; if (fd) - stub->args.open.fd = fd_ref (fd); + stub->args.fd = fd_ref (fd); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: return stub; } call_stub_t * -fop_open_cbk_stub (call_frame_t *frame, - fop_open_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - fd_t *fd) - +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; @@ -873,22 +852,22 @@ fop_open_cbk_stub (call_frame_t *frame, 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; + stub->fn_cbk.open = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (fd) - stub->args.open_cbk.fd = fd_ref (fd); + stub->args_cbk.fd = fd_ref (fd); + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: return stub; } call_stub_t * -fop_readv_stub (call_frame_t *frame, - fop_readv_t fn, - fd_t *fd, - size_t size, - off_t off, uint32_t flags) +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; @@ -897,28 +876,25 @@ fop_readv_stub (call_frame_t *frame, stub = stub_new (frame, 1, GF_FOP_READ); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.readv.fn = fn; + stub->fn.readv = fn; if (fd) - stub->args.readv.fd = fd_ref (fd); - stub->args.readv.size = size; - stub->args.readv.off = off; - stub->args.readv.flags = flags; + stub->args.fd = fd_ref (fd); + stub->args.size = size; + stub->args.offset = off; + stub->args.flags = flags; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: return stub; } 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; @@ -927,28 +903,26 @@ fop_readv_cbk_stub (call_frame_t *frame, 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; + 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.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->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; } 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, uint32_t flags, - 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; @@ -958,28 +932,25 @@ fop_writev_stub (call_frame_t *frame, stub = stub_new (frame, 1, GF_FOP_WRITE); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.writev.fn = fn; + stub->fn.writev = 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.flags = flags; - stub->args.writev.iobref = iobref_ref (iobref); - + 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; } 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; @@ -988,23 +959,23 @@ fop_writev_cbk_stub (call_frame_t *frame, 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; + 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.writev_cbk.postbuf = *postbuf; + 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; } - 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; @@ -1013,20 +984,19 @@ fop_flush_stub (call_frame_t *frame, stub = stub_new (frame, 1, GF_FOP_FLUSH); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.flush.fn = fn; + stub->fn.flush = fn; if (fd) - stub->args.flush.fd = fd_ref (fd); + stub->args.fd = fd_ref (fd); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: return stub; } call_stub_t * -fop_flush_cbk_stub (call_frame_t *frame, - fop_flush_cbk_t fn, - int32_t op_ret, - int32_t op_errno) - +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; @@ -1035,21 +1005,19 @@ fop_flush_cbk_stub (call_frame_t *frame, 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; } - - 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; @@ -1058,22 +1026,21 @@ fop_fsync_stub (call_frame_t *frame, stub = stub_new (frame, 1, GF_FOP_FSYNC); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.fsync.fn = fn; + stub->fn.fsync = fn; if (fd) - stub->args.fsync.fd = fd_ref (fd); - stub->args.fsync.datasync = datasync; + stub->args.fd = fd_ref (fd); + stub->args.datasync = datasync; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: return stub; } call_stub_t * -fop_fsync_cbk_stub (call_frame_t *frame, - fop_fsync_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - 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; @@ -1082,22 +1049,23 @@ fop_fsync_cbk_stub (call_frame_t *frame, 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; } 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; @@ -1107,22 +1075,21 @@ fop_opendir_stub (call_frame_t *frame, 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); + stub->fn.opendir = fn; + loc_copy (&stub->args.loc, loc); if (fd) - stub->args.opendir.fd = fd_ref (fd); + stub->args.fd = fd_ref (fd); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: return stub; } call_stub_t * -fop_opendir_cbk_stub (call_frame_t *frame, - fop_opendir_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - fd_t *fd) - +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; @@ -1131,22 +1098,22 @@ fop_opendir_cbk_stub (call_frame_t *frame, 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); + stub->args_cbk.fd = fd_ref (fd); + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: 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; @@ -1155,21 +1122,20 @@ fop_fsyncdir_stub (call_frame_t *frame, stub = stub_new (frame, 1, GF_FOP_FSYNCDIR); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.fsyncdir.fn = fn; + stub->fn.fsyncdir = fn; if (fd) - stub->args.fsyncdir.fd = fd_ref (fd); - stub->args.fsyncdir.datasync = datasync; + stub->args.fd = fd_ref (fd); + stub->args.datasync = datasync; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: return stub; } call_stub_t * -fop_fsyncdir_cbk_stub (call_frame_t *frame, - fop_fsyncdir_cbk_t fn, - int32_t op_ret, - int32_t op_errno) - +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; @@ -1178,18 +1144,19 @@ fop_fsyncdir_cbk_stub (call_frame_t *frame, 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; } 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; @@ -1199,20 +1166,19 @@ fop_statfs_stub (call_frame_t *frame, 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; } 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; @@ -1221,22 +1187,22 @@ fop_statfs_cbk_stub (call_frame_t *frame, 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; + 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.statfs_cbk.buf = *buf; + stub->args_cbk.statvfs = *buf; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: return stub; } call_stub_t * -fop_setxattr_stub (call_frame_t *frame, - fop_setxattr_t fn, - loc_t *loc, - dict_t *dict, - int32_t flags) +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; @@ -1246,12 +1212,14 @@ fop_setxattr_stub (call_frame_t *frame, 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); + stub->fn.setxattr = fn; + loc_copy (&stub->args.loc, loc); /* TODO */ if (dict) - stub->args.setxattr.dict = dict_ref (dict); - stub->args.setxattr.flags = flags; + stub->args.xattr = dict_ref (dict); + stub->args.flags = flags; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: return stub; } @@ -1261,7 +1229,7 @@ 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 *stub = NULL; @@ -1270,18 +1238,19 @@ fop_setxattr_cbk_stub (call_frame_t *frame, 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; } + 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; @@ -1291,22 +1260,22 @@ fop_getxattr_stub (call_frame_t *frame, 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); + stub->args.name = gf_strdup (name); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: return stub; } call_stub_t * -fop_getxattr_cbk_stub (call_frame_t *frame, - fop_getxattr_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - dict_t *dict) +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; @@ -1315,23 +1284,22 @@ fop_getxattr_cbk_stub (call_frame_t *frame, 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; + stub->fn_cbk.getxattr = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; /* TODO */ if (dict) - stub->args.getxattr_cbk.dict = dict_ref (dict); + stub->args_cbk.xattr = dict_ref (dict); + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: 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; @@ -1341,23 +1309,22 @@ fop_fsetxattr_stub (call_frame_t *frame, 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; + stub->args.xattr = dict_ref (dict); + stub->args.flags = flags; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: 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; @@ -1366,19 +1333,19 @@ fop_fsetxattr_cbk_stub (call_frame_t *frame, 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; } 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; @@ -1388,22 +1355,22 @@ fop_fgetxattr_stub (call_frame_t *frame, 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); + stub->args.name = gf_strdup (name); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: 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; @@ -1412,23 +1379,22 @@ fop_fgetxattr_cbk_stub (call_frame_t *frame, 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); + stub->args_cbk.xattr = dict_ref (dict); + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: 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; @@ -1439,19 +1405,19 @@ fop_removexattr_stub (call_frame_t *frame, 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; } 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; @@ -1460,18 +1426,19 @@ fop_removexattr_cbk_stub (call_frame_t *frame, 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; } + call_stub_t * -fop_fremovexattr_stub (call_frame_t *frame, - fop_fremovexattr_t fn, - fd_t *fd, - const char *name) +fop_fremovexattr_stub (call_frame_t *frame, fop_fremovexattr_t fn, + fd_t *fd, const char *name, dict_t *xdata) { call_stub_t *stub = NULL; @@ -1482,19 +1449,19 @@ fop_fremovexattr_stub (call_frame_t *frame, stub = stub_new (frame, 1, GF_FOP_FREMOVEXATTR); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.fremovexattr.fn = fn; - stub->args.fremovexattr.fd = fd_ref (fd); - stub->args.fremovexattr.name = gf_strdup (name); + stub->fn.fremovexattr = fn; + stub->args.fd = fd_ref (fd); + stub->args.name = gf_strdup (name); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: return stub; } call_stub_t * -fop_fremovexattr_cbk_stub (call_frame_t *frame, - fop_fremovexattr_cbk_t fn, - int32_t op_ret, - int32_t op_errno) +fop_fremovexattr_cbk_stub (call_frame_t *frame, fop_fremovexattr_cbk_t fn, + int32_t op_ret, int32_t op_errno, dict_t *xdata) { call_stub_t *stub = NULL; @@ -1503,19 +1470,20 @@ fop_fremovexattr_cbk_stub (call_frame_t *frame, stub = stub_new (frame, 0, GF_FOP_FREMOVEXATTR); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.fremovexattr_cbk.fn = fn; - stub->args.fremovexattr_cbk.op_ret = op_ret; - stub->args.fremovexattr_cbk.op_errno = op_errno; + stub->fn_cbk.fremovexattr = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: return stub; } + 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_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; @@ -1525,23 +1493,22 @@ fop_lk_stub (call_frame_t *frame, stub = stub_new (frame, 1, GF_FOP_LK); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.lk.fn = fn; + stub->fn.lk = fn; if (fd) - stub->args.lk.fd = fd_ref (fd); - stub->args.lk.cmd = cmd; - stub->args.lk.lock = *lock; + 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; } 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_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; @@ -1550,18 +1517,22 @@ fop_lk_cbk_stub (call_frame_t *frame, stub = stub_new (frame, 0, GF_FOP_LK); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.lk_cbk.fn = fn; - stub->args.lk_cbk.op_ret = op_ret; - stub->args.lk_cbk.op_errno = op_errno; + 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.lk_cbk.lock = *lock; + stub->args_cbk.lock = *lock; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: 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) + const char *volume, loc_t *loc, int32_t cmd, + struct gf_flock *lock, dict_t *xdata) { call_stub_t *stub = NULL; @@ -1571,21 +1542,24 @@ fop_inodelk_stub (call_frame_t *frame, fop_inodelk_t fn, stub = stub_new (frame, 1, GF_FOP_INODELK); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.inodelk.fn = fn; + stub->fn.inodelk = fn; if (volume) - stub->args.inodelk.volume = gf_strdup (volume); + stub->args.volume = gf_strdup (volume); - loc_copy (&stub->args.inodelk.loc, loc); - stub->args.inodelk.cmd = cmd; - stub->args.inodelk.lock = *lock; + 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; @@ -1594,10 +1568,12 @@ fop_inodelk_cbk_stub (call_frame_t *frame, fop_inodelk_cbk_t fn, 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; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: return stub; } @@ -1605,7 +1581,8 @@ out: 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; @@ -1615,17 +1592,19 @@ fop_finodelk_stub (call_frame_t *frame, fop_finodelk_t fn, 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); + stub->args.fd = fd_ref (fd); if (volume) - stub->args.finodelk.volume = gf_strdup (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; + if (xdata) + stub->args.xdata = dict_ref (xdata); out: return stub; } @@ -1633,7 +1612,7 @@ out: 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; @@ -1642,10 +1621,12 @@ fop_finodelk_cbk_stub (call_frame_t *frame, fop_inodelk_cbk_t fn, 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; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: return stub; } @@ -1654,7 +1635,7 @@ out: 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) + entrylk_cmd cmd, entrylk_type type, dict_t *xdata) { call_stub_t *stub = NULL; @@ -1663,25 +1644,29 @@ fop_entrylk_stub (call_frame_t *frame, fop_entrylk_t fn, stub = stub_new (frame, 1, GF_FOP_ENTRYLK); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.entrylk.fn = fn; + stub->fn.entrylk = fn; if (volume) - stub->args.entrylk.volume = gf_strdup (volume); + stub->args.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); + stub->args.name = gf_strdup (name); + if (xdata) + stub->args.xdata = dict_ref (xdata); out: return stub; } + call_stub_t * fop_entrylk_cbk_stub (call_frame_t *frame, fop_entrylk_cbk_t fn, - int32_t op_ret, int32_t op_errno) + int32_t op_ret, int32_t op_errno, dict_t *xdata) { call_stub_t *stub = NULL; @@ -1690,10 +1675,12 @@ fop_entrylk_cbk_stub (call_frame_t *frame, fop_entrylk_cbk_t fn, 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; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: return stub; } @@ -1702,7 +1689,7 @@ out: 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) + entrylk_cmd cmd, entrylk_type type, dict_t *xdata) { call_stub_t *stub = NULL; @@ -1711,25 +1698,28 @@ fop_fentrylk_stub (call_frame_t *frame, fop_fentrylk_t fn, 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); + 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; + stub->args.fd = fd_ref (fd); + stub->args.entrylkcmd = cmd; + stub->args.entrylktype = type; if (name) - stub->args.fentrylk.name = gf_strdup (name); + stub->args.name = gf_strdup (name); + 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; @@ -1738,21 +1728,21 @@ fop_fentrylk_cbk_stub (call_frame_t *frame, fop_fentrylk_cbk_t fn, 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; + 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; @@ -1762,14 +1752,10 @@ fop_readdirp_cbk_stub (call_frame_t *frame, 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. - */ GF_VALIDATE_OR_GOTO ("call-stub", entries, out); if (op_ret > 0) { @@ -1780,21 +1766,23 @@ fop_readdirp_cbk_stub (call_frame_t *frame, 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.readdirp_cbk.entries.list); + &stub->args_cbk.entries.list); } } + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: return stub; } call_stub_t * -fop_readdir_cbk_stub (call_frame_t *frame, - fop_readdir_cbk_t fn, - int32_t op_ret, - int32_t op_errno, - gf_dirent_t *entries) +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; @@ -1804,14 +1792,10 @@ fop_readdir_cbk_stub (call_frame_t *frame, 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. - */ GF_VALIDATE_OR_GOTO ("call-stub", entries, out); if (op_ret > 0) { @@ -1823,62 +1807,61 @@ fop_readdir_cbk_stub (call_frame_t *frame, stub_entry->d_ino = entry->d_ino; list_add_tail (&stub_entry->list, - &stub->args.readdir_cbk.entries.list); + &stub->args_cbk.entries.list); } } + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: return stub; } + call_stub_t * -fop_readdir_stub (call_frame_t *frame, - fop_readdir_t fn, - fd_t *fd, - size_t size, - off_t off) +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; stub = stub_new (frame, 1, GF_FOP_READDIR); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.readdir.fn = fn; - stub->args.readdir.fd = fd_ref (fd); - stub->args.readdir.size = size; - stub->args.readdir.off = off; + 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, - dict_t *dict) +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; stub = stub_new (frame, 1, GF_FOP_READDIRP); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.readdirp.fn = fn; - stub->args.readdirp.fd = fd_ref (fd); - stub->args.readdirp.size = size; - stub->args.readdirp.off = off; - stub->args.readdirp.dict = dict; - + 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; @@ -1888,22 +1871,22 @@ fop_rchecksum_stub (call_frame_t *frame, 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; } 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; @@ -1912,28 +1895,27 @@ fop_rchecksum_cbk_stub (call_frame_t *frame, 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.rchecksum_cbk.strong_checksum = - memdup (strong_checksum, MD5_DIGEST_LEN); + stub->args_cbk.strong_checksum = + memdup (strong_checksum, MD5_DIGEST_LENGTH); } + + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: return stub; } call_stub_t * -fop_xattrop_cbk_stub (call_frame_t *frame, - fop_xattrop_cbk_t fn, - int32_t op_ret, - int32_t op_errno) +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; @@ -1942,21 +1924,21 @@ fop_xattrop_cbk_stub (call_frame_t *frame, stub = stub_new (frame, 0, GF_FOP_XATTROP); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.xattrop_cbk.fn = fn; - stub->args.xattrop_cbk.op_ret = op_ret; - stub->args.xattrop_cbk.op_errno = op_errno; + stub->fn_cbk.xattrop = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: return stub; } 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); @@ -1964,23 +1946,23 @@ fop_fxattrop_cbk_stub (call_frame_t *frame, stub = stub_new (frame, 0, GF_FOP_FXATTROP); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.fxattrop_cbk.fn = fn; - stub->args.fxattrop_cbk.op_ret = op_ret; - stub->args.fxattrop_cbk.op_errno = op_errno; + stub->fn_cbk.fxattrop = fn; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; if (xattr) - stub->args.fxattrop_cbk.xattr = dict_ref (xattr); + stub->args_cbk.xattr = dict_ref (xattr); + if (xdata) + stub->args_cbk.xdata = dict_ref (xdata); out: return stub; } call_stub_t * -fop_xattrop_stub (call_frame_t *frame, - fop_xattrop_t fn, - loc_t *loc, - gf_xattrop_flags_t optype, - dict_t *xattr) +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; @@ -1990,23 +1972,24 @@ fop_xattrop_stub (call_frame_t *frame, stub = stub_new (frame, 1, GF_FOP_XATTROP); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.xattrop.fn = fn; + stub->fn.xattrop = 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); + 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; @@ -2016,25 +1999,25 @@ fop_fxattrop_stub (call_frame_t *frame, stub = stub_new (frame, 1, GF_FOP_FXATTROP); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.fxattrop.fn = fn; + stub->fn.fxattrop = 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); + 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; @@ -2043,27 +2026,28 @@ fop_setattr_cbk_stub (call_frame_t *frame, 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; } + 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; @@ -2072,25 +2056,26 @@ fop_fsetattr_cbk_stub (call_frame_t *frame, 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; } + 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; @@ -2100,25 +2085,26 @@ fop_setattr_stub (call_frame_t *frame, stub = stub_new (frame, 1, GF_FOP_SETATTR); GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - stub->args.setattr.fn = fn; + stub->fn.setattr = 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; } + 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; @@ -2128,1779 +2114,695 @@ fop_fsetattr_stub (call_frame_t *frame, stub = stub_new (frame, 1, GF_FOP_FSETATTR); GF_VALIDATE_OR_GOTO ("call-stub", stub, 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; } -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) { + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_FALLOCATE); 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; - } + stub->fn_cbk.fallocate = fn; - 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; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; - 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; + 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_UNLINK: - { - stub->args.unlink.fn (stub->frame, - stub->frame->this, - &stub->args.unlink.loc); - } - break; +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; - case GF_FOP_RMDIR: - { - stub->args.rmdir.fn (stub->frame, stub->frame->this, - &stub->args.rmdir.loc, - stub->args.rmdir.flags); - } - break; + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fn, out); - 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; + stub = stub_new (frame, 1, GF_FOP_FALLOCATE); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - case GF_FOP_RENAME: - { - stub->args.rename.fn (stub->frame, - stub->frame->this, - &stub->args.rename.old, - &stub->args.rename.new); - } - break; + stub->fn.fallocate = fn; - case GF_FOP_LINK: - { - stub->args.link.fn (stub->frame, - stub->frame->this, - &stub->args.link.oldloc, - &stub->args.link.newloc); - } - break; + if (fd) + stub->args.fd = fd_ref (fd); - case GF_FOP_TRUNCATE: - { - stub->args.truncate.fn (stub->frame, - stub->frame->this, - &stub->args.truncate.loc, - stub->args.truncate.off); - break; - } + stub->args.flags = mode; + stub->args.offset = offset; + stub->args.size = len; - 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, - stub->args.readv.flags); - break; - } + if (xdata) + stub->args.xdata = dict_ref (xdata); +out: + return stub; - 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.flags, - 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; - } +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; - case GF_FOP_FSYNC: - { - stub->args.fsync.fn (stub->frame, - stub->frame->this, - stub->args.fsync.fd, - stub->args.fsync.datasync); - break; - } + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - 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; - } + stub = stub_new (frame, 0, GF_FOP_DISCARD); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - case GF_FOP_GETXATTR: - { - stub->args.getxattr.fn (stub->frame, - stub->frame->this, - &stub->args.getxattr.loc, - stub->args.getxattr.name); - break; - } + stub->fn_cbk.discard = fn; - 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; - } + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; - case GF_FOP_FGETXATTR: - { - stub->args.fgetxattr.fn (stub->frame, - stub->frame->this, - stub->args.fgetxattr.fd, - stub->args.fgetxattr.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_REMOVEXATTR: - { - stub->args.removexattr.fn (stub->frame, - stub->frame->this, - &stub->args.removexattr.loc, - stub->args.removexattr.name); - break; - } +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; - case GF_FOP_FREMOVEXATTR: - { - stub->args.fremovexattr.fn (stub->frame, - stub->frame->this, - stub->args.fremovexattr.fd, - stub->args.fremovexattr.name); - break; - } + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fn, out); - case GF_FOP_OPENDIR: - { - stub->args.opendir.fn (stub->frame, - stub->frame->this, - &stub->args.opendir.loc, - stub->args.opendir.fd); - break; - } + stub = stub_new (frame, 1, GF_FOP_DISCARD); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - case GF_FOP_FSYNCDIR: - { - stub->args.fsyncdir.fn (stub->frame, - stub->frame->this, - stub->args.fsyncdir.fd, - stub->args.fsyncdir.datasync); - break; - } + stub->fn.discard = fn; - case GF_FOP_ACCESS: - { - stub->args.access.fn (stub->frame, - stub->frame->this, - &stub->args.access.loc, - stub->args.access.mask); - break; - } + if (fd) + stub->args.fd = fd_ref (fd); - case GF_FOP_FTRUNCATE: - { - stub->args.ftruncate.fn (stub->frame, - stub->frame->this, - stub->args.ftruncate.fd, - stub->args.ftruncate.off); - break; - } + stub->args.offset = offset; + stub->args.size = len; - case GF_FOP_FSTAT: - { - stub->args.fstat.fn (stub->frame, - stub->frame->this, - stub->args.fstat.fd); - break; - } + if (xdata) + stub->args.xdata = dict_ref (xdata); +out: + return stub; - 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; - } +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; - 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; - } + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); - 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; - } + stub = stub_new (frame, 0, GF_FOP_ZEROFILL); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - 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; - } + stub->fn_cbk.zerofill = fn; - break; + stub->args_cbk.op_ret = op_ret; + stub->args_cbk.op_errno = op_errno; - case GF_FOP_LOOKUP: - { - stub->args.lookup.fn (stub->frame, - stub->frame->this, - &stub->args.lookup.loc, - stub->args.lookup.xattr_req); - 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_RCHECKSUM: - { - stub->args.rchecksum.fn (stub->frame, - stub->frame->this, - stub->args.rchecksum.fd, - stub->args.rchecksum.offset, - stub->args.rchecksum.len); - 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_READDIR: - { - stub->args.readdir.fn (stub->frame, - stub->frame->this, - stub->args.readdir.fd, - stub->args.readdir.size, - stub->args.readdir.off); - break; - } + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fn, out); - 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, - stub->args.readdirp.dict); - break; - } + stub = stub_new (frame, 1, GF_FOP_ZEROFILL); + GF_VALIDATE_OR_GOTO ("call-stub", stub, 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->fn.zerofill = fn; - 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); + if (fd) + stub->args.fd = fd_ref (fd); - 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_callingfn ("call-stub", GF_LOG_ERROR, - "Invalid value of FOP (%d)", - stub->fop); - break; - } + stub->args.offset = offset; + stub->args.size = len; - } + if (xdata) + stub->args.xdata = dict_ref (xdata); out: - return; -} + return stub; +} static void -call_resume_unwind (call_stub_t *stub) +call_resume_wind (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); + 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: - { - 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); - + 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: - { - 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->fn.stat (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.xdata); 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.readlink (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.size, + stub->args.xdata); 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; - } - + 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: - { - 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); - - break; - } - + 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: - { - 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; - } - + stub->fn.unlink (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.xflag, + stub->args.xdata); + 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; - } - + stub->fn.rmdir (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.flags, + stub->args.xdata); + 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; - + 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: - { - 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); - break; - } - + stub->fn.rename (stub->frame, stub->frame->this, + &stub->args.loc, &stub->args.loc2, + stub->args.xdata); + 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; - } - + stub->fn.link (stub->frame, stub->frame->this, + &stub->args.loc, &stub->args.loc2, + stub->args.xdata); + 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); + stub->fn.truncate (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.offset, + stub->args.xdata); 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; - + 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: - { - 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); + 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: - { - 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; - + stub->fn.statfs (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.xdata); + 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); - + stub->fn.flush (stub->frame, stub->frame->this, + stub->args.fd, stub->args.xdata); 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); + stub->fn.fsync (stub->frame, stub->frame->this, + stub->args.fd, stub->args.datasync, + stub->args.xdata); break; - } - case GF_FOP_SETXATTR: - { - if (!stub->args.setxattr_cbk.fn) - STACK_UNWIND (stub->frame, - stub->args.setxattr_cbk.op_ret, - stub->args.setxattr_cbk.op_errno); - - else - stub->args.setxattr_cbk.fn (stub->frame, - stub->frame->cookie, - stub->frame->this, - stub->args.setxattr_cbk.op_ret, - stub->args.setxattr_cbk.op_errno); - + stub->fn.setxattr (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.xattr, + stub->args.flags, stub->args.xdata); 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); + stub->fn.getxattr (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.name, + stub->args.xdata); 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); - + 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: - { - 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); + stub->fn.fgetxattr (stub->frame, stub->frame->this, + stub->args.fd, stub->args.name, + stub->args.xdata); 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); - + stub->fn.removexattr (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.name, + stub->args.xdata); break; - } - case GF_FOP_FREMOVEXATTR: - { - if (!stub->args.fremovexattr_cbk.fn) - STACK_UNWIND (stub->frame, - stub->args.fremovexattr_cbk.op_ret, - stub->args.fremovexattr_cbk.op_errno); - else - stub->args.fremovexattr_cbk.fn (stub->frame, - stub->frame->cookie, - stub->frame->this, - stub->args.fremovexattr_cbk.op_ret, - stub->args.fremovexattr_cbk.op_errno); - + stub->fn.fremovexattr (stub->frame, stub->frame->this, + stub->args.fd, stub->args.name, + stub->args.xdata); 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); + stub->fn.opendir (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.fd, + stub->args.xdata); 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); + stub->fn.fsyncdir (stub->frame, stub->frame->this, + stub->args.fd, stub->args.datasync, + stub->args.xdata); break; - } - case GF_FOP_ACCESS: - { - if (!stub->args.access_cbk.fn) - STACK_UNWIND (stub->frame, - stub->args.access_cbk.op_ret, - stub->args.access_cbk.op_errno); - else - stub->args.access_cbk.fn (stub->frame, - stub->frame->cookie, - stub->frame->this, - stub->args.access_cbk.op_ret, - stub->args.access_cbk.op_errno); - + stub->fn.access (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.mask, + stub->args.xdata); 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); + stub->fn.ftruncate (stub->frame, stub->frame->this, + stub->args.fd, stub->args.offset, + stub->args.xdata); 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); - + stub->fn.fstat (stub->frame, stub->frame->this, + stub->args.fd, stub->args.xdata); 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); + 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: - { - 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); + 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: - { - 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); + 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: - { - 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); + 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: - { - 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; - } - + 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: - { - 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); - + stub->fn.lookup (stub->frame, stub->frame->this, + &stub->args.loc, stub->args.xdata); 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->fn.rchecksum (stub->frame, stub->frame->this, + stub->args.fd, stub->args.offset, + stub->args.size, stub->args.xdata); 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.readdir (stub->frame, stub->frame->this, + stub->args.fd, stub->args.size, + stub->args.offset, stub->args.xdata); break; - } - case GF_FOP_READDIRP: - { - if (!stub->args.readdirp_cbk.fn) - STACK_UNWIND (stub->frame, - stub->args.readdirp_cbk.op_ret, - stub->args.readdirp_cbk.op_errno, - &stub->args.readdirp_cbk.entries); - else - stub->args.readdirp_cbk.fn (stub->frame, - stub->frame->cookie, - stub->frame->this, - stub->args.readdirp_cbk.op_ret, - stub->args.readdirp_cbk.op_errno, - &stub->args.readdirp_cbk.entries); - - if (stub->args.readdirp_cbk.op_ret > 0) - gf_dirent_free (&stub->args.readdirp_cbk.entries); - + 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: - { - 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); - + 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: - { - 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); - + stub->fn.fxattrop (stub->frame, stub->frame->this, + stub->args.fd, stub->args.optype, + stub->args.xattr, stub->args.xdata); break; - } case GF_FOP_SETATTR: - { - if (!stub->args.setattr_cbk.fn) - STACK_UNWIND (stub->frame, - stub->args.setattr_cbk.op_ret, - stub->args.setattr_cbk.op_errno, - &stub->args.setattr_cbk.statpre, - &stub->args.setattr_cbk.statpost); - else - stub->args.setattr_cbk.fn ( - stub->frame, - stub->frame->cookie, - stub->frame->this, - stub->args.setattr_cbk.op_ret, - stub->args.setattr_cbk.op_errno, - &stub->args.setattr_cbk.statpre, - &stub->args.setattr_cbk.statpost); + stub->fn.setattr (stub->frame, stub->frame->this, + &stub->args.loc, &stub->args.stat, + stub->args.valid, stub->args.xdata); break; - } case GF_FOP_FSETATTR: - { - if (!stub->args.fsetattr_cbk.fn) - STACK_UNWIND (stub->frame, - stub->args.fsetattr_cbk.op_ret, - stub->args.fsetattr_cbk.op_errno, - &stub->args.fsetattr_cbk.statpre, - &stub->args.fsetattr_cbk.statpost); - else - stub->args.fsetattr_cbk.fn ( - stub->frame, - stub->frame->cookie, - stub->frame->this, - stub->args.fsetattr_cbk.op_ret, - stub->args.fsetattr_cbk.op_errno, - &stub->args.fsetattr_cbk.statpre, - &stub->args.fsetattr_cbk.statpost); + stub->fn.fsetattr (stub->frame, stub->frame->this, + stub->args.fd, &stub->args.stat, + stub->args.valid, stub->args.xdata); + break; + case GF_FOP_FALLOCATE: + stub->fn.fallocate(stub->frame, stub->frame->this, + stub->args.fd, stub->args.flags, + stub->args.offset, stub->args.size, + stub->args.xdata); + break; + case GF_FOP_DISCARD: + stub->fn.discard(stub->frame, stub->frame->this, + stub->args.fd, stub->args.offset, + stub->args.size, stub->args.xdata); + break; + case GF_FOP_ZEROFILL: + stub->fn.zerofill(stub->frame, stub->frame->this, + stub->args.fd, stub->args.offset, + stub->args.size, stub->args.xdata); break; - } + default: - { gf_log_callingfn ("call-stub", GF_LOG_ERROR, "Invalid value of FOP (%d)", stub->fop); break; } - } 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_wind (call_stub_t *stub) +call_resume_unwind (call_stub_t *stub) { + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + switch (stub->fop) { case GF_FOP_OPEN: - { - loc_wipe (&stub->args.open.loc); - if (stub->args.open.fd) - fd_unref (stub->args.open.fd); + STUB_UNWIND (stub, open, stub->args_cbk.fd, + stub->args_cbk.xdata); 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); + 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: - { - loc_wipe (&stub->args.stat.loc); + STUB_UNWIND (stub, stat, &stub->args_cbk.stat, + stub->args_cbk.xdata); break; - } case GF_FOP_READLINK: - { - loc_wipe (&stub->args.readlink.loc); - break; - } - + STUB_UNWIND (stub, readlink, stub->args_cbk.buf, + &stub->args_cbk.stat, stub->args.xdata); + break; case GF_FOP_MKNOD: - { - loc_wipe (&stub->args.mknod.loc); - if (stub->args.mknod.params) - dict_unref (stub->args.mknod.params); - } - break; - + 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: - { - loc_wipe (&stub->args.mkdir.loc); - if (stub->args.mkdir.params) - dict_unref (stub->args.mkdir.params); - } - break; - + 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: - { - loc_wipe (&stub->args.unlink.loc); - } - break; - + STUB_UNWIND (stub, unlink, &stub->args_cbk.preparent, + &stub->args_cbk.postparent, stub->args_cbk.xdata); + break; case GF_FOP_RMDIR: - { - loc_wipe (&stub->args.rmdir.loc); - } - break; - + STUB_UNWIND (stub, rmdir, &stub->args_cbk.preparent, + &stub->args_cbk.postparent, stub->args_cbk.xdata); + 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; - + 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: - { - loc_wipe (&stub->args.rename.old); - loc_wipe (&stub->args.rename.new); - } - break; - + 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: - { - loc_wipe (&stub->args.link.oldloc); - loc_wipe (&stub->args.link.newloc); - } - break; - + 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: - { - loc_wipe (&stub->args.truncate.loc); - break; - } - + STUB_UNWIND (stub, truncate, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); + break; case GF_FOP_READ: - { - if (stub->args.readv.fd) - fd_unref (stub->args.readv.fd); - break; - } - + 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: - { - 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; - } - + STUB_UNWIND (stub, writev, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); + break; case GF_FOP_STATFS: - { - loc_wipe (&stub->args.statfs.loc); - break; - } + STUB_UNWIND (stub, statfs, &stub->args_cbk.statvfs, + stub->args_cbk.xdata); + break; case GF_FOP_FLUSH: - { - if (stub->args.flush.fd) - fd_unref (stub->args.flush.fd); - break; - } - + STUB_UNWIND (stub, flush, stub->args_cbk.xdata); + break; case GF_FOP_FSYNC: - { - if (stub->args.fsync.fd) - fd_unref (stub->args.fsync.fd); - break; - } - + STUB_UNWIND (stub, fsync, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); + break; case GF_FOP_SETXATTR: - { - loc_wipe (&stub->args.setxattr.loc); - if (stub->args.setxattr.dict) - dict_unref (stub->args.setxattr.dict); - break; - } - + STUB_UNWIND (stub, setxattr, stub->args_cbk.xdata); + 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_UNWIND (stub, getxattr, stub->args_cbk.xattr, + stub->args_cbk.xdata); + break; case GF_FOP_FSETXATTR: - { - fd_unref (stub->args.fsetxattr.fd); - if (stub->args.fsetxattr.dict) - dict_unref (stub->args.fsetxattr.dict); - break; - } - + STUB_UNWIND (stub, fsetxattr, stub->args_cbk.xdata); + break; case GF_FOP_FGETXATTR: - { - if (stub->args.fgetxattr.name) - GF_FREE ((char *)stub->args.fgetxattr.name); - fd_unref (stub->args.fgetxattr.fd); - break; - } - + STUB_UNWIND (stub, fgetxattr, stub->args_cbk.xattr, + stub->args_cbk.xdata); + break; case GF_FOP_REMOVEXATTR: - { - loc_wipe (&stub->args.removexattr.loc); - GF_FREE ((char *)stub->args.removexattr.name); - break; - } - + STUB_UNWIND (stub, removexattr, stub->args_cbk.xdata); + break; case GF_FOP_FREMOVEXATTR: - { - fd_unref (stub->args.fremovexattr.fd); - GF_FREE ((char *)stub->args.fremovexattr.name); - break; - } - + STUB_UNWIND (stub, fremovexattr, stub->args_cbk.xdata); + break; case GF_FOP_OPENDIR: - { - loc_wipe (&stub->args.opendir.loc); - if (stub->args.opendir.fd) - fd_unref (stub->args.opendir.fd); - break; - } - + STUB_UNWIND (stub, opendir, stub->args_cbk.fd, + stub->args_cbk.xdata); + break; case GF_FOP_FSYNCDIR: - { - if (stub->args.fsyncdir.fd) - fd_unref (stub->args.fsyncdir.fd); + STUB_UNWIND (stub, fsyncdir, stub->args_cbk.xdata); break; - } - case GF_FOP_ACCESS: - { - loc_wipe (&stub->args.access.loc); + STUB_UNWIND (stub, access, stub->args_cbk.xdata); break; - } - case GF_FOP_FTRUNCATE: - { - if (stub->args.ftruncate.fd) - fd_unref (stub->args.ftruncate.fd); + STUB_UNWIND (stub, ftruncate, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); break; - } - case GF_FOP_FSTAT: - { - if (stub->args.fstat.fd) - fd_unref (stub->args.fstat.fd); + STUB_UNWIND (stub, fstat, &stub->args_cbk.stat, + stub->args_cbk.xdata); break; - } - case GF_FOP_LK: - { - if (stub->args.lk.fd) - fd_unref (stub->args.lk.fd); - break; - } - + STUB_UNWIND (stub, lk, &stub->args_cbk.lock, + stub->args_cbk.xdata); + break; case GF_FOP_INODELK: - { - if (stub->args.inodelk.volume) - GF_FREE ((char *)stub->args.inodelk.volume); - - loc_wipe (&stub->args.inodelk.loc); + STUB_UNWIND (stub, inodelk, stub->args_cbk.xdata); 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); + STUB_UNWIND (stub, finodelk, stub->args_cbk.xdata); 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; - } + STUB_UNWIND (stub, entrylk, stub->args_cbk.xdata); + break; case GF_FOP_FENTRYLK: - { - if (stub->args.fentrylk.volume) - GF_FREE ((char *)stub->args.fentrylk.volume); - - if (stub->args.fentrylk.name) - GF_FREE ((char *)stub->args.fentrylk.name); - - if (stub->args.fentrylk.fd) - fd_unref (stub->args.fentrylk.fd); + STUB_UNWIND (stub, fentrylk, stub->args_cbk.xdata); break; - } - case GF_FOP_LOOKUP: - { - loc_wipe (&stub->args.lookup.loc); - if (stub->args.lookup.xattr_req) - dict_unref (stub->args.lookup.xattr_req); + 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: - { - if (stub->args.rchecksum.fd) - fd_unref (stub->args.rchecksum.fd); - break; - } - + STUB_UNWIND (stub, rchecksum, stub->args_cbk.weak_checksum, + stub->args_cbk.strong_checksum, stub->args_cbk.xdata); + break; case GF_FOP_READDIR: - { - if (stub->args.readdir.fd) - fd_unref (stub->args.readdir.fd); - break; - } - + STUB_UNWIND (stub, readdir, &stub->args_cbk.entries, + stub->args_cbk.xdata); + break; case GF_FOP_READDIRP: - { - if (stub->args.readdirp.fd) - fd_unref (stub->args.readdirp.fd); + STUB_UNWIND (stub, readdir, &stub->args_cbk.entries, + stub->args_cbk.xdata); break; - } - case GF_FOP_XATTROP: - { - loc_wipe (&stub->args.xattrop.loc); - dict_unref (stub->args.xattrop.xattr); - break; - } + STUB_UNWIND (stub, xattrop, stub->args_cbk.xattr, + stub->args_cbk.xdata); + break; case GF_FOP_FXATTROP: - { - if (stub->args.fxattrop.fd) - fd_unref (stub->args.fxattrop.fd); - dict_unref (stub->args.fxattrop.xattr); - break; - } + STUB_UNWIND (stub, fxattrop, stub->args_cbk.xattr, + stub->args_cbk.xdata); + break; case GF_FOP_SETATTR: - { - loc_wipe (&stub->args.setattr.loc); + STUB_UNWIND (stub, setattr, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); break; - } case GF_FOP_FSETATTR: - { - if (stub->args.fsetattr.fd) - fd_unref (stub->args.fsetattr.fd); + STUB_UNWIND (stub, fsetattr, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); + break; + case GF_FOP_FALLOCATE: + STUB_UNWIND(stub, fallocate, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); + break; + case GF_FOP_DISCARD: + STUB_UNWIND(stub, discard, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); + break; + case GF_FOP_ZEROFILL: + STUB_UNWIND(stub, zerofill, &stub->args_cbk.prestat, + &stub->args_cbk.poststat, stub->args_cbk.xdata); break; - } + default: - { gf_log_callingfn ("call-stub", GF_LOG_ERROR, "Invalid value of FOP (%d)", stub->fop); break; } - } +out: + return; } static void -call_stub_destroy_unwind (call_stub_t *stub) +call_stub_wipe_args (call_stub_t *stub) { - switch (stub->fop) { - case GF_FOP_OPEN: - { - if (stub->args.open_cbk.fd) - fd_unref (stub->args.open_cbk.fd); - } - break; - - case GF_FOP_CREATE: - { - if (stub->args.create_cbk.fd) - fd_unref (stub->args.create_cbk.fd); - - if (stub->args.create_cbk.inode) - inode_unref (stub->args.create_cbk.inode); - } - break; - - case GF_FOP_STAT: - break; - - 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: - break; - - case GF_FOP_RMDIR: - break; - - case GF_FOP_SYMLINK: - { - if (stub->args.symlink_cbk.inode) - inode_unref (stub->args.symlink_cbk.inode); - } - break; - - case GF_FOP_RENAME: - break; - - case GF_FOP_LINK: - { - if (stub->args.link_cbk.inode) - inode_unref (stub->args.link_cbk.inode); - } - break; - - case GF_FOP_TRUNCATE: - 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: - break; - - case GF_FOP_STATFS: - break; - - case GF_FOP_FLUSH: - break; - - case GF_FOP_FSYNC: - break; - - case GF_FOP_SETXATTR: - break; - - case GF_FOP_GETXATTR: - { - if (stub->args.getxattr_cbk.dict) - dict_unref (stub->args.getxattr_cbk.dict); - } - break; + loc_wipe (&stub->args.loc); - case GF_FOP_FSETXATTR: - break; + loc_wipe (&stub->args.loc2); - case GF_FOP_FGETXATTR: - { - if (stub->args.fgetxattr_cbk.dict) - dict_unref (stub->args.fgetxattr_cbk.dict); - } - break; + if (stub->args.fd) + fd_unref (stub->args.fd); - case GF_FOP_REMOVEXATTR: - break; - case GF_FOP_FREMOVEXATTR: - break; + GF_FREE ((char *)stub->args.linkname); - case GF_FOP_OPENDIR: - { - if (stub->args.opendir_cbk.fd) - fd_unref (stub->args.opendir_cbk.fd); - } - break; + GF_FREE (stub->args.vector); - case GF_FOP_FSYNCDIR: - break; + if (stub->args.iobref) + iobref_unref (stub->args.iobref); - case GF_FOP_ACCESS: - break; + if (stub->args.xattr) + dict_unref (stub->args.xattr); - case GF_FOP_FTRUNCATE: - break; + GF_FREE ((char *)stub->args.name); - case GF_FOP_FSTAT: - break; + GF_FREE ((char *)stub->args.volume); - case GF_FOP_LK: - break; + if (stub->args.xdata) + dict_unref (stub->args.xdata); +} - case GF_FOP_INODELK: - break; - case GF_FOP_FINODELK: - break; +static void +call_stub_wipe_args_cbk (call_stub_t *stub) +{ + if (stub->args_cbk.inode) + inode_unref (stub->args_cbk.inode); - case GF_FOP_ENTRYLK: - break; + GF_FREE ((char *)stub->args_cbk.buf); - case GF_FOP_FENTRYLK: - break; + GF_FREE (stub->args_cbk.vector); - case GF_FOP_LOOKUP: - { - if (stub->args.lookup_cbk.inode) - inode_unref (stub->args.lookup_cbk.inode); + if (stub->args_cbk.iobref) + iobref_unref (stub->args_cbk.iobref); - if (stub->args.lookup_cbk.dict) - dict_unref (stub->args.lookup_cbk.dict); - } - break; + if (stub->args_cbk.fd) + fd_unref (stub->args_cbk.fd); - case GF_FOP_RCHECKSUM: - { - if (stub->args.rchecksum_cbk.op_ret >= 0) { - GF_FREE (stub->args.rchecksum_cbk.strong_checksum); - } - } - break; + if (stub->args_cbk.xattr) + dict_unref (stub->args_cbk.xattr); - case GF_FOP_READDIR: - { - if (stub->args.readdir_cbk.op_ret > 0) { - gf_dirent_free (&stub->args.readdir_cbk.entries); - } - } - break; + GF_FREE (stub->args_cbk.strong_checksum); - case GF_FOP_READDIRP: - { - if (stub->args.readdirp_cbk.op_ret > 0) { - gf_dirent_free (&stub->args.readdirp_cbk.entries); - } - } - break; + if (stub->args_cbk.xdata) + dict_unref (stub->args_cbk.xdata); - 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; - } - - case GF_FOP_FSETATTR: - { - break; - } - - default: - { - gf_log_callingfn ("call-stub", GF_LOG_ERROR, - "Invalid value of FOP (%d)", - stub->fop); - break; - } - } + if (!list_empty (&stub->args_cbk.entries.list)) + gf_dirent_free (&stub->args_cbk.entries); } @@ -3909,18 +2811,19 @@ call_stub_destroy (call_stub_t *stub) { GF_VALIDATE_OR_GOTO ("call-stub", stub, out); - if (stub->wind) { - call_stub_destroy_wind (stub); - } else { - call_stub_destroy_unwind (stub); - } + if (stub->wind) + call_stub_wipe_args (stub); + else + call_stub_wipe_args_cbk (stub); stub->stub_mem_pool = NULL; + mem_put (stub); out: return; } + void call_resume (call_stub_t *stub) { @@ -3945,3 +2848,26 @@ call_resume (call_stub_t *stub) out: 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 081f6d200..45bef8044 100644 --- a/libglusterfs/src/call-stub.h +++ b/libglusterfs/src/call-stub.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CALL_STUB_H_ @@ -34,576 +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; - uint32_t flags; - } 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; - uint32_t flags; - 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; - - - /* fremovexattr */ - struct { - fop_fremovexattr_t fn; - fd_t *fd; - const char *name; - } fremovexattr; - struct { - fop_fremovexattr_cbk_t fn; - int32_t op_ret, op_errno; - } fremovexattr_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; - dict_t *dict; - } 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, @@ -612,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, @@ -647,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, @@ -661,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, @@ -687,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, @@ -701,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, @@ -715,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, @@ -728,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, @@ -740,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, @@ -754,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, @@ -771,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, @@ -787,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, @@ -803,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, @@ -811,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, uint32_t flags); + off_t off, uint32_t flags, dict_t *xdata); call_stub_t * fop_readv_cbk_stub (call_frame_t *frame, @@ -835,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, @@ -844,7 +422,7 @@ fop_writev_stub (call_frame_t *frame, struct iovec *vector, int32_t count, off_t off, uint32_t flags, - struct iobref *iobref); + struct iobref *iobref, dict_t *xdata); call_stub_t * fop_writev_cbk_stub (call_frame_t *frame, @@ -852,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, @@ -877,177 +455,177 @@ 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); + 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); + 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); + 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); + 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, @@ -1055,27 +633,27 @@ fop_readdirp_stub (call_frame_t *frame, fd_t *fd, size_t size, off_t off, - dict_t *dict); + 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, @@ -1083,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, @@ -1124,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, @@ -1139,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 cea782293..e14a3044c 100644 --- a/libglusterfs/src/checksum.c +++ b/libglusterfs/src/checksum.c @@ -1,28 +1,17 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ -#include <inttypes.h> +#include <openssl/md5.h> +#include <stdint.h> #include "glusterfs.h" -#include "md5.h" -#include "checksum.h" - /* * The "weak" checksum required for the rsync algorithm, @@ -31,22 +20,26 @@ * * "a simple 32 bit checksum that can be upadted from either end * (inspired by Mark Adler's Adler-32 checksum)" + * + * Note: these functions are only called to compute checksums on + * pathnames; they don't need to handle arbitrarily long strings of + * data. Thus int32_t and uint32_t are sufficient */ uint32_t -gf_rsync_weak_checksum (char *buf1, int32_t len) +gf_rsync_weak_checksum (unsigned char *buf, size_t len) { - int32_t i; + int32_t i = 0; uint32_t s1, s2; - signed char *buf = (signed char *) buf1; uint32_t csum; s1 = s2 = 0; - for (i = 0; i < (len-4); i+=4) { - s2 += 4*(s1 + buf[i]) + 3*buf[i+1] + 2*buf[i+2] + buf[i+3]; - - s1 += buf[i+0] + buf[i+1] + buf[i+2] + buf[i+3]; + if (len >= 4) { + for (; i < (len-4); i+=4) { + s2 += 4*(s1 + buf[i]) + 3*buf[i+1] + 2*buf[i+2] + buf[i+3]; + s1 += buf[i+0] + buf[i+1] + buf[i+2] + buf[i+3]; + } } for (; i < len; i++) { @@ -66,13 +59,7 @@ gf_rsync_weak_checksum (char *buf1, int32_t len) */ void -gf_rsync_strong_checksum (char *buf, int32_t len, uint8_t *sum) +gf_rsync_strong_checksum (unsigned char *data, size_t len, unsigned char *md5) { - md_context m; - - md5_begin (&m); - md5_update (&m, (unsigned char *) buf, len); - md5_result (&m, (unsigned char *) sum); - - return; + MD5(data, len, md5); } diff --git a/libglusterfs/src/checksum.h b/libglusterfs/src/checksum.h index 3542036bf..bf7eeede8 100644 --- a/libglusterfs/src/checksum.h +++ b/libglusterfs/src/checksum.h @@ -1,27 +1,20 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef __CHECKSUM_H__ #define __CHECKSUM_H__ -uint32_t gf_rsync_weak_checksum (char *buf, int32_t len); +uint32_t +gf_rsync_weak_checksum (unsigned char *buf, size_t len); -void gf_rsync_strong_checksum (char *buf, int32_t len, uint8_t *sum); +void +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 068bd8460..827475282 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -52,8 +43,9 @@ #include "glusterfs.h" #include "stack.h" #include "globals.h" -#include "md5.h" #include "lkowner.h" +#include "syscall.h" +#include <ifaddrs.h> #ifndef AI_ADDRCONFIG #define AI_ADDRCONFIG 0 @@ -67,6 +59,99 @@ struct dnscache6 { 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) @@ -123,7 +208,9 @@ gf_resolve_ip6 (const char *hostname, memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; +#ifndef __NetBSD__ hints.ai_flags = AI_ADDRCONFIG; +#endif ret = gf_asprintf (&port_str, "%d", port); if (-1 == ret) { @@ -192,28 +279,101 @@ err: } +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); + ctx = THIS->ctx; + xld.logfp = ctx->log.gf_log_logfile; - fprintf (gf_log_logfile, "Given volfile:\n"); - fprintf (gf_log_logfile, + fprintf (ctx->log.gf_log_logfile, "Final graph:\n"); + fprintf (ctx->log.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+---------------------------------------" + + xlator_foreach_depth_first (graph->top, xldump, &xld); + + fprintf (ctx->log.gf_log_logfile, + "+---------------------------------------" "---------------------------------------+\n"); - fflush (gf_log_logfile); - fseek (specfp, 0L, SEEK_SET); + fflush (ctx->log.gf_log_logfile); } static void @@ -348,26 +508,31 @@ out: /* 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); + 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; { - 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); @@ -375,10 +540,10 @@ gf_print_trace (int32_t signum) 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", + else + sprintf (msg,"frame : type(%d) op(%d)\n", tmp->root->type, - gf_mgmt_list[tmp->root->op]); + tmp->root->op); ret = write (fd, msg, strlen (msg)); if (ret < 0) @@ -404,9 +569,7 @@ gf_print_trace (int32_t signum) { /* 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; @@ -562,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; @@ -616,6 +778,8 @@ gf_string2time (const char *str, uint32_t *n) old_errno = errno; errno = 0; value = strtol (str, &tail, 0); + if (str == tail) + errno = EINVAL; if (errno == ERANGE || errno == EINVAL) return -1; @@ -634,11 +798,10 @@ gf_string2time (const char *str, uint32_t *n) return 0; } - int -gf_string2percent (const char *str, uint32_t *n) +gf_string2percent (const char *str, double *n) { - unsigned long value = 0; + double value = 0; char *tail = NULL; int old_errno = 0; const char *s = NULL; @@ -659,7 +822,9 @@ gf_string2percent (const char *str, uint32_t *n) old_errno = errno; errno = 0; - value = strtol (str, &tail, 0); + value = strtod (str, &tail); + if (str == tail) + errno = EINVAL; if (errno == ERANGE || errno == EINVAL) return -1; @@ -693,6 +858,8 @@ _gf_string2long (const char *str, long *n, int base) old_errno = errno; errno = 0; value = strtol (str, &tail, base); + if (str == tail) + errno = EINVAL; if (errno == ERANGE || errno == EINVAL) return -1; @@ -733,6 +900,8 @@ _gf_string2ulong (const char *str, unsigned long *n, int base) old_errno = errno; errno = 0; value = strtoul (str, &tail, base); + if (str == tail) + errno = EINVAL; if (errno == ERANGE || errno == EINVAL) return -1; @@ -773,6 +942,8 @@ _gf_string2uint (const char *str, unsigned int *n, int base) old_errno = errno; errno = 0; value = strtoul (str, &tail, base); + if (str == tail) + errno = EINVAL; if (errno == ERANGE || errno == EINVAL) return -1; @@ -804,6 +975,8 @@ _gf_string2double (const char *str, double *n) old_errno = errno; errno = 0; value = strtod (str, &tail); + if (str == tail) + errno = EINVAL; if (errno == ERANGE || errno == EINVAL) return -1; @@ -835,6 +1008,8 @@ _gf_string2longlong (const char *str, long long *n, int base) old_errno = errno; errno = 0; value = strtoll (str, &tail, base); + if (str == tail) + errno = EINVAL; if (errno == ERANGE || errno == EINVAL) return -1; @@ -875,6 +1050,8 @@ _gf_string2ulonglong (const char *str, unsigned long long *n, int base) old_errno = errno; errno = 0; value = strtoull (str, &tail, base); + if (str == tail) + errno = EINVAL; if (errno == ERANGE || errno == EINVAL) return -1; @@ -948,7 +1125,7 @@ gf_string2int8 (const char *str, int8_t *n) if (rv != 0) return rv; - if (l >= INT8_MIN && l <= INT8_MAX) { + if ((l >= INT8_MIN) && (l <= INT8_MAX)) { *n = (int8_t) l; return 0; } @@ -967,7 +1144,7 @@ gf_string2int16 (const char *str, int16_t *n) if (rv != 0) return rv; - if (l >= INT16_MIN && l <= INT16_MAX) { + if ((l >= INT16_MIN) && (l <= INT16_MAX)) { *n = (int16_t) l; return 0; } @@ -986,7 +1163,7 @@ gf_string2int32 (const char *str, int32_t *n) if (rv != 0) return rv; - if (l >= INT32_MIN && l <= INT32_MAX) { + if ((l >= INT32_MIN) && (l <= INT32_MAX)) { *n = (int32_t) l; return 0; } @@ -1005,7 +1182,7 @@ gf_string2int64 (const char *str, int64_t *n) if (rv != 0) return rv; - if (l >= INT64_MIN && l <= INT64_MAX) { + if ((l >= INT64_MIN) && (l <= INT64_MAX)) { *n = (int64_t) l; return 0; } @@ -1217,7 +1394,7 @@ err: int gf_string2bytesize (const char *str, uint64_t *n) { - uint64_t value = 0ULL; + double value = 0.0; char *tail = NULL; int old_errno = 0; const char *s = NULL; @@ -1238,7 +1415,9 @@ gf_string2bytesize (const char *str, uint64_t *n) old_errno = errno; errno = 0; - value = strtoull (str, &tail, 10); + value = strtod (str, &tail); + if (str == tail) + errno = EINVAL; if (errno == ERANGE || errno == EINVAL) return -1; @@ -1262,7 +1441,77 @@ gf_string2bytesize (const char *str, uint64_t *n) return -1; } - *n = value; + if ((UINT64_MAX - value) < 0) { + errno = ERANGE; + return -1; + } + + *n = (uint64_t) value; + + return 0; +} + +int +gf_string2percent_or_bytesize (const char *str, + uint64_t *n, + gf_boolean_t *is_percent) +{ + double value = 0ULL; + char *tail = NULL; + int old_errno = 0; + const char *s = NULL; + + if (str == NULL || n == NULL) { + gf_log_callingfn (THIS->name, GF_LOG_WARNING, + "argument invalid"); + errno = EINVAL; + return -1; + } + + for (s = str; *s != '\0'; s++) { + if (isspace (*s)) + continue; + if (*s == '-') + return -1; + break; + } + + old_errno = errno; + errno = 0; + value = strtod (str, &tail); + if (str == tail) + errno = EINVAL; + + if (errno == ERANGE || errno == EINVAL) + return -1; + + if (errno == 0) + errno = old_errno; + + if (tail[0] != '\0') { + if (strcasecmp (tail, GF_UNIT_KB_STRING) == 0) + value *= GF_UNIT_KB; + else if (strcasecmp (tail, GF_UNIT_MB_STRING) == 0) + value *= GF_UNIT_MB; + else if (strcasecmp (tail, GF_UNIT_GB_STRING) == 0) + value *= GF_UNIT_GB; + else if (strcasecmp (tail, GF_UNIT_TB_STRING) == 0) + value *= GF_UNIT_TB; + else if (strcasecmp (tail, GF_UNIT_PB_STRING) == 0) + value *= GF_UNIT_PB; + else if (strcasecmp (tail, GF_UNIT_PERCENT_STRING) == 0) + *is_percent = _gf_true; + else + return -1; + } + + /* Error out if we cannot store the value in uint64 */ + if ((UINT64_MAX - value) < 0) { + errno = ERANGE; + return -1; + } + + *n = (uint64_t) value; return 0; } @@ -1528,64 +1777,112 @@ get_nth_word (const char *str, int n) return word; } -/* RFC 1123 & 952 */ - -/* The functions below validate given internet addresses and - * wildcard internet address for correctness. - * All return 1 on success and 0 on failure - */ - +/* 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; - char ret = 0; - int flag = 0; + int i = 0; + int str_len = 0; + char ret = 1; + char *dup_addr = NULL; + char *temp_str = NULL; + char *save_ptr = NULL; - if ((length > 255) || (length == 1)) + if ((length > _POSIX_HOST_NAME_MAX) || (length < 1)) { + ret = 0; goto out; + } - if (!isalnum (address[length - 1])) + dup_addr = gf_strdup (address); + if (!dup_addr) { + ret = 0; goto out; + } - for (i = 0; i < length; i++) { - if (!isalnum (address[i]) && (address[i] != '.') - && (address[i] != '-')) - goto out; + if (!isalnum (dup_addr[length - 1]) && (dup_addr[length - 1] != '*')) { + ret = 0; + goto out; + } - if (isalpha(address[i])) - flag = 1; + /* Check for consecutive dots, which is invalid in a hostname and is + * ignored by strtok() + */ + if (strstr (dup_addr, "..")) { + ret = 0; + goto out; } - if (flag) - ret = 1; + /* 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) +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 = 0; + 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++; - value = strtol (prev, &endptr, 10); - if ((value > 255) || (value < 0) || - (endptr != NULL && *endptr != '\0')) - goto out; + 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) - ret = 1; + if ((octets > 4) || (octets < 4 && !is_wildcard)) { + ret = 0; + } out: GF_FREE (tmp); @@ -1593,27 +1890,55 @@ out: } char -valid_ipv6_address (char *address, int length) +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 = 0; + 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++; - value = strtol (prev, &endptr, 16); - if ((value > 0xffff) || (value < 0) - || (endptr != NULL && *endptr != '\0')) - goto out; + 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) - ret = 1; + if ((hex_numbers > 8) || (hex_numbers < 8 && !is_wildcard + && !is_compressed)) { + ret = 0; + } out: GF_FREE (tmp); @@ -1621,7 +1946,7 @@ out: } char -valid_internet_address (char *address) +valid_internet_address (char *address, gf_boolean_t wildcard_acc) { char ret = 0; int length = 0; @@ -1635,8 +1960,8 @@ valid_internet_address (char *address) if (length == 0) goto out; - if (valid_ipv4_address (address, length) - || valid_ipv6_address (address, length) + if (valid_ipv4_address (address, length, wildcard_acc) + || valid_ipv6_address (address, length, wildcard_acc) || valid_host_name (address, length)) ret = 1; @@ -1644,109 +1969,55 @@ out: return ret; } -char -valid_ipv4_wildcard_check (char *address) +/** + * 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) { - char ret = 0; - int octets = 0; - char *tmp = NULL; - char *prev = NULL; - char *endptr = NULL; - int value = 0; - int is_wildcard = 0; - - tmp = gf_strdup (address); - prev = strtok (tmp, "."); - - while (prev != NULL) { - octets++; - - if (!strcmp (prev, "*")) { - is_wildcard = 1; - } else { - value = strtol (prev, &endptr, 10); - - if ((value > 255) || (value < 0) || - (endptr != NULL && *endptr != '\0')) - goto out; - } - prev = strtok (NULL, "."); + if (!a || !b) { + gf_log ("common-utils", GF_LOG_ERROR, "Invalid arguments" + " to gf_sock_union_equal_addr"); + return _gf_false; } - if (is_wildcard && (octets <= 4)) - ret = 1; - -out: - if (tmp) - GF_FREE (tmp); - return ret; - -} + if (a->storage.ss_family != b->storage.ss_family) + return _gf_false; -char -valid_ipv6_wildcard_check (char *address) -{ - char ret = 0; - int hex_numbers = 0; - int value = 0; - char *tmp = NULL; - char *prev = NULL; - char *endptr = NULL; - int is_wildcard = 0; - - tmp = gf_strdup (address); - prev = strtok (tmp, ":"); - - while (prev != NULL) { - hex_numbers++; - - if (!strcmp (prev, "*")) { - is_wildcard = 1; - } else { - value = strtol (prev, &endptr, 16); - - if ((value > 0xffff) || (value < 0) || - (endptr != NULL && *endptr != '\0')) - goto out; - } - prev = strtok (NULL, ":"); - } - - if (is_wildcard && (hex_numbers <= 8)) - ret = 1; -out: - if (tmp) - GF_FREE (tmp); - return ret; -} + 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; -char -valid_wildcard_internet_address (char *address) -{ - char ret = 0; + 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; - if (address == NULL) { - gf_log_callingfn (THIS->name, GF_LOG_WARNING, - "argument invalid"); - goto out; + default: + gf_log ("common-utils", GF_LOG_DEBUG, + "Unsupported/invalid address family"); + break; } - if (strlen (address) == 0) - goto out; - - if (valid_ipv4_wildcard_check (address) || - valid_ipv6_wildcard_check (address)) - ret = 1; - -out: - return ret; + return _gf_false; } /*Thread safe conversion function*/ char * uuid_utoa (uuid_t uuid) { - char *uuid_buffer = glusterfs_uuid_buf_get(); + char *uuid_buffer = glusterfs_uuid_buf_get(THIS->ctx); uuid_unparse (uuid, uuid_buffer); return uuid_buffer; } @@ -1765,7 +2036,7 @@ uuid_utoa_r (uuid_t uuid, char *dst) char * lkowner_utoa (gf_lkowner_t *lkowner) { - char *lkowner_buffer = glusterfs_lkowner_buf_get(); + char *lkowner_buffer = glusterfs_lkowner_buf_get(THIS->ctx); lkowner_unparse (lkowner, lkowner_buffer, GF_LKOWNER_BUF_SIZE); return lkowner_buffer; } @@ -1780,19 +2051,6 @@ lkowner_utoa_r (gf_lkowner_t *lkowner, char *dst, int len) return dst; } -void _get_md5_str (char *out_str, size_t outlen, - const uint8_t *input, int n) -{ - uint8_t out[MD5_DIGEST_LEN] = {0}; - int j = 0; - - GF_ASSERT (outlen >= (2*MD5_DIGEST_LEN + 1)); - get_md5 (out, input, n); - for (j = 0; j < MD5_DIGEST_LEN; j++) - snprintf(out_str + j * 2, outlen-j*2, "%02x", out[j]); - -} - void* gf_array_elem (void *a, int index, size_t elem_size) { uint8_t* ptr = a; @@ -1855,8 +2113,7 @@ gf_is_str_int (const char *value) } out: - if (fptr) - GF_FREE (fptr); + GF_FREE (fptr); return flag; } @@ -1866,9 +2123,9 @@ out: */ inline int32_t -gf_roundup_power_of_two (uint32_t nr) +gf_roundup_power_of_two (int32_t nr) { - uint32_t result = 1; + int32_t result = 1; if (nr < 0) { gf_log ("common-utils", GF_LOG_WARNING, @@ -1889,13 +2146,8 @@ out: * power of two is returned. */ -/* - * 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 (uint32_t nr) +gf_roundup_next_power_of_two (int32_t nr) { int32_t result = 1; @@ -1998,10 +2250,659 @@ get_mem_size () 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_client_pid_check (gf_client_pid_t npid) +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) { - return ( (npid > GF_CLIENT_PID_MIN) && (npid < GF_CLIENT_PID_MAX) ) - ? 0 : -1; + 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 63566fb53..3c99a4212 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _COMMON_UTILS_H @@ -32,6 +23,7 @@ #include <string.h> #include <assert.h> #include <pthread.h> +#include <openssl/md5.h> #ifndef GF_BSD_HOST_OS #include <alloca.h> #endif @@ -69,9 +61,13 @@ void trap (void); #define GF_UNIT_TB_STRING "TB" #define GF_UNIT_PB_STRING "PB" +#define GF_UNIT_PERCENT_STRING "%" + #define GEOREP "geo-replication" #define GHADOOP "glusterfs-hadoop" +#define GF_SELINUX_XATTR_KEY "security.selinux" + #define WIPE(statp) do { typeof(*statp) z = {0,}; if (statp) *statp = z; } while (0) #define IS_EXT_FS(fs_name) \ @@ -79,6 +75,12 @@ void trap (void); !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, @@ -97,7 +99,7 @@ enum _gf_client_pid GF_CLIENT_PID_MAX = 0, GF_CLIENT_PID_GSYNCD = -1, GF_CLIENT_PID_HADOOP = -2, - GF_CLIENT_PID_MIN = -3 + GF_CLIENT_PID_DEFRAG = -3, }; typedef enum _gf_boolean gf_boolean_t; @@ -108,15 +110,14 @@ 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; \ @@ -126,7 +127,7 @@ extern char *gf_mgmt_list[GF_MGMT_MAXVALUE]; "invalid argument: " #arg); \ goto label; \ } \ - } while (0); + } while (0) #define GF_VALIDATE_OR_GOTO(name,arg,label) do { \ if (!arg) { \ @@ -135,7 +136,7 @@ extern char *gf_mgmt_list[GF_MGMT_MAXVALUE]; "invalid argument: " #arg); \ goto label; \ } \ - } while (0); + } while (0) #define GF_VALIDATE_OR_GOTO_WITH_ERROR(name, arg, label, errno, error) do { \ if (!arg) { \ @@ -144,15 +145,15 @@ extern char *gf_mgmt_list[GF_MGMT_MAXVALUE]; "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) \ + GF_ASSERT (0); \ errno = error; \ goto label; \ } \ - }while (0); + }while (0) #define GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO(name,arg,label) \ do { \ @@ -163,7 +164,7 @@ extern char *gf_mgmt_list[GF_MGMT_MAXVALUE]; "invalid argument: " #arg); \ goto label; \ } \ - } while (0); + } while (0) #define GF_REMOVE_SLASH_FROM_PATH(path, string) \ do { \ @@ -173,28 +174,44 @@ extern char *gf_mgmt_list[GF_MGMT_MAXVALUE]; if (string[i-1] == '/') \ string[i-1] = '-'; \ } \ - } while (0); \ - + } while (0) -#define GF_IF_INTERNAL_XATTR_GOTO(pattern, dict, trav, op_errno, label) \ - do{ \ +#define GF_IF_INTERNAL_XATTR_GOTO(pattern, dict, op_errno, label) \ + do { \ if (!dict) { \ - gf_log (THIS->name, GF_LOG_ERROR, \ + gf_log (this->name, GF_LOG_ERROR, \ "setxattr dict is null"); \ goto label; \ } \ - trav = dict->members_list; \ - while (trav) { \ - if (!fnmatch (pattern, trav->key, 0)) { \ - gf_log (THIS->name, GF_LOG_ERROR, \ - "attempt to set internal" \ - " xattr: %s", trav->key); \ - op_errno = EPERM; \ - goto label; \ - } \ - trav = trav->next; \ + 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); \ + } 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) @@ -208,7 +225,7 @@ extern char *gf_mgmt_list[GF_MGMT_MAXVALUE]; gf_log_callingfn ("", GF_LOG_ERROR, \ "Assertion failed: " #x); \ } \ - } while (0); + } while (0) #endif #define GF_UUID_ASSERT(u) \ @@ -250,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; @@ -330,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) { @@ -375,19 +451,52 @@ 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 */ -int32_t gf_roundup_power_of_two (uint32_t 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 (uint32_t nr); +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, @@ -421,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); @@ -442,20 +553,20 @@ void skip_word (char **str); 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); -char valid_ipv6_address (char *address, int length); -char valid_internet_address (char *address); +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 _get_md5_str (char *out_str, size_t outlen, - const uint8_t *input, int n); 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); @@ -466,5 +577,18 @@ 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_client_pid_check (gf_client_pid_t npid); +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 2aeb3d805..fd5cc49ce 100644 --- a/libglusterfs/src/compat-errno.c +++ b/libglusterfs/src/compat-errno.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H diff --git a/libglusterfs/src/compat-errno.h b/libglusterfs/src/compat-errno.h index a61457960..65e52081d 100644 --- a/libglusterfs/src/compat-errno.h +++ b/libglusterfs/src/compat-errno.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef __COMPAT_ERRNO_H__ diff --git a/libglusterfs/src/compat.c b/libglusterfs/src/compat.c index 20e165a7a..eb6d8d4b7 100644 --- a/libglusterfs/src/compat.c +++ b/libglusterfs/src/compat.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -151,8 +142,7 @@ done: *path = export_path; } out: - if (freeptr) - GF_FREE (freeptr); + GF_FREE (freeptr); if (ret && export_path) GF_FREE (export_path); @@ -204,8 +194,7 @@ solaris_xattr_resolve_path (const char *real_path, char **path) *path = gf_strdup (xattr_path); } out: - if (export_path) - GF_FREE (export_path); + GF_FREE (export_path); if (*path) return 0; else @@ -239,8 +228,7 @@ solaris_setxattr(const char *path, const char* key, const char *value, path, errno); ret = -1; } - if (mapped_path) - GF_FREE (mapped_path); + GF_FREE (mapped_path); return ret; } @@ -306,8 +294,7 @@ solaris_listxattr(const char *path, char *list, size_t size) close (attrdirfd); } out: - if (mapped_path) - GF_FREE (mapped_path); + GF_FREE (mapped_path); return len; } @@ -389,8 +376,7 @@ solaris_removexattr(const char *path, const char* key) ret = -1; } - if (mapped_path) - GF_FREE (mapped_path); + GF_FREE (mapped_path); return ret; } @@ -430,8 +416,7 @@ solaris_getxattr(const char *path, errno = ENODATA; ret = -1; } - if (mapped_path) - GF_FREE (mapped_path); + GF_FREE (mapped_path); return ret; } @@ -503,8 +488,7 @@ int solaris_unlink (const char *path) } out: - if (mapped_path) - GF_FREE (mapped_path); + GF_FREE (mapped_path); return unlink (path); } diff --git a/libglusterfs/src/compat.h b/libglusterfs/src/compat.h index cb71d32ce..2bd982541 100644 --- a/libglusterfs/src/compat.h +++ b/libglusterfs/src/compat.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef __COMPAT_H__ @@ -41,6 +32,12 @@ #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 @@ -116,13 +113,6 @@ enum { #define F_SETLK64 F_SETLK #define F_SETLKW64 F_SETLKW -#ifdef __NetBSD__ -char *basename_r(const char *); -char *dirname_r(char *); - -#define basename(path) basename_r(path) -#define dirname(path) dirname_r(path) -#endif /* __NetBSD__ */ #endif /* GF_BSD_HOST_OS */ #ifdef GF_DARWIN_HOST_OS @@ -350,6 +340,18 @@ dirent_size (struct dirent *entry) 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 */ 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 index 778196164..348e3ad40 100644 --- a/libglusterfs/src/daemon.c +++ b/libglusterfs/src/daemon.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include <fcntl.h> diff --git a/libglusterfs/src/daemon.h b/libglusterfs/src/daemon.h index bf1d67cca..80836a326 100644 --- a/libglusterfs/src/daemon.h +++ b/libglusterfs/src/daemon.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _DAEMON_H diff --git a/libglusterfs/src/defaults.c b/libglusterfs/src/defaults.c index f3a8d2832..2ebb25150 100644 --- a/libglusterfs/src/defaults.c +++ b/libglusterfs/src/defaults.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ /* libglusterfs/src/defaults.c: @@ -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,93 +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); + 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) + int32_t op_ret, int32_t op_errno, + dict_t *xdata) { - STACK_UNWIND_STRICT (fremovexattr, 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; } @@ -381,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) { @@ -438,266 +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, - uint32_t flags, 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, - flags, 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, uint32_t flags) + 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, flags); + 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) + const char *name, dict_t *xdata) { STACK_WIND (frame, default_fremovexattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fremovexattr, fd, name); + 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; } @@ -705,376 +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, dict_t *dict) + 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, dict); + 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, uint32_t flags, - struct iobref *iobref) + struct iobref *iobref, dict_t *xdata) { - STACK_WIND (frame, default_writev_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->writev, fd, vector, count, off, - flags, 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, uint32_t flags) + 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, flags); + 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) + const char *name, dict_t *xdata) { - STACK_WIND (frame, default_fremovexattr_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fremovexattr, fd, name); + 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; } @@ -1082,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, dict_t *dict) + 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, dict); + 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; } @@ -1198,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; } @@ -1205,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; } @@ -1223,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; } @@ -1235,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; diff --git a/libglusterfs/src/defaults.h b/libglusterfs/src/defaults.h index f30bd8332..0747027bc 100644 --- a/libglusterfs/src/defaults.h +++ b/libglusterfs/src/defaults.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ /* libglusterfs/src/defaults.h: @@ -31,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,84 +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, - uint32_t flags); + uint32_t flags, dict_t *xdata); int32_t default_writev (call_frame_t *frame, xlator_t *this, @@ -127,218 +131,224 @@ int32_t default_writev (call_frame_t *frame, int32_t count, off_t offset, uint32_t flags, - struct iobref *iobref); + 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); + 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, dict_t *dict); + 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, uint32_t flags); + off_t offset, uint32_t flags, dict_t *xdata); int32_t default_writev_resume (call_frame_t *frame, xlator_t *this, @@ -346,345 +356,362 @@ int32_t default_writev_resume (call_frame_t *frame, struct iovec *vector, int32_t count, off_t offset, uint32_t flags, - struct iobref *iobref); + 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); + 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, dict_t *dict); + 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); + 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, diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c index fd9dd1cd7..3b7ddce5e 100644 --- a/libglusterfs/src/dict.c +++ b/libglusterfs/src/dict.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include <unistd.h> @@ -23,6 +14,7 @@ #include <stdio.h> #include <inttypes.h> #include <limits.h> +#include <fnmatch.h> #ifndef _CONFIG_H #define _CONFIG_H @@ -36,23 +28,14 @@ #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); - return data_pair_ptr; -} +#include "globals.h" data_t * get_new_data () { data_t *data = NULL; - data = (data_t *) GF_CALLOC (1, sizeof (data_t), gf_common_mt_data_t); + data = mem_get0 (THIS->ctx->dict_data_pool); if (!data) { return NULL; } @@ -64,19 +47,39 @@ get_new_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) { 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->members) { - GF_FREE (dict); - return NULL; + 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); @@ -143,13 +146,11 @@ data_destroy (data_t *data) else GF_FREE (data->data); } - if (data->vec) - GF_FREE (data->vec); } data->len = 0xbabababa; if (!data->is_const) - GF_FREE (data); + mem_put (data); } } @@ -162,9 +163,7 @@ data_copy (data_t *old) return NULL; } - data_t *newdata = (data_t *) GF_CALLOC (1, sizeof (*newdata), - gf_common_mt_data_t); - + data_t *newdata = mem_get0 (THIS->ctx->dict_data_pool); if (!newdata) { return NULL; } @@ -176,12 +175,6 @@ data_copy (data_t *old) 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; - } } LOCK_INIT (&newdata->lock); @@ -189,11 +182,8 @@ data_copy (data_t *old) err_out: - if (newdata->data) - FREE (newdata->data); - if (newdata->vec) - FREE (newdata->vec); - GF_FREE (newdata); + FREE (newdata->data); + mem_put (newdata); return NULL; } @@ -219,7 +209,7 @@ _dict_lookup (dict_t *this, char *key) } int32_t -dict_lookup (dict_t *this, char *key, data_pair_t **data) +dict_lookup (dict_t *this, char *key, data_t **data) { if (!this || !key || !data) { gf_log_callingfn ("dict", GF_LOG_WARNING, @@ -227,22 +217,22 @@ dict_lookup (dict_t *this, char *key, data_pair_t **data) return -1; } + data_pair_t *tmp = NULL; LOCK (&this->lock); { - *data = _dict_lookup (this, key); + tmp = _dict_lookup (this, key); } UNLOCK (&this->lock); - if (*data) - return 0; - else + + if (!tmp) return -1; + *data = tmp->value; + return 0; } static int32_t -_dict_set (dict_t *this, - char *key, - data_t *value) +_dict_set (dict_t *this, char *key, data_t *value, gf_boolean_t replace) { int hashval; data_pair_t *pair; @@ -261,34 +251,54 @@ _dict_set (dict_t *this, 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) { - return -1; - } + /* Search for a existing key if 'replace' is asked for */ + if (replace) { + pair = _dict_lookup (this, key); - pair->key = (char *) GF_CALLOC (1, strlen (key) + 1, - gf_common_mt_char); - if (!pair->key) { - GF_FREE (pair); + 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; + } + } - if (key_free) - GF_FREE (key); - return -1; + if (this->free_pair_in_use) { + pair = mem_get0 (THIS->ctx->dict_pair_pool); + if (!pair) { + if (key_free) + GF_FREE (key); + return -1; + } + } + else { + pair = &this->free_pair; + this->free_pair_in_use = _gf_true; } - strcpy (pair->key, key); + 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]; @@ -321,7 +331,28 @@ dict_set (dict_t *this, LOCK (&this->lock); - ret = _dict_set (this, key, value); + ret = _dict_set (this, key, value, 1); + + UNLOCK (&this->lock); + + return ret; +} + + +int32_t +dict_add (dict_t *this, char *key, data_t *value) +{ + int32_t ret; + + if (!this || !value) { + gf_log_callingfn ("dict", GF_LOG_WARNING, + "!this || !value for key=%s", key); + return -1; + } + + LOCK (&this->lock); + + ret = _dict_set (this, key, value, 0); UNLOCK (&this->lock); @@ -385,7 +416,12 @@ dict_del (dict_t *this, char *key) pair->next->prev = pair->prev; GF_FREE (pair->key); - GF_FREE (pair); + if (pair == &this->free_pair) { + this->free_pair_in_use = _gf_false; + } + else { + mem_put (pair); + } this->count--; break; } @@ -416,19 +452,21 @@ dict_destroy (dict_t *this) pair = pair->next; data_unref (prev->value); GF_FREE (prev->key); - GF_FREE (prev); + if (prev != &this->free_pair) { + mem_put (prev); + } prev = pair; } - GF_FREE (this->members); + if (this->members != &this->members_internal) { + mem_put (this->members); + } - if (this->extra_free) - GF_FREE (this->extra_free); - if (this->extra_stdfree) - free (this->extra_stdfree); + GF_FREE (this->extra_free); + free (this->extra_stdfree); if (!this->is_static) - GF_FREE (this); + mem_put (this); return; } @@ -509,236 +547,6 @@ data_ref (data_t *this) return this; } -/* - Serialization format: - ---- - Count:8 - Key_len:8:Value_len:8 - Key - Value - . - . - . -*/ - -int32_t -dict_serialized_length_old (dict_t *this) -{ - - if (!this) { - gf_log_callingfn ("dict", GF_LOG_WARNING, "dict is NULL"); - return -1; - } - - int32_t len = 9; /* count + \n */ - int32_t count = this->count; - data_pair_t *pair = this->members_list; - - while (count) { - len += 18; - len += strlen (pair->key) + 1; - if (pair->value->vec) { - int i; - for (i=0; i<pair->value->len; i++) { - len += pair->value->vec[i].iov_len; - } - } else { - len += pair->value->len; - } - pair = pair->next; - count--; - } - - return len; -} - -int32_t -dict_serialize_old (dict_t *this, char *buf) -{ - if (!this || !buf) { - gf_log_callingfn ("dict", GF_LOG_WARNING, "dict is NULL"); - return -1; - } - - data_pair_t *pair = this->members_list; - int32_t count = this->count; - uint64_t dcount = this->count; - - // FIXME: magic numbers - - sprintf (buf, "%08"PRIx64"\n", dcount); - buf += 9; - while (count) { - uint64_t keylen = strlen (pair->key) + 1; - uint64_t vallen = pair->value->len; - - sprintf (buf, "%08"PRIx64":%08"PRIx64"\n", keylen, vallen); - buf += 18; - memcpy (buf, pair->key, keylen); - buf += keylen; - memcpy (buf, pair->value->data, pair->value->len); - buf += pair->value->len; - pair = pair->next; - count--; - } - return (0); -} - - -dict_t * -dict_unserialize_old (char *buf, int32_t size, dict_t **fill) -{ - int32_t ret = 0; - int32_t cnt = 0; - - if (!buf || !fill || !(*fill)) { - gf_log_callingfn ("dict", GF_LOG_WARNING, "buf is 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; - } - - for (cnt = 0; cnt < count; cnt++) { - data_t *value = NULL; - char *key = NULL; - uint64_t key_len, value_len; - - ret = sscanf (buf, "%"SCNx64":%"SCNx64"\n", &key_len, &value_len); - if (ret != 2) { - gf_log ("dict", GF_LOG_ERROR, - "sscanf for key_len and value_len failed"); - goto err; - } - buf += 18; - - key = buf; - buf += key_len; - - value = get_new_data (); - value->len = value_len; - value->data = buf; - value->is_static = 1; - buf += value_len; - - dict_set (*fill, key, value); - } - - goto ret; - -err: - GF_FREE (*fill); - *fill = NULL; - -ret: - return *fill; -} - - -int32_t -dict_iovec_len (dict_t *this) -{ - if (!this) { - gf_log_callingfn ("dict", GF_LOG_WARNING, "dict is NULL"); - return -1; - } - - int32_t len = 0; - data_pair_t *pair = this->members_list; - - len++; /* initial header */ - while (pair) { - len++; /* pair header */ - len++; /* key */ - - if (pair->value->vec) - len += pair->value->len; - else - len++; - pair = pair->next; - } - - return len; -} - -int32_t -dict_to_iovec (dict_t *this, - struct iovec *vec, - int32_t count) -{ - if (!this || !vec) { - gf_log_callingfn ("dict", GF_LOG_WARNING, "dict is NULL"); - return -1; - } - - int32_t i = 0; - data_pair_t *pair = this->members_list; - - vec[0].iov_len = 9; - if (vec[0].iov_base) - sprintf (vec[0].iov_base, - "%08"PRIx64"\n", - (int64_t)this->count); - i++; - - while (pair) { - int64_t keylen = strlen (pair->key) + 1; - int64_t vallen = 0; - - if (pair->value->vec) { - int i; - - for (i=0; i<pair->value->len; i++) { - vallen += pair->value->vec[i].iov_len; - } - } else { - vallen = pair->value->len; - } - - vec[i].iov_len = 18; - if (vec[i].iov_base) - sprintf (vec[i].iov_base, - "%08"PRIx64":%08"PRIx64"\n", - keylen, - vallen); - i++; - - vec[i].iov_len = keylen; - vec[i].iov_base = pair->key; - i++; - - if (pair->value->vec) { - int k; - - for (k=0; k<pair->value->len; k++) { - vec[i].iov_len = pair->value->vec[k].iov_len; - vec[i].iov_base = pair->value->vec[k].iov_base; - i++; - } - } else { - vec[i].iov_len = pair->value->len; - vec[i].iov_base = pair->value->data; - i++; - } - - pair = pair->next; - } - - return 0; -} - data_t * int_to_data (int64_t value) { @@ -1088,6 +896,8 @@ data_to_int32 (data_t *data) int16_t data_to_int16 (data_t *data) { + int16_t value = 0; + if (!data) { gf_log_callingfn ("dict", GF_LOG_WARNING, "data is NULL"); return -1; @@ -1100,14 +910,25 @@ data_to_int16 (data_t *data) memcpy (str, data->data, data->len); str[data->len] = '\0'; - return strtol (str, NULL, 0); + errno = 0; + value = 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) { - int32_t value = 0; + int8_t value = 0; if (!data) { gf_log_callingfn ("dict", GF_LOG_WARNING, "data is NULL"); @@ -1121,15 +942,16 @@ data_to_int8 (data_t *data) memcpy (str, data->data, data->len); str[data->len] = '\0'; - errno = 0; - value = strtol (str, NULL, 0); + errno = 0; + value = strtol (str, NULL, 0); - if ((SCHAR_MAX > value) || (SCHAR_MIN < value)) { - errno = ERANGE; + if ((value > SCHAR_MAX) || (value < SCHAR_MIN)) { + errno = ERANGE; gf_log_callingfn ("dict", GF_LOG_WARNING, - "Error in data conversion: detected overflow"); + "Error in data conversion: " + "detected overflow"); return -1; - } + } return (int8_t)value; } @@ -1169,6 +991,8 @@ data_to_uint32 (data_t *data) uint16_t data_to_uint16 (data_t *data) { + uint16_t value = 0; + if (!data) return -1; @@ -1179,7 +1003,18 @@ data_to_uint16 (data_t *data) memcpy (str, data->data, data->len); str[data->len] = '\0'; - return strtol (str, NULL, 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 @@ -1243,47 +1078,141 @@ data_to_bin (data_t *data) 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), + 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; + 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; } -static void +/** + * 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 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 void +static int _remove (dict_t *dict, char *key, data_t *value, void *unused) { dict_del ((dict_t *)dict, key); + return 0; } @@ -2330,7 +2259,6 @@ _dict_serialized_length (dict_t *this) int ret = -EINVAL; int count = 0; int len = 0; - int i = 0; data_pair_t * pair = NULL; len = DICT_HDR_LEN; @@ -2365,28 +2293,15 @@ _dict_serialized_length (dict_t *this) 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; } + len += pair->value->len; + pair = pair->next; count--; } @@ -2661,6 +2576,7 @@ dict_unserialize (char *orig_buf, int32_t size, dict_t **fill) "available (%lu) < required (%lu)", (long)(orig_buf + size), (long)(buf + vallen)); + goto out; } value = get_new_data (); value->len = vallen; @@ -2668,7 +2584,7 @@ dict_unserialize (char *orig_buf, int32_t size, dict_t **fill) value->is_static = 0; buf += vallen; - dict_set (*fill, key, value); + dict_add (*fill, key, value); } ret = 0; @@ -2689,7 +2605,7 @@ out: */ 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; @@ -2826,3 +2742,40 @@ dict_serialize_value_with_delim (dict_t *this, char *buf, int32_t *serz_len, 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 8e81e539b..9b41b5a7d 100644 --- a/libglusterfs/src/dict.h +++ b/libglusterfs/src/dict.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _DICT_H @@ -38,13 +29,11 @@ typedef struct _data_pair data_pair_t; #define GF_PROTOCOL_DICT_SERIALIZE(this,from_dict,to,len,ope,labl) do { \ int ret = 0; \ - size_t dictlen = 0; \ \ if (!from_dict) \ break; \ \ - ret = dict_allocate_and_serialize (from_dict, to, \ - &dictlen); \ + 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)", \ @@ -52,32 +41,25 @@ typedef struct _data_pair data_pair_t; ope = EINVAL; \ goto labl; \ } \ - len = dictlen; \ } while (0) #define GF_PROTOCOL_DICT_UNSERIALIZE(xl,to,buff,len,ret,ope,labl) do { \ - char *buf = NULL; \ if (!len) \ break; \ to = dict_new(); \ GF_VALIDATE_OR_GOTO (xl->name, to, labl); \ \ - buf = memdup (buff, len); \ - GF_VALIDATE_OR_GOTO (xl->name, buf, labl); \ - \ - ret = dict_unserialize (buf, len, &to); \ + ret = dict_unserialize (buff, len, &to); \ if (ret < 0) { \ gf_log (xl->name, GF_LOG_WARNING, \ "failed to unserialize dictionary (%s)", \ (#to)); \ \ ope = EINVAL; \ - GF_FREE (buf); \ goto labl; \ } \ \ - to->extra_free = buf; \ } while (0) struct _data { @@ -85,7 +67,6 @@ struct _data { 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; @@ -109,13 +90,20 @@ struct _dict { 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); @@ -124,10 +112,7 @@ 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_iovec_len (dict_t *dict); -int32_t dict_to_iovec (dict_t *dict, struct iovec *vec, int32_t count); +int32_t dict_allocate_and_serialize (dict_t *this, char **buf, u_int *length); void dict_destroy (dict_t *dict); void dict_unref (dict_t *dict); @@ -135,7 +120,7 @@ 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_pair_t **data); +int32_t dict_lookup (dict_t *this, char *key, data_t **data); /* TODO: provide converts for differnt byte sizes, signedness, and void * */ @@ -178,16 +163,26 @@ 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); +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); @@ -237,4 +232,6 @@ 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 c117a4ae2..0197e7948 100644 --- a/libglusterfs/src/event.c +++ b/libglusterfs/src/event.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include <sys/poll.h> @@ -35,851 +26,17 @@ #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) { - 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; - - 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; -} - - -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) - 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) { - 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); - 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; -} - - -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; + extern struct event_ops event_ops_poll; #ifdef HAVE_SYS_EPOLL_H + extern struct event_ops event_ops_epoll; + event_pool = event_ops_epoll.new (count); if (event_pool) { diff --git a/libglusterfs/src/event.h b/libglusterfs/src/event.h index 0e87f0cd7..7ed182492 100644 --- a/libglusterfs/src/event.h +++ b/libglusterfs/src/event.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _EVENT_H_ @@ -30,8 +21,8 @@ struct event_pool; struct event_ops; struct event_data { - int fd; - int idx; + int fd; + int idx; } __attribute__ ((__packed__, __may_alias__)); @@ -39,28 +30,27 @@ 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 { 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 62a70c457..36cc4d056 100644 --- a/libglusterfs/src/fd.c +++ b/libglusterfs/src/fd.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include "fd.h" @@ -130,7 +121,7 @@ gf_fd_fdtable_alloc (void) } -fdentry_t * +static fdentry_t * __gf_fd_fdtable_get_all_fds (fdtable_t *fdtable, uint32_t *count) { fdentry_t *fdentries = NULL; @@ -168,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) { @@ -309,6 +347,54 @@ unlock_out: } +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) { @@ -401,7 +487,7 @@ fd_destroy (fd_t *fd) goto out; if (IA_ISDIR (fd->inode->ia_type)) { - for (i = 0; i < fd->xl_count; i++) { + for (i = 0; i < fd->xl_count; i++) { if (fd->_ctx[i].key) { xl = fd->_ctx[i].xl_key; old_THIS = THIS; @@ -427,8 +513,14 @@ fd_destroy (fd_t *fd) LOCK_DESTROY (&fd->lock); 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; + fd_lk_ctx_unref (fd->lk_ctx); mem_put (fd); out: return; @@ -463,7 +555,9 @@ fd_unref (fd_t *fd) fd_t * __fd_bind (fd_t *fd) { + list_del_init (&fd->inode_list); list_add (&fd->inode_list, &fd->inode->fd_list); + fd->inode->fd_count++; return fd; } @@ -488,7 +582,7 @@ fd_bind (fd_t *fd) static fd_t * -__fd_create (inode_t *inode, pid_t pid) +__fd_create (inode_t *inode, uint64_t pid) { fd_t *fd = NULL; @@ -505,11 +599,12 @@ __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) { - mem_put (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; @@ -518,6 +613,13 @@ __fd_create (inode_t *inode, pid_t pid) LOCK_INIT (&fd->lock); out: return fd; + +free_fd_ctx: + GF_FREE (fd->_ctx); +free_fd: + mem_put (fd); + + return NULL; } @@ -526,6 +628,21 @@ 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; @@ -538,7 +655,7 @@ out: static fd_t * -__fd_lookup (inode_t *inode, pid_t pid) +__fd_lookup (inode_t *inode, uint64_t pid) { fd_t *iter_fd = NULL; fd_t *fd = NULL; @@ -548,6 +665,12 @@ __fd_lookup (inode_t *inode, pid_t pid) 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; @@ -570,6 +693,25 @@ fd_lookup (inode_t *inode, pid_t pid) LOCK (&inode->lock); { + fd = __fd_lookup (inode, (uint64_t)pid); + } + UNLOCK (&inode->lock); + + return fd; +} + +fd_t * +fd_lookup_uint64 (inode_t *inode, uint64_t pid) +{ + fd_t *fd = NULL; + + if (!inode) { + gf_log_callingfn ("fd", GF_LOG_WARNING, "!inode"); + return NULL; + } + + LOCK (&inode->lock); + { fd = __fd_lookup (inode, pid); } UNLOCK (&inode->lock); @@ -577,25 +719,48 @@ fd_lookup (inode_t *inode, pid_t pid) 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; -fd_t * + 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 (inode, -1); + 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, -1); + fd = __fd_create (inode, 0); if (!fd) return NULL; + fd->anonymous = _gf_true; + __fd_bind (fd); - } - __fd_ref (fd); + __fd_ref (fd); + } return fd; } @@ -615,11 +780,28 @@ fd_anonymous (inode_t *inode) 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->pid == -1); + return (fd && fd->anonymous); } @@ -641,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; @@ -662,9 +847,33 @@ __fd_ctx_set (fd_t *fd, xlator_t *xlator, uint64_t value) } if (set_idx == -1) { - gf_log_callingfn ("", GF_LOG_WARNING, "%p %s", fd, xlator->name); - 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; @@ -797,9 +1006,16 @@ fd_dump (fd_t *fd, char *prefix) return; memset(key, 0, sizeof(key)); - gf_proc_dump_write("pid", "%d", fd->pid); + 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, "inode", NULL); + gf_proc_dump_add_section(key); + inode_dump (fd->inode, key); + } + } @@ -829,10 +1045,8 @@ fdtable_dump (fdtable_t *fdtable, char *prefix) 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"); @@ -852,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; } @@ -870,15 +1090,13 @@ 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) { 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]; } } @@ -890,7 +1108,7 @@ unlock: 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) @@ -899,9 +1117,7 @@ unlock: } out: - if (fd_ctx != NULL) { - GF_FREE (fd_ctx); - } + GF_FREE (fd_ctx); return; } diff --git a/libglusterfs/src/fd.h b/libglusterfs/src/fd.h index d4cd9bd06..c1b9157d8 100644 --- a/libglusterfs/src/fd.h +++ b/libglusterfs/src/fd.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _FD_H @@ -30,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,12 +41,8 @@ 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; struct list_head inode_list; @@ -59,6 +51,8 @@ struct _fd { '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; @@ -92,7 +86,7 @@ typedef struct _fdtable fdtable_t; #include "xlator.h" -inline void +void gf_fd_put (fdtable_t *fdtable, int32_t fd); @@ -117,6 +111,10 @@ gf_fd_fdtable_destroy (fdtable_t *fdtable); fd_t * +__fd_ref (fd_t *fd); + + +fd_t * fd_ref (fd_t *fd); @@ -127,10 +125,17 @@ 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); @@ -159,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); @@ -168,13 +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); #endif /* _FD_H */ diff --git a/libglusterfs/src/gf-dirent.c b/libglusterfs/src/gf-dirent.c index 8d15b0405..bb028c967 100644 --- a/libglusterfs/src/gf-dirent.c +++ b/libglusterfs/src/gf-dirent.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ diff --git a/libglusterfs/src/gf-dirent.h b/libglusterfs/src/gf-dirent.h index 29b4aba80..588d522db 100644 --- a/libglusterfs/src/gf-dirent.h +++ b/libglusterfs/src/gf-dirent.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ @@ -54,9 +45,10 @@ struct _gf_dirent_t { struct iatt d_stat; dict_t *dict; inode_t *inode; - char d_name[0]; + 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); 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 9355a3a46..259c5c885 100644 --- a/libglusterfs/src/globals.c +++ b/libglusterfs/src/globals.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -28,115 +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) { - gf_log_callingfn ("", GF_LOG_WARNING, "init called again"); - goto out; - } - - glusterfs_ctx = CALLOC (1, sizeof (*glusterfs_ctx)); - if (!glusterfs_ctx) { - ret = -1; - goto out; - } - - INIT_LIST_HEAD (&glusterfs_ctx->graphs); - INIT_LIST_HEAD (&glusterfs_ctx->mempool_list); - 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); } @@ -153,7 +103,6 @@ glusterfs_this_init () global_xlator.name = "glusterfs"; global_xlator.type = "global"; - global_xlator.ctx = glusterfs_ctx; INIT_LIST_HEAD (&global_xlator.volume_options); @@ -176,8 +125,6 @@ __glusterfs_this_location () ret = pthread_setspecific (this_xlator_key, this_location); if (ret != 0) { - gf_log ("", GF_LOG_WARNING, "pthread setspecific failed"); - FREE (this_location); this_location = NULL; goto out; @@ -219,10 +166,55 @@ glusterfs_this_set (xlator_t *this) return 0; } -/* SYNCTASK */ +/* SYNCOPCTX */ +static pthread_key_t syncopctx_key; -static pthread_key_t synctask_key; +static void +syncopctx_key_destroy (void *ptr) +{ + struct syncopctx *opctx = ptr; + if (opctx) { + if (opctx->groups) + GF_FREE (opctx->groups); + + GF_FREE (opctx); + } + + return; +} + +void * +syncopctx_getctx () +{ + void *opctx = NULL; + + opctx = pthread_getspecific (syncopctx_key); + + return opctx; +} + +int +syncopctx_setctx (void *ctx) +{ + int ret = 0; + + ret = pthread_setspecific (syncopctx_key, ctx); + + return ret; +} + +static int +syncopctx_init (void) +{ + int ret; + + ret = pthread_key_create (&syncopctx_key, syncopctx_key_destroy); + + return ret; +} + +/* SYNCTASK */ int synctask_init () @@ -234,7 +226,6 @@ synctask_init () return ret; } - void * synctask_get () { @@ -258,13 +249,10 @@ synctask_set (void *synctask) //UUID_BUFFER -static pthread_key_t uuid_buf_key; -static char global_uuid_buf[GF_UUID_BUF_SIZE]; void glusterfs_uuid_buf_destroy (void *ptr) { - if (ptr) - FREE (ptr); + FREE (ptr); } int @@ -287,7 +275,7 @@ glusterfs_uuid_buf_get () if(!buf) { buf = MALLOC (GF_UUID_BUF_SIZE); ret = pthread_setspecific (uuid_buf_key, (void *) buf); - if(ret) + if (ret) buf = global_uuid_buf; } return buf; @@ -295,13 +283,10 @@ glusterfs_uuid_buf_get () /* LKOWNER_BUFFER */ -static pthread_key_t lkowner_buf_key; -static char global_lkowner_buf[GF_LKOWNER_BUF_SIZE]; void glusterfs_lkowner_buf_destroy (void *ptr) { - if (ptr) - FREE (ptr); + FREE (ptr); } int @@ -324,27 +309,18 @@ glusterfs_lkowner_buf_get () if(!buf) { buf = MALLOC (GF_LKOWNER_BUF_SIZE); ret = pthread_setspecific (lkowner_buf_key, (void *) buf); - if(ret) + if (ret) buf = global_lkowner_buf; } return buf; } int -glusterfs_globals_init () +glusterfs_globals_init (glusterfs_ctx_t *ctx) { int ret = 0; - gf_op_list_init (); - - gf_log_globals_init (); - - ret = glusterfs_ctx_init (); - if (ret) { - gf_log ("", GF_LOG_CRITICAL, - "ERROR: glusterfs context init failed"); - goto out; - } + gf_log_globals_init (ctx); ret = glusterfs_this_init (); if (ret) { @@ -367,42 +343,19 @@ glusterfs_globals_init () goto out; } - gf_mem_acct_enable_set (); - ret = synctask_init (); if (ret) { gf_log ("", GF_LOG_CRITICAL, "ERROR: glusterfs synctask init failed"); goto out; } + + ret = syncopctx_init (); + if (ret) { + gf_log ("", GF_LOG_CRITICAL, + "ERROR: glusterfs syncopctx init failed"); + goto out; + } out: return ret; } - - -char eventstring[GF_EVENT_MAXVAL+1][64] = { - "Invalid event", - "Parent Up", - "Poll In", - "Poll Out", - "Poll Err", - "Child Up", - "Child Down", - "Child Connecting", - "Child Modified", - "Transport Cleanup", - "Transport Connected", - "Volfile Modified", - "New Volfile", - "Translator Info", - "Trigger Volume Heal", - "Authentication Failed", - "Invalid event", -}; - -/* 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 86e1f0324..3085db21c 100644 --- a/libglusterfs/src/globals.h +++ b/libglusterfs/src/globals.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _GLOBALS_H @@ -22,33 +13,50 @@ #define GF_DEFAULT_BASE_PORT 24007 -#include "glusterfs.h" - -/* CTX */ -#define CTX (glusterfs_ctx_get()) - -glusterfs_ctx_t *glusterfs_ctx_get (); +#define GD_OP_VERSION_KEY "operating-version" +#define GD_MIN_OP_VERSION_KEY "minimum-operating-version" +#define GD_MAX_OP_VERSION_KEY "maximum-operating-version" + +/* Gluster versions - OP-VERSION mapping + * + * 3.3.0 - 1 + * 3.4.0 - 2 + * 3.next (3.5?) - 3 + * + * TODO: Change above comment once gluster version is finalised + * TODO: Finalize the op-version ranges + */ +#define GD_OP_VERSION_MIN 1 /* MIN is the fresh start op-version, mostly + should not change */ +#define GD_OP_VERSION_MAX 3 /* MAX VERSION is the maximum count in VME table, + should keep changing with introduction of newer + versions */ #include "xlator.h" /* THIS */ #define THIS (*__glusterfs_this_location()) -#define GF_UUID_BUF_SIZE 50 - xlator_t **__glusterfs_this_location (); xlator_t *glusterfs_this_get (); int glusterfs_this_set (xlator_t *); +/* 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 8360077ec..2f1e12ee7 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _GLUSTERFS_H @@ -41,16 +32,23 @@ #include <arpa/inet.h> #include <sys/poll.h> #include <pthread.h> +#include <limits.h> /* For PATH_MAX */ #include "list.h" #include "logging.h" +#include "lkowner.h" #define GF_YES 1 #define GF_NO 0 #ifndef O_LARGEFILE /* savannah bug #20053, patch for compiling on darwin */ -#define O_LARGEFILE 0 +#define O_LARGEFILE 0100000 /* from bits/fcntl.h */ +#endif + +#ifndef O_FMODE_EXEC +/* redhat bug 843080, added from linux/fs.h */ +#define O_FMODE_EXEC 040 //0x20 #endif #ifndef O_DIRECT @@ -72,27 +70,63 @@ #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 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" @@ -109,16 +143,29 @@ #define GLUSTERFS_RPC_REPLY_SIZE 24 #define ZR_FILE_CONTENT_REQUEST(key) (!strncmp(key, ZR_FILE_CONTENT_STR, \ - ZR_FILE_CONTENT_STRLEN)) + ZR_FILE_CONTENT_STRLEN)) -/* TODO: Should we use PATH-MAX? On some systems it may save space */ -#define ZR_PATH_MAX 4096 +#define DEFAULT_VAR_RUN_DIRECTORY DATADIR "/run/gluster" +#define GF_REPLICATE_TRASH_DIR ".landfill" /* GlusterFS's maximum supported Auxilary GIDs */ /* TODO: Keeping it to 200, so that we can fit in 2KB buffer for auth data * in RPC server code, if there is ever need for having more aux-gids, then * we have to add aux-gid in payload of actors */ -#define GF_MAX_AUX_GROUPS 200 +#define GF_MAX_AUX_GROUPS 65536 + +#define GF_UUID_BUF_SIZE 50 + +#define GF_REBALANCE_TID_KEY "rebalance-id" +#define GF_REMOVE_BRICK_TID_KEY "remove-brick-id" +#define GF_REPLACE_BRICK_TID_KEY "replace-brick-id" + +#define UUID_CANONICAL_FORM_LEN 36 + +/* Adding this here instead of any glusterd*.h files as it is also required by + * cli + */ +#define DEFAULT_GLUSTERD_SOCKFILE DATADIR "/run/glusterd.socket" /* NOTE: add members ONLY at the end (just before _MAXVALUE) */ typedef enum { @@ -153,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, @@ -168,6 +215,9 @@ typedef enum { GF_FOP_RELEASEDIR, GF_FOP_GETSPEC, GF_FOP_FREMOVEXATTR, + GF_FOP_FALLOCATE, + GF_FOP_DISCARD, + GF_FOP_ZEROFILL, GF_FOP_MAXVALUE, } glusterfs_fop_t; @@ -217,21 +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_ARRAY64 + GF_XATTROP_ADD_ARRAY, + GF_XATTROP_ADD_ARRAY64, + GF_XATTROP_OR_ARRAY, + GF_XATTROP_AND_ARRAY } gf_xattrop_flags_t; @@ -240,68 +292,79 @@ 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; + char *pid_file; char *sock_file; - int no_daemon_mode; - char *run_id; - int debug_mode; + 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; + 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; + /* key args */ + char *mount_point; + char *volfile_id; /* required for portmap */ int brick_port; @@ -326,17 +389,19 @@ struct _glusterfs_graph { 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 */ @@ -350,21 +415,34 @@ struct _glusterfs_ctx { int graph_id; /* Incremented per graph, value should indicate how many times the graph has got changed */ - pid_t mtab_pid; /* pid of the process which updates the mtab */ + 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 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; + 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, @@ -379,14 +457,14 @@ typedef enum { GF_EVENT_VOLFILE_MODIFIED, GF_EVENT_GRAPH_NEW, GF_EVENT_TRANSLATOR_INFO, - GF_EVENT_TRIGGER_HEAL, + 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; -/* gf_lkowner_t is defined in lkowner.h */ -#include "lkowner.h" - struct gf_flock { short l_type; short l_whence; @@ -396,9 +474,6 @@ struct gf_flock { gf_lkowner_t l_owner; }; - -extern char *glusterfs_strevent (glusterfs_event_t ev); - #define GF_MUST_CHECK __attribute__((warn_unused_result)) /* * Some macros (e.g. ALLOC_OR_GOTO) set variables in function scope, but the diff --git a/libglusterfs/src/graph-print.c b/libglusterfs/src/graph-print.c index 432f9a1de..d860d63b3 100644 --- a/libglusterfs/src/graph-print.c +++ b/libglusterfs/src/graph-print.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -33,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 @@ -89,19 +81,31 @@ gpprintf (struct gf_printer *gp, const char *format, ...) return ret; } -static int -glusterfs_graph_print (struct gf_printer *gp, glusterfs_graph_t *graph) -{ #define GPPRINTF(gp, fmt, ...) do { \ ret = gpprintf (gp, fmt, ## __VA_ARGS__); \ if (ret == -1) \ goto out; \ else \ - len += ret; \ + gp->len += ret; \ } while (0) +static int +_print_volume_options (dict_t *d, char *k, data_t *v, + void *tmp) +{ + struct gf_printer *gp = tmp; + int ret = 0; + GPPRINTF (gp, " option %s %s\n", k, v->data); + return 0; +out: + /* means, it is a failure */ + return -1; +} + +static int +glusterfs_graph_print (struct gf_printer *gp, glusterfs_graph_t *graph) +{ xlator_t *trav = NULL; - data_pair_t *pair = NULL; xlator_list_t *xch = NULL; int ret = 0; ssize_t len = 0; @@ -114,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,6 +137,7 @@ glusterfs_graph_print (struct gf_printer *gp, glusterfs_graph_t *graph) } out: + len = gp->len; if (ret == -1) { gf_log ("graph-print", GF_LOG_ERROR, "printing failed"); diff --git a/libglusterfs/src/graph-utils.h b/libglusterfs/src/graph-utils.h index d125fbe0d..207664fdb 100644 --- a/libglusterfs/src/graph-utils.h +++ b/libglusterfs/src/graph-utils.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _GRAPH_H_ diff --git a/libglusterfs/src/graph.c b/libglusterfs/src/graph.c index 830c88363..e76df1ca5 100644 --- a/libglusterfs/src/graph.c +++ b/libglusterfs/src/graph.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -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"); @@ -131,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; @@ -157,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", @@ -187,7 +176,7 @@ glusterfs_graph_acl (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) return 0; ret = glusterfs_graph_insert (graph, ctx, "system/posix-acl", - "posix-acl-autoload"); + "posix-acl-autoload", 1); return ret; } @@ -203,7 +192,7 @@ glusterfs_graph_worm (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) return 0; ret = glusterfs_graph_insert (graph, ctx, "features/worm", - "worm-autoload"); + "worm-autoload", 1); return ret; } @@ -219,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) @@ -310,7 +314,7 @@ glusterfs_graph_init (glusterfs_graph_t *graph) } -static void +static int _log_if_unknown_option (dict_t *dict, char *key, data_t *value, void *data) { volume_option_t *found = NULL; @@ -325,7 +329,7 @@ _log_if_unknown_option (dict_t *dict, char *key, data_t *value, void *data) "option '%s' is not recognized", key); } - return; + return 0; } @@ -349,8 +353,7 @@ 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, @@ -364,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); @@ -454,6 +456,14 @@ glusterfs_graph_prepare (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) return -1; } + /* XXX: gfid-access */ + ret = glusterfs_graph_gfid_access (graph, ctx); + if (ret) { + gf_log ("graph", GF_LOG_ERROR, + "glusterfs graph 'gfid-access' failed"); + return -1; + } + /* XXX: this->ctx setting */ for (trav = graph->first; trav; trav = trav->next) { trav->ctx = ctx; @@ -505,11 +515,14 @@ 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) { - gf_log ("graph", GF_LOG_ERROR, "graph new notification failed"); - 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 */ @@ -522,18 +535,204 @@ glusterfs_graph_activate (glusterfs_graph_t *graph, glusterfs_ctx_t *ctx) 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); } @@ -541,5 +740,12 @@ glusterfs_graph_reconfigure (glusterfs_graph_t *oldgraph, int glusterfs_graph_destroy (glusterfs_graph_t *graph) { + xlator_tree_free (graph->first); + + if (graph) { + list_del_init (&graph->list); + GF_FREE (graph); + } + return 0; } diff --git a/libglusterfs/src/graph.l b/libglusterfs/src/graph.l index 04fff2582..e4eba9cbe 100644 --- a/libglusterfs/src/graph.l +++ b/libglusterfs/src/graph.l @@ -1,23 +1,13 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ - %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 62c57dd6c..a220abeb9 100644 --- a/libglusterfs/src/graph.y +++ b/libglusterfs/src/graph.y @@ -1,23 +1,13 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ - %token VOLUME_BEGIN VOLUME_END OPTION NEWLINE SUBVOLUME ID WHITESPACE COMMENT TYPE STRING_TOK %{ @@ -28,6 +18,7 @@ #include <sys/mman.h> #include <sys/types.h> #include <sys/wait.h> +#include <pthread.h> #define RELAX_POISONING @@ -47,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 (); %} @@ -88,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; } @@ -100,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; } @@ -112,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; } @@ -125,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; @@ -139,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; } @@ -159,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; } @@ -204,7 +195,7 @@ out: static int volume_type (char *type) { - extern int yylineno; + extern int graphyylineno; int32_t ret = 0; if (!type) { @@ -218,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; } @@ -235,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; @@ -252,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; } @@ -271,7 +262,7 @@ out: static int volume_sub (char *sub) { - extern int yylineno; + extern int graphyylineno; xlator_t *trav = NULL; int ret = 0; @@ -293,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; } @@ -301,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; } @@ -338,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'"); } @@ -386,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; @@ -491,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; } @@ -532,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); @@ -539,7 +532,7 @@ out: } -extern FILE *yyin; +extern FILE *graphyyin; glusterfs_graph_t * glusterfs_graph_new () @@ -563,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 b5752956c..f79165b22 100644 --- a/libglusterfs/src/hashfn.c +++ b/libglusterfs/src/hashfn.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include <stdint.h> diff --git a/libglusterfs/src/hashfn.h b/libglusterfs/src/hashfn.h index af306745b..06ae37e79 100644 --- a/libglusterfs/src/hashfn.h +++ b/libglusterfs/src/hashfn.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef __HASHFN_H__ diff --git a/libglusterfs/src/iatt.h b/libglusterfs/src/iatt.h index b84eaa379..60ae59047 100644 --- a/libglusterfs/src/iatt.h +++ b/libglusterfs/src/iatt.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ @@ -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) { @@ -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 4685ec8d2..15e0ccf78 100644 --- a/libglusterfs/src/inode.c +++ b/libglusterfs/src/inode.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -143,8 +134,7 @@ __dentry_unset (dentry_t *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); @@ -320,7 +310,7 @@ __inode_destroy (inode_t *inode) goto noctx; } - 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; @@ -538,10 +528,9 @@ __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), + newi->_ctx = GF_CALLOC (1, + (sizeof (struct _inode_ctx) * table->ctxcount), gf_common_mt_inode_ctx); - if (newi->_ctx == NULL) { LOCK_DESTROY (&newi->lock); mem_put (newi); @@ -660,6 +649,50 @@ inode_grep (inode_table_t *table, inode_t *parent, const char *name) return inode; } + +inode_t * +inode_resolve (inode_table_t *table, char *path) +{ + 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; +} + + int inode_grep_for_gfid (inode_table_t *table, inode_t *parent, const char *name, uuid_t gfid, ia_type_t *type) @@ -795,24 +828,36 @@ __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->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; @@ -902,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) @@ -1038,8 +1131,9 @@ __inode_path (inode_t *inode, const char *name, char **bufp) int len = 0; char *buf = NULL; - if (!inode) { - gf_log_callingfn (THIS->name, GF_LOG_WARNING, "inode not found"); + if (!inode || uuid_is_null (inode->gfid)) { + GF_ASSERT (0); + gf_log_callingfn (THIS->name, GF_LOG_WARNING, "invalid inode"); return -1; } @@ -1096,7 +1190,7 @@ __inode_path (inode_t *inode, const char *name, char **bufp) if (!__is_root_gfid (itrav->gfid)) { snprintf (&buf[i-GFID_STR_PFX_LEN], GFID_STR_PFX_LEN, - "<gfid:%s>", uuid_utoa (itrav->gfid)); + INODE_PATH_FMT, uuid_utoa (itrav->gfid)); buf[i-1] = '>'; } @@ -1108,9 +1202,7 @@ __inode_path (inode_t *inode, const char *name, char **bufp) 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, "/"); @@ -1206,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; } @@ -1223,6 +1315,7 @@ 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; @@ -1254,7 +1347,9 @@ inode_table_new (size_t lru_limit, xlator_t *xl) 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) goto out; @@ -1286,10 +1381,8 @@ inode_table_new (size_t lru_limit, xlator_t *xl) out: if (ret) { if (new) { - if (new->inode_hash) - GF_FREE (new->inode_hash); - if (new->name_hash) - GF_FREE (new->name_hash); + GF_FREE (new->inode_hash); + GF_FREE (new->name_hash); if (new->dentry_pool) mem_pool_destroy (new->dentry_pool); if (new->inode_pool) @@ -1355,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; @@ -1374,7 +1466,7 @@ __inode_ctx_set2 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p, 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 (set_idx == -1) set_idx = index; @@ -1401,6 +1493,18 @@ 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_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, @@ -1420,34 +1524,97 @@ inode_ctx_set2 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p, 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); + + return ret; +} + int __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; } @@ -1470,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, @@ -1483,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; @@ -1508,6 +1710,97 @@ unlock: return ret; } +/* function behavior: + - if value1 is set, value1 in ctx is reset to 0 with current value passed + back in value1 address. + - if value2 is set, value2 in ctx is reset to 0 with current value passed + back in value2 address. + - if both are set, both fields are reset. +*/ +static int +__inode_ctx_reset2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2) +{ + int index = 0; + int ret = 0; + + if (!inode || !xlator) + return -1; + + LOCK (&inode->lock); + { + for (index = 0; index < inode->table->ctxcount; + index++) { + if (inode->_ctx[index].xl_key == xlator) + break; + } + + if (index == inode->table->ctxcount) { + ret = -1; + goto unlock; + } + + if (inode->_ctx[index].value1 && value1) { + *value1 = inode->_ctx[index].value1; + inode->_ctx[index].value1 = 0; + } + if (inode->_ctx[index].value2 && value2) { + *value2 = inode->_ctx[index].value2; + inode->_ctx[index].value2 = 0; + } + } +unlock: + UNLOCK (&inode->lock); + + return ret; +} + +int +inode_ctx_reset2 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p, + uint64_t *value2_p) +{ + uint64_t tmp_value1 = 0; + uint64_t tmp_value2 = 0; + int ret = 0; + + ret = __inode_ctx_reset2 (inode, xlator, &tmp_value1, &tmp_value2); + if (!ret) { + if (value1_p) + *value1_p = tmp_value1; + if (value2_p) + *value2_p = tmp_value2; + } + return ret; +} + +int +inode_ctx_reset1 (inode_t *inode, xlator_t *xlator, uint64_t *value2_p) +{ + uint64_t tmp_value2 = 0; + int ret = 0; + + ret = __inode_ctx_reset2 (inode, xlator, NULL, &tmp_value2); + + if (!ret && value2_p) + *value2_p = tmp_value2; + + return ret; + +} +int +inode_ctx_reset0 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p) +{ + uint64_t tmp_value1 = 0; + int ret = 0; + + ret = __inode_ctx_reset2 (inode, xlator, &tmp_value1, NULL); + + if (!ret && value1_p) + *value1_p = tmp_value1; + + return ret; +} + void inode_dump (inode_t *inode, char *prefix) @@ -1517,10 +1810,6 @@ inode_dump (inode_t *inode, char *prefix) int i = 0; 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) @@ -1536,43 +1825,36 @@ inode_dump (inode_t *inode, char *prefix) { 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) { 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) { - 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) @@ -1581,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; } @@ -1650,7 +1918,7 @@ inode_dump_to_dict (inode_t *inode, char *prefix, dict_t *dict) memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.gfid", prefix); - ret = dict_set_str (dict, key, gf_strdup (uuid_utoa (inode->gfid))); + ret = dict_set_dynstr (dict, key, gf_strdup (uuid_utoa (inode->gfid))); if (ret) goto out; diff --git a/libglusterfs/src/inode.h b/libglusterfs/src/inode.h index 7dda0401d..a88976265 100644 --- a/libglusterfs/src/inode.h +++ b/libglusterfs/src/inode.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _INODE_H @@ -28,7 +19,8 @@ #include <stdint.h> #include <sys/types.h> -#define DEFAULT_INODE_MEMPOOL_ENTRIES 16384 +#define DEFAULT_INODE_MEMPOOL_ENTRIES 32 * 1024 +#define INODE_PATH_FMT "<gfid:%s>" struct _inode_table; typedef struct _inode_table inode_table_t; @@ -64,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 */ }; @@ -80,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; @@ -95,6 +90,7 @@ 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 */ ia_type_t ia_type; /* what kind of file */ struct list_head fd_list; /* list of open files on this inode */ @@ -139,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); @@ -162,6 +161,11 @@ __inode_path (inode_t *inode, const char *name, char **bufp); inode_t * inode_from_path (inode_table_t *table, const char *path); +inode_t * +inode_resolve (inode_table_t *table, char *path); + +/* deal with inode ctx's both values */ + int inode_ctx_set2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, uint64_t *value2); @@ -180,26 +184,66 @@ int inode_ctx_del2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, uint64_t *value2); -#define __inode_ctx_set(i,x,v_p) __inode_ctx_set2(i,x,v_p,0) -#define inode_ctx_set(i,x,v_p) inode_ctx_set2(i,x,v_p,0) +int +inode_ctx_reset2 (inode_t *inode, xlator_t *xlator, uint64_t *value1, + uint64_t *value2); + +/* deal with inode ctx's 1st value */ + +int +inode_ctx_set0 (inode_t *inode, xlator_t *xlator, uint64_t *value1); + +int +__inode_ctx_set0 (inode_t *inode, xlator_t *xlator, uint64_t *value1); + +int +inode_ctx_get0 (inode_t *inode, xlator_t *xlator, uint64_t *value1); +int +__inode_ctx_get0 (inode_t *inode, xlator_t *xlator, uint64_t *value1); + +int +inode_ctx_reset0 (inode_t *inode, xlator_t *xlator, uint64_t *value1); + +/* deal with inode ctx's 2st value */ + +int +inode_ctx_set1 (inode_t *inode, xlator_t *xlator, uint64_t *value2); + +int +__inode_ctx_set1 (inode_t *inode, xlator_t *xlator, uint64_t *value2); + +int +inode_ctx_get1 (inode_t *inode, xlator_t *xlator, uint64_t *value2); +int +__inode_ctx_get1 (inode_t *inode, xlator_t *xlator, uint64_t *value2); + +int +inode_ctx_reset1 (inode_t *inode, xlator_t *xlator, uint64_t *value2); + static inline int __inode_ctx_put(inode_t *inode, xlator_t *this, uint64_t v) { - return __inode_ctx_set2 (inode, this, &v, 0); + 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_set2(inode, this, &v, 0); + return inode_ctx_set0 (inode, this, &v); } -#define __inode_ctx_get(i,x,v) __inode_ctx_get2(i,x,v,0) -#define inode_ctx_get(i,x,v) inode_ctx_get2(i,x,v,0) +#define __inode_ctx_set(i,x,v_p) __inode_ctx_set0(i,x,v_p) -#define inode_ctx_del(i,x,v) inode_ctx_del2(i,x,v,0) +#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); diff --git a/libglusterfs/src/iobuf.c b/libglusterfs/src/iobuf.c index 93bc7732e..a89e96267 100644 --- a/libglusterfs/src/iobuf.c +++ b/libglusterfs/src/iobuf.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ @@ -317,6 +308,31 @@ 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 (void) @@ -333,7 +349,7 @@ iobuf_pool_new (void) goto out; pthread_mutex_init (&iobuf_pool->mutex, NULL); - for (i = 0; i < IOBUF_ARENA_MAX_INDEX; i++) { + 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]); @@ -351,6 +367,9 @@ iobuf_pool_new (void) 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: @@ -509,6 +528,50 @@ out: } struct iobuf * +iobuf_get_from_stdalloc (struct iobuf_pool *iobuf_pool, size_t page_size) +{ + 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; @@ -521,10 +584,17 @@ iobuf_get2 (struct iobuf_pool *iobuf_pool, size_t page_size) rounded_size = gf_iobuf_get_pagesize (page_size); if (rounded_size == -1) { - gf_log ("iobuf", GF_LOG_ERROR, "page_size (%zu) of " - "iobufs in arena being requested is greater than max " - "available", page_size); - return NULL; + /* 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); @@ -593,9 +663,13 @@ __iobuf_put (struct iobuf *iobuf, struct iobuf_arena *iobuf_arena) index = gf_iobuf_get_arena_index (iobuf_arena->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", iobuf_arena->page_size); + 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; } @@ -767,6 +841,29 @@ out: } +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; +} + + int __iobref_add (struct iobref *iobref, struct iobuf *iobuf) { @@ -967,6 +1064,8 @@ iobuf_stats_dump (struct iobuf_pool *iobuf_pool) 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) { diff --git a/libglusterfs/src/iobuf.h b/libglusterfs/src/iobuf.h index d0f868286..5595309e1 100644 --- a/libglusterfs/src/iobuf.h +++ b/libglusterfs/src/iobuf.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _IOBUF_H_ @@ -40,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; @@ -71,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 */ }; @@ -113,21 +112,17 @@ struct iobuf_pool { int arena_cnt; 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 - */ + /* 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 - */ + /* array of arenas without free iobufs */ struct list_head purge[GF_VARIABLE_IOBUF_COUNT]; - /* - array of of arenas which can be - purged - */ + /* array of of arenas which can be purged */ + + uint64_t request_misses; /* mostly the requests for higher + value of iobufs */ }; @@ -155,7 +150,7 @@ 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); diff --git a/libglusterfs/src/latency.c b/libglusterfs/src/latency.c index dfce235c0..b22f72950 100644 --- a/libglusterfs/src/latency.c +++ b/libglusterfs/src/latency.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ @@ -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; @@ -145,6 +136,22 @@ gf_update_latency (call_frame_t *frame) 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,23 +164,22 @@ 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); } + + 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_INFO, diff --git a/libglusterfs/src/latency.h b/libglusterfs/src/latency.h index 70499d4ba..81acbf484 100644 --- a/libglusterfs/src/latency.h +++ b/libglusterfs/src/latency.h @@ -1,25 +1,17 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef __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 db4e1ab30..392c22ceb 100644 --- a/libglusterfs/src/list.h +++ b/libglusterfs/src/list.h @@ -1,26 +1,16 @@ /* - Copyright (c) 2008-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2014 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _LLIST_H #define _LLIST_H - struct list_head { struct list_head *next; struct list_head *prev; @@ -54,6 +44,31 @@ list_add_tail (struct list_head *new, struct list_head *head) } +/* This function will insert the element to the list in a order. + Order will be based on the compare function provided as a input. + If element to be inserted in ascending order compare should return: + 0: if both the arguments are equal + >0: if first argument is greater than second argument + <0: if first argument is less than second argument */ +static inline void +list_add_order (struct list_head *new, struct list_head *head, + int (*compare)(struct list_head *, struct list_head *)) +{ + struct list_head *pos = head->prev; + + while ( pos != head ) { + if (compare(new, pos) >= 0) + break; + + /* Iterate the list in the reverse order. This will have + better efficiency if the elements are inserted in the + ascending order */ + pos = pos->prev; + } + + list_add (new, pos); +} + static inline void list_del (struct list_head *old) { @@ -184,4 +199,16 @@ list_append_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 index 5fee17b3d..969d13e50 100644 --- a/libglusterfs/src/lkowner.h +++ b/libglusterfs/src/lkowner.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2012 Red Hat <http://www.redhat.com/> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> This file is part of GlusterFS. - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _LK_OWNER_H @@ -49,7 +40,7 @@ lkowner_unparse (gf_lkowner_t *lkowner, char *buf, int buf_len) buf[j] = '-'; j++; } - sprintf (&buf[j], "%02x", lkowner->data[i]); + sprintf (&buf[j], "%02hhx", lkowner->data[i]); j += 2; if (j == buf_len) break; diff --git a/libglusterfs/src/locking.h b/libglusterfs/src/locking.h index 44ea12eee..79c6992af 100644 --- a/libglusterfs/src/locking.h +++ b/libglusterfs/src/locking.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _LOCKING_H diff --git a/libglusterfs/src/logging.c b/libglusterfs/src/logging.c index 5485260bc..5deb90cda 100644 --- a/libglusterfs/src/logging.c +++ b/libglusterfs/src/logging.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -31,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,50 +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_INFO; -static int gf_log_syslog = 1; -static gf_loglevel_t sys_log_level = GF_LOG_CRITICAL; - -char gf_log_xl_log_set; -gf_loglevel_t gf_log_loglevel = GF_LOG_INFO; /* 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; } @@ -105,98 +103,312 @@ 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); +} + + +#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) +{ + int _option = option; + int _facility = facility; + + if (-1 == _option) { + _option = LOG_PID | LOG_NDELAY; + } + if (-1 == _facility) { + _facility = LOG_LOCAL1; + } + + setlocale(LC_ALL, ""); + bindtextdomain("gluster", "/usr/share/locale"); + textdomain("gluster"); + + openlog(ident, _option, _facility); } +/** + * _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; + } + + for (p = (unsigned char *)str; + *p && (pos + 1) < len; + p++) + { + if (json_exceptions[*p] == 0) { + buf[pos++] = *p; + continue; + } + + 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; +} + + +/** + * gf_syslog -function to submit message to syslog specific to gluster + * @error_code: error code defined by log book + * @facility_priority: facility_priority of syslog() + * @format: optional format string to syslog() + * + * @return: void + */ +void +gf_syslog (int error_code, int facility_priority, char *format, ...) +{ + char *msg = NULL; + char json_msg[GF_JSON_MSG_LENGTH]; + GF_UNUSED char *p = NULL; + const char *error_message = NULL; + char json_error_message[GF_JSON_MSG_LENGTH]; + va_list ap; + + error_message = gf_get_error_message (error_code); + + va_start (ap, format); + if (format) { + vasprintf (&msg, format, ap); + p = _json_escape (msg, json_msg, GF_JSON_MSG_LENGTH); + if (error_message) { + p = _json_escape (error_message, json_error_message, + GF_JSON_MSG_LENGTH); + syslog (facility_priority, GF_SYSLOG_CEE_FORMAT, + json_msg, error_code, json_error_message); + } else { + /* ignore the error code because no error message for it + and use normal syslog */ + syslog (facility_priority, "%s", msg); + } + free (msg); + } else { + if (error_message) { + /* no user message: treat error_message as msg */ + syslog (facility_priority, GF_SYSLOG_CEE_FORMAT, + json_error_message, error_code, + json_error_message); + } else { + /* cannot produce log as neither error_message nor + msg available */ + } + } + va_end (ap); +} +#endif /* GF_USE_SYSLOG */ + void -gf_log_globals_init (void) +gf_log_globals_init (void *data) { - pthread_mutex_init (&logfile_mutex, NULL); + 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 (const char *file) +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) { - gf_log_logfile = stderr; - + ctx->log.gf_log_logfile = stderr; + ctx->log.logfile = stderr; return 0; } - filename = gf_strdup (file); - if (!filename) { + ctx->log.filename = gf_strdup (file); + if (!ctx->log.filename) { fprintf (stderr, "ERROR: updating log-filename failed: %s\n", strerror (errno)); return -1; } - logfile = fopen (file, "a"); - if (!logfile){ + 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; } - gf_log_logfile = logfile; + ctx->log.gf_log_logfile = ctx->log.logfile; return 0; } - - -struct _msg_queue { - struct list_head msgs; -}; - -struct _log_msg { - const char *msg; - struct list_head queue; -}; - - -void -gf_log_lock (void) -{ - pthread_mutex_lock (&logfile_mutex); -} - - -void -gf_log_unlock (void) -{ - pthread_mutex_unlock (&logfile_mutex); -} - - -void -gf_log_cleanup (void) -{ - pthread_mutex_destroy (&logfile_mutex); -} - void set_sys_log_level (gf_loglevel_t level) { - sys_log_level = level; + THIS->ctx->log.sys_log_level = level; } int @@ -205,22 +417,23 @@ _gf_log_nomem (const char *domain, const char *file, size_t size) { const char *basename = NULL; - struct tm *tm = NULL; xlator_t *this = NULL; struct timeval tv = {0,}; int ret = 0; - char msg[8092]; - char timestr[256]; - char callstr[4096]; + char msg[8092] = {0,}; + char timestr[256] = {0,}; + char callstr[4096] = {0,}; + glusterfs_ctx_t *ctx = NULL; this = THIS; + ctx = this->ctx; - if (gf_log_xl_log_set) { + if (ctx->log.gf_log_xl_log_set) { if (this->loglevel && (level > this->loglevel)) goto out; - else if (level > gf_log_loglevel) - goto out; } + if (level > ctx->log.loglevel) + goto out; static char *level_strings[] = {"", /* NONE */ "M", /* EMERGENCY */ @@ -241,6 +454,12 @@ _gf_log_nomem (const char *domain, const char *file, return -1; } + basename = strrchr (file, '/'); + if (basename) + basename++; + else + basename = file; + #if HAVE_BACKTRACE /* Print 'calling function' */ do { @@ -267,36 +486,45 @@ _gf_log_nomem (const char *domain, const char *file, } 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); - tm = localtime (&tv.tv_sec); + 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 (&logfile_mutex); + pthread_mutex_lock (&ctx->log.logfile_mutex); { - 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 = 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 unlock; - } - - if (logfile) { - fprintf (logfile, "%s\n", msg); - fflush (logfile); + if (ctx->log.logfile) { + fprintf (ctx->log.logfile, "%s\n", msg); } else { fprintf (stderr, "%s\n", msg); } @@ -304,13 +532,13 @@ _gf_log_nomem (const char *domain, const char *file, #ifdef GF_LINUX_HOST_OS /* We want only serious log in 'syslog', not our debug and trace logs */ - if (gf_log_syslog && level && (level <= sys_log_level)) + 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); out: return ret; } @@ -320,7 +548,6 @@ _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; xlator_t *this = NULL; char *str1 = NULL; char *str2 = NULL; @@ -331,15 +558,17 @@ _gf_log_callingfn (const char *domain, const char *file, const char *function, size_t len = 0; int ret = 0; va_list ap; + glusterfs_ctx_t *ctx = NULL; this = THIS; + ctx = this->ctx; - if (gf_log_xl_log_set) { + if (ctx->log.gf_log_xl_log_set) { if (this->loglevel && (level > this->loglevel)) goto out; - else if (level > gf_log_loglevel) - goto out; } + if (level > ctx->log.loglevel) + goto out; static char *level_strings[] = {"", /* NONE */ "M", /* EMERGENCY */ @@ -360,6 +589,12 @@ _gf_log_callingfn (const char *domain, const char *file, const char *function, return -1; } + basename = strrchr (file, '/'); + if (basename) + basename++; + else + basename = file; + #if HAVE_BACKTRACE /* Print 'calling function' */ do { @@ -386,50 +621,65 @@ _gf_log_callingfn (const char *domain, const char *file, const char *function, } 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); - - 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] %s %d-%s: ", - timestr, level_strings[level], - basename, line, function, callstr, - ((this->graph) ? this->graph->id:0), domain); - if (-1 == ret) { - goto unlock; - } + 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; + } - ret = vasprintf (&str2, fmt, ap); - if (-1 == ret) { - goto unlock; - } + ret = vasprintf (&str2, fmt, ap); + if (-1 == ret) { + goto out; + } - 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); - if (logfile) { - fprintf (logfile, "%s\n", msg); - fflush (logfile); + pthread_mutex_lock (&ctx->log.logfile_mutex); + { + if (ctx->log.logfile) { + fprintf (ctx->log.logfile, "%s\n", msg); } else { fprintf (stderr, "%s\n", msg); } @@ -437,25 +687,21 @@ _gf_log_callingfn (const char *domain, const char *file, const char *function, #ifdef GF_LINUX_HOST_OS /* We want only serious log in 'syslog', not our debug and trace logs */ - if (gf_log_syslog && level && (level <= sys_log_level)) + 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; } @@ -463,28 +709,29 @@ int _gf_log (const char *domain, const char *file, const char *function, int line, gf_loglevel_t level, const char *fmt, ...) { - const char *basename = NULL; - FILE *new_logfile = NULL; - va_list ap; - 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; + char *str1 = NULL; + char *str2 = NULL; + char *msg = NULL; + size_t len = 0; + int ret = 0; + int fd = -1; + xlator_t *this = NULL; + glusterfs_ctx_t *ctx = NULL; this = THIS; + ctx = this->ctx; - if (gf_log_xl_log_set) { + if (ctx->log.gf_log_xl_log_set) { if (this->loglevel && (level > this->loglevel)) goto out; - else if (level > gf_log_loglevel) - goto out; } + if (level > ctx->log.loglevel) + goto out; static char *level_strings[] = {"", /* NONE */ "M", /* EMERGENCY */ @@ -505,124 +752,221 @@ _gf_log (const char *domain, const char *file, const char *function, int line, return -1; } + basename = strrchr (file, '/'); + if (basename) + basename++; + else + basename = file; - if (logrotate) { - logrotate = 0; +#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; + } - new_logfile = fopen (filename, "a"); + va_start (ap, fmt); + vasprintf (&str2, fmt, ap); + va_end (ap); + + 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)", - filename, strerror (errno)); + ctx->log.filename, strerror (errno)); goto log; } - if (logfile) - fclose (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); - gf_log_logfile = logfile = new_logfile; } 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); + 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; + } - 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 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); + { - if (logfile) { - 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 <= sys_log_level)) + 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); - } +err: + GF_FREE (msg); - if (str1) - GF_FREE (str1); + GF_FREE (str1); - if (str2) - FREE (str2); + FREE (str2); out: return (0); } +int +_gf_log_eh (const char *function, const char *fmt, ...) +{ + int ret = -1; + va_list ap; + char *str1 = NULL; + char *str2 = NULL; + char *msg = NULL; + xlator_t *this = NULL; + + this = THIS; + + ret = gf_asprintf (&str1, "[%d] %s: ", + ((this->graph)?this->graph->id:0), + function); + if (-1 == ret) { + goto out; + } + + va_start (ap, fmt); + + ret = vasprintf (&str2, fmt, ap); + if (-1 == ret) { + goto out; + } + + va_end (ap); + + msg = GF_MALLOC (strlen (str1) + strlen (str2) + 1, gf_common_mt_char); + if (!msg) { + ret = -1; + goto out; + } + + strcpy (msg, str1); + strcat (msg, str2); + + ret = eh_save_history (this->history, msg); + +out: + GF_FREE (str1); + + /* Use FREE instead of GF_FREE since str2 was allocated by vasprintf */ + if (str2) + FREE (str2); + + return ret; +} int gf_cmd_log_init (const char *filename) { + int fd = -1; + xlator_t *this = NULL; + glusterfs_ctx_t *ctx = NULL; + + this = THIS; + ctx = this->ctx; + 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 (!cmd_log_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 (cmdlogfile) { - fclose (cmdlogfile); - cmdlogfile = NULL; + 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, + + 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", cmd_log_filename, strerror (errno)); + "(%s)\n", ctx->log.cmd_log_filename, strerror (errno)); return -1; } return 0; @@ -631,17 +975,18 @@ 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; @@ -654,11 +999,8 @@ gf_cmd_log (const char *domain, const char *fmt, ...) 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); @@ -681,19 +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 cb23cb54f..cc806a767 100644 --- a/libglusterfs/src/logging.h +++ b/libglusterfs/src/logging.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef __LOGGING_H__ @@ -28,6 +19,7 @@ #include <stdint.h> #include <stdio.h> #include <stdarg.h> +#include <pthread.h> #ifdef GF_DARWIN_HOST_OS #define GF_PRI_FSBLK "u" @@ -43,6 +35,7 @@ #define GF_PRI_BLKSIZE PRId32 #define GF_PRI_SIZET "zu" + #if 0 /* Syslog definitions :-) */ #define LOG_EMERG 0 /* system is unusable */ @@ -68,25 +61,67 @@ typedef enum { GF_LOG_TRACE, /* full trace of operation */ } gf_loglevel_t; -extern gf_loglevel_t gf_log_loglevel; -extern char gf_log_xl_log_set; +#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); + +int _gf_log_eh (const char *function, const char *fmt, ...); + + #define FMT_WARN(fmt...) do { if (0) printf (fmt); } while (0) #define gf_log(dom, levl, fmt...) do { \ FMT_WARN (fmt); \ - \ - if ((levl > gf_log_loglevel) && !gf_log_xl_log_set) \ - break; \ _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 { \ FMT_WARN (fmt); \ - \ - if ((levl > gf_log_loglevel) && !gf_log_xl_log_set) \ - break; \ _gf_log_callingfn (dom, __FILE__, __FUNCTION__, __LINE__, \ levl, ##fmt); \ } while (0) @@ -94,8 +129,6 @@ extern char gf_log_xl_log_set; /* No malloc or calloc should be called in this function */ #define gf_log_nomem(dom, levl, size) do { \ - if ((levl > gf_log_loglevel) && !gf_log_xl_log_set) \ - break; \ _gf_log_nomem (dom, __FILE__, __FUNCTION__, __LINE__, \ levl, size); \ } while (0) @@ -106,31 +139,6 @@ extern char gf_log_xl_log_set; gf_log (args); \ } - -void gf_log_logrotate (int signum); - -void gf_log_globals_init (void); -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, ...) - __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); - -int gf_log_from_client (const char *msg, char *identifier); - -void gf_log_lock (void); -void gf_log_unlock (void); - void gf_log_disable_syslog (void); void gf_log_enable_syslog (void); gf_loglevel_t gf_log_get_loglevel (void); @@ -138,6 +146,13 @@ void gf_log_set_loglevel (gf_loglevel_t level); gf_loglevel_t gf_log_get_xl_loglevel (void *xl); void gf_log_set_xl_loglevel (void *xl, gf_loglevel_t level); +int gf_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); + #define GF_DEBUG(xl, format, args...) \ gf_log ((xl)->name, GF_LOG_DEBUG, format, ##args) #define GF_INFO(xl, format, args...) \ @@ -147,10 +162,4 @@ void gf_log_set_xl_loglevel (void *xl, gf_loglevel_t level); #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); #endif /* __LOGGING_H__ */ diff --git a/libglusterfs/src/mem-pool.c b/libglusterfs/src/mem-pool.c index f94723ba3..b901dd7a8 100644 --- a/libglusterfs/src/mem-pool.c +++ b/libglusterfs/src/mem-pool.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include "mem-pool.h" @@ -39,37 +30,18 @@ #define GLUSTERFS_ENV_MEM_ACCT_STR "GLUSTERFS_DISABLE_MEM_ACCT" -static int gf_mem_acct_enable = 0; - -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; - -#ifdef DEBUG - gf_mem_acct_enable = 1; - return; -#endif - - opt = getenv (GLUSTERFS_ENV_MEM_ACCT_STR); + glusterfs_ctx_t *ctx = NULL; - 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 @@ -84,17 +56,11 @@ 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); { @@ -134,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; @@ -160,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; @@ -185,7 +151,7 @@ __gf_realloc (void *ptr, size_t size) xlator_t *xl = NULL; uint32_t type = 0; - if (!gf_mem_acct_enable) + if (!THIS->ctx->mem_acct_enable) return REALLOC (ptr, size); tot_size = size + GF_MEM_HEADER_SIZE + GF_MEM_TRAILER_SIZE; @@ -258,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; } @@ -268,20 +234,16 @@ __gf_free (void *free_ptr) ptr = (char *)free_ptr - 8 - 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; @@ -294,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); @@ -326,7 +287,7 @@ mem_pool_new_fn (unsigned long sizeof_type, glusterfs_ctx_t *ctx = NULL; if (!sizeof_type || !count) { - gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument"); + gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument"); return NULL; } padded_sizeof_type = sizeof_type + GF_MEM_POOL_PAD_BOUNDARY; @@ -369,7 +330,7 @@ mem_pool_new_fn (unsigned long sizeof_type, mem_pool->pool_end = pool + (count * (padded_sizeof_type)); /* add this pool to the global list */ - ctx = glusterfs_ctx_get (); + ctx = THIS->ctx; if (!ctx) goto out; @@ -385,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; } @@ -406,7 +367,7 @@ mem_get (struct mem_pool *mem_pool) struct mem_pool **pool_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; } @@ -451,10 +412,12 @@ mem_get (struct mem_pool *mem_pool) * because it is too much work knowing that a better slab * allocator is coming RSN. */ + 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); - gf_log_callingfn ("mem-pool", GF_LOG_DEBUG, "Mem pool is full. " - "Callocing mem"); /* Memory coming from the heap need not be transformed from a * chunkhead to a usable pointer since it is not coming from @@ -475,7 +438,7 @@ static int __is_member (struct mem_pool *pool, void *ptr) { if (!pool || !ptr) { - gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument"); + gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument"); return -1; } @@ -500,20 +463,22 @@ mem_put (void *ptr) struct mem_pool *pool = NULL; if (!ptr) { - gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument"); + 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 ("mem-pool", GF_LOG_ERROR, "ptr header is corrupted"); + gf_log_callingfn ("mem-pool", GF_LOG_ERROR, + "ptr header is corrupted"); return; } pool = *tmp; if (!pool) { - gf_log ("mem-pool", GF_LOG_ERROR, "mem-pool ptr is NULL"); + gf_log_callingfn ("mem-pool", GF_LOG_ERROR, + "mem-pool ptr is NULL"); return; } LOCK (&pool->lock); @@ -553,6 +518,7 @@ mem_put (void *ptr) * not have enough info to distinguish between the two * situations. */ + pool->curr_stdalloc--; GF_FREE (list); break; default: diff --git a/libglusterfs/src/mem-pool.h b/libglusterfs/src/mem-pool.h index a23b12202..31f49f75c 100644 --- a/libglusterfs/src/mem-pool.h +++ b/libglusterfs/src/mem-pool.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _MEM_POOL_H_ @@ -116,7 +107,26 @@ void* __gf_default_realloc (void *oldptr, size_t size) #define GF_REALLOC(ptr, size) __gf_realloc (ptr, size) -#define GF_FREE(free_ptr) __gf_free (free_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; + + 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) @@ -137,6 +147,21 @@ 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; @@ -147,7 +172,10 @@ struct mem_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; }; @@ -163,7 +191,6 @@ 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 b8c61d689..666bd120a 100644 --- a/libglusterfs/src/mem-types.h +++ b/libglusterfs/src/mem-types.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef __MEM_TYPES_H__ @@ -106,6 +97,29 @@ enum gf_common_mem_types_ { gf_common_mt_trie_end = 81, gf_common_mt_run_argv = 82, gf_common_mt_run_logbuf = 83, - gf_common_mt_end = 84 + 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 index b8d3b6ae5..842b6413a 100644 --- a/libglusterfs/src/options.c +++ b/libglusterfs/src/options.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -62,7 +53,6 @@ out: return ret; } - static int xlator_option_validate_int (xlator_t *xl, const char *key, const char *value, volume_option_t *opt, char **op_errstr) @@ -80,18 +70,37 @@ xlator_option_validate_int (xlator_t *xl, const char *key, const char *value, goto out; } - if ((opt->min == 0) && (opt->max == 0)) { - gf_log (xl->name, GF_LOG_DEBUG, + 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 ((inputll < opt->min) || (inputll > opt->max)) { + 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 " - "[%"PRId64" - %"PRId64"]", + "[%.0f - %.0f]", inputll, key, value, opt->min, opt->max); gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); goto out; @@ -110,7 +119,7 @@ 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 = -1; + int ret = 0; char errstr[256]; /* Check the range */ @@ -119,37 +128,34 @@ xlator_option_validate_sizet (xlator_t *xl, const char *key, const char *value, "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_DEBUG, + 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)) { - if (strncmp (key, "cache-size", 10) == 0) { + if ((strncmp (key, "cache-size", 10) == 0) && + (size > opt->max)) { snprintf (errstr, 256, "Cache size %"PRId64" is out of " - "range [%"PRId64" - %"PRId64"]", + "range [%.0f - %.0f]", size, opt->min, opt->max); - //*op_errstr = gf_strdup (errstr); gf_log (xl->name, GF_LOG_WARNING, "%s", errstr); - ret = 0; - goto out; } else { snprintf (errstr, 256, "'%"PRId64"' in 'option %s %s' " - "is out of range [%"PRId64" - %"PRId64"]", + "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 = -1; } } - ret = 0; out: if (ret && op_errstr) *op_errstr = gf_strdup (errstr); @@ -222,6 +228,46 @@ out: 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, @@ -229,8 +275,7 @@ xlator_option_validate_str (xlator_t *xl, const char *key, const char *value, { int ret = -1; int i = 0; - char errstr[256]; - char given_array[4096] = {0,}; + char errstr[4096] = {0,}; /* Check if the '*str' is valid */ if (GF_OPTION_LIST_EMPTY(opt)) { @@ -238,6 +283,9 @@ xlator_option_validate_str (xlator_t *xl, const char *key, const char *value, 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) { @@ -252,7 +300,8 @@ xlator_option_validate_str (xlator_t *xl, const char *key, const char *value, #endif } - if ((i <= ZR_OPTION_MAX_ARRAY_SIZE) && (!opt->value[i])) { + 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 @@ -262,26 +311,15 @@ xlator_option_validate_str (xlator_t *xl, const char *key, const char *value, * matched all possible input values. */ - 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, 256, - "option %s %s: '%s' is not valid " - "(possible options are %s)", - key, value, value, given_array); - gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); - goto out; - } - ret = 0; + out: - if (ret && op_errstr) - *op_errstr = gf_strdup (errstr); + 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; } @@ -290,10 +328,9 @@ static int xlator_option_validate_percent (xlator_t *xl, const char *key, const char *value, volume_option_t *opt, char **op_errstr) { - int ret = -1; - char errstr[256]; - uint32_t percent = 0; - + double percent = 0; + int ret = -1; + char errstr[256]; /* Check if the value is valid percentage */ if (gf_string2percent (value, &percent) != 0) { @@ -304,9 +341,9 @@ xlator_option_validate_percent (xlator_t *xl, const char *key, const char *value goto out; } - if ((percent < 0) || (percent > 100)) { + if ((percent < 0.0) || (percent > 100.0)) { snprintf (errstr, 256, - "'%d' in 'option %s %s' is out of range [0 - 100]", + "'%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; @@ -319,8 +356,6 @@ out: return ret; } - -/* TODO: clean this up */ static int xlator_option_validate_percent_or_sizet (xlator_t *xl, const char *key, const char *value, @@ -328,88 +363,43 @@ xlator_option_validate_percent_or_sizet (xlator_t *xl, const char *key, { int ret = -1; char errstr[256]; - uint32_t percent = 0; 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); - /* Check if the value is valid percentage */ - if (gf_string2percent (value, &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 (value, &size) == 0) { - /* Check the range */ - if ((opt->min == 0) && (opt->max == 0)) { - gf_log (xl->name, GF_LOG_DEBUG, - "no range check rquired for " - "'option %s %s'", - key, value); - // It is a size - ret = 0; - goto out; - } - if ((size < opt->min) || (size > opt->max)) { - snprintf (errstr, 256, - "'%"PRId64"' in 'option %s %s' " - "is out of range [%"PRId64" - " - "%"PRId64"]", - size, key, value, - opt->min, opt->max); - gf_log (xl->name, GF_LOG_ERROR, "%s", - errstr); - goto out; - } - // It is a size - ret = 0; - goto out; - } else { - // It's not a percent or size - snprintf (errstr, 256, - "invalid number format \"%s\" " - "in \"option %s\"", - value, key); - gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); - goto out; - } - } - // It is a percent - ret = 0; - goto out; - } else { - if (gf_string2bytesize (value, &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'", - key, value); - // It is a size - ret = 0; - goto out; - } - if ((size < opt->min) || (size > opt->max)) { - snprintf (errstr, 256, - "'%"PRId64"' in 'option %s %s'" - " is out of range [%"PRId64" -" - " %"PRId64"]", - size, key, value, opt->min, opt->max); - gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); - goto out; - } - } else { - // It's not a percent or size - snprintf (errstr, 256, - "invalid number format \"%s\" in \"option %s\"", - value, key); - gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); - goto out; - } - //It is a size - ret = 0; - goto out; - } - ret = 0; out: if (ret && op_errstr) *op_errstr = gf_strdup (errstr); @@ -425,7 +415,7 @@ xlator_option_validate_time (xlator_t *xl, const char *key, const char *value, char errstr[256]; uint32_t input_time = 0; - /* Check if the value is valid percentage */ + /* Check if the value is valid time */ if (gf_string2time (value, &input_time) != 0) { snprintf (errstr, 256, "invalid time format \"%s\" in " @@ -436,7 +426,7 @@ xlator_option_validate_time (xlator_t *xl, const char *key, const char *value, } if ((opt->min == 0) && (opt->max == 0)) { - gf_log (xl->name, GF_LOG_DEBUG, + gf_log (xl->name, GF_LOG_TRACE, "no range check required for " "'option %s %s'", key, value); @@ -447,7 +437,7 @@ xlator_option_validate_time (xlator_t *xl, const char *key, const char *value, if ((input_time < opt->min) || (input_time > opt->max)) { snprintf (errstr, 256, "'%"PRIu32"' in 'option %s %s' is " - "out of range [%"PRId64" - %"PRId64"]", + "out of range [%.0f - %.0f]", input_time, key, value, opt->min, opt->max); gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); @@ -466,35 +456,55 @@ static int xlator_option_validate_double (xlator_t *xl, const char *key, const char *value, volume_option_t *opt, char **op_errstr) { - int ret = -1; - char errstr[256]; - double val = 0.0; - - /* Check if the value is valid double */ - if (gf_string2double (value, &val) != 0) { - snprintf (errstr, 256, - "invalid double \"%s\" in \"option %s\"", - value, key); - gf_log (xl->name, GF_LOG_ERROR, "%s", errstr); - goto out; - } + double input = 0.0; + int ret = -1; + char errstr[256]; - if (val < 0.0) { + /* Check the range */ + if (gf_string2double (value, &input) != 0) { snprintf (errstr, 256, - "invalid double \"%s\" in \"option %s\"", + "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)) { - gf_log (xl->name, GF_LOG_DEBUG, + 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) @@ -510,10 +520,11 @@ xlator_option_validate_addr (xlator_t *xl, const char *key, const char *value, int ret = -1; char errstr[256]; - if (!valid_internet_address ((char *)value)) { + if (!valid_internet_address ((char *)value, _gf_false)) { snprintf (errstr, 256, - "internet address '%s' does not conform to standards.", - value); + "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); @@ -524,6 +535,178 @@ xlator_option_validate_addr (xlator_t *xl, const char *key, const char *value, 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, @@ -532,7 +715,6 @@ xlator_option_validate_any (xlator_t *xl, const char *key, const char *value, return 0; } - typedef int (xlator_option_validator_t) (xlator_t *xl, const char *key, const char *value, volume_option_t *opt, char **operrstr); @@ -556,6 +738,11 @@ xlator_option_validate (xlator_t *xl, char *key, char *value, [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, }; @@ -574,7 +761,7 @@ out: } -static volume_option_t * +volume_option_t * xlator_volume_option_get_list (volume_opt_list_t *vol_list, const char *key) { volume_option_t *opt = NULL; @@ -591,7 +778,7 @@ xlator_volume_option_get_list (volume_opt_list_t *vol_list, const char *key) } else opt = vol_list->given_opt; - for (index = 0; opt[index].key && opt[index].key[0]; index++) { + 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) @@ -623,7 +810,7 @@ xlator_volume_option_get (xlator_t *xl, const char *key) } -static void +static int xl_opt_validate (dict_t *dict, char *key, data_t *value, void *data) { xlator_t *xl = NULL; @@ -644,7 +831,7 @@ xl_opt_validate (dict_t *dict, char *key, data_t *value, void *data) opt = xlator_volume_option_get_list (vol_opt, key); if (!opt) - return; + return 0; ret = xlator_option_validate (xl, key, value->data, opt, &errstr); if (ret) @@ -662,7 +849,7 @@ xl_opt_validate (dict_t *dict, char *key, data_t *value, void *data) dict_set (dict, opt->key[0], value); dict_del (dict, key); } - return; + return 0; } @@ -867,11 +1054,8 @@ out: static int -not_null (char *in, char **out) +pass (char *in, char **out) { - if (!in || !out) - return -1; - *out = in; return 0; } @@ -892,46 +1076,52 @@ xl_by_name (char *in, xlator_t **out) static int -pc_or_size (char *in, uint64_t *out) +pc_or_size (char *in, double *out) { - uint32_t pc = 0; + double pc = 0; int ret = 0; + uint64_t size = 0; if (gf_string2percent (in, &pc) == 0) { - if (pc > 100) { - ret = gf_string2bytesize (in, out); + if (pc > 100.0) { + ret = gf_string2bytesize (in, &size); + if (!ret) + *out = size; } else { *out = pc; } } else { - ret = gf_string2bytesize (in, out); + ret = gf_string2bytesize (in, &size); + if (!ret) + *out = size; } return ret; } - -DEFINE_INIT_OPT(char *, str, not_null); +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(uint32_t, percent, gf_string2percent); -DEFINE_INIT_OPT(uint64_t, percent_or_size, pc_or_size); +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, not_null); +DEFINE_INIT_OPT(char *, path, pass); +DEFINE_INIT_OPT(double, double, gf_string2double); -DEFINE_RECONF_OPT(char *, str, not_null); +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(uint32_t, percent, gf_string2percent); -DEFINE_RECONF_OPT(uint64_t, percent_or_size, pc_or_size); +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, not_null); +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 index 40089ac63..e2a25baa9 100644 --- a/libglusterfs/src/options.h +++ b/libglusterfs/src/options.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _OPTIONS_H @@ -44,25 +35,38 @@ typedef enum { 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]; + char *key[ZR_VOLUME_MAX_NUM_KEY]; /* different key, same meaning */ - volume_option_type_t type; - int64_t min; /* 0 means no range */ - int64_t max; /* 0 means no range */ - char *value[ZR_OPTION_MAX_ARRAY_SIZE]; + 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 */ + 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; @@ -89,6 +93,9 @@ 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 \ @@ -101,11 +108,12 @@ 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(uint32_t, percent); -DECLARE_INIT_OPT(uint64_t, percent_or_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) \ @@ -137,10 +145,11 @@ xlator_option_init_##type (xlator_t *this, dict_t *options, char *key, \ 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_DEBUG, \ + gf_log (this->name, GF_LOG_TRACE, \ "option %s using default value %s", \ key, value); \ } else { \ @@ -179,11 +188,12 @@ 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(uint32_t, percent); -DECLARE_RECONF_OPT(uint64_t, percent_or_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) \ @@ -215,6 +225,7 @@ xlator_option_reconf_##type (xlator_t *this, dict_t *options, char *key, \ 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) { \ diff --git a/libglusterfs/src/rbthash.c b/libglusterfs/src/rbthash.c index beda672d0..0d7b9e521 100644 --- a/libglusterfs/src/rbthash.c +++ b/libglusterfs/src/rbthash.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ @@ -217,8 +208,7 @@ 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)) @@ -237,7 +227,7 @@ rbthash_deinit_entry (rbthash_table_t *tbl, rbthash_entry_t *entry) } -inline struct rbthash_bucket * +static inline struct rbthash_bucket * rbthash_entry_bucket (rbthash_table_t *tbl, rbthash_entry_t * entry) { int nbucket = 0; @@ -311,7 +301,7 @@ 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; diff --git a/libglusterfs/src/rbthash.h b/libglusterfs/src/rbthash.h index 02a65b4a8..b093ce998 100644 --- a/libglusterfs/src/rbthash.h +++ b/libglusterfs/src/rbthash.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2008-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef __RBTHASH_TABLE_H_ diff --git a/libglusterfs/src/run.c b/libglusterfs/src/run.c index 46bb37d73..4fd2a3a0d 100644 --- a/libglusterfs/src/run.c +++ b/libglusterfs/src/run.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _GNU_SOURCE @@ -30,7 +21,9 @@ #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) @@ -74,7 +67,10 @@ runner_chio (runner_t *runner, int fd) { GF_ASSERT (fd > 0 && fd < 3); - return runner->chio[fd]; + if ((fd > 0) && (fd < 3)) + return runner->chio[fd]; + + return NULL; } static void @@ -191,7 +187,7 @@ runner_log (runner_t *runner, const char *dom, gf_loglevel_t lvl, if (len > 0) buf[len - 1] = '\0'; - gf_log (dom, lvl, "%s: %s", msg, buf); + gf_log_callingfn (dom, lvl, "%s: %s", msg, buf); GF_FREE (buf); } @@ -201,7 +197,8 @@ runner_redir (runner_t *runner, int fd, int tgt_fd) { GF_ASSERT (fd > 0 && fd < 3); - runner->chfd[fd] = (tgt_fd >= 0) ? tgt_fd : -2; + if ((fd > 0) && (fd < 3)) + runner->chfd[fd] = (tgt_fd >= 0) ? tgt_fd : -2; } int @@ -293,7 +290,11 @@ runner_start (runner_t *runner) } else ret = -1; #else - for (i = 3; i < 65536; i++) { + 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); } @@ -364,9 +365,11 @@ runner_end (runner_t *runner) ret = runner_end_reuse (runner); - for (p = runner->argv; *p; p++) - GF_FREE (*p); - GF_FREE (runner->argv); + 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]); @@ -379,10 +382,8 @@ runner_run_generic (runner_t *runner, int (*rfin)(runner_t *runner)) int ret = 0; ret = runner_start (runner); - if (ret != 0) - return -1; - return rfin (runner) ? -1 : 0; + return -(rfin (runner) || ret); } int @@ -391,6 +392,25 @@ 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) { @@ -422,7 +442,7 @@ TBANNER (const char *txt) } int -main () +main (int argc, char **argv) { runner_t runner; char buf[80]; @@ -430,6 +450,8 @@ main () int ret; int fd; long pathmax = pathconf ("/", _PC_PATH_MAX); + struct timeval tv = {0,}; + struct timeval *tvp = NULL; wdbuf = malloc (pathmax); assert (wdbuf); @@ -468,7 +490,7 @@ main () printf ("%d %d [%s]\n", ret, errno, strerror (errno)); TBANNER ("output redirection"); - fd = open ("/tmp/foof", O_WRONLY|O_CREAT|O_TRUNC, 0600); + fd = mkstemp ("/tmp/foof"); assert (fd != -1); runinit (&runner); runner_add_args (&runner, "echo", "foo", NULL); @@ -479,6 +501,13 @@ main () 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 index 70b61aff8..d7554ef6d 100644 --- a/libglusterfs/src/run.h +++ b/libglusterfs/src/run.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef __RUN_H__ @@ -175,6 +166,12 @@ int runner_end_reuse (runner_t *runner); 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. * diff --git a/libglusterfs/src/scheduler.c b/libglusterfs/src/scheduler.c deleted file mode 100644 index f27875dc2..000000000 --- a/libglusterfs/src/scheduler.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. -*/ - -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - -#include <dlfcn.h> -#include <netdb.h> -#include "xlator.h" -#include "scheduler.h" -#include "list.h" - -struct sched_ops * -get_scheduler (xlator_t *xl, const char *name) -{ - struct sched_ops *tmp_sched = NULL; - volume_opt_list_t *vol_opt = NULL; - char *sched_file = NULL; - void *handle = NULL; - int ret = 0; - - if (name == NULL) { - gf_log ("scheduler", GF_LOG_ERROR, - "'name' not specified, EINVAL"); - return NULL; - } - - ret = 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 acb6597b9..000000000 --- a/libglusterfs/src/scheduler.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. -*/ - -#ifndef _SCHEDULER_H -#define _SCHEDULER_H - -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - -#include "xlator.h" - -struct sched_ops { - int32_t (*init) (xlator_t *this); - void (*fini) (xlator_t *this); - void (*update) (xlator_t *this); - xlator_t *(*schedule) (xlator_t *this, const void *path); - void (*notify) (xlator_t *xl, int32_t event, void *data); - 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 29b44aedf..37b338f51 100644 --- a/libglusterfs/src/stack.c +++ b/libglusterfs/src/stack.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include "statedump.h" @@ -35,6 +26,44 @@ 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,...) { @@ -43,6 +72,7 @@ gf_proc_dump_call_frame (call_frame_t *call_frame, const char *key_buf,...) va_list ap; call_frame_t my_frame; int ret = -1; + char timestr[256] = {0,}; if (!call_frame) return; @@ -56,15 +86,21 @@ gf_proc_dump_call_frame (call_frame_t *call_frame, const char *key_buf,...) va_end(ap); ret = TRY_LOCK(&call_frame->lock); - if (ret) { - gf_log("", GF_LOG_WARNING, "Unable to dump call frame" - " errno: %s", strerror (errno)); - return; - } + if (ret) + goto out; memcpy(&my_frame, call_frame, sizeof(my_frame)); UNLOCK(&call_frame->lock); + 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); @@ -82,6 +118,14 @@ gf_proc_dump_call_frame (call_frame_t *call_frame, const char *key_buf,...) 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; + } } @@ -92,6 +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 timestr[256] = {0,}; if (!call_stack) return; @@ -105,15 +150,26 @@ gf_proc_dump_call_stack (call_stack_t *call_stack, const char *key_buf,...) vsnprintf(prefix, GF_DUMP_MAX_BUF_LEN, key_buf, ap); va_end(ap); + if (call_stack->ctx->measure_latency) { + gf_time_fmt (timestr, sizeof timestr, call_stack->tv.tv_sec, + gf_timefmt_FT); + snprintf (timestr + strlen (timestr), + sizeof timestr - strlen (timestr), + ".%"GF_PRI_SUSECONDS, call_stack->tv.tv_usec); + gf_proc_dump_write("callstack-creation-time", "%s", timestr); + } + gf_proc_dump_write("uid", "%d", call_stack->uid); gf_proc_dump_write("gid", "%d", call_stack->gid); gf_proc_dump_write("pid", "%d", call_stack->pid); gf_proc_dump_write("unique", "%Ld", call_stack->unique); + gf_proc_dump_write("lk-owner", "%s", lkowner_utoa (&call_stack->lk_owner)); if (call_stack->type == GF_OP_TYPE_FOP) - gf_proc_dump_write("op", "%s", gf_fop_list[call_stack->op]); - else if (call_stack->type == GF_OP_TYPE_MGMT) - gf_proc_dump_write("op", "%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_write("type", "%d", call_stack->type); gf_proc_dump_write("cnt", "%d", cnt); @@ -136,19 +192,18 @@ 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"); + section_added = _gf_true; gf_proc_dump_write("callpool_address","%p", call_pool); gf_proc_dump_write("callpool.cnt","%d", call_pool->cnt); @@ -159,6 +214,17 @@ gf_proc_dump_pending_frames (call_pool_t *call_pool) i++; } 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 @@ -186,7 +252,7 @@ gf_proc_dump_call_frame_to_dict (call_frame_t *call_frame, memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.translator", prefix); - ret = dict_set_str (dict, key, gf_strdup (tmp_frame.this->name)); + ret = dict_set_dynstr (dict, key, gf_strdup (tmp_frame.this->name)); if (ret) return; @@ -199,7 +265,7 @@ gf_proc_dump_call_frame_to_dict (call_frame_t *call_frame, if (tmp_frame.parent) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.parent", prefix); - ret = dict_set_str (dict, key, + ret = dict_set_dynstr (dict, key, gf_strdup (tmp_frame.parent->this->name)); if (ret) return; @@ -208,7 +274,8 @@ gf_proc_dump_call_frame_to_dict (call_frame_t *call_frame, if (tmp_frame.wind_from) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.windfrom", prefix); - ret = dict_set_str (dict, key, gf_strdup (tmp_frame.wind_from)); + ret = dict_set_dynstr (dict, key, + gf_strdup (tmp_frame.wind_from)); if (ret) return; } @@ -216,7 +283,8 @@ gf_proc_dump_call_frame_to_dict (call_frame_t *call_frame, if (tmp_frame.wind_to) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.windto", prefix); - ret = dict_set_str (dict, key, gf_strdup (tmp_frame.wind_to)); + ret = dict_set_dynstr (dict, key, + gf_strdup (tmp_frame.wind_to)); if (ret) return; } @@ -224,7 +292,8 @@ gf_proc_dump_call_frame_to_dict (call_frame_t *call_frame, if (tmp_frame.unwind_from) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.unwindfrom", prefix); - ret = dict_set_str (dict, key, gf_strdup (tmp_frame.unwind_from)); + ret = dict_set_dynstr (dict, key, + gf_strdup (tmp_frame.unwind_from)); if (ret) return; } @@ -232,7 +301,8 @@ gf_proc_dump_call_frame_to_dict (call_frame_t *call_frame, if (tmp_frame.unwind_to) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.unwind_to", prefix); - ret = dict_set_str (dict, key, gf_strdup (tmp_frame.unwind_to)); + ret = dict_set_dynstr (dict, key, + gf_strdup (tmp_frame.unwind_to)); } return; @@ -281,10 +351,10 @@ gf_proc_dump_call_stack_to_dict (call_stack_t *call_stack, snprintf (key, sizeof (key), "%s.op", prefix); if (call_stack->type == GF_OP_TYPE_FOP) ret = dict_set_str (dict, key, - gf_fop_list[call_stack->op]); - else if (call_stack->type == GF_OP_TYPE_MGMT) - ret = dict_set_str (dict, key, - gf_mgmt_list[call_stack->op]); + (char *)gf_fop_list[call_stack->op]); + else + ret = dict_set_str (dict, key, "other"); + if (ret) return; diff --git a/libglusterfs/src/stack.h b/libglusterfs/src/stack.h index c84040576..f2d2ef950 100644 --- a/libglusterfs/src/stack.h +++ b/libglusterfs/src/stack.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ /* @@ -34,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> @@ -45,6 +36,7 @@ typedef struct _call_pool_t call_pool_t; #include "common-utils.h" #include "globals.h" #include "lkowner.h" +#include "client_t.h" #define NFS_PID 1 #define LOW_PRIO_PROC_PID -1 @@ -55,7 +47,7 @@ typedef int32_t (*ret_fn_t) (call_frame_t *frame, int32_t op_errno, ...); -struct _call_pool_t { +struct call_pool { union { struct list_head all_frames; struct { @@ -91,6 +83,8 @@ struct _call_frame_t { const char *unwind_to; }; +#define SMALL_GROUP_COUNT 128 + struct _call_stack_t { union { struct list_head all_frames; @@ -101,20 +95,24 @@ struct _call_stack_t { }; call_pool_t *pool; gf_lock_t stack_lock; - void *trans; + 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[GF_MAX_AUX_GROUPS]; + 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; }; @@ -131,11 +129,10 @@ struct _call_stack_t { 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) @@ -155,7 +152,7 @@ FRAME_DESTROY (call_frame_t *frame) mem_put (frame); if (local) - GF_FREE (local); + mem_put (local); } @@ -177,16 +174,37 @@ STACK_DESTROY (call_stack_t *stack) } LOCK_DESTROY (&stack->frames.lock); + LOCK_DESTROY (&stack->stack_lock); while (stack->frames.next) { FRAME_DESTROY (stack->frames.next); } + + GF_FREE (stack->groups_large); + mem_put (stack); if (local) - GF_FREE (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 @@ -227,6 +245,7 @@ STACK_DESTROY (call_stack_t *stack) _new->wind_from = __FUNCTION__; \ _new->wind_to = #fn; \ _new->unwind_to = #rfn; \ + \ LOCK_INIT (&_new->lock); \ LOCK(&frame->root->stack_lock); \ { \ @@ -240,11 +259,27 @@ STACK_DESTROY (call_stack_t *stack) UNLOCK(&frame->root->stack_lock); \ old_THIS = THIS; \ THIS = obj; \ + if (frame->this->ctx->measure_latency) \ + gf_latency_begin (_new, fn); \ fn (_new, obj, params); \ THIS = old_THIS; \ } while (0) +/* make a call without switching frames */ +#define STACK_WIND_TAIL(frame, obj, fn, params ...) \ + do { \ + xlator_t *old_THIS = NULL; \ + \ + frame->this = obj; \ + frame->wind_to = #fn; \ + old_THIS = THIS; \ + THIS = obj; \ + fn (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 { \ @@ -279,6 +314,8 @@ STACK_DESTROY (call_stack_t *stack) fn##_cbk = rfn; \ old_THIS = THIS; \ THIS = obj; \ + if (obj->ctx->measure_latency) \ + gf_latency_begin (_new, fn); \ fn (_new, obj, params); \ THIS = old_THIS; \ } while (0) @@ -305,6 +342,8 @@ STACK_DESTROY (call_stack_t *stack) THIS = _parent->this; \ frame->complete = _gf_true; \ 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) @@ -332,11 +371,31 @@ STACK_DESTROY (call_stack_t *stack) THIS = _parent->this; \ frame->complete = _gf_true; \ 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) +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) { @@ -360,14 +419,27 @@ copy_frame (call_frame_t *frame) newstack->ngrps = oldstack->ngrps; newstack->op = oldstack->op; newstack->type = oldstack->type; + if (call_stack_alloc_groups (newstack, oldstack->ngrps) != 0) { + mem_put (newstack); + return NULL; + } memcpy (newstack->groups, oldstack->groups, - sizeof (gid_t) * GF_MAX_AUX_GROUPS); + sizeof (gid_t) * oldstack->ngrps); newstack->unique = oldstack->unique; newstack->frames.this = frame->this; newstack->frames.root = newstack; newstack->pool = oldstack->pool; newstack->lk_owner = oldstack->lk_owner; + newstack->ctx = oldstack->ctx; + + if (newstack->ctx->measure_latency) { + if (gettimeofday (&newstack->tv, NULL) == -1) + gf_log ("stack", GF_LOG_ERROR, "gettimeofday () failed." + " (%s)", strerror (errno)); + memcpy (&newstack->frames.begin, &newstack->tv, + sizeof (newstack->tv)); + } LOCK_INIT (&newstack->frames.lock); LOCK_INIT (&newstack->stack_lock); @@ -382,39 +454,9 @@ copy_frame (call_frame_t *frame) return &newstack->frames; } - -static inline call_frame_t * -create_frame (xlator_t *xl, call_pool_t *pool) -{ - call_stack_t *stack = NULL; - - if (!xl || !pool) { - return NULL; - } - - stack = mem_get0 (pool->stack_mem_pool); - if (!stack) - return NULL; - - stack->pool = pool; - stack->frames.root = stack; - stack->frames.this = xl; - - LOCK (&pool->lock); - { - list_add (&stack->all_frames, &pool->all_frames); - pool->cnt++; - } - UNLOCK (&pool->lock); - - LOCK_INIT (&stack->frames.lock); - LOCK_INIT (&stack->stack_lock); - - return &stack->frames; -} - void gf_proc_dump_pending_frames(call_pool_t *call_pool); void gf_proc_dump_pending_frames_to_dict (call_pool_t *call_pool, dict_t *dict); +call_frame_t *create_frame (xlator_t *xl, call_pool_t *pool); gf_boolean_t __is_fuse_call (call_frame_t *frame); #endif /* _STACK_H */ diff --git a/libglusterfs/src/statedump.c b/libglusterfs/src/statedump.c index 8c6fe9215..8175faba4 100644 --- a/libglusterfs/src/statedump.c +++ b/libglusterfs/src/statedump.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include <stdarg.h> @@ -30,7 +21,8 @@ #endif /* MALLOC_H */ /* We don't want gf_log in this function because it may cause - 'deadlock' with statedump */ + '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 @@ -61,17 +53,12 @@ gf_proc_dump_unlock (void) pthread_mutex_unlock (&gf_proc_dump_mutex); } - static int -gf_proc_dump_open (char *dump_dir, char *brickname) +gf_proc_dump_open (char *tmpname) { - char path[PATH_MAX] = {0,}; int dump_fd = -1; - snprintf (path, sizeof (path), "%s/%s.%d.dump", (dump_dir ? - dump_dir : "/tmp"), brickname, getpid()); - - dump_fd = open (path, O_CREAT|O_RDWR|O_TRUNC|O_APPEND, 0600); + dump_fd = mkstemp (tmpname); if (dump_fd < 0) return -1; @@ -79,7 +66,6 @@ gf_proc_dump_open (char *dump_dir, char *brickname) return 0; } - static void gf_proc_dump_close (void) { @@ -87,6 +73,45 @@ 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; + + 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, ...) @@ -305,6 +330,9 @@ gf_proc_dump_mempool_info (glusterfs_ctx_t *ctx) 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); } } @@ -356,6 +384,17 @@ gf_proc_dump_mempool_info_to_dict (glusterfs_ctx_t *ctx, dict_t *dict) 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); @@ -375,7 +414,7 @@ gf_proc_dump_xlator_info (xlator_t *top) if (!top) return; - ctx = glusterfs_ctx_get (); + ctx = top->ctx; trav = top; while (trav) { @@ -389,8 +428,6 @@ gf_proc_dump_xlator_info (xlator_t *top) (trav->itable)) { snprintf (itable_key, 1024, "%d.%s.itable", ctx->graph_id, trav->name); - - inode_table_dump (trav->itable, itable_key); } if (!trav->dumpops) { @@ -410,6 +447,10 @@ gf_proc_dump_xlator_info (xlator_t *top) GF_PROC_DUMP_IS_XL_OPTION_ENABLED (fd)) trav->dumpops->fd (trav); + if (trav->dumpops->history && + GF_PROC_DUMP_IS_XL_OPTION_ENABLED (history)) + trav->dumpops->history (trav); + trav = trav->next; } @@ -420,24 +461,20 @@ static void gf_proc_dump_oldgraph_xlator_info (xlator_t *top) { xlator_t *trav = NULL; - glusterfs_ctx_t *ctx = NULL; - char itable_key[1024] = {0,}; if (!top) return; - ctx = glusterfs_ctx_get (); - trav = top; while (trav) { gf_proc_dump_xlator_mem_info_only_in_use (trav); if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED (inode) && (trav->itable)) { - snprintf (itable_key, 1024, "%d.%s.itable", - ctx->graph_id, trav->name); - - inode_table_dump (trav->itable, itable_key); + /*TODO: dump inode table info if necessary by + printing the graph id (taken by glusterfs_cbtx_t) + in the key + */ } if (!trav->dumpops) { @@ -472,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; } @@ -490,7 +567,8 @@ gf_proc_dump_disable_all_options () 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; } @@ -502,25 +580,27 @@ gf_proc_dump_parse_set_option (char *key, char *value) char buf[GF_DUMP_MAX_BUF_LEN]; int ret = -1; - if (!strncasecmp (key, "all", 3)) { + if (!strcasecmp (key, "all")) { (void)gf_proc_dump_enable_all_options (); return 0; - } else if (!strncasecmp (key, "mem", 3)) { + } else if (!strcasecmp (key, "mem")) { opt_key = &dump_options.dump_mem; - } else if (!strncasecmp (key, "iobuf", 5)) { + } else if (!strcasecmp (key, "iobuf")) { opt_key = &dump_options.dump_iobuf; - } else if (!strncasecmp (key, "callpool", 8)) { + } else if (!strcasecmp (key, "callpool")) { opt_key = &dump_options.dump_callpool; - } else if (!strncasecmp (key, "priv", 4)) { + } else if (!strcasecmp (key, "priv")) { opt_key = &dump_options.xl_options.dump_priv; - } else if (!strncasecmp (key, "fd", 2)) { + } else if (!strcasecmp (key, "fd")) { opt_key = &dump_options.xl_options.dump_fd; - } else if (!strncasecmp (key, "inode", 5)) { + } else if (!strcasecmp (key, "inode")) { opt_key = &dump_options.xl_options.dump_inode; - } else if (!strncasecmp (key, "inodectx", strlen ("inodectx"))) { + } else if (!strcasecmp (key, "inodectx")) { opt_key = &dump_options.xl_options.dump_inodectx; - } else if (!strncasecmp (key, "fdctx", strlen ("fdctx"))) { + } 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) { @@ -529,11 +609,9 @@ gf_proc_dump_parse_set_option (char *key, char *value) "matched key : %s\n", key); ret = write (gf_dump_fd, buf, strlen (buf)); - /* warning suppression */ - if (ret >= 0) { + if (ret >= 0) ret = -1; - goto out; - } + goto out; } @@ -548,33 +626,49 @@ out: } static int -gf_proc_dump_options_init (char *dump_name) +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; 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), - "/tmp/glusterdump.%d.options", getpid ()); - + 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); @@ -588,28 +682,33 @@ gf_proc_dump_options_init (char *dump_name) continue; } - snprintf (dumpbuf, sizeof (dumpbuf), "[Debug]:key=%s, value=%s\n",key,value); - ret = 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 i = 0; - int ret = -1; - glusterfs_ctx_t *ctx = NULL; - glusterfs_graph_t *trav = NULL; - char brick_name[PATH_MAX] = {0,}; + 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 (); - ctx = glusterfs_ctx_get (); if (!ctx) goto out; @@ -618,14 +717,44 @@ gf_proc_dump_info (int signum) } else strncpy (brick_name, "glusterdump", sizeof (brick_name)); - ret = gf_proc_dump_options_init (brick_name); + ret = gf_proc_dump_options_init (); if (ret < 0) goto out; - ret = gf_proc_dump_open (ctx->statedump_path, brick_name); + 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); @@ -657,8 +786,24 @@ gf_proc_dump_info (int signum) i++; } - gf_proc_dump_close (); + ret = gettimeofday (&tv, NULL); + if (0 == ret) { + gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT); + snprintf (timestr + strlen (timestr), + sizeof timestr - strlen (timestr), + ".%"GF_PRI_SUSECONDS, tv.tv_usec); + } + + snprintf (sign_string, sizeof (sign_string), "\nDUMP-END-TIME: %s", + timestr); + ret = write (gf_dump_fd, sign_string, strlen (sign_string)); + out: + 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; diff --git a/libglusterfs/src/statedump.h b/libglusterfs/src/statedump.h index cdeb5b7fc..8342b120a 100644 --- a/libglusterfs/src/statedump.h +++ b/libglusterfs/src/statedump.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ @@ -32,6 +23,7 @@ typedef struct gf_dump_xl_options_ { 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_ { @@ -39,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; @@ -63,13 +56,21 @@ void _gf_proc_dump_build_key (char *key, const char *prefix, char *fmt,...) #define GF_PROC_DUMP_SET_OPTION(opt,val) opt = val +#define GF_CHECK_DUMP_OPTION_ENABLED(option_dump, var, label) \ + do { \ + if (option_dump == _gf_true) { \ + var = _gf_false; \ + goto label; \ + } \ + } while (0); + void gf_proc_dump_init(); void gf_proc_dump_fini(void); void gf_proc_dump_cleanup(void); -void gf_proc_dump_info(int signum); +void gf_proc_dump_info(int signum, glusterfs_ctx_t *ctx); int gf_proc_dump_add_section(char *key,...); 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 7b6f78248..c1620bb70 100644 --- a/libglusterfs/src/syncop.c +++ b/libglusterfs/src/syncop.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com> + Copyright (c) 2008-2013 Red Hat, Inc. <http://www.redhat.com> This file is part of GlusterFS. - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -24,57 +15,250 @@ #include "syncop.h" -call_frame_t * -syncop_create_frame () +int +syncopctx_setfsuid (void *uid) { - struct synctask *task = NULL; - 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->frame; - } +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,33 +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 *old_task) { - int ret; struct synctask *task = NULL; /* Do not trust the pointer received. It may be wrong and can lead to crashes. */ task = synctask_get (); - ret = task->syncfn (task->opaque); - task->synccbk (ret, task->frame, task->opaque); + task->ret = task->syncfn (task->opaque); + if (task->synccbk) + task->synccbk (task->ret, task->frame, task->opaque); - /* cannot destroy @task right here as we are - in the execution stack of @task itself - */ - task->complete = 1; - synctask_wake (task); + task->state = SYNCTASK_DONE; synctask_yield (task); } @@ -125,36 +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, - call_frame_t *frame, 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); - VALIDATE_OR_GOTO (cbk, err); - VALIDATE_OR_GOTO (frame, 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->syncfn = fn; newtask->synccbk = cbk; newtask->opaque = opaque; - newtask->frame = frame; + + /* 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, @@ -173,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; @@ -218,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; @@ -249,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) { @@ -256,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)); @@ -275,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); @@ -286,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; @@ -304,8 +955,8 @@ syncop_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (op_ret == 0) { args->iatt1 = *iatt; args->iatt2 = *parent; - if (xattr) - args->xattr = dict_ref (xattr); + if (xdata) + args->xdata = dict_ref (xdata); } __wake (args); @@ -315,22 +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 (parent) *parent = args.iatt2; - if (xattr_rsp) - *xattr_rsp = args.xattr; - else if (args.xattr) - dict_unref (args.xattr); + if (xdata_rsp) + *xdata_rsp = args.xdata; + else if (args.xdata) + dict_unref (args.xdata); errno = args.op_errno; return args.op_ret; @@ -348,6 +999,8 @@ entry_copy (gf_dirent_t *source) sink->d_type = source->d_type; sink->d_stat = source->d_stat; + if (source->inode) + sink->inode = inode_ref (source->inode); return sink; } @@ -357,7 +1010,7 @@ syncop_readdirp_cbk (call_frame_t *frame, xlator_t *this, int32_t op_ret, int32_t op_errno, - gf_dirent_t *entries) + gf_dirent_t *entries, dict_t *xdata) { struct syncargs *args = NULL; gf_dirent_t *entry = NULL; @@ -412,12 +1065,71 @@ syncop_readdirp (xlator_t *subvol, } int32_t +syncop_readdir_cbk (call_frame_t *frame, + void *cookie, + xlator_t *this, + int32_t op_ret, + int32_t op_errno, + gf_dirent_t *entries, dict_t *xdata) +{ + struct syncargs *args = NULL; + gf_dirent_t *entry = NULL; + gf_dirent_t *tmp = NULL; + + int count = 0; + + args = cookie; + + INIT_LIST_HEAD (&args->entries.list); + + args->op_ret = op_ret; + args->op_errno = op_errno; + + if (op_ret >= 0) { + list_for_each_entry (entry, &entries->list, list) { + tmp = entry_copy (entry); + gf_log (this->name, GF_LOG_TRACE, + "adding entry=%s, count=%d", + tmp->d_name, count); + list_add_tail (&tmp->list, &(args->entries.list)); + count++; + } + } + + __wake (args); + + return 0; + +} + +int +syncop_readdir (xlator_t *subvol, + fd_t *fd, + size_t size, + off_t off, + gf_dirent_t *entries) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_readdir_cbk, subvol->fops->readdir, + fd, size, off, NULL); + + if (entries) + list_splice_init (&args.entries.list, &entries->list); + /* TODO: need to free all the 'args.entries' in 'else' case */ + + errno = args.op_errno; + return args.op_ret; + +} + +int32_t syncop_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, - fd_t *fd) + fd_t *fd, dict_t *xdata) { struct syncargs *args = NULL; @@ -439,7 +1151,7 @@ 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; @@ -447,8 +1159,36 @@ syncop_opendir (xlator_t *subvol, } 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) + int op_ret, int op_errno, dict_t *xdata) { struct syncargs *args = NULL; @@ -468,7 +1208,7 @@ 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); + loc, name, NULL); errno = args.op_errno; return args.op_ret; @@ -476,7 +1216,7 @@ syncop_removexattr (xlator_t *subvol, loc_t *loc, const char *name) int syncop_fremovexattr_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; @@ -496,7 +1236,7 @@ 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); + subvol->fops->fremovexattr, fd, name, NULL); errno = args.op_errno; return args.op_ret; @@ -504,7 +1244,7 @@ syncop_fremovexattr (xlator_t *subvol, fd_t *fd, const char *name) 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; @@ -525,7 +1265,7 @@ 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; @@ -533,7 +1273,7 @@ syncop_setxattr (xlator_t *subvol, loc_t *loc, dict_t *dict, int32_t flags) int syncop_fsetxattr_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; @@ -554,7 +1294,7 @@ 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); + fd, dict, flags, NULL); errno = args.op_errno; return args.op_ret; @@ -562,7 +1302,7 @@ syncop_fsetxattr (xlator_t *subvol, fd_t *fd, dict_t *dict, int32_t flags) int syncop_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int op_ret, int op_errno, dict_t *dict) + int op_ret, int op_errno, dict_t *dict, dict_t *xdata) { struct syncargs *args = NULL; @@ -584,7 +1324,7 @@ 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); + loc, NULL, NULL); if (dict) *dict = args.xattr; @@ -601,7 +1341,7 @@ 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); + loc, key, NULL); if (dict) *dict = args.xattr; @@ -618,7 +1358,7 @@ 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); + fd, key, NULL); if (dict) *dict = args.xattr; @@ -632,7 +1372,7 @@ syncop_fgetxattr (xlator_t *subvol, fd_t *fd, dict_t **dict, const char *key) int syncop_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, - struct statvfs *buf) + struct statvfs *buf, dict_t *xdata) { struct syncargs *args = NULL; @@ -659,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; @@ -671,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; @@ -698,7 +1438,7 @@ 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; @@ -717,7 +1457,7 @@ syncop_fsetattr (xlator_t *subvol, fd_t *fd, struct iatt *iatt, int valid, struct syncargs args = {0, }; SYNCOP (subvol, (&args), syncop_setattr_cbk, subvol->fops->fsetattr, - fd, iatt, valid); + fd, iatt, valid, NULL); if (preop) *preop = args.iatt1; @@ -731,7 +1471,7 @@ syncop_fsetattr (xlator_t *subvol, fd_t *fd, struct iatt *iatt, int valid, 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) + int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata) { struct syncargs *args = NULL; @@ -740,9 +1480,6 @@ syncop_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, args->op_ret = op_ret; args->op_errno = op_errno; - if (op_ret != -1) - fd_ref (fd); - __wake (args); return 0; @@ -754,7 +1491,7 @@ 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, 0); + loc, flags, fd, NULL); errno = args.op_errno; return args.op_ret; @@ -765,7 +1502,8 @@ syncop_open (xlator_t *subvol, loc_t *loc, int32_t flags, fd_t *fd) 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) + int32_t count, struct iatt *stbuf, struct iobref *iobref, + dict_t *xdata) { struct syncargs *args = NULL; @@ -797,11 +1535,14 @@ syncop_readv (xlator_t *subvol, fd_t *fd, size_t size, off_t off, struct syncargs args = {0, }; SYNCOP (subvol, (&args), syncop_readv_cbk, subvol->fops->readv, - fd, size, off, flags); + fd, size, off, flags, NULL); + + if (args.op_ret < 0) + goto out; if (vector) *vector = args.vector; - else if (args.vector) + else GF_FREE (args.vector); if (count) @@ -813,6 +1554,7 @@ syncop_readv (xlator_t *subvol, fd_t *fd, size_t size, off_t off, else if (args.iobref) iobref_unref (args.iobref); +out: errno = args.op_errno; return args.op_ret; @@ -821,7 +1563,7 @@ syncop_readv (xlator_t *subvol, fd_t *fd, size_t size, off_t off, 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) + struct iatt *postbuf, dict_t *xdata) { struct syncargs *args = NULL; @@ -836,14 +1578,15 @@ syncop_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } int -syncop_writev (xlator_t *subvol, fd_t *fd, struct iovec *vector, +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, vector, count, offset, flags, iobref); + fd, (struct iovec *) vector, count, offset, flags, iobref, + NULL); errno = args.op_errno; return args.op_ret; @@ -859,7 +1602,7 @@ int syncop_write (xlator_t *subvol, fd_t *fd, const char *buf, int size, vec.iov_base = (void *)buf; SYNCOP (subvol, (&args), syncop_writev_cbk, subvol->fops->writev, - fd, &vec, 1, offset, flags, iobref); + fd, &vec, 1, offset, flags, iobref, NULL); errno = args.op_errno; return args.op_ret; @@ -878,7 +1621,7 @@ 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) + struct iatt *postparent, dict_t *xdata) { struct syncargs *args = NULL; @@ -887,8 +1630,8 @@ syncop_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, args->op_ret = op_ret; args->op_errno = op_errno; - if (op_ret != -1) - fd_ref (fd); + if (buf) + args->iatt1 = *buf; __wake (args); @@ -897,14 +1640,17 @@ syncop_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int syncop_create (xlator_t *subvol, loc_t *loc, int32_t flags, mode_t mode, - fd_t *fd, dict_t *dict) + 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, fd, dict); + loc, flags, mode, 0, fd, xdata); errno = args.op_errno; + if (iatt) + *iatt = args.iatt1; + return args.op_ret; } @@ -912,7 +1658,7 @@ syncop_create (xlator_t *subvol, loc_t *loc, int32_t flags, mode_t mode, 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) + struct iatt *postparent, dict_t *xdata) { struct syncargs *args = NULL; @@ -931,16 +1677,114 @@ syncop_unlink (xlator_t *subvol, loc_t *loc) { struct syncargs args = {0, }; - SYNCOP (subvol, (&args), syncop_unlink_cbk, subvol->fops->unlink, loc); + 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) + struct iatt *postbuf, dict_t *xdata) { struct syncargs *args = NULL; @@ -960,7 +1804,7 @@ 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); + fd, offset, NULL); errno = args.op_errno; return args.op_ret; @@ -972,7 +1816,7 @@ 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); + loc, offset, NULL); errno = args.op_errno; return args.op_ret; @@ -981,7 +1825,7 @@ syncop_truncate (xlator_t *subvol, loc_t *loc, off_t offset) 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) + struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata) { struct syncargs *args = NULL; @@ -997,12 +1841,43 @@ syncop_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } int -syncop_fsync (xlator_t *subvol, fd_t *fd) +syncop_fsync (xlator_t *subvol, fd_t *fd, int dataonly) { struct syncargs args = {0, }; SYNCOP (subvol, (&args), syncop_fsync_cbk, subvol->fops->fsync, - fd, 0); + 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; @@ -1011,7 +1886,7 @@ syncop_fsync (xlator_t *subvol, fd_t *fd) int syncop_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct iatt *stbuf) + int32_t op_ret, int32_t op_errno, struct iatt *stbuf, dict_t *xdata) { struct syncargs *args = NULL; @@ -1034,7 +1909,7 @@ 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); + fd, NULL); if (stbuf) *stbuf = args.iatt1; @@ -1050,7 +1925,7 @@ 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); + loc, NULL); if (stbuf) *stbuf = args.iatt1; @@ -1064,7 +1939,7 @@ 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) + struct iatt *postparent, dict_t *xdata) { struct syncargs *args = NULL; @@ -1072,6 +1947,8 @@ syncop_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, args->op_ret = op_ret; args->op_errno = op_errno; + if (buf) + args->iatt1 = *buf; __wake (args); @@ -1079,14 +1956,18 @@ syncop_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } int -syncop_symlink (xlator_t *subvol, loc_t *loc, char *newpath, dict_t *dict) +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, dict); + newpath, loc, 0, dict); errno = args.op_errno; + if (iatt) + *iatt = args.iatt1; + return args.op_ret; } @@ -1094,7 +1975,7 @@ syncop_symlink (xlator_t *subvol, loc_t *loc, char *newpath, dict_t *dict) 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) + struct iatt *stbuf, dict_t *xdata) { struct syncargs *args = NULL; @@ -1117,12 +1998,11 @@ 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); + loc, size, NULL); if (buffer) *buffer = args.buffer; - else if (args.buffer) - GF_FREE (args.buffer); + else GF_FREE (args.buffer); errno = args.op_errno; return args.op_ret; @@ -1132,7 +2012,7 @@ 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) + struct iatt *postparent, dict_t *xdata) { struct syncargs *args = NULL; @@ -1141,6 +2021,9 @@ syncop_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, args->op_ret = op_ret; args->op_errno = op_errno; + if (buf) + args->iatt1 = *buf; + __wake (args); return 0; @@ -1148,14 +2031,207 @@ syncop_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int syncop_mknod (xlator_t *subvol, loc_t *loc, mode_t mode, dev_t rdev, - dict_t *dict) + dict_t *dict, struct iatt *iatt) { struct syncargs args = {0, }; SYNCOP (subvol, (&args), syncop_mknod_cbk, subvol->fops->mknod, - loc, mode, rdev, dict); + 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 627fb6197..f790981f0 100644 --- a/libglusterfs/src/syncop.h +++ b/libglusterfs/src/syncop.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _SYNCOP_H @@ -30,8 +21,19 @@ #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; @@ -40,37 +42,91 @@ 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; @@ -83,82 +139,197 @@ struct syncargs { 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); \ - } \ +#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 __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); \ - } \ +#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 __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 __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); \ \ - frame = syncop_create_frame (); \ + if (task) { \ + frame->root->uid = task->uid; \ + frame->root->gid = task->gid; \ + } \ \ __yawn (stb); \ - STACK_WIND_COOKIE (frame, cbk, (void *)stb, subvol, op, params); \ + \ + STACK_WIND_COOKIE (frame, cbk, (void *)stb, subvol, \ + op, params); \ + \ __yield (stb); \ + if (task) \ + STACK_RESET (frame->root); \ + else \ + STACK_DESTROY (frame->root); \ } while (0) #define SYNCENV_DEFAULT_STACKSIZE (2 * 1024 * 1024) -struct syncenv * syncenv_new (); +struct syncenv * syncenv_new (size_t stacksize, int procmin, int procmax); void syncenv_destroy (struct syncenv *); +void syncenv_scale (struct syncenv *env); int synctask_new (struct syncenv *, synctask_fn_t, synctask_cbk_t, call_frame_t* frame, void *); -void synctask_zzzz (struct synctask *task); -void synctask_yawn (struct synctask *task); +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 */ @@ -169,6 +340,9 @@ int syncop_readdirp (xlator_t *subvol, fd_t *fd, size_t size, off_t off, /* out */ gf_dirent_t *entries); +int syncop_readdir (xlator_t *subvol, fd_t *fd, size_t size, off_t off, + gf_dirent_t *entries); + int syncop_opendir (xlator_t *subvol, loc_t *loc, fd_t *fd); int syncop_setattr (xlator_t *subvol, loc_t *loc, struct iatt *iatt, int valid, @@ -190,13 +364,13 @@ 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); + 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, struct iovec *vector, +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, @@ -208,14 +382,31 @@ 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 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, char *newpath, dict_t *dict); +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); + 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 8e2d56b8d..e8954cc23 100644 --- a/libglusterfs/src/syscall.c +++ b/libglusterfs/src/syscall.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -241,7 +232,12 @@ sys_statvfs (const char *path, struct statvfs *buf) int sys_close (int fd) { - return close (fd); + int ret = -1; + + if (fd >= 0) + ret = close (fd); + + return ret; } @@ -462,3 +458,26 @@ 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 f5325b4cd..f1c9f58c3 100644 --- a/libglusterfs/src/syscall.h +++ b/libglusterfs/src/syscall.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef __SYSCALL_H__ @@ -148,4 +139,6 @@ 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 d8f53a8d1..a059cc212 100644 --- a/libglusterfs/src/timer.c +++ b/libglusterfs/src/timer.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -26,19 +17,18 @@ #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) { @@ -57,10 +47,8 @@ gf_timer_call_after (glusterfs_ctx_t *ctx, if (!event) { 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; @@ -136,7 +124,7 @@ void * gf_timer_proc (void *ctx) { gf_timer_registry_t *reg = NULL; - const struct timespec sleepts = {.tv_sec = 1, .tv_nsec = 0, }; + const struct timespec sleepts = {.tv_sec = 1, .tv_nsec = 0, }; if (ctx == NULL) { @@ -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); @@ -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 3f1dc7adb..2f963adbf 100644 --- a/libglusterfs/src/timer.h +++ b/libglusterfs/src/timer.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _TIMER_H @@ -34,7 +25,7 @@ typedef void (*gf_timer_cbk_t) (void *); struct _gf_timer { struct _gf_timer *next, *prev; - struct timeval at; + struct timespec at; gf_timer_cbk_t callbk; void *data; xlator_t *xl; @@ -53,7 +44,7 @@ typedef struct _gf_timer_registry gf_timer_registry_t; gf_timer_t * gf_timer_call_after (glusterfs_ctx_t *ctx, - struct timeval delta, + struct timespec delta, gf_timer_cbk_t cbk, 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 index 0572bfd3e..f96bbebf6 100644 --- a/libglusterfs/src/trie.c +++ b/libglusterfs/src/trie.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include <stdio.h> @@ -123,8 +114,7 @@ trienode_free (trienode_t *node) trienode_free (trav); } - if (node->data) - GF_FREE (node->data); + GF_FREE (node->data); GF_FREE (node); } @@ -382,8 +372,7 @@ trie_measure_vec (trie_t *trie, const char *word, struct trienodevec *nodevec) static int trienode_reset (trienode_t *node, void *data) { - if (node->data) - GF_FREE (node->data); + GF_FREE (node->data); return 0; } diff --git a/libglusterfs/src/trie.h b/libglusterfs/src/trie.h index 2c2e05320..0356e6621 100644 --- a/libglusterfs/src/trie.h +++ b/libglusterfs/src/trie.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2007-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _TRIE_H_ diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c index 428357633..a277c58a8 100644 --- a/libglusterfs/src/xlator.c +++ b/libglusterfs/src/xlator.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _CONFIG_H @@ -88,6 +79,9 @@ fill_defaults (xlator_t *xl) 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); @@ -128,18 +122,9 @@ xlator_volopt_dynload (char *xlator_type, void **dl_handle, int ret = -1; char *name = NULL; void *handle = NULL; - volume_opt_list_t *vol_opt = NULL; GF_VALIDATE_OR_GOTO ("xlator", xlator_type, out); - GF_ASSERT (dl_handle); - - if (*dl_handle) - if (dlclose (*dl_handle)) - gf_log ("xlator", GF_LOG_WARNING, "Unable to close " - "previously opened handle( may be stale)." - "Ignoring the invalid handle"); - ret = gf_asprintf (&name, "%s/%s.so", XLATORDIR, xlator_type); if (-1 == ret) { gf_log ("xlator", GF_LOG_ERROR, "asprintf failed"); @@ -155,28 +140,20 @@ xlator_volopt_dynload (char *xlator_type, void **dl_handle, gf_log ("xlator", GF_LOG_WARNING, "%s", dlerror ()); goto out; } - *dl_handle = handle; - - vol_opt = GF_CALLOC (1, sizeof (volume_opt_list_t), - gf_common_mt_volume_opt_list_t); - - if (!vol_opt) { - goto out; - } - - if (!(vol_opt->given_opt = dlsym (handle, "options"))) { + if (!(opt_list->given_opt = dlsym (handle, "options"))) { dlerror (); - gf_log ("xlator", GF_LOG_DEBUG, - "Strict option validation not enforced -- neglecting"); + gf_log ("xlator", GF_LOG_ERROR, + "Failed to load xlator opt table"); + goto out; } - opt_list->given_opt = vol_opt->given_opt; - INIT_LIST_HEAD (&vol_opt->list); - list_add_tail (&vol_opt->list, &opt_list->list); + *dl_handle = handle; ret = 0; out: + GF_FREE (name); + gf_log ("xlator", GF_LOG_DEBUG, "Returning %d", ret); return ret; @@ -190,7 +167,7 @@ xlator_dynload (xlator_t *xl) 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); @@ -225,40 +202,55 @@ xlator_dynload (xlator_t *xl) goto out; } - if (!(xl->init = dlsym (handle, "init"))) { - gf_log ("xlator", GF_LOG_WARNING, "dlsym(init) on %s", - dlerror ()); - goto out; - } + /* + * 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_WARNING, "dlsym(fini) on %s", - dlerror ()); - goto out; - } + 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, + 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()); - } - vol_opt = GF_CALLOC (1, sizeof (volume_opt_list_t), gf_common_mt_volume_opt_list_t); @@ -268,9 +260,10 @@ xlator_dynload (xlator_t *xl) if (!(vol_opt->given_opt = dlsym (handle, "options"))) { dlerror (); - gf_log (xl->name, GF_LOG_DEBUG, + 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); @@ -278,8 +271,7 @@ xlator_dynload (xlator_t *xl) ret = 0; out: - if (name) - GF_FREE (name); + GF_FREE (name); return ret; } @@ -329,6 +321,24 @@ out: } +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) { @@ -352,7 +362,6 @@ out: return search; } - static int __xlator_init(xlator_t *xl) { @@ -430,6 +439,9 @@ xlator_fini_rec (xlator_t *xl) xl->fini (xl); + if (xl->local_pool) + mem_pool_destroy (xl->local_pool); + THIS = old_THIS; } else { gf_log (xl->name, GF_LOG_DEBUG, "No fini() found"); @@ -465,12 +477,12 @@ 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)); @@ -504,10 +516,26 @@ out: return; } +int +xlator_list_destroy (xlator_list_t *list) +{ + xlator_list_t *next = NULL; + + while (list) { + next = list->next; + GF_FREE (list); + list = next; + } + + return 0; +} + int xlator_tree_free (xlator_t *tree) { + volume_opt_list_t *vol_opt = NULL; + volume_opt_list_t *tmp = NULL; xlator_t *trav = tree; xlator_t *prev = tree; @@ -518,9 +546,19 @@ xlator_tree_free (xlator_t *tree) while (prev) { trav = prev->next; - dict_destroy (prev->options); + 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; } @@ -549,6 +587,67 @@ loc_wipe (loc_t *loc) memset (loc, 0, sizeof (*loc)); } +int +loc_path (loc_t *loc, const char *bname) +{ + int ret = 0; + + if (loc->path) + goto out; + + ret = -1; + + if (bname && !strlen (bname)) + bname = NULL; + + if (!bname) + goto inode_path; + + if (loc->parent && !uuid_is_null (loc->parent->gfid)) { + ret = inode_path (loc->parent, bname, (char**)&loc->path); + } else if (!uuid_is_null (loc->pargfid)) { + ret = gf_asprintf ((char**)&loc->path, INODE_PATH_FMT"/%s", + uuid_utoa (loc->pargfid), bname); + } + + if (loc->path) + goto out; + +inode_path: + if (loc->inode && !uuid_is_null (loc->inode->gfid)) { + ret = inode_path (loc->inode, NULL, (char **)&loc->path); + } else if (!uuid_is_null (loc->gfid)) { + ret = gf_asprintf ((char**)&loc->path, INODE_PATH_FMT, + uuid_utoa (loc->gfid)); + } +out: + return ret; +} + +void +loc_gfid (loc_t *loc, uuid_t gfid) +{ + if (!gfid) + goto out; + uuid_clear (gfid); + + if (!loc) + goto out; + else if (!uuid_is_null (loc->gfid)) + uuid_copy (gfid, loc->gfid); + else if (loc->inode && (!uuid_is_null (loc->inode->gfid))) + uuid_copy (gfid, loc->inode->gfid); +out: + return; +} + +char* +loc_gfid_utoa (loc_t *loc) +{ + uuid_t gfid; + loc_gfid (loc, gfid); + return uuid_utoa (gfid); +} int loc_copy (loc_t *dst, loc_t *src) @@ -560,6 +659,7 @@ loc_copy (loc_t *dst, loc_t *src) 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); @@ -567,45 +667,38 @@ loc_copy (loc_t *dst, loc_t *src) if (src->parent) dst->parent = inode_ref (src->parent); - dst->path = gf_strdup (src->path); + if (src->path) { + dst->path = gf_strdup (src->path); - if (!dst->path) - goto out; + if (!dst->path) + goto out; - dst->name = strrchr (dst->path, '/'); - if (dst->name) - dst->name++; + if (src->name) + dst->name = strrchr (dst->path, '/'); + if (dst->name) + dst->name++; + } ret = 0; out: - if (ret == -1) { - if (dst->inode) - inode_unref (dst->inode); - - if (dst->parent) - inode_unref (dst->parent); - } + if (ret == -1) + loc_wipe (dst); err: return ret; } - -int -xlator_list_destroy (xlator_list_t *list) +gf_boolean_t +loc_is_root (loc_t *loc) { - xlator_list_t *next = NULL; - - while (list) { - next = list->next; - GF_FREE (list); - list = next; + 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 0; + return _gf_false; } - int xlator_destroy (xlator_t *xl) { @@ -615,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) @@ -693,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) diff --git a/libglusterfs/src/xlator.h b/libglusterfs/src/xlator.h index c8eff3353..b57e5873e 100644 --- a/libglusterfs/src/xlator.h +++ b/libglusterfs/src/xlator.h @@ -1,20 +1,11 @@ /* - Copyright (c) 2006-2011 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 General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #ifndef _XLATOR_H @@ -29,7 +20,7 @@ #include <stdint.h> #include <inttypes.h> - +#include "event-history.h" #include "logging.h" #include "common-utils.h" #include "dict.h" @@ -75,6 +66,7 @@ typedef int32_t (*event_notify_fn_t) (xlator_t *this, int32_t event, void *data, #include "globals.h" #include "iatt.h" #include "options.h" +#include "client_t.h" struct _loc { @@ -106,7 +98,8 @@ 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, @@ -117,7 +110,7 @@ typedef int32_t (*fop_getspec_t) (call_frame_t *frame, 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, @@ -127,7 +120,7 @@ typedef int32_t (*fop_lookup_cbk_t) (call_frame_t *frame, int32_t op_errno, inode_t *inode, struct iatt *buf, - dict_t *xattr, + dict_t *xdata, struct iatt *postparent); typedef int32_t (*fop_stat_cbk_t) (call_frame_t *frame, @@ -135,14 +128,14 @@ typedef int32_t (*fop_stat_cbk_t) (call_frame_t *frame, xlator_t *this, int32_t op_ret, int32_t op_errno, - struct iatt *buf); + 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); + struct iatt *buf, dict_t *xdata); typedef int32_t (*fop_truncate_cbk_t) (call_frame_t *frame, void *cookie, @@ -150,7 +143,7 @@ typedef int32_t (*fop_truncate_cbk_t) (call_frame_t *frame, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf); + struct iatt *postbuf, dict_t *xdata); typedef int32_t (*fop_ftruncate_cbk_t) (call_frame_t *frame, void *cookie, @@ -158,13 +151,13 @@ typedef int32_t (*fop_ftruncate_cbk_t) (call_frame_t *frame, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf); + 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); + int32_t op_errno, dict_t *xdata); typedef int32_t (*fop_readlink_cbk_t) (call_frame_t *frame, void *cookie, @@ -172,7 +165,7 @@ typedef int32_t (*fop_readlink_cbk_t) (call_frame_t *frame, int32_t op_ret, int32_t op_errno, const char *path, - struct iatt *buf); + struct iatt *buf, dict_t *xdata); typedef int32_t (*fop_mknod_cbk_t) (call_frame_t *frame, void *cookie, @@ -182,7 +175,7 @@ typedef int32_t (*fop_mknod_cbk_t) (call_frame_t *frame, 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, @@ -192,7 +185,7 @@ typedef int32_t (*fop_mkdir_cbk_t) (call_frame_t *frame, 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, @@ -200,7 +193,7 @@ typedef int32_t (*fop_unlink_cbk_t) (call_frame_t *frame, 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, @@ -208,7 +201,7 @@ typedef int32_t (*fop_rmdir_cbk_t) (call_frame_t *frame, 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, @@ -218,7 +211,7 @@ typedef int32_t (*fop_symlink_cbk_t) (call_frame_t *frame, 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, @@ -229,7 +222,7 @@ typedef int32_t (*fop_rename_cbk_t) (call_frame_t *frame, 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, @@ -239,7 +232,7 @@ typedef int32_t (*fop_link_cbk_t) (call_frame_t *frame, 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, @@ -250,14 +243,14 @@ typedef int32_t (*fop_create_cbk_t) (call_frame_t *frame, 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); + fd_t *fd, dict_t *xdata); typedef int32_t (*fop_readv_cbk_t) (call_frame_t *frame, void *cookie, @@ -267,7 +260,7 @@ typedef int32_t (*fop_readv_cbk_t) (call_frame_t *frame, struct iovec *vector, int32_t count, struct iatt *stbuf, - struct iobref *iobref); + struct iobref *iobref, dict_t *xdata); typedef int32_t (*fop_writev_cbk_t) (call_frame_t *frame, void *cookie, @@ -275,13 +268,13 @@ typedef int32_t (*fop_writev_cbk_t) (call_frame_t *frame, int32_t op_ret, int32_t op_errno, struct iatt *prebuf, - struct iatt *postbuf); + 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); + int32_t op_errno, dict_t *xdata); typedef int32_t (*fop_fsync_cbk_t) (call_frame_t *frame, void *cookie, @@ -289,124 +282,124 @@ typedef int32_t (*fop_fsync_cbk_t) (call_frame_t *frame, 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + dict_t *xattr, dict_t *xdata); typedef int32_t (*fop_setattr_cbk_t) (call_frame_t *frame, @@ -415,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, @@ -423,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); + dict_t *xdata); typedef int32_t (*fop_stat_t) (call_frame_t *frame, xlator_t *this, - loc_t *loc); + loc_t *loc, dict_t *xdata); typedef int32_t (*fop_fstat_t) (call_frame_t *frame, xlator_t *this, - fd_t *fd); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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. @@ -499,19 +515,16 @@ 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, - uint32_t flags); + uint32_t flags, dict_t *xdata); typedef int32_t (*fop_writev_t) (call_frame_t *frame, xlator_t *this, @@ -520,132 +533,152 @@ typedef int32_t (*fop_writev_t) (call_frame_t *frame, int32_t count, off_t offset, uint32_t flags, - struct iobref *iobref); + struct iobref *iobref, dict_t *xdata); typedef int32_t (*fop_flush_t) (call_frame_t *frame, xlator_t *this, - fd_t *fd); + 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); + 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); + 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); + int32_t datasync, dict_t *xdata); typedef int32_t (*fop_statfs_t) (call_frame_t *frame, xlator_t *this, - loc_t *loc); + 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); + 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); + 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); + 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); + 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); + struct gf_flock *flock, dict_t *xdata); typedef int32_t (*fop_inodelk_t) (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); typedef int32_t (*fop_finodelk_t) (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); typedef int32_t (*fop_entrylk_t) (call_frame_t *frame, xlator_t *this, const char *volume, loc_t *loc, const char *basename, entrylk_cmd cmd, - entrylk_type type); + entrylk_type type, dict_t *xdata); typedef int32_t (*fop_fentrylk_t) (call_frame_t *frame, xlator_t *this, const char *volume, fd_t *fd, const char *basename, entrylk_cmd cmd, - entrylk_type type); + 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); + 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, - dict_t *dict); + 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); + 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); + 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; @@ -690,6 +723,9 @@ struct xlator_fops { fop_setattr_t setattr; fop_fsetattr_t fsetattr; fop_getspec_t getspec; + fop_fallocate_t fallocate; + fop_discard_t discard; + fop_zerofill_t zerofill; /* these entries are used for a typechecking hack in STACK_WIND _only_ */ fop_lookup_cbk_t lookup_cbk; @@ -734,6 +770,9 @@ struct xlator_fops { 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, @@ -742,10 +781,17 @@ typedef int32_t (*cbk_forget_t) (xlator_t *this, typedef int32_t (*cbk_release_t) (xlator_t *this, 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); @@ -770,6 +816,8 @@ typedef int32_t (*dumpop_inodectx_to_dict_t) (xlator_t *this, inode_t *ino, 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; @@ -781,6 +829,7 @@ struct xlator_dumpops { 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 { @@ -818,16 +867,43 @@ struct _xlator { fop_latency_t latencies[GF_FOP_MAXVALUE]; /* Misc */ + eh_t *history; /* event history context */ glusterfs_ctx_t *ctx; glusterfs_graph_t *graph; /* not set for fuse */ inode_table_t *itable; char init_succeeded; void *private; struct mem_acct mem_acct; + uint64_t winds; + char switched; + + /* for the memory pool of 'frame->local' */ + struct mem_pool *local_pool; + gf_boolean_t is_autoloaded; }; +typedef struct { + int32_t (*init) (xlator_t *this); + void (*fini) (xlator_t *this); + int32_t (*reconfigure) (xlator_t *this, + dict_t *options); + event_notify_fn_t notify; +} class_methods_t; + #define xlator_has_parent(xl) (xl->parents != NULL) +#define XLATOR_NOTIFY(_xl, params ...) \ + do { \ + xlator_t *_old_THIS = NULL; \ + \ + _old_THIS = THIS; \ + THIS = _xl; \ + \ + ret = _xl->notify (_xl, params);\ + \ + THIS = _old_THIS; \ + } while (0); + int32_t xlator_set_type_virtual (xlator_t *xl, const char *type); int32_t xlator_set_type (xlator_t *xl, const char *type); @@ -851,6 +927,11 @@ void xlator_foreach (xlator_t *this, 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); void inode_destroy_notify (inode_t *inode, const char *xlname); @@ -858,9 +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 is_gf_log_command (xlator_t *trans, const char *name, char *value); int glusterd_check_log_level (const char *value); int xlator_volopt_dynload (char *xlator_type, void **dl_handle, volume_opt_list_t *vol_opt_handle); +enum gf_hdsk_event_notify_op { + GF_EN_DEFRAG_STATUS, + GF_EN_MAX, +}; +gf_boolean_t +is_graph_topology_equal (glusterfs_graph_t *graph1, glusterfs_graph_t *graph2); +int +glusterfs_volfile_reconfigure (int oldvollen, FILE *newvolfile_fp, + glusterfs_ctx_t *ctx, const char *oldvolfile); #endif /* _XLATOR_H */ |
