From b6cc23204f1941184cb08ec3d84beecd2d06fd91 Mon Sep 17 00:00:00 2001 From: Atin Mukherjee Date: Wed, 9 Apr 2014 11:53:33 +0530 Subject: glusterfs-server : barrier timeout tuning fix Problem : Reconfiguration of barrier timeout through gluster volume set shows a success but it never changes the default timeout value which is 120 seconds. After digging into the code deeper, it was found that timeout is never modified in reconfigure() as the first check i.e. whether barrier is already enabled or disabled always fails since barrier option is not modified in this request. Fix : Introduced notify() in barrier translator which will take care of the rpc request to enable/disable barrier. reconfigure() will simply set barrier enable/disable and timeout options blindly without any validation. Please note this patch only contains the changes in barrier translator however from complete code flow perspective the caller in the glusterfsd mgmt should call notify instead of reconfigure to fix this problem. Change-Id: I1371b294935f6054da7c1dc6a9a19f1d861e60fb BUG: 1085671 Signed-off-by: Atin Mukherjee Reviewed-on: http://review.gluster.org/7428 Reviewed-by: Varun Shastry Reviewed-by: Krishnan Parthasarathi Tested-by: Gluster Build System Reviewed-by: Vijay Bellur --- xlators/features/barrier/src/barrier.c | 82 +++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 12 deletions(-) (limited to 'xlators/features') diff --git a/xlators/features/barrier/src/barrier.c b/xlators/features/barrier/src/barrier.c index e5465d1b4..9937698ed 100644 --- a/xlators/features/barrier/src/barrier.c +++ b/xlators/features/barrier/src/barrier.c @@ -333,6 +333,74 @@ out: return ret; } +int +notify (xlator_t *this, int event, void *data, ...) +{ + barrier_priv_t *priv = NULL; + dict_t *dict = NULL; + gf_boolean_t past = _gf_false; + int ret = -1; + gf_boolean_t barrier_enabled = _gf_false; + struct list_head queue = {0,}; + + priv = this->private; + GF_ASSERT (priv); + INIT_LIST_HEAD (&queue); + + switch (event) { + case GF_EVENT_TRANSLATOR_OP: + { + dict = data; + GF_OPTION_RECONF ("barrier", barrier_enabled, dict, + bool, out); + + LOCK (&priv->lock); + { + past = priv->barrier_enabled; + + switch (past) { + case _gf_false: + if (barrier_enabled) { + ret = __barrier_enable (this,priv); + if (ret) + goto unlock; + } else { + gf_log (this->name, GF_LOG_ERROR, + "Already disabled."); + goto unlock; + } + break; + + case _gf_true: + if (!barrier_enabled) { + __barrier_disable(this, &queue); + } else { + gf_log (this->name, GF_LOG_ERROR, + "Already enabled"); + goto unlock; + } + break; + } + ret = 0; + } +unlock: + UNLOCK (&priv->lock); + + if (!list_empty (&queue)) + barrier_dequeue_all (this, &queue); + // missing break is intentional + } + default: + { + default_notify (this, event, data); + ret = 0; + goto out; + } + } +out: + return ret; +} + int reconfigure (xlator_t *this, dict_t *options) { @@ -359,13 +427,9 @@ reconfigure (xlator_t *this, dict_t *options) case _gf_false: if (barrier_enabled) { ret = __barrier_enable (this, priv); - if (ret) + if (ret) { goto unlock; - - } else { - gf_log (this->name, GF_LOG_ERROR, - "Already disabled"); - goto unlock; + } } break; @@ -373,16 +437,10 @@ reconfigure (xlator_t *this, dict_t *options) if (!barrier_enabled) { __barrier_disable (this, &queue); - } else { - gf_log (this->name, GF_LOG_ERROR, - "Already enabled"); - goto unlock; } break; } - priv->timeout.tv_sec = timeout; - ret = 0; } unlock: -- cgit From a3cb38e3edf005bef73da4c9cfd958474a14d50f Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Thu, 17 Apr 2014 15:54:34 -0700 Subject: build: MacOSX Porting fixes git@forge.gluster.org:~schafdog/glusterfs-core/osx-glusterfs Working functionality on MacOSX - GlusterD (management daemon) - GlusterCLI (management cli) - GlusterFS FUSE (using OSXFUSE) - GlusterNFS (without NLM - issues with rpc.statd) Change-Id: I20193d3f8904388e47344e523b3787dbeab044ac BUG: 1089172 Signed-off-by: Harshavardhana Signed-off-by: Dennis Schafroth Tested-by: Harshavardhana Tested-by: Dennis Schafroth Reviewed-on: http://review.gluster.org/7503 Tested-by: Gluster Build System Reviewed-by: Anand Avati --- xlators/features/changelog/src/Makefile.am | 2 +- xlators/features/changelog/src/changelog-helpers.h | 14 +- xlators/features/compress/src/Makefile.am | 2 +- xlators/features/index/src/index.c | 4 +- xlators/features/locks/src/inodelk.c | 2 +- xlators/features/locks/src/posix.c | 11 +- xlators/features/mac-compat/src/Makefile.am | 5 +- xlators/features/mac-compat/src/mac-compat.c | 246 +++++++++++++++------ xlators/features/mac-compat/src/mac-compat.h | 41 ++++ xlators/features/marker/src/marker-quota-helper.h | 2 +- xlators/features/marker/src/marker-quota.c | 6 +- xlators/features/marker/src/marker.c | 32 +-- xlators/features/quota/src/quota.c | 8 +- xlators/features/quota/src/quotad-aggregator.c | 2 +- 14 files changed, 268 insertions(+), 109 deletions(-) create mode 100644 xlators/features/mac-compat/src/mac-compat.h (limited to 'xlators/features') diff --git a/xlators/features/changelog/src/Makefile.am b/xlators/features/changelog/src/Makefile.am index 54c21ac21..c5d5e100e 100644 --- a/xlators/features/changelog/src/Makefile.am +++ b/xlators/features/changelog/src/Makefile.am @@ -12,7 +12,7 @@ changelog_la_SOURCES = changelog.c changelog-rt.c changelog-helpers.c \ changelog_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src -fPIC -D_FILE_OFFSET_BITS=64 \ - -D_GNU_SOURCE -D$(GF_HOST_OS) -shared -nostartfiles -DDATADIR=\"$(localstatedir)\" + -D_GNU_SOURCE -D$(GF_HOST_OS) -shared -DDATADIR=\"$(localstatedir)\" AM_CFLAGS = -Wall $(GF_CFLAGS) diff --git a/xlators/features/changelog/src/changelog-helpers.h b/xlators/features/changelog/src/changelog-helpers.h index b441f7068..53588f55e 100644 --- a/xlators/features/changelog/src/changelog-helpers.h +++ b/xlators/features/changelog/src/changelog-helpers.h @@ -268,9 +268,11 @@ typedef struct { void changelog_thread_cleanup (xlator_t *this, pthread_t thr_id); -inline void * + +void * changelog_get_usable_buffer (changelog_local_t *local); -inline void + +void changelog_set_usable_record_and_length (changelog_local_t *local, size_t len, int xr); void @@ -290,16 +292,16 @@ int changelog_inject_single_event (xlator_t *this, changelog_priv_t *priv, changelog_log_data_t *cld); -inline size_t +size_t changelog_entry_length (); -inline int +int changelog_write (int fd, char *buffer, size_t len); int changelog_write_change (changelog_priv_t *priv, char *buffer, size_t len); -inline int +int changelog_handle_change (xlator_t *this, changelog_priv_t *priv, changelog_log_data_t *cld); -inline void +void changelog_update (xlator_t *this, changelog_priv_t *priv, changelog_local_t *local, changelog_log_type type); void * diff --git a/xlators/features/compress/src/Makefile.am b/xlators/features/compress/src/Makefile.am index 0bf757c06..263b21b78 100644 --- a/xlators/features/compress/src/Makefile.am +++ b/xlators/features/compress/src/Makefile.am @@ -10,7 +10,7 @@ cdc_la_SOURCES = cdc.c cdc-helper.c cdc_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D$(GF_HOST_OS) \ --shared -nostartfiles $(LIBZ_CFLAGS) +-shared $(LIBZ_CFLAGS) AM_CFLAGS = -Wall $(GF_CFLAGS) diff --git a/xlators/features/index/src/index.c b/xlators/features/index/src/index.c index 5c1c65fbd..4b2eb2e29 100644 --- a/xlators/features/index/src/index.c +++ b/xlators/features/index/src/index.c @@ -497,13 +497,13 @@ fop_fxattrop_index_action (xlator_t *this, inode_t *inode, dict_t *xattr) _xattrop_index_action (this, inode, xattr); } -inline gf_boolean_t +static inline gf_boolean_t index_xattrop_track (loc_t *loc, gf_xattrop_flags_t flags, dict_t *dict) { return (flags == GF_XATTROP_ADD_ARRAY); } -inline gf_boolean_t +static inline gf_boolean_t index_fxattrop_track (fd_t *fd, gf_xattrop_flags_t flags, dict_t *dict) { return (flags == GF_XATTROP_ADD_ARRAY); diff --git a/xlators/features/locks/src/inodelk.c b/xlators/features/locks/src/inodelk.c index e7093e60e..2d9aa83ec 100644 --- a/xlators/features/locks/src/inodelk.c +++ b/xlators/features/locks/src/inodelk.c @@ -35,7 +35,7 @@ __pl_inodelk_ref (pl_inode_lock_t *lock) lock->ref++; } -void +inline void __pl_inodelk_unref (pl_inode_lock_t *lock) { lock->ref--; diff --git a/xlators/features/locks/src/posix.c b/xlators/features/locks/src/posix.c index 2db327687..337623d65 100644 --- a/xlators/features/locks/src/posix.c +++ b/xlators/features/locks/src/posix.c @@ -294,7 +294,7 @@ pl_locks_by_fd (pl_inode_t *pl_inode, fd_t *fd) { list_for_each_entry (l, &pl_inode->ext_list, list) { - if ((l->fd_num == fd_to_fdnum(fd))) { + if (l->fd_num == fd_to_fdnum(fd)) { found = 1; break; } @@ -319,7 +319,7 @@ delete_locks_of_fd (xlator_t *this, pl_inode_t *pl_inode, fd_t *fd) { list_for_each_entry_safe (l, tmp, &pl_inode->ext_list, list) { - if ((l->fd_num == fd_to_fdnum(fd))) { + if (l->fd_num == fd_to_fdnum(fd)) { if (l->blocked) { list_move_tail (&l->list, &blocked_list); continue; @@ -644,7 +644,8 @@ pl_fgetxattr_handle_lockinfo (xlator_t *this, fd_t *fd, pl_inode_t *pl_inode = NULL; char *key = NULL, *buf = NULL; int32_t op_ret = 0; - unsigned long fdnum = 0, len = 0; + unsigned long fdnum = 0; + int32_t len = 0; dict_t *tmp = NULL; pl_inode = pl_inode_get (this, fd->inode); @@ -1340,7 +1341,7 @@ __fd_has_locks (pl_inode_t *pl_inode, fd_t *fd) posix_lock_t *l = NULL; list_for_each_entry (l, &pl_inode->ext_list, list) { - if ((l->fd_num == fd_to_fdnum(fd))) { + if (l->fd_num == fd_to_fdnum(fd)) { found = 1; break; } @@ -1369,7 +1370,7 @@ __dup_locks_to_fdctx (pl_inode_t *pl_inode, fd_t *fd, int ret = 0; list_for_each_entry (l, &pl_inode->ext_list, list) { - if ((l->fd_num == fd_to_fdnum(fd))) { + if (l->fd_num == fd_to_fdnum(fd)) { duplock = lock_dup (l); if (!duplock) { ret = -1; diff --git a/xlators/features/mac-compat/src/Makefile.am b/xlators/features/mac-compat/src/Makefile.am index f8567edce..42ed350e9 100644 --- a/xlators/features/mac-compat/src/Makefile.am +++ b/xlators/features/mac-compat/src/Makefile.am @@ -6,9 +6,10 @@ mac_compat_la_LDFLAGS = -module -avoid-version mac_compat_la_SOURCES = mac-compat.c mac_compat_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la +noinst_HEADERS = mac-compat.h + AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src AM_CFLAGS = -Wall $(GF_CFLAGS) -CLEANFILES = - +CLEANFILES = diff --git a/xlators/features/mac-compat/src/mac-compat.c b/xlators/features/mac-compat/src/mac-compat.c index 7cb550ad5..0eaf563e8 100644 --- a/xlators/features/mac-compat/src/mac-compat.c +++ b/xlators/features/mac-compat/src/mac-compat.c @@ -15,35 +15,28 @@ #include "xlator.h" #include "defaults.h" #include "compat-errno.h" +#include "syscall.h" +#include "mem-pool.h" +#include "mac-compat.h" - -enum apple_xattr { - GF_FINDER_INFO_XATTR, - GF_RESOURCE_FORK_XATTR, - GF_XATTR_ALL, - GF_XATTR_NONE -}; - -static char *apple_xattr_name[] = { - [GF_FINDER_INFO_XATTR] = "com.apple.FinderInfo", - [GF_RESOURCE_FORK_XATTR] = "com.apple.ResourceFork" -}; - -static const char *apple_xattr_value[] = { - [GF_FINDER_INFO_XATTR] = - /* 1 2 3 4 5 6 7 8 */ - "\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0" - "\0\0\0\0\0\0\0\0", - [GF_RESOURCE_FORK_XATTR] = "" -}; - -static int32_t apple_xattr_len[] = { - [GF_FINDER_INFO_XATTR] = 32, - [GF_RESOURCE_FORK_XATTR] = 1 -}; - +static int +dict_key_remove_namespace(dict_t *dict, char *key, data_t *value, void *data) +{ + /* + char buffer[3*value->len+1]; + int index = 0; + for (index = 0; index < value->len; index++) + sprintf(buffer+3*index, " %02x", value->data[index]); + */ + xlator_t *this = (xlator_t *) data; + if (strncmp(key, "user.", 5) == 0) { + dict_set (dict, key + 5, value); + gf_log (this->name, GF_LOG_DEBUG, + "remove_namespace_dict: %s -> %s ", key, key + 5); + dict_del (dict, key); + } + return 0; +} int32_t maccomp_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, @@ -53,54 +46,91 @@ maccomp_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, intptr_t ax = (intptr_t)this->private; int i = 0; + gf_log (this->name, GF_LOG_DEBUG, + "getxattr_cbk: dict %p private: %p xdata %p ", dict, + this->private, xdata); + + if (dict) { + dict_foreach(dict, dict_key_remove_namespace, this); + } + else { + // TODO: we expect dict to exist here, don't know why this + // this is needed + dict = dict_new(); + } + gf_log (this->name, GF_LOG_DEBUG, + "getxattr_cbk: dict %p ax: %ld op_ret %d op_err %d ", dict, ax, + op_ret, op_errno); if ((ax == GF_XATTR_ALL && op_ret >= 0) || ax != GF_XATTR_NONE) { op_ret = op_errno = 0; - for (i = 0; i < GF_XATTR_ALL; i++) { if (dict_get (dict, apple_xattr_name[i])) continue; - + /* set dummy data */ + gf_log (this->name, GF_LOG_DEBUG, + "getxattr_cbk: setting dummy data %p, %s", dict, + apple_xattr_name[i]); if (dict_set (dict, apple_xattr_name[i], bin_to_data ((void *)apple_xattr_value[i], apple_xattr_len[i])) == -1) { op_ret = -1; - op_errno = ENOMEM; + op_errno = ENOATTR; break; } } } - STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict, xdata); - return 0; } -int32_t -maccomp_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, - const char *name, dict_t *xdata) +static +int prepend_xattr_user_namespace(dict_t *dict, char *key, data_t *value, void *obj) { - intptr_t ax = GF_XATTR_NONE; - int i = 0; + xlator_t *this = (xlator_t *) obj; + dict_t *newdict = (dict_t *) this->private; + char *newkey = NULL; + gf_add_prefix(XATTR_USER_PREFIX, key, &newkey); + key = newkey; + dict_set(newdict, (char *)key, value); + if (newkey) + GF_FREE(newkey); + return 0; +} +intptr_t +check_name(const char *name, char **newkey) +{ + intptr_t ax = GF_XATTR_NONE; if (name) { + int i = 0; for (i = 0; i < GF_XATTR_ALL; i++) { if (strcmp (apple_xattr_name[i], name) == 0) { ax = i; - break; } } + gf_add_prefix("user.", name, newkey); } else ax = GF_XATTR_ALL; + return ax; +} - this->private = (void *)ax; +int32_t +maccomp_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata) +{ + char *newkey = NULL; + this->private = (void *) check_name(name, &newkey); + gf_log (this->name, GF_LOG_DEBUG, + "getxattr: name %s private: %p xdata %p ", name, + this->private, xdata); STACK_WIND (frame, maccomp_getxattr_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->getxattr, - loc, name, xdata); + loc, newkey, xdata); return 0; } @@ -109,30 +139,17 @@ int32_t maccomp_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, dict_t *xdata) { - intptr_t ax = GF_XATTR_NONE; - int i = 0; - - if (name) { - for (i = 0; i < GF_XATTR_ALL; i++) { - if (strcmp (apple_xattr_name[i], name) == 0) { - ax = i; - - break; - } - } - } else - ax = GF_XATTR_ALL; - - this->private = (void *)ax; + char *newkey = NULL; + this->private = (void *) check_name(name, &newkey); STACK_WIND (frame, maccomp_getxattr_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->fgetxattr, - fd, name, xdata); + fd, newkey, xdata); + GF_FREE(newkey); return 0; } - int32_t maccomp_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) @@ -141,12 +158,56 @@ maccomp_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (op_ret == -1 && ax != GF_XATTR_NONE) op_ret = op_errno = 0; - + gf_log (this->name, GF_LOG_DEBUG, + "setxattr_cbk op_ret %d op_errno %d private: %p xdata %p ", + op_ret, op_errno, this->private, xdata); STACK_UNWIND_STRICT (setxattr, frame, op_ret, op_errno, xdata); + return 0; +} +int32_t +maccomp_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *iatt1, + struct iatt *iattr2, dict_t *xdata) +{ + gf_log (this->name, GF_LOG_DEBUG, + "setattr_cbk op_ret %d op_errno %d private: %p xdata %p ", + op_ret, op_errno, this->private, xdata); + STACK_UNWIND_STRICT (setattr, frame, op_ret, op_errno, + iatt1, iattr2, xdata); return 0; } +int map_flags(int flags) +{ + /* DARWIN has different defines on XATTR_ flags. + There do not seem to be a POSIX standard + Parse any other flags over. + NOFOLLOW is always true on Linux and Darwin + */ + int linux_flags = flags & ~(GF_XATTR_CREATE | GF_XATTR_REPLACE | XATTR_REPLACE); + if (XATTR_CREATE & flags) + linux_flags |= GF_XATTR_CREATE; + if (XATTR_REPLACE & flags) + linux_flags |= GF_XATTR_REPLACE; + return linux_flags; +} + +int32_t +maccomp_fremovexattr (call_frame_t *frame, xlator_t *this, fd_t *fd, + const char *name, dict_t *xdata) +{ + char *newkey = NULL; + + this->private = (void *) check_name(name, &newkey); + + STACK_WIND (frame, default_fremovexattr_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fremovexattr, + fd, newkey, xdata); + GF_FREE(newkey); + return 0; +} int32_t maccomp_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, @@ -162,16 +223,56 @@ maccomp_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, break; } } + dict_t *newdict = dict_new(); + this->private = (void *) newdict; + dict_foreach(dict, prepend_xattr_user_namespace, this); this->private = (void *)ax; - + int linux_flags = map_flags(flags); + gf_log (this->name, GF_LOG_DEBUG, + "setxattr flags: %d -> %d dict %p private: %p xdata %p ", + flags, linux_flags, dict, this->private, xdata); STACK_WIND (frame, maccomp_setxattr_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->setxattr, - loc, dict, flags, xdata); + loc, newdict, linux_flags, xdata); + dict_unref(newdict); return 0; } +int32_t +maccomp_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, struct iatt *iattr, + int32_t flags, dict_t *xdata) +{ + gf_log (this->name, GF_LOG_DEBUG, + "setattr iattr %p private: %p xdata %p ", + iattr, this->private, xdata); + STACK_WIND (frame, maccomp_setattr_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->setattr, + loc, iattr, flags, xdata); + return 0; +} + +int32_t +maccomp_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata) +{ + char *newkey = NULL; + this->private = (void *) check_name(name, &newkey); + + STACK_WIND (frame, default_removexattr_cbk, + FIRST_CHILD(this), + FIRST_CHILD(this)->fops->removexattr, + loc, newkey, xdata); + + gf_log (this->name, GF_LOG_TRACE, + "removeattr name %p private: %p xdata %p ", + name, this->private, xdata); + GF_FREE(newkey); + return 0; + +} int32_t maccomp_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, @@ -188,12 +289,20 @@ maccomp_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, } } - this->private = (void *)ax; + dict_t *newdict = dict_new(); + this->private = (void *) newdict; + dict_foreach(dict, prepend_xattr_user_namespace, this); + this->private = (void *)ax; + int linux_flags = map_flags(flags); + gf_log (this->name, GF_LOG_DEBUG, + "fsetxattr flags: %d -> %d dict %p private: %p xdata %p ", + flags, linux_flags, dict, this->private, xdata); STACK_WIND (frame, maccomp_setxattr_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->fsetxattr, - fd, dict, flags, xdata); + fd, newdict, linux_flags, xdata); + dict_unref(newdict); return 0; } @@ -224,10 +333,13 @@ fini (xlator_t *this) struct xlator_fops fops = { - .getxattr = maccomp_getxattr, - .fgetxattr = maccomp_fgetxattr, - .setxattr = maccomp_setxattr, - .fsetxattr = maccomp_fsetxattr, + .getxattr = maccomp_getxattr, + .fgetxattr = maccomp_fgetxattr, + .setxattr = maccomp_setxattr, + .setattr = maccomp_setattr, + .fsetxattr = maccomp_fsetxattr, + .removexattr = maccomp_removexattr, + .fremovexattr = maccomp_fremovexattr, }; struct xlator_cbks cbks; diff --git a/xlators/features/mac-compat/src/mac-compat.h b/xlators/features/mac-compat/src/mac-compat.h new file mode 100644 index 000000000..b033ca0e4 --- /dev/null +++ b/xlators/features/mac-compat/src/mac-compat.h @@ -0,0 +1,41 @@ +/* + Copyright (c) 2014 Red Hat, Inc. + 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 __MAC_COMPAT_H__ +#define __MAC_COMPAT_H__ + +enum apple_xattr { + GF_FINDER_INFO_XATTR, + GF_RESOURCE_FORK_XATTR, + GF_XATTR_ALL, + GF_XATTR_NONE +}; + +static char *apple_xattr_name[] = { + [GF_FINDER_INFO_XATTR] = "com.apple.FinderInfo", + [GF_RESOURCE_FORK_XATTR] = "com.apple.ResourceFork" +}; + +static const char *apple_xattr_value[] = { + [GF_FINDER_INFO_XATTR] = + /* 1 2 3 4 5 6 7 8 */ + "\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0", + [GF_RESOURCE_FORK_XATTR] = "" +}; + +static int32_t apple_xattr_len[] = { + [GF_FINDER_INFO_XATTR] = 32, + [GF_RESOURCE_FORK_XATTR] = 1 +}; + +#endif /* __MAC_COMPAT_H__ */ diff --git a/xlators/features/marker/src/marker-quota-helper.h b/xlators/features/marker/src/marker-quota-helper.h index 6cdd14881..b200413b0 100644 --- a/xlators/features/marker/src/marker-quota-helper.h +++ b/xlators/features/marker/src/marker-quota-helper.h @@ -9,7 +9,7 @@ */ #ifndef _MARKER_QUOTA_HELPER_H -#define _MARKER_QUOTA_HELPER +#define _MARKER_QUOTA_HELPER_H #ifndef _CONFIG_H #define _CONFIG_H diff --git a/xlators/features/marker/src/marker-quota.c b/xlators/features/marker/src/marker-quota.c index a758e938f..1903fdc40 100644 --- a/xlators/features/marker/src/marker-quota.c +++ b/xlators/features/marker/src/marker-quota.c @@ -365,7 +365,10 @@ mq_update_size_xattr (call_frame_t *frame, void *cookie, xlator_t *this, local->loc.path, ntoh64 (*delta)); new_dict = dict_new (); - if (!new_dict); + if (!new_dict) { + errno = ENOMEM; + goto err; + } ret = dict_set_bin (new_dict, QUOTA_SIZE_KEY, delta, 8); if (ret) @@ -385,7 +388,6 @@ mq_update_size_xattr (call_frame_t *frame, void *cookie, xlator_t *this, err: if (op_ret == -1 || ret == -1) { local->err = -1; - mq_release_lock_on_dirty_inode (frame, NULL, this, 0, 0, NULL); } diff --git a/xlators/features/marker/src/marker.c b/xlators/features/marker/src/marker.c index a27a266f0..adcf3d8e7 100644 --- a/xlators/features/marker/src/marker.c +++ b/xlators/features/marker/src/marker.c @@ -255,18 +255,18 @@ out: return 0; } -int32_t +gf_boolean_t call_from_special_client (call_frame_t *frame, xlator_t *this, const char *name) { struct volume_mark *vol_mark = NULL; marker_conf_t *priv = NULL; - gf_boolean_t ret = _gf_true; + gf_boolean_t is_true = _gf_true; priv = (marker_conf_t *)this->private; if (frame->root->pid != GF_CLIENT_PID_GSYNCD || name == NULL || strcmp (name, MARKER_XATTR_PREFIX "." VOLUME_MARK) != 0) { - ret = _gf_false; + is_true = _gf_false; goto out; } @@ -274,7 +274,7 @@ call_from_special_client (call_frame_t *frame, xlator_t *this, const char *name) marker_getxattr_stampfile_cbk (frame, this, name, vol_mark, NULL); out: - return ret; + return is_true; } int32_t @@ -348,10 +348,10 @@ int32_t marker_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, dict_t *xdata) { - gf_boolean_t ret = _gf_false; - marker_conf_t *priv = NULL; - unsigned long cookie = 0; - marker_local_t *local = NULL; + gf_boolean_t is_true = _gf_false; + marker_conf_t *priv = NULL; + unsigned long cookie = 0; + marker_local_t *local = NULL; priv = this->private; @@ -362,16 +362,15 @@ marker_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, MARKER_INIT_LOCAL (frame, local); - ret = loc_copy (&local->loc, loc); - if (ret < 0) - goto out; + if ((loc_copy (&local->loc, loc)) < 0) + goto out; gf_log (this->name, GF_LOG_DEBUG, "USER:PID = %d", frame->root->pid); if (priv && priv->feature_enabled & GF_XTIME) - ret = call_from_special_client (frame, this, name); + is_true = call_from_special_client (frame, this, name); - if (ret == _gf_false) { + if (is_true == _gf_false) { if (name == NULL) { /* Signifies that marker translator * has to filter the quota's xattr's, @@ -380,10 +379,11 @@ marker_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, */ cookie = 1; } - STACK_WIND_COOKIE (frame, marker_getxattr_cbk, (void *)cookie, + STACK_WIND_COOKIE (frame, marker_getxattr_cbk, + (void *)cookie, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->getxattr, loc, - name, xdata); + FIRST_CHILD(this)->fops->getxattr, + loc, name, xdata); } return 0; diff --git a/xlators/features/quota/src/quota.c b/xlators/features/quota/src/quota.c index 4beaae341..2ca4da0c1 100644 --- a/xlators/features/quota/src/quota.c +++ b/xlators/features/quota/src/quota.c @@ -244,7 +244,7 @@ out: return; } -inline void +static inline void quota_link_count_decrement (quota_local_t *local) { call_stub_t *stub = NULL; @@ -270,7 +270,7 @@ out: return; } -inline void +static inline void quota_handle_validate_error (quota_local_t *local, int32_t op_ret, int32_t op_errno) { @@ -377,7 +377,7 @@ quota_timeout (struct timeval *tv, int32_t timeout) return timed_out; } -inline void +static inline void quota_add_parent (quota_dentry_t *dentry, struct list_head *list) { quota_dentry_t *entry = NULL; @@ -928,7 +928,7 @@ err: return 0; } -inline int +static inline int quota_get_limits (xlator_t *this, dict_t *dict, int64_t *hard_lim, int64_t *soft_lim) { diff --git a/xlators/features/quota/src/quotad-aggregator.c b/xlators/features/quota/src/quotad-aggregator.c index f3f65ca2a..5f13fd251 100644 --- a/xlators/features/quota/src/quotad-aggregator.c +++ b/xlators/features/quota/src/quotad-aggregator.c @@ -227,7 +227,7 @@ quotad_aggregator_getlimit (rpcsvc_request_t *req) if (ret) goto err; - ret = dict_set_int32 (state->xdata, GET_ANCESTRY_PATH_KEY,42); + ret = dict_set_int32 (state->xdata, GET_ANCESTRY_PATH_KEY, 42); if (ret) goto err; -- cgit From 500a656c91558dd7913f572369f20b8550e9e98d Mon Sep 17 00:00:00 2001 From: Krutika Dhananjay Date: Sat, 19 Apr 2014 20:03:38 +0530 Subject: features/locks: Remove stale inodelk objects from 'blocked_locks' list * In the event of a DISCONNECT from a client, as part of cleanup, inodelk objects are not removed from the blocked_locks list before being unref'd and freed, causing the brick process to crash at some point when the (now) stale object is accessed again in the list. * Also during cleanup, it is pointless to try and grant lock to a previously blocked inodelk (say L1) as part of releasing another conflicting lock (L2), (which is a side-effect of L1 not being deleted from blocked_locks list before grant_blocked_inode_locks() in cleanup) if L1 is also associated with the DISCONNECTing client. This patch fixes the problem. * Also, the codepath in cleanup of entrylks seems to be granting blocked inodelks, when it should be attempting to grant blocked entrylks, which is fixed in this patch. Change-Id: I8493365c33020333b3f61aa15f505e4e7e6a9891 BUG: 1089470 Signed-off-by: Krutika Dhananjay Reviewed-on: http://review.gluster.org/7512 Reviewed-by: Raghavendra G Reviewed-by: Pranith Kumar Karampuri Tested-by: Gluster Build System Reviewed-by: Krishnan Parthasarathi Reviewed-by: Anand Avati --- xlators/features/locks/src/entrylk.c | 2 +- xlators/features/locks/src/inodelk.c | 56 ++++++++++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 6 deletions(-) (limited to 'xlators/features') diff --git a/xlators/features/locks/src/entrylk.c b/xlators/features/locks/src/entrylk.c index dc86512be..4f5d8aca2 100644 --- a/xlators/features/locks/src/entrylk.c +++ b/xlators/features/locks/src/entrylk.c @@ -749,7 +749,7 @@ pl_entrylk_client_cleanup (xlator_t *this, pl_ctx_t *ctx) dom = get_domain (pinode, l->volume); - grant_blocked_inode_locks (this, pinode, dom); + grant_blocked_entry_locks (this, pinode, dom); pthread_mutex_lock (&pinode->mutex); { diff --git a/xlators/features/locks/src/inodelk.c b/xlators/features/locks/src/inodelk.c index 2d9aa83ec..d105e14f2 100644 --- a/xlators/features/locks/src/inodelk.c +++ b/xlators/features/locks/src/inodelk.c @@ -404,7 +404,7 @@ pl_inodelk_log_cleanup (pl_inode_lock_t *lock) } -/* Release all entrylks from this client */ +/* Release all inodelks from this client */ int pl_inodelk_client_cleanup (xlator_t *this, pl_ctx_t *ctx) { @@ -414,15 +414,16 @@ pl_inodelk_client_cleanup (xlator_t *this, pl_ctx_t *ctx) pl_inode_t *pl_inode = NULL; struct list_head released; + struct list_head unwind; INIT_LIST_HEAD (&released); + INIT_LIST_HEAD (&unwind); pthread_mutex_lock (&ctx->lock); { list_for_each_entry_safe (l, tmp, &ctx->inodelk_lockers, client_list) { list_del_init (&l->client_list); - list_add_tail (&l->client_list, &released); pl_inodelk_log_cleanup (l); @@ -430,19 +431,64 @@ pl_inodelk_client_cleanup (xlator_t *this, pl_ctx_t *ctx) pthread_mutex_lock (&pl_inode->mutex); { - __delete_inode_lock (l); + /* If the inodelk object is part of granted list but not + * blocked list, then perform the following actions: + * i. delete the object from granted list; + * ii. grant other locks (from other clients) that may + * have been blocked on this inodelk; and + * iii. unref the object. + * + * If the inodelk object (L1) is part of both granted + * and blocked lists, then this means that a parallel + * unlock on another inodelk (L2 say) may have 'granted' + * L1 and added it to 'granted' list in + * __grant_blocked_node_locks() (although using the + * 'blocked_locks' member). In that case, the cleanup + * codepath must try and grant other overlapping + * blocked inodelks from other clients, now that L1 is + * out of their way and then unref L1 in the end, and + * leave it to the other thread (the one executing + * unlock codepath) to unwind L1's frame, delete it from + * blocked_locks list, and perform the last unref on L1. + * + * If the inodelk object (L1) is part of blocked list + * only, the cleanup code path must: + * i. delete it from the blocked_locks list inside + * this critical section, + * ii. unwind its frame with EAGAIN, + * iii. try and grant blocked inode locks from other + * clients that were otherwise grantable, but just + * got blocked to avoid leaving L1 to starve + * forever. + * iv. unref the object. + */ + if (!list_empty (&l->list)) { + __delete_inode_lock (l); + list_add_tail (&l->client_list, + &released); + } else { + list_del_init(&l->blocked_locks); + list_add_tail (&l->client_list, + &unwind); + } } pthread_mutex_unlock (&pl_inode->mutex); } } pthread_mutex_unlock (&ctx->lock); - list_for_each_entry_safe (l, tmp, &released, client_list) { + list_for_each_entry_safe (l, tmp, &unwind, client_list) { list_del_init (&l->client_list); - if (l->frame) + if (l->frame) STACK_UNWIND_STRICT (inodelk, l->frame, -1, EAGAIN, NULL); + list_add_tail (&l->client_list, &released); + + } + + list_for_each_entry_safe (l, tmp, &released, client_list) { + list_del_init (&l->client_list); pl_inode = l->pl_inode; -- cgit From 40675af8b4a1a90331e353295c75c0ea63457cf6 Mon Sep 17 00:00:00 2001 From: Kotresh H R Date: Thu, 24 Apr 2014 14:21:46 +0530 Subject: feature/changelog: Change default rollover and fsync-interval time This will change the following default configurables. 1. rollover-time: from 60 to 15. 2. fsync-interval: from 0 to 5. Change-Id: I9c8db01376967c4f19547ec87f54833f8b139d29 Signed-off-by: Kotresh H R Reviewed-on: http://review.gluster.org/7545 Reviewed-by: Venky Shankar Tested-by: Venky Shankar --- xlators/features/changelog/src/changelog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'xlators/features') diff --git a/xlators/features/changelog/src/changelog.c b/xlators/features/changelog/src/changelog.c index 5fe3b4362..3e40984f6 100644 --- a/xlators/features/changelog/src/changelog.c +++ b/xlators/features/changelog/src/changelog.c @@ -1553,13 +1553,13 @@ struct volume_options options[] = { .description = "encoding type for changelogs" }, {.key = {"rollover-time"}, - .default_value = "60", + .default_value = "15", .type = GF_OPTION_TYPE_TIME, .description = "time to switch to a new changelog file (in seconds)" }, {.key = {"fsync-interval"}, .type = GF_OPTION_TYPE_TIME, - .default_value = "0", + .default_value = "5", .description = "do not open CHANGELOG file with O_SYNC mode." " instead perform fsync() at specified intervals" }, -- cgit From 6a188c6b2c95d16c1bb6391c9fcb8ef808c2141b Mon Sep 17 00:00:00 2001 From: Krutika Dhananjay Date: Thu, 24 Apr 2014 16:37:05 +0530 Subject: features/locks: Remove stale entrylk objects from 'blocked_locks' list * In the event of a DISCONNECT from a client, as part of cleanup, entrylk objects are not removed from the blocked_locks list before being unref'd and freed, causing the brick process to crash at some point when the (now) stale object is accessed again in the list. * Also during cleanup, it is pointless to try and grant lock to a previously blocked entrylk (say L1) as part of releasing another conflicting lock (L2), (which is a side-effect of L1 not being deleted from blocked_locks list before grant_blocked_entry_locks() in cleanup) if L1 is also associated with the DISCONNECTing client. This patch fixes the problem. Change-Id: I3d684c6bafc7e6db89ba68f0a2ed1dcb333791c6 BUG: 1089470 Signed-off-by: Krutika Dhananjay Reviewed-on: http://review.gluster.org/7560 Reviewed-by: Pranith Kumar Karampuri Tested-by: Gluster Build System Reviewed-by: Anand Avati --- xlators/features/locks/src/entrylk.c | 50 +++++++++++++++++++++++++++++++++--- xlators/features/locks/src/inodelk.c | 2 +- 2 files changed, 48 insertions(+), 4 deletions(-) (limited to 'xlators/features') diff --git a/xlators/features/locks/src/entrylk.c b/xlators/features/locks/src/entrylk.c index 4f5d8aca2..8496d9d8d 100644 --- a/xlators/features/locks/src/entrylk.c +++ b/xlators/features/locks/src/entrylk.c @@ -715,15 +715,16 @@ pl_entrylk_client_cleanup (xlator_t *this, pl_ctx_t *ctx) pl_inode_t *pinode = NULL; struct list_head released; + struct list_head unwind; INIT_LIST_HEAD (&released); + INIT_LIST_HEAD (&unwind); pthread_mutex_lock (&ctx->lock); { list_for_each_entry_safe (l, tmp, &ctx->entrylk_lockers, client_list) { list_del_init (&l->client_list); - list_add_tail (&l->client_list, &released); pl_entrylk_log_cleanup (l); @@ -731,19 +732,62 @@ pl_entrylk_client_cleanup (xlator_t *this, pl_ctx_t *ctx) pthread_mutex_lock (&pinode->mutex); { - list_del_init (&l->domain_list); + /* If the entrylk object is part of granted list but not + * blocked list, then perform the following actions: + * i. delete the object from granted list; + * ii. grant other locks (from other clients) that may + * have been blocked on this entrylk; and + * iii. unref the object. + * + * If the entrylk object (L1) is part of both granted + * and blocked lists, then this means that a parallel + * unlock on another entrylk (L2 say) may have 'granted' + * L1 and added it to 'granted' list in + * __grant_blocked_entry_locks() (although using the + * 'blocked_locks' member). In that case, the cleanup + * codepath must try and grant other overlapping + * blocked entrylks from other clients, now that L1 is + * out of their way and then unref L1 in the end, and + * leave it to the other thread (the one executing + * unlock codepath) to unwind L1's frame, delete it from + * blocked_locks list, and perform the last unref on L1. + * + * If the entrylk object (L1) is part of blocked list + * only, the cleanup code path must: + * i. delete it from the blocked_locks list inside + * this critical section, + * ii. unwind its frame with EAGAIN, + * iii. try and grant blocked entry locks from other + * clients that were otherwise grantable, but were + * blocked to avoid leaving L1 to starve forever. + * iv. unref the object. + */ + if (!list_empty (&l->domain_list)) { + list_del_init (&l->domain_list); + list_add_tail (&l->client_list, + &released); + } else { + list_del_init (&l->blocked_locks); + list_add_tail (&l->client_list, + &unwind); + } } pthread_mutex_unlock (&pinode->mutex); } } pthread_mutex_unlock (&ctx->lock); - list_for_each_entry_safe (l, tmp, &released, client_list) { + list_for_each_entry_safe (l, tmp, &unwind, client_list) { list_del_init (&l->client_list); if (l->frame) STACK_UNWIND_STRICT (entrylk, l->frame, -1, EAGAIN, NULL); + list_add_tail (&l->client_list, &released); + } + + list_for_each_entry_safe (l, tmp, &released, client_list) { + list_del_init (&l->client_list); pinode = l->pinode; diff --git a/xlators/features/locks/src/inodelk.c b/xlators/features/locks/src/inodelk.c index d105e14f2..c76cb7f91 100644 --- a/xlators/features/locks/src/inodelk.c +++ b/xlators/features/locks/src/inodelk.c @@ -26,7 +26,7 @@ inline void __delete_inode_lock (pl_inode_lock_t *lock) { - list_del (&lock->list); + list_del_init (&lock->list); } static inline void -- cgit From d2cdc392accdd35995370ee5b52aee5e5af7dee4 Mon Sep 17 00:00:00 2001 From: Niels de Vos Date: Sun, 27 Apr 2014 15:03:58 +0200 Subject: Update references to the maillinglist to gluster-devel@gluster.org gluster-devel@nongnu.org has moved to gluster-devel@gluster.org. All occurrences in the current (non legacy) documentation and code have been adjusted. Change-Id: I053162e633f7ea14fd3eed239ded017df165147c BUG: 1091705 Signed-off-by: Niels de Vos Reviewed-on: http://review.gluster.org/7573 Reviewed-by: Justin Clift Reviewed-by: Anand Avati Tested-by: Anand Avati --- xlators/features/glupy/src/setup.py.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'xlators/features') diff --git a/xlators/features/glupy/src/setup.py.in b/xlators/features/glupy/src/setup.py.in index 1aea9875f..b9ee02c2b 100644 --- a/xlators/features/glupy/src/setup.py.in +++ b/xlators/features/glupy/src/setup.py.in @@ -16,7 +16,7 @@ setup( description='Glupy is the Python translator interface for GlusterFS', long_description=DESC, author='Gluster Community', - author_email='gluster-devel@nongnu.org', + author_email='gluster-devel@gluster.org', license='LGPLv3', url='http://gluster.org/', package_dir={'gluster':''}, -- cgit From 22f47322d246c94d0bec8e893e4837a67d39f544 Mon Sep 17 00:00:00 2001 From: Atin Mukherjee Date: Mon, 3 Mar 2014 18:00:59 +0530 Subject: Barrier: Barrier translator options configuration barrier enable/disable, barrier-timeout configuration in barrier translator. Change-Id: I7cbf9cd4f5e55d42dcc6b7cd6827234566c7b6f3 BUG: 1060002 Signed-off-by: Atin Mukherjee Reviewed-on: http://review.gluster.org/7177 Reviewed-by: Kaushal M Tested-by: Gluster Build System --- xlators/features/barrier/src/barrier.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'xlators/features') diff --git a/xlators/features/barrier/src/barrier.c b/xlators/features/barrier/src/barrier.c index 9937698ed..5edb9cdd3 100644 --- a/xlators/features/barrier/src/barrier.c +++ b/xlators/features/barrier/src/barrier.c @@ -415,7 +415,7 @@ reconfigure (xlator_t *this, dict_t *options) GF_ASSERT (priv); GF_OPTION_RECONF ("barrier", barrier_enabled, options, bool, out); - GF_OPTION_RECONF ("timeout", timeout, options, time, out); + GF_OPTION_RECONF ("barrier-timeout", timeout, options, time, out); INIT_LIST_HEAD (&queue); @@ -490,7 +490,7 @@ init (xlator_t *this) LOCK_INIT (&priv->lock); GF_OPTION_INIT ("barrier", priv->barrier_enabled, bool, out); - GF_OPTION_INIT ("timeout", timeout, time, out); + GF_OPTION_INIT ("barrier-timeout", timeout, time, out); priv->timeout.tv_sec = timeout; INIT_LIST_HEAD (&priv->queue); @@ -646,7 +646,7 @@ struct volume_options options[] = { "write (with O_SYNC), fsync. It is turned \"off\" by " "default." }, - { .key = {"timeout"}, + { .key = {"barrier-timeout"}, .type = GF_OPTION_TYPE_TIME, .default_value = "120", .description = "After 'timeout' seconds since the time 'barrier' " -- cgit From f2bac9f9d5b9956969ddd25a54bc636b82f6923e Mon Sep 17 00:00:00 2001 From: Kotresh H R Date: Thu, 13 Feb 2014 23:53:27 +0530 Subject: features/libgfchangelog: APIs to process history changelogs. 1. Create directories in following fashion for history API's usage when consumer is registered with libgfchangelog shared library through gf_changelog_register. scratch_dir/.history scratch_dir/.history/.current scratch_dir/.history/.processed scratch_dir/.history/.processing 2. Added new file 'gf-history-changelog.c' and following APIs are provided for consumers to process history changelogs. 1. gf_history_changelog_scan: Move processed history changelog file from .processing to .processed 2. gf_history_changelog_next_change: Return the next history changelog file entry. Zero means all history chanelogs are consumed. 3. gf_history_changelog_done: Scan .processing directory and generate a list of change entries. 4. gf_history_changelog_start_fresh: For a set of changelogs, start from the begining. NOTE: Though this patch provides above funcationalities. It is considered functionally full with the patch (http://review.gluster.org/#/c/6930/). Change-Id: I200780c7278e0a6c008910d93faad5858a4b3e76 Original-author: Kotresh H R Signed-off-by: Kotresh H R Signed-off-by: Ajeet Jha Reviewed-on: http://review.gluster.org/6998 Tested-by: Gluster Build System Reviewed-by: Venky Shankar Tested-by: Venky Shankar --- xlators/features/changelog/lib/src/Makefile.am | 3 +- .../changelog/lib/src/gf-changelog-helpers.h | 4 + xlators/features/changelog/lib/src/gf-changelog.c | 57 ++++- .../changelog/lib/src/gf-history-changelog.c | 274 +++++++++++++++++++++ 4 files changed, 336 insertions(+), 2 deletions(-) create mode 100644 xlators/features/changelog/lib/src/gf-history-changelog.c (limited to 'xlators/features') diff --git a/xlators/features/changelog/lib/src/Makefile.am b/xlators/features/changelog/lib/src/Makefile.am index 775f026cf..28d5a70aa 100644 --- a/xlators/features/changelog/lib/src/Makefile.am +++ b/xlators/features/changelog/lib/src/Makefile.am @@ -17,7 +17,8 @@ lib_LTLIBRARIES = libgfchangelog.la CONTRIB_BUILDDIR = $(top_builddir)/contrib libgfchangelog_la_SOURCES = gf-changelog.c gf-changelog-process.c \ - gf-changelog-helpers.c $(CONTRIBDIR)/uuid/clear.c \ + gf-changelog-helpers.c gf-history-changelog.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 \ diff --git a/xlators/features/changelog/lib/src/gf-changelog-helpers.h b/xlators/features/changelog/lib/src/gf-changelog-helpers.h index 7e13d9376..2d545da9e 100644 --- a/xlators/features/changelog/lib/src/gf-changelog-helpers.h +++ b/xlators/features/changelog/lib/src/gf-changelog-helpers.h @@ -23,6 +23,7 @@ #define GF_CHANGELOG_CURRENT_DIR ".current" #define GF_CHANGELOG_PROCESSED_DIR ".processed" #define GF_CHANGELOG_PROCESSING_DIR ".processing" +#define GF_CHANGELOG_HISTORY_DIR ".history" #ifndef MAXLINE #define MAXLINE 4096 @@ -68,6 +69,9 @@ typedef struct gf_changelog { char gfc_processing_dir[PATH_MAX]; pthread_t gfc_changelog_processor; + + /* Holds gfc for History API */ + struct gf_changelog *hist_gfc; } gf_changelog_t; int diff --git a/xlators/features/changelog/lib/src/gf-changelog.c b/xlators/features/changelog/lib/src/gf-changelog.c index 4b2b25ad5..0827f2cac 100644 --- a/xlators/features/changelog/lib/src/gf-changelog.c +++ b/xlators/features/changelog/lib/src/gf-changelog.c @@ -82,6 +82,10 @@ __attribute__ ((destructor)) gf_changelog_dtor (void) gfc = this->private; if (gfc) { + if (gfc->hist_gfc) { + gf_changelog_cleanup(gfc->hist_gfc); + GF_FREE (gfc->hist_gfc); + } gf_changelog_cleanup (gfc); GF_FREE (gfc); } @@ -437,6 +441,7 @@ gf_changelog_register (char *brick_path, char *scratch_dir, int errn = 0; xlator_t *this = NULL; gf_changelog_t *gfc = NULL; + char hist_scratch_dir[PATH_MAX] = {0,}; this = THIS; if (!this->ctx) @@ -460,6 +465,52 @@ gf_changelog_register (char *brick_path, char *scratch_dir, goto cleanup; } + /* Begin: Changes for History API */ + gfc->hist_gfc = NULL; + + gfc->hist_gfc = GF_CALLOC (1, sizeof (*gfc), + gf_changelog_mt_libgfchangelog_t); + if (!gfc->hist_gfc) + goto cleanup; + + gfc->hist_gfc->gfc_dir = NULL; + gfc->hist_gfc->gfc_fd = gfc->hist_gfc->gfc_sockfd = -1; + gfc->hist_gfc->this = NULL; + + (void) strncpy (hist_scratch_dir, scratch_dir, PATH_MAX); + (void) snprintf (hist_scratch_dir, PATH_MAX, + "%s/"GF_CHANGELOG_HISTORY_DIR"/", + gfc->gfc_working_dir); + + ret = mkdir_p (hist_scratch_dir, 0600, _gf_false); + if (ret) { + errn = errno; + goto cleanup; + } + + gfc->hist_gfc->gfc_working_dir = realpath (hist_scratch_dir, NULL); + if (!gfc->hist_gfc->gfc_working_dir) { + errn = errno; + goto cleanup; + } + + ret = gf_changelog_open_dirs (gfc->hist_gfc); + if (ret) { + errn = errno; + gf_log (this->name, GF_LOG_ERROR, + "could not create entries in history scratch dir"); + goto cleanup; + } + + (void) strncpy (gfc->hist_gfc->gfc_brickpath, brick_path, PATH_MAX); + + for (i=0; i < 256; i++) { + gfc->hist_gfc->rfc3986[i] = + (isalnum(i) || i == '~' || + i == '-' || i == '.' || i == '_') ? i : 0; + } + /* End: Changes for History API*/ + ret = gf_changelog_open_dirs (gfc); if (ret) { errn = errno; @@ -494,7 +545,7 @@ gf_changelog_register (char *brick_path, char *scratch_dir, goto cleanup; } - for (; i < 256; i++) { + for (i=0; i < 256; i++) { gfc->rfc3986[i] = (isalnum(i) || i == '~' || i == '-' || i == '.' || i == '_') ? i : 0; @@ -506,6 +557,10 @@ gf_changelog_register (char *brick_path, char *scratch_dir, goto out; cleanup: + if (gfc->hist_gfc) { + gf_changelog_cleanup (gfc->hist_gfc); + GF_FREE (gfc->hist_gfc); + } gf_changelog_cleanup (gfc); GF_FREE (gfc); this->private = NULL; diff --git a/xlators/features/changelog/lib/src/gf-history-changelog.c b/xlators/features/changelog/lib/src/gf-history-changelog.c new file mode 100644 index 000000000..bfc4cd37d --- /dev/null +++ b/xlators/features/changelog/lib/src/gf-history-changelog.c @@ -0,0 +1,274 @@ +#include +#include +#include +#include + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include + +#include "globals.h" +#include "glusterfs.h" +#include "logging.h" + +#include "gf-changelog-helpers.h" + +/* from the changelog translator */ +#include "changelog-misc.h" +#include "changelog-mem-types.h" + +/*@API + * gf_history_changelog_done: + * Move processed history changelog file from .processing + * to .processed + * + * ARGUMENTS: + * file(IN): path to processed history changelog file in + * .processing directory. + * + * RETURN VALUE: + * 0: On success. + * -1: On error. + */ +int +gf_history_changelog_done (char *file) +{ + int ret = -1; + char *buffer = NULL; + xlator_t *this = NULL; + gf_changelog_t *gfc = NULL; + gf_changelog_t *hist_gfc = NULL; + char to_path[PATH_MAX] = {0,}; + + errno = EINVAL; + + this = THIS; + if (!this) + goto out; + + gfc = (gf_changelog_t *) this->private; + if (!gfc) + goto out; + + hist_gfc = gfc->hist_gfc; + if (!hist_gfc) + goto out; + + if (!file || !strlen (file)) + goto out; + + /* make sure 'file' is inside ->gfc_working_dir */ + buffer = realpath (file, NULL); + if (!buffer) + goto out; + + if (strncmp (hist_gfc->gfc_working_dir, + buffer, strlen (hist_gfc->gfc_working_dir))) + goto out; + + (void) snprintf (to_path, PATH_MAX, "%s%s", + hist_gfc->gfc_processed_dir, basename (buffer)); + gf_log (this->name, GF_LOG_DEBUG, + "moving %s to processed directory", file); + ret = rename (buffer, to_path); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "cannot move %s to %s (reason: %s)", + file, to_path, strerror (errno)); + goto out; + } + + ret = 0; + + out: + if (buffer) + free (buffer); /* allocated by realpath() */ + return ret; +} +/** + * @API + * gf_history_changelog_start_fresh: + * For a set of changelogs, start from the begining. + * It will truncates the history tracker fd. + * + * RETURN VALUES: + * 0: On success. + * -1: On error. + */ +int +gf_history_changelog_start_fresh () +{ + xlator_t *this = NULL; + gf_changelog_t *gfc = NULL; + gf_changelog_t *hist_gfc = NULL; + + this = THIS; + if (!this) + goto out; + + errno = EINVAL; + + gfc = (gf_changelog_t *) this->private; + if (!gfc) + goto out; + + hist_gfc = gfc->hist_gfc; + if (!hist_gfc) + goto out; + + if (gf_ftruncate (hist_gfc->gfc_fd, 0)) + goto out; + + return 0; + + out: + return -1; +} + +/* + * @API + * gf_history_changelog_next_change: + * Return the next history changelog file entry. Zero means all + * history chanelogs are consumed. + * + * ARGUMENTS: + * bufptr(OUT): Path to unprocessed history changelog file + * from tracker file. + * maxlen(IN): Usually PATH_MAX. + * + * RETURN VALUES: + * size: On success. + * -1 : On error. + */ +ssize_t +gf_history_changelog_next_change (char *bufptr, size_t maxlen) +{ + ssize_t size = 0; + int tracker_fd = 0; + xlator_t *this = NULL; + gf_changelog_t *gfc = NULL; + gf_changelog_t *hist_gfc = NULL; + char buffer[PATH_MAX] = {0,}; + + errno = EINVAL; + + this = THIS; + if (!this) + goto out; + + gfc = (gf_changelog_t *) this->private; + if (!gfc) + goto out; + + hist_gfc = gfc->hist_gfc; + if (!hist_gfc) + goto out; + + tracker_fd = hist_gfc->gfc_fd; + + size = gf_readline (tracker_fd, buffer, maxlen); + if (size < 0) + goto out; + if (size == 0) + return 0; + + memcpy (bufptr, buffer, size - 1); + *(buffer + size) = '\0'; + + return size; + + out: + return -1; +} + +/* + * @API + * gf_history_changelog_scan: + * Scan and generate a list of change entries. + * Calling this api multiple times (without calling gf_changlog_done()) + * would result new changelogs(s) being refreshed in the tracker file. + * This call also acts as a cancellation point for the consumer. + * + * RETURN VALUES: + * nr_entries: On success. + * -1 : On error. + */ +ssize_t +gf_history_changelog_scan () +{ + int ret = 0; + int tracker_fd = 0; + size_t len = 0; + size_t off = 0; + xlator_t *this = NULL; + size_t nr_entries = 0; + gf_changelog_t *gfc = NULL; + gf_changelog_t *hist_gfc = NULL; + struct dirent *entryp = NULL; + struct dirent *result = NULL; + char buffer[PATH_MAX] = {0,}; + + this = THIS; + if (!this) + goto out; + + gfc = (gf_changelog_t *) this->private; + if (!gfc) + goto out; + + hist_gfc = gfc->hist_gfc; + if (!hist_gfc) + goto out; + + errno = EINVAL; + + tracker_fd = hist_gfc->gfc_fd; + + if (gf_ftruncate (tracker_fd, 0)) + goto out; + + len = offsetof(struct dirent, d_name) + + pathconf(hist_gfc->gfc_processing_dir, _PC_NAME_MAX) + 1; + entryp = GF_CALLOC (1, len, + gf_changelog_mt_libgfchangelog_dirent_t); + if (!entryp) + goto out; + + rewinddir (hist_gfc->gfc_dir); + while (1) { + ret = readdir_r (hist_gfc->gfc_dir, entryp, &result); + if (ret || !result) + break; + + if ( !strcmp (basename (entryp->d_name), ".") + || !strcmp (basename (entryp->d_name), "..") ) + continue; + + nr_entries++; + + GF_CHANGELOG_FILL_BUFFER (hist_gfc->gfc_processing_dir, + buffer, off, + strlen (hist_gfc->gfc_processing_dir)); + GF_CHANGELOG_FILL_BUFFER (entryp->d_name, buffer, + off, strlen (entryp->d_name)); + GF_CHANGELOG_FILL_BUFFER ("\n", buffer, off, 1); + + if (gf_changelog_write (tracker_fd, buffer, off) != off) { + gf_log (this->name, GF_LOG_ERROR, + "error writing changelog filename" + " to tracker file"); + break; + } + off = 0; + } + + GF_FREE (entryp); + + if (!result) { + if (gf_lseek (tracker_fd, 0, SEEK_SET) != -1) + return nr_entries; + } + out: + return -1; +} -- cgit