diff options
Diffstat (limited to 'xlators/features/upcall/src')
| -rw-r--r-- | xlators/features/upcall/src/Makefile.am | 12 | ||||
| -rw-r--r-- | xlators/features/upcall/src/upcall-cache-invalidation.h | 38 | ||||
| -rw-r--r-- | xlators/features/upcall/src/upcall-internal.c | 1028 | ||||
| -rw-r--r-- | xlators/features/upcall/src/upcall-mem-types.h | 13 | ||||
| -rw-r--r-- | xlators/features/upcall/src/upcall-messages.h | 54 | ||||
| -rw-r--r-- | xlators/features/upcall/src/upcall.c | 3050 | ||||
| -rw-r--r-- | xlators/features/upcall/src/upcall.h | 199 |
7 files changed, 2511 insertions, 1883 deletions
diff --git a/xlators/features/upcall/src/Makefile.am b/xlators/features/upcall/src/Makefile.am index a81c36940e5..72b7f55ae0a 100644 --- a/xlators/features/upcall/src/Makefile.am +++ b/xlators/features/upcall/src/Makefile.am @@ -1,20 +1,22 @@ +if WITH_SERVER xlator_LTLIBRARIES = upcall.la +endif xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features -upcall_la_LDFLAGS = $(GF_XLATOR_DEFAULT_LDFLAGS) +upcall_la_LDFLAGS = -module $(GF_XLATOR_DEFAULT_LDFLAGS) upcall_la_SOURCES = upcall.c upcall-internal.c upcall_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \ - $(top_builddir)/rpc/rpc-lib/src/libgfrpc.la \ - $(top_builddir)/rpc/xdr/src/libgfxdr.la + $(top_builddir)/rpc/rpc-lib/src/libgfrpc.la \ + $(top_builddir)/rpc/xdr/src/libgfxdr.la noinst_HEADERS = upcall.h upcall-mem-types.h upcall-messages.h \ upcall-cache-invalidation.h AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \ - -I$(top_srcdir)/rpc/rpc-lib/src \ - -I$(top_srcdir)/rpc/xdr/src + -I$(top_srcdir)/rpc/rpc-lib/src \ + -I$(top_srcdir)/rpc/xdr/src -I$(top_builddir)/rpc/xdr/src AM_CFLAGS = -Wall -fno-strict-aliasing $(GF_CFLAGS) diff --git a/xlators/features/upcall/src/upcall-cache-invalidation.h b/xlators/features/upcall/src/upcall-cache-invalidation.h index 77286b063d8..db649b2c9a6 100644 --- a/xlators/features/upcall/src/upcall-cache-invalidation.h +++ b/xlators/features/upcall/src/upcall-cache-invalidation.h @@ -15,42 +15,4 @@ * events post its last access */ #define CACHE_INVALIDATION_TIMEOUT "60" -/* Flags sent for cache_invalidation */ -#define UP_NLINK 0x00000001 /* update nlink */ -#define UP_MODE 0x00000002 /* update mode and ctime */ -#define UP_OWN 0x00000004 /* update mode,uid,gid and ctime */ -#define UP_SIZE 0x00000008 /* update fsize */ -#define UP_TIMES 0x00000010 /* update all times */ -#define UP_ATIME 0x00000020 /* update atime only */ -#define UP_PERM 0x00000040 /* update fields needed for - permission checking */ -#define UP_RENAME 0x00000080 /* this is a rename op - - delete the cache entry */ -#define UP_FORGET 0x00000100 /* inode_forget on server side - - invalidate the cache entry */ -#define UP_PARENT_TIMES 0x00000200 /* update parent dir times */ - -/* for fops - open, read, lk, */ -#define UP_UPDATE_CLIENT (UP_ATIME) - -/* for fop - write, truncate */ -#define UP_WRITE_FLAGS (UP_SIZE | UP_TIMES) - -/* for fop - setattr */ -#define UP_ATTR_FLAGS (UP_SIZE | UP_TIMES | UP_OWN | \ - UP_MODE | UP_PERM) -/* for fop - rename */ -#define UP_RENAME_FLAGS (UP_RENAME) - -/* to invalidate parent directory entries for fops -rename, unlink, - * rmdir, mkdir, create */ -#define UP_PARENT_DENTRY_FLAGS (UP_PARENT_TIMES) - -/* for fop - unlink, link, rmdir, mkdir */ -#define UP_NLINK_FLAGS (UP_NLINK | UP_TIMES) - -/* xlator options */ -gf_boolean_t is_cache_invalidation_enabled(xlator_t *this); -int32_t get_cache_invalidation_timeout(xlator_t *this); - #endif /* __UPCALL_CACHE_INVALIDATION_H__ */ diff --git a/xlators/features/upcall/src/upcall-internal.c b/xlators/features/upcall/src/upcall-internal.c index 81199eb074c..c641bd6f432 100644 --- a/xlators/features/upcall/src/upcall-internal.c +++ b/xlators/features/upcall/src/upcall-internal.c @@ -12,375 +12,287 @@ #include <fcntl.h> #include <limits.h> -#include "glusterfs.h" -#include "compat.h" -#include "xlator.h" -#include "inode.h" -#include "logging.h" -#include "common-utils.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/compat.h> +#include <glusterfs/xlator.h> +#include <glusterfs/logging.h> +#include <glusterfs/common-utils.h> -#include "statedump.h" -#include "syncop.h" +#include <glusterfs/statedump.h> +#include <glusterfs/syncop.h> #include "upcall.h" #include "upcall-mem-types.h" #include "glusterfs3-xdr.h" #include "protocol-common.h" -#include "defaults.h" +#include <glusterfs/defaults.h> /* * Check if any of the upcall options are enabled: * - cache_invalidation - * - XXX: lease_lk */ gf_boolean_t -is_upcall_enabled(xlator_t *this) { - upcall_private_t *priv = NULL; - gf_boolean_t is_enabled = _gf_false; - - if (this->private) { - priv = (upcall_private_t *)this->private; - - if (priv->cache_invalidation_enabled) { - is_enabled = _gf_true; - } - } - - return is_enabled; -} - -/* - * Check if any of cache_invalidation is enabled - */ -gf_boolean_t -is_cache_invalidation_enabled(xlator_t *this) { - upcall_private_t *priv = NULL; - gf_boolean_t is_enabled = _gf_false; - - if (this->private) { - priv = (upcall_private_t *)this->private; +is_upcall_enabled(xlator_t *this) +{ + upcall_private_t *priv = NULL; - if (priv->cache_invalidation_enabled) { - is_enabled = _gf_true; - } - } + if (this->private) { + priv = (upcall_private_t *)this->private; + return priv->cache_invalidation_enabled; + } - return is_enabled; + return _gf_false; } /* * Get the cache_invalidation_timeout */ -int32_t -get_cache_invalidation_timeout(xlator_t *this) { - upcall_private_t *priv = NULL; - int32_t timeout = 0; - - if (this->private) { - priv = (upcall_private_t *)this->private; - timeout = priv->cache_invalidation_timeout; - } - - return timeout; -} - -/* - * Allocate and add a new client entry to the given upcall entry - */ -upcall_client_t* -add_upcall_client (call_frame_t *frame, client_t *client, - upcall_inode_ctx_t *up_inode_ctx) +static int32_t +get_cache_invalidation_timeout(xlator_t *this) { - upcall_client_t *up_client_entry = NULL; + upcall_private_t *priv = NULL; - pthread_mutex_lock (&up_inode_ctx->client_list_lock); - { - up_client_entry = __add_upcall_client (frame, - client, - up_inode_ctx); - } - pthread_mutex_unlock (&up_inode_ctx->client_list_lock); + if (this->private) { + priv = (upcall_private_t *)this->private; + return priv->cache_invalidation_timeout; + } - return up_client_entry; + return 0; } -upcall_client_t* -__add_upcall_client (call_frame_t *frame, client_t *client, - upcall_inode_ctx_t *up_inode_ctx) +static upcall_client_t * +__add_upcall_client(call_frame_t *frame, client_t *client, + upcall_inode_ctx_t *up_inode_ctx, time_t now) { - upcall_client_t *up_client_entry = NULL; - - up_client_entry = GF_CALLOC (1, sizeof(*up_client_entry), - gf_upcall_mt_upcall_client_entry_t); - if (!up_client_entry) { - gf_msg ("upcall", GF_LOG_WARNING, 0, - UPCALL_MSG_NO_MEMORY, - "Memory allocation failed"); - return NULL; - } - INIT_LIST_HEAD (&up_client_entry->client_list); - up_client_entry->client_uid = gf_strdup(client->client_uid); - up_client_entry->access_time = time(NULL); - up_client_entry->expire_time_attr = - get_cache_invalidation_timeout(frame->this); + upcall_client_t *up_client_entry = GF_MALLOC( + sizeof(*up_client_entry), gf_upcall_mt_upcall_client_entry_t); + if (!up_client_entry) { + gf_msg("upcall", GF_LOG_WARNING, 0, UPCALL_MSG_NO_MEMORY, + "Memory allocation failed"); + return NULL; + } + INIT_LIST_HEAD(&up_client_entry->client_list); + up_client_entry->client_uid = gf_strdup(client->client_uid); + up_client_entry->access_time = now; + up_client_entry->expire_time_attr = get_cache_invalidation_timeout( + frame->this); - list_add_tail (&up_client_entry->client_list, - &up_inode_ctx->client_list); + list_add_tail(&up_client_entry->client_list, &up_inode_ctx->client_list); - gf_log (THIS->name, GF_LOG_DEBUG, "upcall_entry_t client added - %s", - up_client_entry->client_uid); + gf_log(THIS->name, GF_LOG_DEBUG, "upcall_entry_t client added - %s", + up_client_entry->client_uid); - return up_client_entry; + return up_client_entry; } -/* - * Given client->uid, retrieve the corresponding upcall client entry. - * If none found, create a new entry. - */ -upcall_client_t* -__get_upcall_client (call_frame_t *frame, client_t *client, - upcall_inode_ctx_t *up_inode_ctx) +static int +__upcall_inode_ctx_set(inode_t *inode, xlator_t *this) { - upcall_client_t *up_client_entry = NULL; - upcall_client_t *up_client = NULL; - upcall_client_t *tmp = NULL; - gf_boolean_t found_client = _gf_false; - - list_for_each_entry_safe (up_client_entry, tmp, - &up_inode_ctx->client_list, - client_list) { - if (strcmp(client->client_uid, - up_client_entry->client_uid) == 0) { - /* found client entry. Update the access_time */ - up_client_entry->access_time = time(NULL); - found_client = _gf_true; - gf_log (THIS->name, GF_LOG_DEBUG, - "upcall_entry_t client found - %s", - up_client_entry->client_uid); - break; - } - } - - if (!found_client) { /* create one */ - up_client_entry = __add_upcall_client (frame, client, - up_inode_ctx); - } - - return up_client_entry; + upcall_inode_ctx_t *inode_ctx = NULL; + upcall_private_t *priv = NULL; + int ret = -1; + uint64_t ctx = 0; + + priv = this->private; + GF_ASSERT(priv); + + ret = __inode_ctx_get(inode, this, &ctx); + + if (!ret) + goto out; + + inode_ctx = GF_MALLOC(sizeof(upcall_inode_ctx_t), + gf_upcall_mt_upcall_inode_ctx_t); + + if (!inode_ctx) { + ret = -ENOMEM; + goto out; + } + + pthread_mutex_init(&inode_ctx->client_list_lock, NULL); + INIT_LIST_HEAD(&inode_ctx->inode_ctx_list); + INIT_LIST_HEAD(&inode_ctx->client_list); + inode_ctx->destroy = 0; + gf_uuid_copy(inode_ctx->gfid, inode->gfid); + + ctx = (long)inode_ctx; + ret = __inode_ctx_set(inode, this, &ctx); + if (ret) { + gf_log(this->name, GF_LOG_DEBUG, "failed to set inode ctx (%p)", inode); + GF_FREE(inode_ctx); + goto out; + } + + /* add this inode_ctx to the global list */ + LOCK(&priv->inode_ctx_lk); + { + list_add_tail(&inode_ctx->inode_ctx_list, &priv->inode_ctx_list); + } + UNLOCK(&priv->inode_ctx_lk); +out: + return ret; } -int -__upcall_inode_ctx_set (inode_t *inode, xlator_t *this) +static upcall_inode_ctx_t * +__upcall_inode_ctx_get(inode_t *inode, xlator_t *this) { - upcall_inode_ctx_t *inode_ctx = NULL; - upcall_private_t *priv = NULL; - int ret = -1; - uint64_t ctx = 0; - - priv = this->private; - GF_ASSERT(priv); + upcall_inode_ctx_t *inode_ctx = NULL; + uint64_t ctx = 0; + int ret = 0; - ret = __inode_ctx_get (inode, this, &ctx); + ret = __inode_ctx_get(inode, this, &ctx); - if (!ret) - goto out; + if (ret < 0) { + ret = __upcall_inode_ctx_set(inode, this); + if (ret < 0) + goto out; - inode_ctx = GF_CALLOC (1, sizeof (upcall_inode_ctx_t), - gf_upcall_mt_upcall_inode_ctx_t); - - if (!inode_ctx) { - ret = -ENOMEM; - goto out; - } + ret = __inode_ctx_get(inode, this, &ctx); + if (ret < 0) + goto out; + } - pthread_mutex_init (&inode_ctx->client_list_lock, NULL); - INIT_LIST_HEAD (&inode_ctx->inode_ctx_list); - INIT_LIST_HEAD (&inode_ctx->client_list); - inode_ctx->destroy = 0; - gf_uuid_copy (inode_ctx->gfid, inode->gfid); - - ctx = (long) inode_ctx; - ret = __inode_ctx_set (inode, this, &ctx); - if (ret) { - gf_log (this->name, GF_LOG_DEBUG, - "failed to set inode ctx (%p)", inode); - goto out; - } + inode_ctx = (upcall_inode_ctx_t *)(long)(ctx); - /* add this inode_ctx to the global list */ - LOCK (&priv->inode_ctx_lk); - { - list_add_tail (&inode_ctx->inode_ctx_list, - &priv->inode_ctx_list); - } - UNLOCK (&priv->inode_ctx_lk); out: - return ret; + return inode_ctx; } upcall_inode_ctx_t * -__upcall_inode_ctx_get (inode_t *inode, xlator_t *this) +upcall_inode_ctx_get(inode_t *inode, xlator_t *this) { - upcall_inode_ctx_t *inode_ctx = NULL; - uint64_t ctx = 0; - int ret = 0; - - ret = __inode_ctx_get (inode, this, &ctx); + upcall_inode_ctx_t *inode_ctx = NULL; - if (ret < 0) { - ret = __upcall_inode_ctx_set (inode, this); - if (ret < 0) - goto out; + LOCK(&inode->lock); + { + inode_ctx = __upcall_inode_ctx_get(inode, this); + } + UNLOCK(&inode->lock); - ret = __inode_ctx_get (inode, this, &ctx); - if (ret < 0) - goto out; - } - - inode_ctx = (upcall_inode_ctx_t *) (long) (ctx); - -out: - return inode_ctx; + return inode_ctx; } -upcall_inode_ctx_t * -upcall_inode_ctx_get (inode_t *inode, xlator_t *this) +static int +__upcall_cleanup_client_entry(upcall_client_t *up_client) { - upcall_inode_ctx_t *inode_ctx = NULL; + list_del_init(&up_client->client_list); - LOCK (&inode->lock); - { - inode_ctx = __upcall_inode_ctx_get (inode, this); - } - UNLOCK (&inode->lock); + GF_FREE(up_client->client_uid); + GF_FREE(up_client); - return inode_ctx; + return 0; } -int -upcall_cleanup_expired_clients (xlator_t *this, - upcall_inode_ctx_t *up_inode_ctx) { +static int +upcall_cleanup_expired_clients(xlator_t *this, upcall_inode_ctx_t *up_inode_ctx, + time_t now) +{ + upcall_client_t *up_client = NULL; + upcall_client_t *tmp = NULL; + int ret = -1; + time_t timeout = 0; + time_t t_expired = 0; + + timeout = get_cache_invalidation_timeout(this); + + pthread_mutex_lock(&up_inode_ctx->client_list_lock); + { + list_for_each_entry_safe(up_client, tmp, &up_inode_ctx->client_list, + client_list) + { + t_expired = now - up_client->access_time; - upcall_client_t *up_client = NULL; - upcall_client_t *tmp = NULL; - int ret = -1; - time_t timeout = 0; - time_t t_expired = 0; + if (t_expired > (2 * timeout)) { + gf_log(THIS->name, GF_LOG_TRACE, "Cleaning up client_entry(%s)", + up_client->client_uid); - timeout = get_cache_invalidation_timeout(this); + ret = __upcall_cleanup_client_entry(up_client); - pthread_mutex_lock (&up_inode_ctx->client_list_lock); - { - list_for_each_entry_safe (up_client, - tmp, - &up_inode_ctx->client_list, - client_list) { - t_expired = time(NULL) - - up_client->access_time; - - if (t_expired > (2*timeout)) { - ret = - __upcall_cleanup_client_entry (up_client); - - if (ret) { - gf_msg ("upcall", GF_LOG_WARNING, 0, - UPCALL_MSG_INTERNAL_ERROR, - "Client entry cleanup failed (%p)", - up_client); - goto out; - } - gf_log (THIS->name, GF_LOG_TRACE, - "Cleaned up client_entry(%s)", - up_client->client_uid); - } + if (ret) { + gf_msg("upcall", GF_LOG_WARNING, 0, + UPCALL_MSG_INTERNAL_ERROR, + "Client entry cleanup failed (%p)", up_client); + goto out; } + } } - pthread_mutex_unlock (&up_inode_ctx->client_list_lock); + } + pthread_mutex_unlock(&up_inode_ctx->client_list_lock); - ret = 0; + ret = 0; out: - return ret; -} - -int -__upcall_cleanup_client_entry (upcall_client_t *up_client) -{ - list_del_init (&up_client->client_list); - - GF_FREE (up_client->client_uid); - GF_FREE (up_client); - - return 0; + return ret; } /* * Free Upcall inode_ctx client list */ int -__upcall_cleanup_inode_ctx_client_list (upcall_inode_ctx_t *inode_ctx) +__upcall_cleanup_inode_ctx_client_list(upcall_inode_ctx_t *inode_ctx) { - upcall_client_t *up_client = NULL; - upcall_client_t *tmp = NULL; + upcall_client_t *up_client = NULL; + upcall_client_t *tmp = NULL; - list_for_each_entry_safe (up_client, tmp, - &inode_ctx->client_list, - client_list) { - __upcall_cleanup_client_entry (up_client); - } + list_for_each_entry_safe(up_client, tmp, &inode_ctx->client_list, + client_list) + { + __upcall_cleanup_client_entry(up_client); + } - return 0; + return 0; } +static void +upcall_cache_forget(xlator_t *this, inode_t *inode, + upcall_inode_ctx_t *up_inode_ctx); + /* * Free upcall_inode_ctx */ int -upcall_cleanup_inode_ctx (xlator_t *this, inode_t *inode) +upcall_cleanup_inode_ctx(xlator_t *this, inode_t *inode) { - uint64_t ctx = 0; - upcall_inode_ctx_t *inode_ctx = NULL; - int ret = 0; - upcall_private_t *priv = NULL; - - priv = this->private; - GF_ASSERT(priv); - - ret = inode_ctx_del (inode, this, &ctx); - - if (ret < 0) { - gf_msg ("upcall", GF_LOG_WARNING, 0, - UPCALL_MSG_INTERNAL_ERROR, - "Failed to del upcall_inode_ctx (%p)", - inode); - goto out; - } + uint64_t ctx = 0; + upcall_inode_ctx_t *inode_ctx = NULL; + int ret = 0; + upcall_private_t *priv = NULL; - inode_ctx = (upcall_inode_ctx_t *)(long) ctx; + priv = this->private; + GF_ASSERT(priv); - if (inode_ctx) { + ret = inode_ctx_del(inode, this, &ctx); - /* Invalidate all the upcall cache entries */ - upcall_cache_forget (this, inode, inode_ctx); + if (ret < 0) { + gf_msg("upcall", GF_LOG_WARNING, 0, UPCALL_MSG_INTERNAL_ERROR, + "Failed to del upcall_inode_ctx (%p)", inode); + goto out; + } - /* do we really need lock? yes now reaper thread - * may also be trying to cleanup the client entries. - */ - pthread_mutex_lock (&inode_ctx->client_list_lock); - { - if (!list_empty (&inode_ctx->client_list)) { - __upcall_cleanup_inode_ctx_client_list (inode_ctx); - } - } - pthread_mutex_unlock (&inode_ctx->client_list_lock); + inode_ctx = (upcall_inode_ctx_t *)(long)ctx; - /* Mark the inode_ctx to be destroyed */ - inode_ctx->destroy = 1; - gf_msg_debug ("upcall", 0, "set upcall_inode_ctx (%p) to destroy mode", - inode_ctx); + if (inode_ctx) { + /* Invalidate all the upcall cache entries */ + upcall_cache_forget(this, inode, inode_ctx); + + /* do we really need lock? yes now reaper thread + * may also be trying to cleanup the client entries. + */ + pthread_mutex_lock(&inode_ctx->client_list_lock); + { + if (!list_empty(&inode_ctx->client_list)) { + __upcall_cleanup_inode_ctx_client_list(inode_ctx); + } } + pthread_mutex_unlock(&inode_ctx->client_list_lock); + + /* Mark the inode_ctx to be destroyed */ + inode_ctx->destroy = 1; + gf_msg_debug("upcall", 0, "set upcall_inode_ctx (%p) to destroy mode", + inode_ctx); + } out: - return ret; + return ret; } /* @@ -389,70 +301,161 @@ out: * which is no longer valid and has destroy bit set. */ void * -upcall_reaper_thread (void *data) +upcall_reaper_thread(void *data) { - upcall_private_t *priv = NULL; - upcall_inode_ctx_t *inode_ctx = NULL; - upcall_inode_ctx_t *tmp = NULL; - xlator_t *this = NULL; - time_t timeout = 0; - - this = (xlator_t *)data; - GF_ASSERT (this); - - priv = this->private; - GF_ASSERT (priv); - - - while (!priv->fini) { - list_for_each_entry_safe (inode_ctx, tmp, - &priv->inode_ctx_list, - inode_ctx_list) { - - /* cleanup expired clients */ - upcall_cleanup_expired_clients (this, inode_ctx); - - if (!inode_ctx->destroy) { - continue; - } - - LOCK (&priv->inode_ctx_lk); - { - /* client list would have been cleaned up*/ - gf_msg_debug ("upcall", 0, "Freeing upcall_inode_ctx (%p)", - inode_ctx); - list_del_init (&inode_ctx->inode_ctx_list); - pthread_mutex_destroy (&inode_ctx->client_list_lock); - GF_FREE (inode_ctx); - inode_ctx = NULL; - } - UNLOCK (&priv->inode_ctx_lk); - } - - /* don't do a very busy loop */ - timeout = get_cache_invalidation_timeout (this); - sleep (timeout / 2); + upcall_private_t *priv = NULL; + upcall_inode_ctx_t *inode_ctx = NULL; + upcall_inode_ctx_t *tmp = NULL; + xlator_t *this = NULL; + time_t timeout = 0; + time_t time_now; + + this = (xlator_t *)data; + GF_ASSERT(this); + + priv = this->private; + GF_ASSERT(priv); + + time_now = gf_time(); + while (!priv->fini) { + list_for_each_entry_safe(inode_ctx, tmp, &priv->inode_ctx_list, + inode_ctx_list) + { + /* cleanup expired clients */ + upcall_cleanup_expired_clients(this, inode_ctx, time_now); + + if (!inode_ctx->destroy) { + continue; + } + + /* client list would have been cleaned up*/ + gf_msg_debug("upcall", 0, "Freeing upcall_inode_ctx (%p)", + inode_ctx); + LOCK(&priv->inode_ctx_lk); + { + list_del_init(&inode_ctx->inode_ctx_list); + pthread_mutex_destroy(&inode_ctx->client_list_lock); + } + UNLOCK(&priv->inode_ctx_lk); + GF_FREE(inode_ctx); + inode_ctx = NULL; } - return NULL; + /* don't do a very busy loop */ + timeout = get_cache_invalidation_timeout(this); + sleep(timeout / 2); + time_now = gf_time(); + } + + return NULL; } /* * Initialize upcall reaper thread. */ int -upcall_reaper_thread_init (xlator_t *this) +upcall_reaper_thread_init(xlator_t *this) +{ + upcall_private_t *priv = NULL; + int ret = -1; + + priv = this->private; + GF_ASSERT(priv); + + ret = gf_thread_create(&priv->reaper_thr, NULL, upcall_reaper_thread, this, + "upreaper"); + + return ret; +} + +int +up_compare_afr_xattr(dict_t *d, char *k, data_t *v, void *tmp) +{ + dict_t *dict = tmp; + + if (!strncmp(k, AFR_XATTR_PREFIX, SLEN(AFR_XATTR_PREFIX)) && + (!is_data_equal(v, dict_get(dict, k)))) + return -1; + + return 0; +} + +static void +up_filter_afr_xattr(dict_t *xattrs, char *xattr, data_t *v) +{ + /* Filter the afr pending xattrs, with value 0. Ideally this should + * be executed only in case of xattrop and not in set and removexattr, + * butset and remove xattr fops do not come with keys AFR_XATTR_PREFIX + */ + if (!strncmp(xattr, AFR_XATTR_PREFIX, SLEN(AFR_XATTR_PREFIX)) && + (mem_0filled(v->data, v->len) == 0)) { + dict_del(xattrs, xattr); + } + return; +} + +static gf_boolean_t +up_key_is_regd_xattr(dict_t *regd_xattrs, char *regd_xattr, data_t *v, + void *xattr) +{ + int ret = _gf_false; + char *key = xattr; + + if (fnmatch(regd_xattr, key, 0) == 0) + ret = _gf_true; + + return ret; +} + +int +up_filter_unregd_xattr(dict_t *xattrs, char *xattr, data_t *v, + void *regd_xattrs) +{ + int ret = 0; + + ret = dict_foreach_match(regd_xattrs, up_key_is_regd_xattr, xattr, + dict_null_foreach_fn, NULL); + if (ret == 0) { + /* xattr was not found in the registered xattr, hence do not + * send notification for its change + */ + dict_del(xattrs, xattr); + goto out; + } + up_filter_afr_xattr(xattrs, xattr, v); +out: + return 0; +} + +int +up_filter_xattr(dict_t *xattr, dict_t *regd_xattrs) { - upcall_private_t *priv = NULL; - int ret = -1; + int ret = 0; - priv = this->private; - GF_ASSERT (priv); + ret = dict_foreach(xattr, up_filter_unregd_xattr, regd_xattrs); - ret = pthread_create (&priv->reaper_thr, NULL, - upcall_reaper_thread, this); + return ret; +} + +static void +upcall_client_cache_invalidate(xlator_t *this, uuid_t gfid, + upcall_client_t *up_client_entry, uint32_t flags, + struct iatt *stbuf, struct iatt *p_stbuf, + struct iatt *oldp_stbuf, dict_t *xattr, + time_t now); - return ret; +gf_boolean_t +up_invalidate_needed(dict_t *xattrs) +{ + if (dict_key_count(xattrs) == 0) { + gf_msg_trace("upcall", 0, + "None of xattrs requested for" + " invalidation, were changed. Nothing to " + "invalidate"); + return _gf_false; + } + + return _gf_true; } /* @@ -466,204 +469,221 @@ upcall_reaper_thread_init (xlator_t *this) * any errors during the process are logged and ignored. */ void -upcall_cache_invalidate (call_frame_t *frame, xlator_t *this, client_t *client, - inode_t *inode, uint32_t flags, struct iatt *stbuf, - struct iatt *p_stbuf, struct iatt *oldp_stbuf) +upcall_cache_invalidate(call_frame_t *frame, xlator_t *this, client_t *client, + inode_t *inode, uint32_t flags, struct iatt *stbuf, + struct iatt *p_stbuf, struct iatt *oldp_stbuf, + dict_t *xattr) { - upcall_client_t *up_client = NULL; - upcall_client_t *up_client_entry = NULL; - upcall_client_t *tmp = NULL; - upcall_inode_ctx_t *up_inode_ctx = NULL; - gf_boolean_t found = _gf_false; - - if (!is_cache_invalidation_enabled(this)) - return; + upcall_client_t *up_client_entry = NULL; + upcall_client_t *tmp = NULL; + upcall_inode_ctx_t *up_inode_ctx = NULL; + gf_boolean_t found = _gf_false; + time_t time_now; + inode_t *linked_inode = NULL; + + if (!is_upcall_enabled(this)) + return; - /* server-side generated fops like quota/marker will not have any - * client associated with them. Ignore such fops. - */ - if (!client) { - gf_msg_debug ("upcall", 0, "Internal fop - client NULL"); - return; + /* server-side generated fops like quota/marker will not have any + * client associated with them. Ignore such fops. + */ + if (!client) { + gf_msg_debug("upcall", 0, "Internal fop - client NULL"); + return; + } + + /* For nameless LOOKUPs, inode created shall always be + * invalid. Hence check if there is any already linked inode. + * If yes, update the inode_ctx of that valid inode + */ + if (inode && (inode->ia_type == IA_INVAL) && stbuf) { + linked_inode = inode_find(inode->table, stbuf->ia_gfid); + if (linked_inode) { + gf_log("upcall", GF_LOG_DEBUG, + "upcall_inode_ctx_get of linked inode (%p)", inode); + up_inode_ctx = upcall_inode_ctx_get(linked_inode, this); } + } - up_inode_ctx = ((upcall_local_t *)frame->local)->upcall_inode_ctx; + if (inode && !up_inode_ctx) + up_inode_ctx = upcall_inode_ctx_get(inode, this); - if (!up_inode_ctx) - up_inode_ctx = upcall_inode_ctx_get (inode, this); - - if (!up_inode_ctx) { - gf_msg ("upcall", GF_LOG_WARNING, 0, - UPCALL_MSG_INTERNAL_ERROR, - "upcall_inode_ctx_get failed (%p)", - inode); - return; - } - - /* In case of LOOKUP, if first time, inode created shall be - * invalid till it gets linked to inode table. Read gfid from - * the stat returned in such cases. + if (!up_inode_ctx) { + gf_msg("upcall", GF_LOG_WARNING, 0, UPCALL_MSG_INTERNAL_ERROR, + "upcall_inode_ctx_get failed (%p)", inode); + return; + } + + /* In case of LOOKUP, if first time, inode created shall be + * invalid till it gets linked to inode table. Read gfid from + * the stat returned in such cases. + */ + if (gf_uuid_is_null(up_inode_ctx->gfid) && stbuf) { + /* That means inode must have been invalid when this inode_ctx + * is created. Copy the gfid value from stbuf instead. */ - if (gf_uuid_is_null (up_inode_ctx->gfid)) { - /* That means inode must have been invalid when this inode_ctx - * is created. Copy the gfid value from stbuf instead. - */ - gf_uuid_copy (up_inode_ctx->gfid, stbuf->ia_gfid); - } - - GF_VALIDATE_OR_GOTO ("upcall_cache_invalidate", - !(gf_uuid_is_null (up_inode_ctx->gfid)), out); - pthread_mutex_lock (&up_inode_ctx->client_list_lock); + gf_uuid_copy(up_inode_ctx->gfid, stbuf->ia_gfid); + } + + if (gf_uuid_is_null(up_inode_ctx->gfid)) { + gf_msg_debug(this->name, 0, + "up_inode_ctx->gfid and " + "stbuf->ia_gfid is NULL, fop:%s", + gf_fop_list[frame->root->op]); + goto out; + } + + time_now = gf_time(); + pthread_mutex_lock(&up_inode_ctx->client_list_lock); + { + list_for_each_entry_safe(up_client_entry, tmp, + &up_inode_ctx->client_list, client_list) { - list_for_each_entry_safe (up_client_entry, tmp, - &up_inode_ctx->client_list, - client_list) { - - /* Do not send UPCALL event if same client. */ - if (!strcmp(client->client_uid, - up_client_entry->client_uid)) { - up_client_entry->access_time = time(NULL); - found = _gf_true; - continue; - } - - /* - * Ignore sending notifications in case of only UP_ATIME - */ - if (!(flags & ~(UP_ATIME))) { - if (found) - break; - else /* we still need to find current client entry*/ - continue; - } - - /* any other client */ - - /* XXX: Send notifications asynchrounously - * instead of in the I/O path - BZ 1200264 - * Also if the file is frequently accessed, set - * expire_time_attr to 0. - */ - upcall_client_cache_invalidate(this, - up_inode_ctx->gfid, - up_client_entry, - flags, stbuf, - p_stbuf, oldp_stbuf); - } + /* Do not send UPCALL event if same client. */ + if (!strcmp(client->client_uid, up_client_entry->client_uid)) { + up_client_entry->access_time = time_now; + found = _gf_true; + continue; + } + + /* + * Ignore sending notifications in case of only UP_ATIME + */ + if (!(flags & ~(UP_ATIME))) { + if (found) + break; + else /* we still need to find current client entry*/ + continue; + } + + /* any other client */ + + /* XXX: Send notifications asynchrounously + * instead of in the I/O path - BZ 1200264 + * Also if the file is frequently accessed, set + * expire_time_attr to 0. + */ + upcall_client_cache_invalidate( + this, up_inode_ctx->gfid, up_client_entry, flags, stbuf, + p_stbuf, oldp_stbuf, xattr, time_now); + } - if (!found) { - up_client_entry = __add_upcall_client (frame, - client, - up_inode_ctx); - } + if (!found) { + up_client_entry = __add_upcall_client(frame, client, up_inode_ctx, + time_now); } - pthread_mutex_unlock (&up_inode_ctx->client_list_lock); + } + pthread_mutex_unlock(&up_inode_ctx->client_list_lock); out: - return; + /* release the ref from inode_find */ + if (linked_inode) + inode_unref(linked_inode); + return; } /* * If the upcall_client_t has recently accessed the file (i.e, within * priv->cache_invalidation_timeout), send a upcall notification. */ -void -upcall_client_cache_invalidate (xlator_t *this, uuid_t gfid, - upcall_client_t *up_client_entry, - uint32_t flags, struct iatt *stbuf, - struct iatt *p_stbuf, - struct iatt *oldp_stbuf) +static void +upcall_client_cache_invalidate(xlator_t *this, uuid_t gfid, + upcall_client_t *up_client_entry, uint32_t flags, + struct iatt *stbuf, struct iatt *p_stbuf, + struct iatt *oldp_stbuf, dict_t *xattr, + time_t now) { - struct gf_upcall up_req = {0,}; - struct gf_upcall_cache_invalidation ca_req = {0,}; - time_t timeout = 0; - int ret = -1; - time_t t_expired = time(NULL) - up_client_entry->access_time; - - GF_VALIDATE_OR_GOTO ("upcall_client_cache_invalidate", - !(gf_uuid_is_null (gfid)), out); - timeout = get_cache_invalidation_timeout(this); + struct gf_upcall up_req = { + 0, + }; + struct gf_upcall_cache_invalidation ca_req = { + 0, + }; + time_t timeout = 0; + int ret = -1; + time_t t_expired = now - up_client_entry->access_time; + + GF_VALIDATE_OR_GOTO("upcall_client_cache_invalidate", + !(gf_uuid_is_null(gfid)), out); + timeout = get_cache_invalidation_timeout(this); + + if (t_expired < timeout) { + /* Send notify call */ + up_req.client_uid = up_client_entry->client_uid; + gf_uuid_copy(up_req.gfid, gfid); + + ca_req.flags = flags; + ca_req.expire_time_attr = up_client_entry->expire_time_attr; + if (stbuf) + ca_req.stat = *stbuf; + if (p_stbuf) + ca_req.p_stat = *p_stbuf; + if (oldp_stbuf) + ca_req.oldp_stat = *oldp_stbuf; + ca_req.dict = xattr; + + up_req.data = &ca_req; + up_req.event_type = GF_UPCALL_CACHE_INVALIDATION; + + gf_log(THIS->name, GF_LOG_TRACE, + "Cache invalidation notification sent to %s", + up_client_entry->client_uid); + + /* Need to send inode flags */ + ret = this->notify(this, GF_EVENT_UPCALL, &up_req); + + /* + * notify may fail as the client could have been + * dis(re)connected. Cleanup the client entry. + */ + if (ret < 0) + __upcall_cleanup_client_entry(up_client_entry); - if (t_expired < timeout) { - /* Send notify call */ - up_req.client_uid = up_client_entry->client_uid; - gf_uuid_copy (up_req.gfid, gfid); - - ca_req.flags = flags; - ca_req.expire_time_attr = - up_client_entry->expire_time_attr; - if (stbuf) - ca_req.stat = *stbuf; - if (p_stbuf) - ca_req.p_stat = *p_stbuf; - if (oldp_stbuf) - ca_req.oldp_stat = *oldp_stbuf; - - up_req.data = &ca_req; - up_req.event_type = GF_UPCALL_CACHE_INVALIDATION; - - gf_log (THIS->name, GF_LOG_TRACE, - "Cache invalidation notification sent to %s", - up_client_entry->client_uid); - - /* Need to send inode flags */ - ret = this->notify (this, GF_EVENT_UPCALL, &up_req); - - /* - * notify may fail as the client could have been - * dis(re)connected. Cleanup the client entry. - */ - if (ret < 0) - __upcall_cleanup_client_entry (up_client_entry); - - } else { - gf_log (THIS->name, GF_LOG_TRACE, - "Cache invalidation notification NOT sent to %s", - up_client_entry->client_uid); - - if (t_expired > (2*timeout)) { - /* Cleanup the entry */ - __upcall_cleanup_client_entry (up_client_entry); - } + } else { + gf_log(THIS->name, GF_LOG_TRACE, + "Cache invalidation notification NOT sent to %s", + up_client_entry->client_uid); + + if (t_expired > (2 * timeout)) { + /* Cleanup the entry */ + __upcall_cleanup_client_entry(up_client_entry); } + } out: - return; + return; } /* - * This is called during upcall_inode_ctx cleanup incase of 'inode_forget'. + * This is called during upcall_inode_ctx cleanup in case of 'inode_forget'. * Send "UP_FORGET" to all the clients so that they invalidate their cache * entry and do a fresh lookup next time when any I/O comes in. */ -void -upcall_cache_forget (xlator_t *this, inode_t *inode, upcall_inode_ctx_t *up_inode_ctx) +static void +upcall_cache_forget(xlator_t *this, inode_t *inode, + upcall_inode_ctx_t *up_inode_ctx) { - upcall_client_t *up_client = NULL; - upcall_client_t *up_client_entry = NULL; - upcall_client_t *tmp = NULL; - uint32_t flags = 0; + upcall_client_t *up_client_entry = NULL; + upcall_client_t *tmp = NULL; + uint32_t flags = UP_FORGET; + time_t time_now; - if (!up_inode_ctx) { - return; - } + if (!up_inode_ctx) { + return; + } - pthread_mutex_lock (&up_inode_ctx->client_list_lock); + time_now = gf_time(); + pthread_mutex_lock(&up_inode_ctx->client_list_lock); + { + list_for_each_entry_safe(up_client_entry, tmp, + &up_inode_ctx->client_list, client_list) { - list_for_each_entry_safe (up_client_entry, tmp, - &up_inode_ctx->client_list, - client_list) { - flags = UP_FORGET; - - /* Set the access time to time(NULL) - * to send notify */ - up_client_entry->access_time = time(NULL); - - upcall_client_cache_invalidate(this, - up_inode_ctx->gfid, - up_client_entry, - flags, NULL, - NULL, NULL); - } + /* Set the access time to gf_time() + * to send notify */ + up_client_entry->access_time = time_now; + upcall_client_cache_invalidate(this, up_inode_ctx->gfid, + up_client_entry, flags, NULL, NULL, + NULL, NULL, time_now); } - pthread_mutex_unlock (&up_inode_ctx->client_list_lock); + } + pthread_mutex_unlock(&up_inode_ctx->client_list_lock); } diff --git a/xlators/features/upcall/src/upcall-mem-types.h b/xlators/features/upcall/src/upcall-mem-types.h index 55793ec65ca..f9883d9d72c 100644 --- a/xlators/features/upcall/src/upcall-mem-types.h +++ b/xlators/features/upcall/src/upcall-mem-types.h @@ -11,14 +11,13 @@ #ifndef __UPCALL_MEM_TYPES_H__ #define __UPCALL_MEM_TYPES_H__ -#include "mem-types.h" +#include <glusterfs/mem-types.h> enum gf_upcall_mem_types_ { - gf_upcall_mt_conf_t = gf_common_mt_end + 1, - gf_upcall_mt_private_t, - gf_upcall_mt_upcall_inode_ctx_t, - gf_upcall_mt_upcall_client_entry_t, - gf_upcall_mt_end + gf_upcall_mt_conf_t = gf_common_mt_end + 1, + gf_upcall_mt_private_t, + gf_upcall_mt_upcall_inode_ctx_t, + gf_upcall_mt_upcall_client_entry_t, + gf_upcall_mt_end }; #endif - diff --git a/xlators/features/upcall/src/upcall-messages.h b/xlators/features/upcall/src/upcall-messages.h index 0cfdfd68b77..4095a34c200 100644 --- a/xlators/features/upcall/src/upcall-messages.h +++ b/xlators/features/upcall/src/upcall-messages.h @@ -11,49 +11,19 @@ #ifndef _UPCALL_MESSAGES_H_ #define _UPCALL_MESSAGES_H_ -#include "glfs-message-id.h" - -/*! \file upcall-messages.h - * \brief UPCALL log-message IDs and their descriptions. - */ - -/* NOTE: Rules for message additions - * 1) Each instance of a message is _better_ left with a unique message ID, even - * if the message format is the same. Reasoning is that, if the message - * format needs to change in one instance, the other instances are not - * impacted or the new change does not change the ID of the instance being - * modified. - * 2) Addition of a message, - * - Should increment the GLFS_NUM_MESSAGES - * - Append to the list of messages defined, towards the end - * - Retain macro naming as glfs_msg_X (for redability across developers) - * NOTE: Rules for message format modifications - * 3) Check across the code if the message ID macro in question is reused - * anywhere. If reused then then the modifications should ensure correctness - * everywhere, or needs a new message ID as (1) above was not adhered to. If - * not used anywhere, proceed with the required modification. - * NOTE: Rules for message deletion - * 4) Check (3) and if used anywhere else, then cannot be deleted. If not used - * anywhere, then can be deleted, but will leave a hole by design, as - * addition rules specify modification to the end of the list and not filling - * holes. - */ - -#define GLFS_COMP_BASE_UPCALL GLFS_MSGID_COMP_UPCALL -#define GLFS_NUM_MESSAGES 1 -#define GLFS_MSGID_END (GLFS_COMP_BASE_UPCALL + GLFS_NUM_MESSAGES + 1) - -#define glfs_msg_start_x GLFS_COMP_BASE_UPCALL, "Invalid: Start of messages" - -/*! - * @messageid 110001 - * @diagnosis Out of Memory - * @recommendedaction None +#include <glusterfs/glfs-message-id.h> + +/* To add new message IDs, append new identifiers at the end of the list. + * + * Never remove a message ID. If it's not used anymore, you can rename it or + * leave it as it is, but not delete it. This is to prevent reutilization of + * IDs by other messages. + * + * The component name must match one of the entries defined in + * glfs-message-id.h. */ -#define UPCALL_MSG_NO_MEMORY (GLFS_COMP_BASE_UPCALL + 1) -#define UPCALL_MSG_INTERNAL_ERROR (GLFS_COMP_BASE_UPCALL + 2) -#define UPCALL_MSG_NOTIFY_FAILED (GLFS_COMP_BASE_UPCALL + 3) -#define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages" +GLFS_MSGID(UPCALL, UPCALL_MSG_NO_MEMORY, UPCALL_MSG_INTERNAL_ERROR, + UPCALL_MSG_NOTIFY_FAILED); #endif /* !_UPCALL_MESSAGES_H_ */ diff --git a/xlators/features/upcall/src/upcall.c b/xlators/features/upcall/src/upcall.c index 9b724928010..0795f58059d 100644 --- a/xlators/features/upcall/src/upcall.c +++ b/xlators/features/upcall/src/upcall.c @@ -13,1821 +13,2493 @@ #include <limits.h> #include <pthread.h> -#include "glusterfs.h" -#include "compat.h" -#include "xlator.h" -#include "inode.h" -#include "logging.h" -#include "common-utils.h" +#include <glusterfs/glusterfs.h> +#include <glusterfs/compat.h> +#include <glusterfs/xlator.h> +#include <glusterfs/logging.h> +#include <glusterfs/common-utils.h> -#include "statedump.h" -#include "syncop.h" +#include <glusterfs/statedump.h> #include "upcall.h" #include "upcall-mem-types.h" #include "glusterfs3-xdr.h" #include "protocol-common.h" -#include "defaults.h" +#include <glusterfs/defaults.h> -int32_t -up_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata) +static int32_t +up_open_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, fd_t *fd, dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - NULL, NULL, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->inode, flags, NULL, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (open, frame, op_ret, op_errno, fd, xdata); + UPCALL_STACK_UNWIND(open, frame, op_ret, op_errno, fd, xdata); - return 0; + return 0; } - -int32_t -up_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, - fd_t *fd, dict_t *xdata) +static int32_t +up_open(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, + fd_t *fd, dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, fd->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_open_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->open, - loc, flags, fd, xdata); + STACK_WIND(frame, up_open_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->open, loc, flags, fd, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (open, frame, -1, op_errno, NULL, NULL); + UPCALL_STACK_UNWIND(open, frame, -1, op_errno, NULL, NULL); - return 0; + return 0; } -int32_t -up_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int op_ret, int op_errno, struct iatt *prebuf, - struct iatt *postbuf, dict_t *xdata) +static int32_t +up_writev_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, + int op_errno, struct iatt *prebuf, struct iatt *postbuf, + dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = UP_WRITE_FLAGS; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - postbuf, NULL, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_WRITE_FLAGS; + upcall_cache_invalidate(frame, this, client, local->inode, flags, postbuf, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (writev, frame, op_ret, op_errno, - prebuf, postbuf, xdata); + UPCALL_STACK_UNWIND(writev, frame, op_ret, op_errno, prebuf, postbuf, + xdata); - return 0; + return 0; } - -int32_t -up_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, - struct iovec *vector, int count, off_t off, uint32_t flags, - struct iobref *iobref, dict_t *xdata) +static int32_t +up_writev(call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, + int count, off_t off, uint32_t flags, struct iobref *iobref, + dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, fd->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_writev_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->writev, - fd, vector, count, off, flags, iobref, xdata); + STACK_WIND(frame, up_writev_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->writev, fd, vector, count, off, flags, + iobref, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (writev, frame, -1, op_errno, NULL, NULL, NULL); + UPCALL_STACK_UNWIND(writev, frame, -1, op_errno, NULL, NULL, NULL); - return 0; + return 0; } - -int32_t -up_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int op_ret, int op_errno, - struct iovec *vector, int count, struct iatt *stbuf, - struct iobref *iobref, dict_t *xdata) +static int32_t +up_readv_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, + int op_errno, struct iovec *vector, int count, struct iatt *stbuf, + struct iobref *iobref, dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - stbuf, NULL, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->inode, flags, stbuf, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (readv, frame, op_ret, op_errno, vector, - count, stbuf, iobref, xdata); + UPCALL_STACK_UNWIND(readv, frame, op_ret, op_errno, vector, count, stbuf, + iobref, xdata); - return 0; + return 0; } -int32_t -up_readv (call_frame_t *frame, xlator_t *this, - fd_t *fd, size_t size, off_t offset, - uint32_t flags, dict_t *xdata) +static int32_t +up_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t offset, uint32_t flags, dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, fd->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_readv_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->readv, - fd, size, offset, flags, xdata); + STACK_WIND(frame, up_readv_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readv, fd, size, offset, flags, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (readv, frame, -1, op_errno, NULL, 0, - NULL, NULL, NULL); + UPCALL_STACK_UNWIND(readv, frame, -1, op_errno, NULL, 0, NULL, NULL, NULL); - return 0; + return 0; } -int32_t -up_lk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct gf_flock *lock, - dict_t *xdata) +static int32_t +up_lk_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, struct gf_flock *lock, dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - NULL, NULL, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->inode, flags, NULL, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (lk, frame, op_ret, op_errno, lock, xdata); + UPCALL_STACK_UNWIND(lk, frame, op_ret, op_errno, lock, xdata); - return 0; + return 0; } -int32_t -up_lk (call_frame_t *frame, xlator_t *this, - fd_t *fd, int32_t cmd, struct gf_flock *flock, dict_t *xdata) +static int32_t +up_lk(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd, + struct gf_flock *flock, dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, fd->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_lk_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->lk, - fd, cmd, flock, xdata); - return 0; + STACK_WIND(frame, up_lk_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->lk, + fd, cmd, flock, xdata); + return 0; err: - UPCALL_STACK_UNWIND (lk, frame, -1, op_errno, NULL, NULL); + UPCALL_STACK_UNWIND(lk, frame, -1, op_errno, NULL, NULL); - return 0; + return 0; } -int32_t -up_truncate_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) +static int32_t +up_truncate_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) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = UP_WRITE_FLAGS; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - postbuf, NULL, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_WRITE_FLAGS; + upcall_cache_invalidate(frame, this, client, local->inode, flags, postbuf, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (truncate, frame, op_ret, op_errno, - prebuf, postbuf, xdata); + UPCALL_STACK_UNWIND(truncate, frame, op_ret, op_errno, prebuf, postbuf, + xdata); - return 0; + return 0; } -int32_t -up_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, - dict_t *xdata) +static int32_t +up_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, + dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, loc->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_truncate_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->truncate, - loc, offset, xdata); + STACK_WIND(frame, up_truncate_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->truncate, loc, offset, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (truncate, frame, -1, op_errno, NULL, NULL, NULL); + UPCALL_STACK_UNWIND(truncate, frame, -1, op_errno, NULL, NULL, NULL); - return 0; + return 0; } -int32_t -up_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int op_ret, int op_errno, struct iatt *statpre, - struct iatt *statpost, dict_t *xdata) +static int32_t +up_setattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, + int op_errno, struct iatt *statpre, struct iatt *statpost, + dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; - - EXIT_IF_UPCALL_OFF (this, out); - - client = frame->root->client; - local = frame->local; - - if ((op_ret < 0) || !local) { - goto out; - } - /* XXX: setattr -> UP_SIZE or UP_OWN or UP_MODE or UP_TIMES - * or INODE_UPDATE (or UP_PERM esp incase of ACLs -> INODE_INVALIDATE) - * Need to check what attr is changed and accordingly pass UP_FLAGS. - * Bug1200271. - */ - flags = UP_ATTR_FLAGS; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - statpost, NULL, NULL); + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + client = frame->root->client; + local = frame->local; + + if ((op_ret < 0) || !local) { + goto out; + } + /* XXX: setattr -> UP_SIZE or UP_OWN or UP_MODE or UP_TIMES + * or INODE_UPDATE (or UP_PERM esp in case of ACLs -> INODE_INVALIDATE) + * Need to check what attr is changed and accordingly pass UP_FLAGS. + * Bug1200271. + */ + flags = UP_ATTR_FLAGS; + /* If mode bits have changed invalidate the xattrs, as posix-acl and + * others store permission related information in xattrs. With changing + * of permissions/mode, we need to make clients to forget all the + * xattrs related to permissions. + * TODO: Invalidate the xattr system.posix_acl_access alone. + */ + if (is_same_mode(statpre->ia_prot, statpost->ia_prot) != 0) + flags |= UP_XATTR; + + upcall_cache_invalidate(frame, this, client, local->inode, flags, statpost, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (setattr, frame, op_ret, op_errno, - statpre, statpost, xdata); + UPCALL_STACK_UNWIND(setattr, frame, op_ret, op_errno, statpre, statpost, + xdata); - return 0; + return 0; } -int32_t -up_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc, - struct iatt *stbuf, int32_t valid, dict_t *xdata) +static int32_t +up_setattr(call_frame_t *frame, xlator_t *this, loc_t *loc, struct iatt *stbuf, + int32_t valid, dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, loc->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_setattr_cbk, - FIRST_CHILD(this), - FIRST_CHILD(this)->fops->setattr, - loc, stbuf, valid, xdata); + STACK_WIND(frame, up_setattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->setattr, loc, stbuf, valid, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (setattr, frame, -1, op_errno, NULL, NULL, NULL); + UPCALL_STACK_UNWIND(setattr, frame, -1, op_errno, NULL, NULL, NULL); - return 0; + return 0; } -int32_t -up_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct iatt *stbuf, - struct iatt *preoldparent, struct iatt *postoldparent, - struct iatt *prenewparent, struct iatt *postnewparent, - dict_t *xdata) +static int32_t +up_rename_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *stbuf, struct iatt *preoldparent, + struct iatt *postoldparent, struct iatt *prenewparent, + struct iatt *postnewparent, dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = (UP_RENAME_FLAGS | UP_PARENT_DENTRY_FLAGS); - upcall_cache_invalidate (frame, this, client, local->inode, flags, - stbuf, postnewparent, postoldparent); + if ((op_ret < 0) || !local) { + goto out; + } + flags = (UP_RENAME_FLAGS | UP_PARENT_DENTRY_FLAGS); + upcall_cache_invalidate(frame, this, client, local->inode, flags, stbuf, + postnewparent, postoldparent, NULL); + + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->rename_oldloc.parent, + flags, postoldparent, NULL, NULL, NULL); + + if (local->rename_oldloc.parent == local->loc.parent) + goto out; + + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->loc.parent, flags, + postnewparent, NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (rename, frame, op_ret, op_errno, - stbuf, preoldparent, postoldparent, - prenewparent, postnewparent, xdata); + UPCALL_STACK_UNWIND(rename, frame, op_ret, op_errno, stbuf, preoldparent, + postoldparent, prenewparent, postnewparent, xdata); - return 0; + return 0; } -int32_t -up_rename (call_frame_t *frame, xlator_t *this, - loc_t *oldloc, loc_t *newloc, dict_t *xdata) +static int32_t +up_rename(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, + dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, oldloc->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, newloc, NULL, oldloc->inode, NULL); + if (!local) { + goto err; + } - /* copy oldloc */ - loc_copy (&local->rename_oldloc, oldloc); + /* copy oldloc */ + loc_copy(&local->rename_oldloc, oldloc); out: - STACK_WIND (frame, up_rename_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->rename, - oldloc, newloc, xdata); + STACK_WIND(frame, up_rename_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->rename, oldloc, newloc, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (rename, frame, -1, op_errno, NULL, - NULL, NULL, NULL, NULL, NULL); + UPCALL_STACK_UNWIND(rename, frame, -1, op_errno, NULL, NULL, NULL, NULL, + NULL, NULL); - return 0; + return 0; } -int32_t -up_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int op_ret, int op_errno, struct iatt *preparent, - struct iatt *postparent, dict_t *xdata) +static int32_t +up_unlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, + int op_errno, struct iatt *preparent, struct iatt *postparent, + dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = (UP_NLINK_FLAGS | UP_PARENT_DENTRY_FLAGS); - upcall_cache_invalidate (frame, this, client, local->inode, flags, - NULL, postparent, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = (UP_NLINK_FLAGS | UP_PARENT_DENTRY_FLAGS); + upcall_cache_invalidate(frame, this, client, local->inode, flags, NULL, + postparent, NULL, NULL); + + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->loc.parent, flags, + postparent, NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (unlink, frame, op_ret, op_errno, - preparent, postparent, xdata); + UPCALL_STACK_UNWIND(unlink, frame, op_ret, op_errno, preparent, postparent, + xdata); - return 0; + return 0; } -int32_t -up_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, - dict_t *xdata) +static int32_t +up_unlink(call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag, + dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, loc->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, loc, NULL, loc->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_unlink_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->unlink, - loc, xflag, xdata); + STACK_WIND(frame, up_unlink_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->unlink, loc, xflag, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (unlink, frame, -1, op_errno, NULL, NULL, NULL); + UPCALL_STACK_UNWIND(unlink, frame, -1, op_errno, NULL, NULL, NULL); - return 0; + return 0; } -int32_t -up_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int op_ret, int op_errno, inode_t *inode, struct iatt *stbuf, - struct iatt *preparent, struct iatt *postparent, dict_t *xdata) +static int32_t +up_link_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, + int op_errno, inode_t *inode, struct iatt *stbuf, + struct iatt *preparent, struct iatt *postparent, dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = (UP_NLINK_FLAGS | UP_PARENT_DENTRY_FLAGS); - upcall_cache_invalidate (frame, this, client, local->inode, flags, - stbuf, postparent, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = (UP_NLINK_FLAGS | UP_PARENT_DENTRY_FLAGS); + upcall_cache_invalidate(frame, this, client, local->inode, flags, stbuf, + postparent, NULL, NULL); + + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->loc.parent, flags, + postparent, NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (link, frame, op_ret, op_errno, - inode, stbuf, preparent, postparent, xdata); + UPCALL_STACK_UNWIND(link, frame, op_ret, op_errno, inode, stbuf, preparent, + postparent, xdata); - return 0; + return 0; } -int32_t -up_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, - loc_t *newloc, dict_t *xdata) +static int32_t +up_link(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, + dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, oldloc->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, newloc, NULL, oldloc->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_link_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->link, - oldloc, newloc, xdata); + STACK_WIND(frame, up_link_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->link, oldloc, newloc, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (link, frame, -1, op_errno, NULL, - NULL, NULL, NULL, NULL); + UPCALL_STACK_UNWIND(link, frame, -1, op_errno, NULL, NULL, NULL, NULL, + NULL); - return 0; + return 0; } -int32_t -up_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) +static int32_t +up_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) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } + if ((op_ret < 0) || !local) { + goto out; + } - flags = (UP_NLINK_FLAGS | UP_PARENT_DENTRY_FLAGS); - upcall_cache_invalidate (frame, this, client, local->inode, flags, - NULL, postparent, NULL); + flags = (UP_NLINK_FLAGS | UP_PARENT_DENTRY_FLAGS); + upcall_cache_invalidate(frame, this, client, local->inode, flags, NULL, + postparent, NULL, NULL); + + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->loc.parent, flags, + postparent, NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (rmdir, frame, op_ret, op_errno, - preparent, postparent, xdata); + UPCALL_STACK_UNWIND(rmdir, frame, op_ret, op_errno, preparent, postparent, + xdata); - return 0; + return 0; } -int32_t -up_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags, - dict_t *xdata) +static int32_t +up_rmdir(call_frame_t *frame, xlator_t *this, loc_t *loc, int flags, + dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, loc->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, loc, NULL, loc->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_rmdir_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->rmdir, - loc, flags, xdata); + STACK_WIND(frame, up_rmdir_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->rmdir, loc, flags, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (rmdir, frame, -1, op_errno, NULL, NULL, NULL); + UPCALL_STACK_UNWIND(rmdir, frame, -1, op_errno, NULL, NULL, NULL); - return 0; + return 0; } -int32_t -up_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int op_ret, int op_errno, inode_t *inode, - struct iatt *stbuf, struct iatt *preparent, - struct iatt *postparent, dict_t *xdata) +static int32_t +up_mkdir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, + int op_errno, inode_t *inode, struct iatt *stbuf, + struct iatt *preparent, struct iatt *postparent, dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } + if ((op_ret < 0) || !local) { + goto out; + } + + /* invalidate parent's entry too */ + flags = UP_TIMES; + upcall_cache_invalidate(frame, this, client, local->inode, flags, + postparent, NULL, NULL, NULL); - /* invalidate parent's entry too */ - flags = UP_TIMES; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - stbuf, postparent, NULL); + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->loc.inode, flags, stbuf, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (mkdir, frame, op_ret, op_errno, - inode, stbuf, preparent, postparent, xdata); + UPCALL_STACK_UNWIND(mkdir, frame, op_ret, op_errno, inode, stbuf, preparent, + postparent, xdata); - return 0; + return 0; } -int32_t -up_mkdir (call_frame_t *frame, xlator_t *this, - loc_t *loc, mode_t mode, mode_t umask, dict_t *params) +static int32_t +up_mkdir(call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, + mode_t umask, dict_t *params) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, loc->parent); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, loc, NULL, loc->parent, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_mkdir_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->mkdir, - loc, mode, umask, params); + STACK_WIND(frame, up_mkdir_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->mkdir, loc, mode, umask, params); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (mkdir, frame, -1, op_errno, NULL, - NULL, NULL, NULL, NULL); + UPCALL_STACK_UNWIND(mkdir, frame, -1, op_errno, NULL, NULL, NULL, NULL, + NULL); - return 0; + return 0; } -int32_t -up_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int op_ret, int op_errno, fd_t *fd, inode_t *inode, - struct iatt *stbuf, struct iatt *preparent, - struct iatt *postparent, dict_t *xdata) +static int32_t +up_create_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, + int op_errno, fd_t *fd, inode_t *inode, struct iatt *stbuf, + struct iatt *preparent, struct iatt *postparent, dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } + if ((op_ret < 0) || !local) { + goto out; + } + + /* As its a new file create, no need of sending notification + * However invalidate parent's entry and update that fact that the + * client has accessed the newly created entry */ + flags = UP_TIMES; + upcall_cache_invalidate(frame, this, client, local->inode, flags, + postparent, NULL, NULL, NULL); - /* As its a new file create, no need of sending notification */ - /* However invalidate parent's entry */ - flags = UP_TIMES; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - stbuf, postparent, NULL); + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->loc.inode, flags, stbuf, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (create, frame, op_ret, op_errno, fd, - inode, stbuf, preparent, postparent, xdata); + UPCALL_STACK_UNWIND(create, frame, op_ret, op_errno, fd, inode, stbuf, + preparent, postparent, xdata); - return 0; + return 0; } -int32_t -up_create (call_frame_t *frame, xlator_t *this, - loc_t *loc, int32_t flags, mode_t mode, - mode_t umask, fd_t *fd, dict_t *params) +static int32_t +up_create(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, + mode_t mode, mode_t umask, fd_t *fd, dict_t *params) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; - - EXIT_IF_UPCALL_OFF (this, out); + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - local = upcall_local_init (frame, this, loc->parent); + EXIT_IF_UPCALL_OFF(this, out); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, loc, NULL, loc->parent, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_create_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->create, - loc, flags, mode, umask, fd, params); + STACK_WIND(frame, up_create_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->create, loc, flags, mode, umask, fd, + params); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (create, frame, -1, op_errno, NULL, - NULL, NULL, NULL, NULL, NULL); + UPCALL_STACK_UNWIND(create, frame, -1, op_errno, NULL, NULL, NULL, NULL, + NULL, NULL); - return 0; + return 0; } -int32_t -up_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int op_ret, int op_errno, - inode_t *inode, struct iatt *stbuf, dict_t *xattr, - struct iatt *postparent) +static int32_t +up_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, + int op_errno, inode_t *inode, struct iatt *stbuf, dict_t *xattr, + struct iatt *postparent) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - stbuf, NULL, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->inode, flags, stbuf, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (lookup, frame, op_ret, op_errno, inode, stbuf, - xattr, postparent); + UPCALL_STACK_UNWIND(lookup, frame, op_ret, op_errno, inode, stbuf, xattr, + postparent); - return 0; + return 0; } -int32_t -up_lookup (call_frame_t *frame, xlator_t *this, - loc_t *loc, dict_t *xattr_req) +static int32_t +up_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, loc->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_lookup_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->lookup, - loc, xattr_req); + STACK_WIND(frame, up_lookup_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->lookup, loc, xattr_req); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (lookup, frame, -1, op_errno, NULL, - NULL, NULL, NULL); + UPCALL_STACK_UNWIND(lookup, frame, -1, op_errno, NULL, NULL, NULL, NULL); - return 0; + return 0; } -int32_t -up_stat_cbk (call_frame_t *frame, void *cookie, - xlator_t *this, int32_t op_ret, int32_t op_errno, - struct iatt *buf, dict_t *xdata) +static int32_t +up_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *buf, dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - buf, NULL, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->inode, flags, buf, NULL, + NULL, NULL); out: - UPCALL_STACK_UNWIND (stat, frame, op_ret, op_errno, buf, - xdata); + UPCALL_STACK_UNWIND(stat, frame, op_ret, op_errno, buf, xdata); - return 0; + return 0; } -int32_t -up_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) +static int32_t +up_stat(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, loc->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_stat_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->stat, - loc, xdata); + STACK_WIND(frame, up_stat_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->stat, loc, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (stat, frame, -1, op_errno, NULL, NULL); + UPCALL_STACK_UNWIND(stat, frame, -1, op_errno, NULL, NULL); - return 0; + return 0; } -int32_t -up_fstat (call_frame_t *frame, xlator_t *this, - fd_t *fd, dict_t *xdata) +static int32_t +up_fstat(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, fd->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_stat_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->fstat, - fd, xdata); + STACK_WIND(frame, up_stat_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fstat, fd, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (fstat, frame, -1, op_errno, NULL, NULL); + UPCALL_STACK_UNWIND(fstat, frame, -1, op_errno, NULL, NULL); - return 0; + return 0; } -int32_t -up_ftruncate (call_frame_t *frame, xlator_t *this, - fd_t *fd, off_t offset, dict_t *xdata) +static int32_t +up_ftruncate(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, fd->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_truncate_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->ftruncate, - fd, offset, xdata); + STACK_WIND(frame, up_truncate_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->ftruncate, fd, offset, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (ftruncate, frame, -1, op_errno, NULL, - NULL, NULL); + UPCALL_STACK_UNWIND(ftruncate, frame, -1, op_errno, NULL, NULL, NULL); - return 0; + return 0; } -int32_t -up_access_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int op_ret, int op_errno, dict_t *xdata) +static int32_t +up_access_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, + int op_errno, dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - NULL, NULL, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->inode, flags, NULL, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (access, frame, op_ret, op_errno, xdata); + UPCALL_STACK_UNWIND(access, frame, op_ret, op_errno, xdata); - return 0; + return 0; } -int32_t -up_access (call_frame_t *frame, xlator_t *this, - loc_t *loc, int32_t mask, dict_t *xdata) +static int32_t +up_access(call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t mask, + dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, loc->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_access_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->access, - loc, mask, xdata); + STACK_WIND(frame, up_access_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->access, loc, mask, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (access, frame, -1, op_errno, NULL); + UPCALL_STACK_UNWIND(access, frame, -1, op_errno, NULL); - return 0; + return 0; } -int32_t -up_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int op_ret, int op_errno, const char *path, - struct iatt *stbuf, dict_t *xdata) +static int32_t +up_readlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, + int op_errno, const char *path, struct iatt *stbuf, + dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - stbuf, NULL, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->inode, flags, stbuf, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (readlink, frame, op_ret, op_errno, path, stbuf, - xdata); + UPCALL_STACK_UNWIND(readlink, frame, op_ret, op_errno, path, stbuf, xdata); - return 0; + return 0; } -int32_t -up_readlink (call_frame_t *frame, xlator_t *this, - loc_t *loc, size_t size, dict_t *xdata) +static int32_t +up_readlink(call_frame_t *frame, xlator_t *this, loc_t *loc, size_t size, + dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, loc->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_readlink_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->readlink, - loc, size, xdata); + STACK_WIND(frame, up_readlink_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readlink, loc, size, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (readlink, frame, -1, op_errno, NULL, - NULL, NULL); + UPCALL_STACK_UNWIND(readlink, frame, -1, op_errno, NULL, NULL, NULL); - return 0; + return 0; } -int32_t -up_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, inode_t *inode, - struct iatt *buf, struct iatt *preparent, - struct iatt *postparent, dict_t *xdata) +static int32_t +up_mknod_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, inode_t *inode, struct iatt *buf, + struct iatt *preparent, struct iatt *postparent, dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } + if ((op_ret < 0) || !local) { + goto out; + } + + /* invalidate parent's entry too */ + flags = UP_TIMES; + upcall_cache_invalidate(frame, this, client, local->inode, flags, + postparent, NULL, NULL, NULL); - /* invalidate parent's entry too */ - flags = UP_TIMES; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - buf, postparent, NULL); + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->loc.inode, flags, buf, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (mknod, frame, op_ret, op_errno, inode, buf, - preparent, postparent, xdata); + UPCALL_STACK_UNWIND(mknod, frame, op_ret, op_errno, inode, buf, preparent, + postparent, xdata); - return 0; + return 0; } -int32_t -up_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, - mode_t mode, dev_t rdev, mode_t umask, dict_t *xdata) +static int32_t +up_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 op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, loc->parent); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, loc, NULL, loc->parent, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_mknod_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->mknod, - loc, mode, rdev, umask, xdata); + STACK_WIND(frame, up_mknod_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->mknod, loc, mode, rdev, umask, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (mknod, frame, -1, op_errno, NULL, - NULL, NULL, NULL, NULL); + UPCALL_STACK_UNWIND(mknod, frame, -1, op_errno, NULL, NULL, NULL, NULL, + NULL); - return 0; + return 0; } -int32_t -up_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, inode_t *inode, - struct iatt *buf, struct iatt *preparent, - struct iatt *postparent, dict_t *xdata) +static int32_t +up_symlink_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } + if ((op_ret < 0) || !local) { + goto out; + } + + /* invalidate parent's entry too */ + flags = UP_TIMES; + upcall_cache_invalidate(frame, this, client, local->inode, flags, + postparent, NULL, NULL, NULL); - /* invalidate parent's entry too */ - flags = UP_TIMES; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - buf, postparent, NULL); + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->loc.inode, flags, buf, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (symlink, frame, op_ret, op_errno, inode, buf, - preparent, postparent, xdata); + UPCALL_STACK_UNWIND(symlink, frame, op_ret, op_errno, inode, buf, preparent, + postparent, xdata); - return 0; + return 0; } -int32_t -up_symlink (call_frame_t *frame, xlator_t *this, - const char *linkpath, loc_t *loc, mode_t umask, - dict_t *xdata) +static int32_t +up_symlink(call_frame_t *frame, xlator_t *this, const char *linkpath, + loc_t *loc, mode_t umask, dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, loc->parent); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, loc, NULL, loc->parent, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_symlink_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->symlink, - linkpath, loc, umask, xdata); + STACK_WIND(frame, up_symlink_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->symlink, linkpath, loc, umask, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (symlink, frame, -1, op_errno, NULL, - NULL, NULL, NULL, NULL); + UPCALL_STACK_UNWIND(symlink, frame, -1, op_errno, NULL, NULL, NULL, NULL, + NULL); - return 0; + return 0; } -int32_t -up_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, fd_t *fd, - dict_t *xdata) +static int32_t +up_opendir_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - NULL, NULL, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->inode, flags, NULL, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (opendir, frame, op_ret, op_errno, fd, xdata); + UPCALL_STACK_UNWIND(opendir, frame, op_ret, op_errno, fd, xdata); - return 0; + return 0; } -int32_t -up_opendir (call_frame_t *frame, xlator_t *this, - loc_t *loc, fd_t *fd, dict_t *xdata) +static int32_t +up_opendir(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, + dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, loc->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_opendir_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->opendir, - loc, fd, xdata); + STACK_WIND(frame, up_opendir_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->opendir, loc, fd, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (opendir, frame, -1, op_errno, NULL, NULL); + UPCALL_STACK_UNWIND(opendir, frame, -1, op_errno, NULL, NULL); - return 0; + return 0; } -int32_t -up_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, struct statvfs *buf, - dict_t *xdata) +static int32_t +up_statfs_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, + int32_t op_errno, struct statvfs *buf, dict_t *xdata) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - NULL, NULL, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->inode, flags, NULL, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (statfs, frame, op_ret, op_errno, buf, xdata); + UPCALL_STACK_UNWIND(statfs, frame, op_ret, op_errno, buf, xdata); - return 0; + return 0; } -int32_t -up_statfs (call_frame_t *frame, xlator_t *this, - loc_t *loc, dict_t *xdata) +static int32_t +up_statfs(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, loc->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_statfs_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->statfs, - loc, xdata); + STACK_WIND(frame, up_statfs_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->statfs, loc, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (statfs, frame, -1, op_errno, NULL, NULL); + UPCALL_STACK_UNWIND(statfs, frame, -1, op_errno, NULL, NULL); - return 0; + return 0; } -int32_t -up_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) +static int32_t +up_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) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = UP_UPDATE_CLIENT; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - NULL, NULL, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->inode, flags, NULL, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (readdir, frame, op_ret, op_errno, entries, xdata); + UPCALL_STACK_UNWIND(readdir, frame, op_ret, op_errno, entries, xdata); - return 0; + return 0; } -int32_t -up_readdir (call_frame_t *frame, xlator_t *this, - fd_t *fd, size_t size, off_t off, dict_t *xdata) +static int32_t +up_readdir(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t off, dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, fd->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_readdir_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->readdir, - fd, size, off, xdata); + STACK_WIND(frame, up_readdir_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readdir, fd, size, off, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (readdir, frame, -1, op_errno, NULL, NULL); + UPCALL_STACK_UNWIND(readdir, frame, -1, op_errno, NULL, NULL); - return 0; + return 0; } -int32_t -up_readdirp (call_frame_t *frame, xlator_t *this, - fd_t *fd, size_t size, off_t off, dict_t *dict) +static int32_t +up_readdirp_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, gf_dirent_t *entries, + dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; + gf_dirent_t *entry = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + client = frame->root->client; + local = frame->local; + + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->inode, flags, NULL, + NULL, NULL, NULL); + + list_for_each_entry(entry, &entries->list, list) + { + if (entry->inode == NULL) { + continue; + } + upcall_cache_invalidate(frame, this, client, entry->inode, flags, + &entry->d_stat, NULL, NULL, NULL); + } - EXIT_IF_UPCALL_OFF (this, out); +out: + UPCALL_STACK_UNWIND(readdirp, frame, op_ret, op_errno, entries, xdata); - local = upcall_local_init (frame, this, fd->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + return 0; +} + +static int32_t +up_readdirp(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, + off_t off, dict_t *dict) +{ + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_readdir_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->readdirp, - fd, size, off, dict); + STACK_WIND(frame, up_readdirp_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->readdirp, fd, size, off, dict); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (readdirp, frame, -1, op_errno, NULL, NULL); + UPCALL_STACK_UNWIND(readdirp, frame, -1, op_errno, NULL, NULL); - return 0; + return 0; } -int32_t -up_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd, - struct iatt *stbuf, int32_t valid, dict_t *xdata) +static int32_t +up_fsetattr(call_frame_t *frame, xlator_t *this, fd_t *fd, struct iatt *stbuf, + int32_t valid, dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, fd->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_setattr_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->fsetattr, - fd, stbuf, valid, xdata); + STACK_WIND(frame, up_setattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsetattr, fd, stbuf, valid, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (fsetattr, frame, -1, op_errno, NULL, - NULL, NULL); + UPCALL_STACK_UNWIND(fsetattr, frame, -1, op_errno, NULL, NULL, NULL); - return 0; + return 0; } -int32_t +static int32_t up_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) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = UP_WRITE_FLAGS; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - post, NULL, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_WRITE_FLAGS; + upcall_cache_invalidate(frame, this, client, local->inode, flags, post, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (fallocate, frame, op_ret, op_errno, pre, - post, xdata); + UPCALL_STACK_UNWIND(fallocate, frame, op_ret, op_errno, pre, post, xdata); - return 0; + return 0; } -int32_t -up_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, - int32_t mode, off_t offset, size_t len, dict_t *xdata) +static int32_t +up_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t mode, + off_t offset, size_t len, dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, fd->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_fallocate_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->fallocate, - fd, mode, offset, len, xdata); + STACK_WIND(frame, up_fallocate_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fallocate, fd, mode, offset, len, + xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (fallocate, frame, -1, op_errno, NULL, - NULL, NULL); + UPCALL_STACK_UNWIND(fallocate, frame, -1, op_errno, NULL, NULL, NULL); - return 0; + return 0; } -int32_t +static int32_t up_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) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = UP_WRITE_FLAGS; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - post, NULL, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_WRITE_FLAGS; + upcall_cache_invalidate(frame, this, client, local->inode, flags, post, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (discard, frame, op_ret, op_errno, pre, - post, xdata); + UPCALL_STACK_UNWIND(discard, frame, op_ret, op_errno, pre, post, xdata); - return 0; + return 0; } -int32_t -up_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, - off_t offset, size_t len, dict_t *xdata) +static int32_t +up_discard(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + size_t len, dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, fd->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_discard_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->discard, - fd, offset, len, xdata); + STACK_WIND(frame, up_discard_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->discard, fd, offset, len, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (discard, frame, -1, op_errno, NULL, - NULL, NULL); + UPCALL_STACK_UNWIND(discard, frame, -1, op_errno, NULL, NULL, NULL); - return 0; + return 0; } -int32_t +static int32_t up_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) { - client_t *client = NULL; - uint32_t flags = 0; - upcall_local_t *local = NULL; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - client = frame->root->client; - local = frame->local; + client = frame->root->client; + local = frame->local; - if ((op_ret < 0) || !local) { - goto out; - } - flags = UP_WRITE_FLAGS; - upcall_cache_invalidate (frame, this, client, local->inode, flags, - post, NULL, NULL); + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_WRITE_FLAGS; + upcall_cache_invalidate(frame, this, client, local->inode, flags, post, + NULL, NULL, NULL); out: - UPCALL_STACK_UNWIND (zerofill, frame, op_ret, op_errno, pre, - post, xdata); + UPCALL_STACK_UNWIND(zerofill, frame, op_ret, op_errno, pre, post, xdata); - return 0; + return 0; } -int -up_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, - off_t offset, off_t len, dict_t *xdata) +static int +up_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + off_t len, dict_t *xdata) { - int32_t op_errno = -1; - upcall_local_t *local = NULL; + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; - EXIT_IF_UPCALL_OFF (this, out); + EXIT_IF_UPCALL_OFF(this, out); - local = upcall_local_init (frame, this, fd->inode); - if (!local) { - op_errno = ENOMEM; - goto err; - } + local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); + if (!local) { + goto err; + } out: - STACK_WIND (frame, up_zerofill_cbk, - FIRST_CHILD(this), FIRST_CHILD(this)->fops->zerofill, - fd, offset, len, xdata); + STACK_WIND(frame, up_zerofill_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->zerofill, fd, offset, len, xdata); - return 0; + return 0; err: - UPCALL_STACK_UNWIND (zerofill, frame, -1, op_errno, NULL, - NULL, NULL); + UPCALL_STACK_UNWIND(zerofill, frame, -1, op_errno, NULL, NULL, NULL); - return 0; + return 0; } -int32_t -mem_acct_init (xlator_t *this) +static int32_t +up_seek_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int op_ret, + int op_errno, off_t offset, dict_t *xdata) { - int ret = -1; + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; - if (!this) - return ret; + EXIT_IF_UPCALL_OFF(this, out); - ret = xlator_mem_acct_init (this, gf_upcall_mt_end + 1); + client = frame->root->client; + local = frame->local; - if (ret != 0) { - gf_msg ("upcall", GF_LOG_WARNING, 0, - UPCALL_MSG_NO_MEMORY, - "Memory allocation failed"); - return ret; - } + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->inode, flags, NULL, + NULL, NULL, NULL); + +out: + UPCALL_STACK_UNWIND(seek, frame, op_ret, op_errno, offset, xdata); + + return 0; +} + +static int32_t +up_seek(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, + gf_seek_what_t what, dict_t *xdata) +{ + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); + if (!local) { + goto err; + } + +out: + STACK_WIND(frame, up_seek_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->seek, fd, offset, what, xdata); + + return 0; + +err: + UPCALL_STACK_UNWIND(seek, frame, -1, op_errno, 0, NULL); + + return 0; +} +static int32_t +up_setxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; + int ret = 0; + struct iatt stbuf = { + 0, + }; + upcall_private_t *priv = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + priv = this->private; + GF_VALIDATE_OR_GOTO(this->name, priv, out); + + client = frame->root->client; + local = frame->local; + + if ((op_ret < 0) || !local) { + goto out; + } + + flags = UP_XATTR; + + ret = up_filter_xattr(local->xattr, priv->xattrs); + if (ret < 0) { + op_ret = ret; + goto out; + } + if (!up_invalidate_needed(local->xattr)) + goto out; + + ret = dict_get_iatt(xdata, GF_POSTSTAT, &stbuf); + if (ret == 0) + flags |= UP_TIMES; + + upcall_cache_invalidate(frame, this, client, local->inode, flags, &stbuf, + NULL, NULL, local->xattr); + +out: + UPCALL_STACK_UNWIND(setxattr, frame, op_ret, op_errno, xdata); + + return 0; +} + +static int32_t +up_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, + int32_t flags, dict_t *xdata) +{ + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + local = upcall_local_init(frame, this, loc, NULL, loc->inode, dict); + if (!local) { + goto err; + } + +out: + STACK_WIND(frame, up_setxattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->setxattr, loc, dict, flags, xdata); + + return 0; + +err: + UPCALL_STACK_UNWIND(setxattr, frame, -1, op_errno, NULL); + + return 0; +} + +static int32_t +up_fsetxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; + int ret = 0; + struct iatt stbuf = { + 0, + }; + upcall_private_t *priv = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + priv = this->private; + GF_VALIDATE_OR_GOTO(this->name, priv, out); + + client = frame->root->client; + local = frame->local; + + if ((op_ret < 0) || !local) { + goto out; + } + + flags = UP_XATTR; + + ret = up_filter_xattr(local->xattr, priv->xattrs); + if (ret < 0) { + op_ret = ret; + goto out; + } + if (!up_invalidate_needed(local->xattr)) + goto out; + + ret = dict_get_iatt(xdata, GF_POSTSTAT, &stbuf); + if (ret == 0) + flags |= UP_TIMES; + + upcall_cache_invalidate(frame, this, client, local->inode, flags, &stbuf, + NULL, NULL, local->xattr); + +out: + UPCALL_STACK_UNWIND(fsetxattr, frame, op_ret, op_errno, xdata); + + return 0; +} + +static int32_t +up_fsetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict, + int32_t flags, dict_t *xdata) +{ + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + local = upcall_local_init(frame, this, NULL, fd, fd->inode, dict); + if (!local) { + goto err; + } + +out: + STACK_WIND(frame, up_fsetxattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsetxattr, fd, dict, flags, xdata); + + return 0; + +err: + UPCALL_STACK_UNWIND(fsetxattr, frame, -1, op_errno, NULL); + + return 0; +} + +static int32_t +up_fremovexattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; + struct iatt stbuf = { + 0, + }; + int ret = 0; + upcall_private_t *priv = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + priv = this->private; + GF_VALIDATE_OR_GOTO(this->name, priv, out); + + client = frame->root->client; + local = frame->local; + + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_XATTR_RM; + + ret = up_filter_xattr(local->xattr, priv->xattrs); + if (ret < 0) { + op_ret = ret; + goto out; + } + if (!up_invalidate_needed(local->xattr)) + goto out; + + ret = dict_get_iatt(xdata, GF_POSTSTAT, &stbuf); + if (ret == 0) + flags |= UP_TIMES; + + upcall_cache_invalidate(frame, this, client, local->inode, flags, &stbuf, + NULL, NULL, local->xattr); + +out: + UPCALL_STACK_UNWIND(fremovexattr, frame, op_ret, op_errno, xdata); + return 0; +} + +static int32_t +up_fremovexattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, + dict_t *xdata) +{ + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; + dict_t *xattr = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + xattr = dict_for_key_value(name, "", 1, _gf_true); + if (!xattr) { + goto err; + } + + local = upcall_local_init(frame, this, NULL, fd, fd->inode, xattr); + if (!local) { + goto err; + } + +out: + if (xattr) + dict_unref(xattr); + + STACK_WIND(frame, up_fremovexattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fremovexattr, fd, name, xdata); + return 0; + +err: + if (xattr) + dict_unref(xattr); + + UPCALL_STACK_UNWIND(fremovexattr, frame, -1, op_errno, NULL); + + return 0; +} + +static int32_t +up_removexattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata) +{ + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; + struct iatt stbuf = { + 0, + }; + int ret = 0; + upcall_private_t *priv = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + priv = this->private; + GF_VALIDATE_OR_GOTO(this->name, priv, out); + + client = frame->root->client; + local = frame->local; + + if ((op_ret < 0) || !local) { + goto out; + } + flags = UP_XATTR_RM; + + ret = up_filter_xattr(local->xattr, priv->xattrs); + if (ret < 0) { + op_ret = ret; + goto out; + } + if (!up_invalidate_needed(local->xattr)) + goto out; + + ret = dict_get_iatt(xdata, GF_POSTSTAT, &stbuf); + if (ret == 0) + flags |= UP_TIMES; + + upcall_cache_invalidate(frame, this, client, local->inode, flags, &stbuf, + NULL, NULL, local->xattr); + +out: + UPCALL_STACK_UNWIND(removexattr, frame, op_ret, op_errno, xdata); + return 0; +} + +static int32_t +up_removexattr(call_frame_t *frame, xlator_t *this, loc_t *loc, + const char *name, dict_t *xdata) +{ + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; + dict_t *xattr = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + xattr = dict_for_key_value(name, "", 1, _gf_true); + if (!xattr) { + goto err; + } + + local = upcall_local_init(frame, this, loc, NULL, loc->inode, xattr); + if (!local) { + goto err; + } + +out: + if (xattr) + dict_unref(xattr); + + STACK_WIND(frame, up_removexattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->removexattr, loc, name, xdata); + return 0; + +err: + if (xattr) + dict_unref(xattr); + + UPCALL_STACK_UNWIND(removexattr, frame, -1, op_errno, NULL); + + return 0; +} + +static int32_t +up_fgetxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata) +{ + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + client = frame->root->client; + local = frame->local; + + if ((op_ret < 0) || !local) { + goto out; + } + + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->inode, flags, NULL, + NULL, NULL, NULL); + +out: + UPCALL_STACK_UNWIND(fgetxattr, frame, op_ret, op_errno, dict, xdata); + return 0; +} + +static int32_t +up_fgetxattr(call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, + dict_t *xdata) +{ + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + local = upcall_local_init(frame, this, NULL, NULL, fd->inode, NULL); + if (!local) { + goto err; + } + +out: + STACK_WIND(frame, up_fgetxattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fgetxattr, fd, name, xdata); + return 0; +err: + UPCALL_STACK_UNWIND(fgetxattr, frame, -1, op_errno, NULL, NULL); + return 0; +} + +static int32_t +up_getxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata) +{ + client_t *client = NULL; + uint32_t flags = 0; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + client = frame->root->client; + local = frame->local; + + if ((op_ret < 0) || !local) { + goto out; + } + + flags = UP_UPDATE_CLIENT; + upcall_cache_invalidate(frame, this, client, local->inode, flags, NULL, + NULL, NULL, NULL); + +out: + UPCALL_STACK_UNWIND(getxattr, frame, op_ret, op_errno, dict, xdata); + return 0; +} + +static int32_t +up_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name, + dict_t *xdata) +{ + int32_t op_errno = ENOMEM; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + local = upcall_local_init(frame, this, NULL, NULL, loc->inode, NULL); + if (!local) { + goto err; + } + +out: + STACK_WIND(frame, up_getxattr_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->getxattr, loc, name, xdata); + return 0; +err: + UPCALL_STACK_UNWIND(getxattr, frame, -1, op_errno, NULL, NULL); + return 0; +} + +/* The xattrops here mainly tracks changes in afr pending xattr. + * 1. xattrop doesn't carry info saying post op/pre op. + * 2. Pre xattrop will have 0 value for all pending xattrs, + * the cbk of pre xattrop carries the on-disk xattr value. + * Non zero on-disk xattr indicates pending healing. + * 3. Post xattrop will either have 0 or 1 as value of pending xattrs, + * 0 on success, 1 on failure. But the post xattrop cbk will have + * 0 or 1 or any higher value. + * 0 - if no healing required* + * 1 - if this is the first time pending xattr is being set. + * n - if there is already a pending xattr set, it will increment + * the on-disk value and send that in cbk. + * Our aim is to send an invalidation, only the first time a pending + * xattr was set on a file. Below are some of the exceptions in handling + * xattrop: + * - Do not filter unregistered xattrs in the cbk, but in the call path. + * Else, we will be invalidating on every preop, if the file already has + * pending xattr set. Filtering unregistered xattrs on the fop path + * ensures we invalidate only in postop, every time a postop comes with + * pending xattr value 1. + * - Consider a brick is down, and the postop sets pending xattrs as long + * as the other brick is down. But we do not want to invalidate every time + * a pending xattr is set, but we want to invalidate only the first time + * a pending xattr is set on any file. Hence, to identify if its the first + * time a pending xattr is set, we compare the value of pending xattrs that + * came in postop and postop cbk, if its same then its the first time. + */ +static int32_t +up_xattrop_cbk(call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata) +{ + client_t *client = NULL; + upcall_local_t *local = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + client = frame->root->client; + local = frame->local; + + if ((op_ret < 0) || !local) { + goto out; + } + + if (up_invalidate_needed(local->xattr)) { + if (dict_foreach(local->xattr, up_compare_afr_xattr, dict) < 0) + goto out; + + upcall_cache_invalidate(frame, this, client, local->inode, UP_XATTR, + NULL, NULL, NULL, local->xattr); + } +out: + if (frame->root->op == GF_FOP_FXATTROP) { + UPCALL_STACK_UNWIND(fxattrop, frame, op_ret, op_errno, dict, xdata); + } else { + UPCALL_STACK_UNWIND(xattrop, frame, op_ret, op_errno, dict, xdata); + } + return 0; +} + +static int32_t +up_xattrop(call_frame_t *frame, xlator_t *this, loc_t *loc, + gf_xattrop_flags_t optype, dict_t *xattr, dict_t *xdata) +{ + int32_t op_errno = EINVAL; + upcall_local_t *local = NULL; + int ret = 0; + upcall_private_t *priv = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + priv = this->private; + GF_VALIDATE_OR_GOTO(this->name, priv, out); + + local = upcall_local_init(frame, this, loc, NULL, loc->inode, xattr); + if (!local) { + op_errno = ENOMEM; + goto err; + } + + ret = up_filter_xattr(local->xattr, priv->xattrs); + if (ret < 0) { + goto err; + } + +out: + STACK_WIND(frame, up_xattrop_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->xattrop, loc, optype, xattr, xdata); + return 0; +err: + UPCALL_STACK_UNWIND(xattrop, frame, -1, op_errno, NULL, NULL); + return 0; +} + +static int32_t +up_fxattrop(call_frame_t *frame, xlator_t *this, fd_t *fd, + gf_xattrop_flags_t optype, dict_t *xattr, dict_t *xdata) +{ + int32_t op_errno = EINVAL; + upcall_local_t *local = NULL; + int ret = 0; + upcall_private_t *priv = NULL; + + EXIT_IF_UPCALL_OFF(this, out); + + priv = this->private; + GF_VALIDATE_OR_GOTO(this->name, priv, out); + + local = upcall_local_init(frame, this, NULL, fd, fd->inode, xattr); + if (!local) { + op_errno = ENOMEM; + goto err; + } + + ret = up_filter_xattr(local->xattr, priv->xattrs); + if (ret < 0) { + goto err; + } + +out: + STACK_WIND(frame, up_xattrop_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fxattrop, fd, optype, xattr, xdata); + return 0; +err: + STACK_UNWIND_STRICT(fxattrop, frame, -1, op_errno, NULL, NULL); + return 0; +} + +int32_t +mem_acct_init(xlator_t *this) +{ + int ret = -1; + + if (!this) return ret; + + ret = xlator_mem_acct_init(this, gf_upcall_mt_end + 1); + + if (ret != 0) { + gf_msg("upcall", GF_LOG_WARNING, 0, UPCALL_MSG_NO_MEMORY, + "Memory allocation failed"); + return ret; + } + + return ret; } void -upcall_local_wipe (xlator_t *this, upcall_local_t *local) +upcall_local_wipe(xlator_t *this, upcall_local_t *local) { - if (local) { - inode_unref (local->inode); - loc_wipe (&local->rename_oldloc); - mem_put (local); - } + if (local) { + inode_unref(local->inode); + if (local->xattr) + dict_unref(local->xattr); + loc_wipe(&local->rename_oldloc); + loc_wipe(&local->loc); + if (local->fd) + fd_unref(local->fd); + mem_put(local); + } } upcall_local_t * -upcall_local_init (call_frame_t *frame, xlator_t *this, inode_t *inode) +upcall_local_init(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, + inode_t *inode, dict_t *xattr) { - upcall_local_t *local = NULL; + upcall_local_t *local = NULL; - local = mem_get0 (THIS->local_pool); + GF_VALIDATE_OR_GOTO("upcall", this, out); + GF_VALIDATE_OR_GOTO(this->name, frame, out); + GF_VALIDATE_OR_GOTO(this->name, inode, out); - if (!local) - goto out; + local = mem_get0(THIS->local_pool); + + if (!local) + goto out; - local->inode = inode_ref (inode); + local->inode = inode_ref(inode); + if (xattr) + local->xattr = dict_copy_with_ref(xattr, NULL); - /* Shall we get inode_ctx and store it here itself? */ - local->upcall_inode_ctx = upcall_inode_ctx_get (inode, this); + if (loc) + loc_copy(&local->loc, loc); + if (fd) + local->fd = fd_ref(fd); - frame->local = local; + frame->local = local; out: - return local; + return local; +} + +static int32_t +update_xattrs(dict_t *dict, char *key, data_t *value, void *data) +{ + dict_t *xattrs = data; + int ret = 0; + + ret = dict_set_int8(xattrs, key, 0); + return ret; +} + +int32_t +up_ipc(call_frame_t *frame, xlator_t *this, int32_t op, dict_t *xdata) +{ + upcall_private_t *priv = NULL; + int ret = 0; + + priv = this->private; + GF_VALIDATE_OR_GOTO(this->name, priv, out); + + if (op != GF_IPC_TARGET_UPCALL) + goto wind; + + /* TODO: Bz-1371622 Along with the xattrs also store list of clients + * that are interested in notifications, so that the notification + * can be sent to the clients that have registered. + * Once this implemented there can be unregister of xattrs for + * notifications. Until then there is no unregister of xattrs*/ + if (xdata && priv->xattrs) { + ret = dict_foreach(xdata, update_xattrs, priv->xattrs); + } + +out: + STACK_UNWIND_STRICT(ipc, frame, ret, 0, NULL); + return 0; + +wind: + STACK_WIND(frame, default_ipc_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->ipc, op, xdata); + return 0; } int -reconfigure (xlator_t *this, dict_t *options) +reconfigure(xlator_t *this, dict_t *options) { - upcall_private_t *priv = NULL; - int ret = -1; + upcall_private_t *priv = NULL; + int ret = -1; - priv = this->private; - GF_ASSERT (priv); + priv = this->private; + GF_VALIDATE_OR_GOTO(this->name, priv, out); - GF_OPTION_RECONF ("cache-invalidation", priv->cache_invalidation_enabled, - options, bool, out); - GF_OPTION_RECONF ("cache-invalidation-timeout", priv->cache_invalidation_timeout, - options, int32, out); + GF_OPTION_RECONF("cache-invalidation", priv->cache_invalidation_enabled, + options, bool, out); + GF_OPTION_RECONF("cache-invalidation-timeout", + priv->cache_invalidation_timeout, options, int32, out); - ret = 0; + ret = 0; - if (priv->cache_invalidation_enabled && - !priv->reaper_init_done) { - ret = upcall_reaper_thread_init (this); + if (priv->cache_invalidation_enabled && !priv->reaper_init_done) { + ret = upcall_reaper_thread_init(this); - if (ret) { - gf_msg ("upcall", GF_LOG_WARNING, 0, - UPCALL_MSG_INTERNAL_ERROR, - "reaper_thread creation failed (%s)." - " Disabling cache_invalidation", - strerror(errno)); - } - priv->reaper_init_done = 1; + if (ret) { + gf_msg("upcall", GF_LOG_WARNING, 0, UPCALL_MSG_INTERNAL_ERROR, + "reaper_thread creation failed (%s)." + " Disabling cache_invalidation", + strerror(errno)); } + priv->reaper_init_done = _gf_true; + } out: - return ret; + return ret; } int -init (xlator_t *this) +init(xlator_t *this) { - int ret = -1; - upcall_private_t *priv = NULL; + int ret = -1; + upcall_private_t *priv = NULL; - priv = GF_CALLOC (1, sizeof (*priv), - gf_upcall_mt_private_t); - if (!priv) { - gf_msg ("upcall", GF_LOG_WARNING, 0, - UPCALL_MSG_NO_MEMORY, - "Memory allocation failed"); - goto out; - } + priv = GF_CALLOC(1, sizeof(*priv), gf_upcall_mt_private_t); + if (!priv) + goto out; - GF_OPTION_INIT ("cache-invalidation", priv->cache_invalidation_enabled, - bool, out); - GF_OPTION_INIT ("cache-invalidation-timeout", - priv->cache_invalidation_timeout, int32, out); + priv->xattrs = dict_new(); + if (!priv->xattrs) + goto out; - LOCK_INIT (&priv->inode_ctx_lk); - INIT_LIST_HEAD (&priv->inode_ctx_list); + GF_OPTION_INIT("cache-invalidation", priv->cache_invalidation_enabled, bool, + out); + GF_OPTION_INIT("cache-invalidation-timeout", + priv->cache_invalidation_timeout, int32, out); - this->private = priv; - priv->fini = 0; - priv->reaper_init_done = 0; + LOCK_INIT(&priv->inode_ctx_lk); + INIT_LIST_HEAD(&priv->inode_ctx_list); - this->local_pool = mem_pool_new (upcall_local_t, 512); - ret = 0; + priv->fini = 0; + priv->reaper_init_done = _gf_false; - if (priv->cache_invalidation_enabled) { - ret = upcall_reaper_thread_init (this); + this->private = priv; + this->local_pool = mem_pool_new(upcall_local_t, 512); + ret = 0; + + if (priv->cache_invalidation_enabled) { + ret = upcall_reaper_thread_init(this); - if (ret) { - gf_msg ("upcall", GF_LOG_WARNING, 0, - UPCALL_MSG_INTERNAL_ERROR, - "reaper_thread creation failed (%s)." - " Disabling cache_invalidation", - strerror(errno)); - } - priv->reaper_init_done = 1; - } -out: if (ret) { - GF_FREE (priv); + gf_msg("upcall", GF_LOG_WARNING, 0, UPCALL_MSG_INTERNAL_ERROR, + "reaper_thread creation failed (%s)." + " Disabling cache_invalidation", + strerror(errno)); } + priv->reaper_init_done = _gf_true; + } +out: + if (ret && priv) { + if (priv->xattrs) + dict_unref(priv->xattrs); - return ret; + GF_FREE(priv); + } + + return ret; } -int -fini (xlator_t *this) +void +fini(xlator_t *this) { - upcall_private_t *priv = NULL; + upcall_private_t *priv = NULL; - priv = this->private; - if (!priv) { - return 0; - } - this->private = NULL; + priv = this->private; + if (!priv) { + return; + } + this->private = NULL; + + priv->fini = 1; - priv->fini = 1; + if (priv->reaper_thr) { + gf_thread_cleanup_xint(priv->reaper_thr); + priv->reaper_thr = 0; + priv->reaper_init_done = _gf_false; + } - pthread_join (priv->reaper_thr, NULL); + dict_unref(priv->xattrs); + LOCK_DESTROY(&priv->inode_ctx_lk); - LOCK_DESTROY (&priv->inode_ctx_lk); + /* Do we need to cleanup the inode_ctxs? IMO not required + * as inode_forget would have been done on all the inodes + * before calling xlator_fini */ + GF_FREE(priv); - /* Do we need to cleanup the inode_ctxs? IMO not required - * as inode_forget would have been done on all the inodes - * before calling xlator_fini */ - GF_FREE (priv); + if (this->local_pool) { + mem_pool_destroy(this->local_pool); + this->local_pool = NULL; + } - return 0; + return; } int -upcall_forget (xlator_t *this, inode_t *inode) +upcall_forget(xlator_t *this, inode_t *inode) { - upcall_cleanup_inode_ctx (this, inode); - return 0; + upcall_private_t *priv = this->private; + + if (!priv) + goto out; + + upcall_cleanup_inode_ctx(this, inode); +out: + return 0; } int -upcall_release (xlator_t *this, fd_t *fd) +upcall_release(xlator_t *this, fd_t *fd) { - return 0; + return 0; } int -notify (xlator_t *this, int32_t event, void *data, ...) +notify(xlator_t *this, int32_t event, void *data, ...) { - int ret = -1; - int32_t val = 0; - struct gf_upcall *up_req = NULL; + int ret = -1; + struct gf_upcall *up_req = NULL; - switch (event) { - case GF_EVENT_UPCALL: - { - gf_log (this->name, GF_LOG_DEBUG, "Upcall Notify event = %d", - event); + switch (event) { + case GF_EVENT_UPCALL: { + gf_log(this->name, GF_LOG_DEBUG, "Upcall Notify event = %d", event); - up_req = (struct gf_upcall *) data; + up_req = (struct gf_upcall *)data; - GF_VALIDATE_OR_GOTO(this->name, up_req, out); + GF_VALIDATE_OR_GOTO(this->name, up_req, out); - ret = default_notify (this, event, up_req); + ret = default_notify(this, event, up_req); - if (ret) { - gf_msg (this->name, GF_LOG_WARNING, 0, - UPCALL_MSG_NOTIFY_FAILED, - "Failed to notify cache invalidation" - " to client(%s)", - up_req->client_uid); - goto out; - } - } - break; + if (ret) { + gf_msg(this->name, GF_LOG_WARNING, 0, UPCALL_MSG_NOTIFY_FAILED, + "Failed to notify cache invalidation" + " to client(%s)", + up_req->client_uid); + goto out; + } + } break; default: - default_notify (this, event, data); - break; - } - ret = 0; + default_notify(this, event, data); + break; + } + ret = 0; out: - return ret; + return ret; } struct xlator_fops fops = { - /* fops which change only "ATIME" do not result - * in any cache invalidation. Hence upcall - * notifications are not sent in this case. - * But however, we need to store/update the - * client info in the upcall state to be able - * to notify them incase of any changes done - * to the data. - * - * Below such fops do not trigger upcall - * notifications but will add/update - * clients info in the upcall inode ctx.*/ - .lookup = up_lookup, - .open = up_open, - .statfs = up_statfs, - .opendir = up_opendir, - .readdir = up_readdir, - .readdirp = up_readdirp, - .stat = up_stat, - .fstat = up_fstat, - .access = up_access, - .readlink = up_readlink, - .readv = up_readv, - .lk = up_lk, - - /* fops doing write */ - .truncate = up_truncate, - .ftruncate = up_ftruncate, - .writev = up_writev, - .zerofill = up_zerofill, - .fallocate = up_fallocate, - .discard = up_discard, - - /* fops changing attributes */ - .fsetattr = up_fsetattr, - .setattr = up_setattr, - - /* fops affecting parent dirent */ - .mknod = up_mknod, - .create = up_create, - .symlink = up_symlink, - .mkdir = up_mkdir, - - /* fops affecting both file and parent - * cache entries */ - .unlink = up_unlink, - .link = up_link, - .rmdir = up_rmdir, - .rename = up_rename, + .ipc = up_ipc, + /* fops which change only "ATIME" do not result + * in any cache invalidation. Hence upcall + * notifications are not sent in this case. + * But however, we need to store/update the + * client info in the upcall state to be able + * to notify them in case of any changes done + * to the data. + * + * Below such fops do not trigger upcall + * notifications but will add/update + * clients info in the upcall inode ctx.*/ + .lookup = up_lookup, + .open = up_open, + .statfs = up_statfs, + .opendir = up_opendir, + .readdir = up_readdir, + .readdirp = up_readdirp, + .stat = up_stat, + .fstat = up_fstat, + .access = up_access, + .readlink = up_readlink, + .readv = up_readv, + .lk = up_lk, + .seek = up_seek, + + /* fops doing write */ + .truncate = up_truncate, + .ftruncate = up_ftruncate, + .writev = up_writev, + .zerofill = up_zerofill, + .fallocate = up_fallocate, + .discard = up_discard, + + /* fops changing attributes */ + .fsetattr = up_fsetattr, + .setattr = up_setattr, + + /* fops affecting parent dirent */ + .mknod = up_mknod, + .create = up_create, + .symlink = up_symlink, + .mkdir = up_mkdir, + + /* fops affecting both file and parent + * cache entries */ + .unlink = up_unlink, + .link = up_link, + .rmdir = up_rmdir, + .rename = up_rename, + + .setxattr = up_setxattr, + .fsetxattr = up_fsetxattr, + .getxattr = up_getxattr, + .fgetxattr = up_fgetxattr, + .fremovexattr = up_fremovexattr, + .removexattr = up_removexattr, + .xattrop = up_xattrop, + .fxattrop = up_fxattrop, #ifdef NOT_SUPPORTED - /* internal lk fops */ - .inodelk = up_inodelk, - .finodelk = up_finodelk, - .entrylk = up_entrylk, - .fentrylk = up_fentrylk, - - /* Below fops follow 'WRITE' which - * would have already sent upcall - * notifications */ - .flush = up_flush, - .fsync = up_fsync, - .fsyncdir = up_fsyncdir, - - /* XXX: Handle xattr fops (BZ-1211863) */ - .getxattr = up_getxattr, - .fgetxattr = up_fgetxattr, - .fremovexattr = up_fremovexattr, - .removexattr = up_removexattr, - .setxattr = up_setxattr, - .fsetxattr = up_fsetxattr, - .xattrop = up_xattrop, - .fxattrop = up_fxattrop, + /* internal lk fops */ + .inodelk = up_inodelk, + .finodelk = up_finodelk, + .entrylk = up_entrylk, + .fentrylk = up_fentrylk, + + /* Below fops follow 'WRITE' which + * would have already sent upcall + * notifications */ + .flush = up_flush, + .fsync = up_fsync, + .fsyncdir = up_fsyncdir, #endif }; struct xlator_cbks cbks = { - .forget = upcall_forget, - .release = upcall_release, + .forget = upcall_forget, + .release = upcall_release, }; struct volume_options options[] = { - { .key = {"cache-invalidation"}, - .type = GF_OPTION_TYPE_BOOL, - .default_value = "off", - .description = "When \"on\", sends cache-invalidation" - " notifications." - }, - { .key = {"cache-invalidation-timeout"}, - .type = GF_OPTION_TYPE_INT, - .default_value = CACHE_INVALIDATION_TIMEOUT, - .description = "After 'timeout' seconds since the time" - " client accessed any file, cache-invalidation" - " notifications are no longer sent to that client." - }, - { .key = {NULL} }, + { + .key = {"cache-invalidation"}, + .type = GF_OPTION_TYPE_BOOL, + .default_value = "off", + .description = "When \"on\", sends cache-invalidation" + " notifications.", + .op_version = {GD_OP_VERSION_3_7_0}, + .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC, + .tags = {"cache", "cacheconsistency", "upcall"}, + }, + {.key = {"cache-invalidation-timeout"}, + .type = GF_OPTION_TYPE_INT, + .default_value = CACHE_INVALIDATION_TIMEOUT, + .description = "After 'timeout' seconds since the time" + " client accessed any file, cache-invalidation" + " notifications are no longer sent to that client.", + .op_version = {GD_OP_VERSION_3_7_0}, + .flags = OPT_FLAG_SETTABLE | OPT_FLAG_DOC, + .tags = {"cache", "cachetimeout", "upcall"}}, + {.key = {NULL}}, +}; + +xlator_api_t xlator_api = { + .init = init, + .fini = fini, + .notify = notify, + .reconfigure = reconfigure, + .mem_acct_init = mem_acct_init, + .op_version = {1}, /* Present from the initial version */ + .fops = &fops, + .cbks = &cbks, + .options = options, + .identifier = "upcall", + .category = GF_MAINTAINED, }; diff --git a/xlators/features/upcall/src/upcall.h b/xlators/features/upcall/src/upcall.h index 344c9c362eb..aa535088ad7 100644 --- a/xlators/features/upcall/src/upcall.h +++ b/xlators/features/upcall/src/upcall.h @@ -10,119 +10,122 @@ #ifndef __UPCALL_H__ #define __UPCALL_H__ -#include "compat-errno.h" +#include <glusterfs/compat-errno.h> #include "upcall-mem-types.h" -#include "client_t.h" +#include <glusterfs/client_t.h> #include "upcall-messages.h" #include "upcall-cache-invalidation.h" -#include "upcall-utils.h" - -#define EXIT_IF_UPCALL_OFF(this, label) do { \ - if (!is_upcall_enabled(this)) \ - goto label; \ -} while (0) - -#define UPCALL_STACK_UNWIND(fop, frame, params ...) do { \ - upcall_local_t *__local = NULL; \ - xlator_t *__xl = NULL; \ - if (frame) { \ - __xl = frame->this; \ - __local = frame->local; \ - frame->local = NULL; \ - } \ - STACK_UNWIND_STRICT (fop, frame, params); \ - upcall_local_wipe (__xl, __local); \ -} while (0) - -#define UPCALL_STACK_DESTROY(frame) do { \ - upcall_local_t *__local = NULL; \ - xlator_t *__xl = NULL; \ - __xl = frame->this; \ - __local = frame->local; \ - frame->local = NULL; \ - STACK_DESTROY (frame->root); \ - upcall_local_wipe (__xl, __local); \ -} while (0) - -struct _upcall_private_t { - gf_boolean_t cache_invalidation_enabled; - int32_t cache_invalidation_timeout; - struct list_head inode_ctx_list; - gf_lock_t inode_ctx_lk; - int32_t reaper_init_done; - pthread_t reaper_thr; - int32_t fini; +#include <glusterfs/upcall-utils.h> + +#define EXIT_IF_UPCALL_OFF(this, label) \ + do { \ + if (!is_upcall_enabled(this)) \ + goto label; \ + } while (0) + +#define UPCALL_STACK_UNWIND(fop, frame, params...) \ + do { \ + upcall_local_t *__local = NULL; \ + xlator_t *__xl = NULL; \ + if (frame) { \ + __xl = frame->this; \ + __local = frame->local; \ + frame->local = NULL; \ + } \ + STACK_UNWIND_STRICT(fop, frame, params); \ + upcall_local_wipe(__xl, __local); \ + } while (0) + +#define UPCALL_STACK_DESTROY(frame) \ + do { \ + upcall_local_t *__local = NULL; \ + xlator_t *__xl = NULL; \ + __xl = frame->this; \ + __local = frame->local; \ + frame->local = NULL; \ + STACK_DESTROY(frame->root); \ + upcall_local_wipe(__xl, __local); \ + } while (0) + +struct _upcall_private { + gf_boolean_t cache_invalidation_enabled; + int32_t cache_invalidation_timeout; + struct list_head inode_ctx_list; + gf_lock_t inode_ctx_lk; + gf_boolean_t reaper_init_done; + pthread_t reaper_thr; + int32_t fini; + dict_t *xattrs; /* list of xattrs registered by clients + for receiving invalidation */ }; -typedef struct _upcall_private_t upcall_private_t; - -struct _upcall_client_t { - struct list_head client_list; - /* strdup to store client_uid, strdup. Free it explicitly */ - char *client_uid; - time_t access_time; /* time last accessed */ - /* the amount of time which client can cache this entry */ - uint32_t expire_time_attr; +typedef struct _upcall_private upcall_private_t; + +struct _upcall_client { + struct list_head client_list; + /* strdup to store client_uid, strdup. Free it explicitly */ + char *client_uid; + time_t access_time; /* time last accessed */ + /* the amount of time which client can cache this entry */ + uint32_t expire_time_attr; }; -typedef struct _upcall_client_t upcall_client_t; +typedef struct _upcall_client upcall_client_t; /* Upcall entries are maintained in inode_ctx */ -struct _upcall_inode_ctx_t { - struct list_head inode_ctx_list; - struct list_head client_list; - pthread_mutex_t client_list_lock; /* mutex for clients list - of this upcall entry */ - int destroy; - uuid_t gfid; /* gfid of the entry */ +struct _upcall_inode_ctx { + struct list_head inode_ctx_list; + struct list_head client_list; + pthread_mutex_t client_list_lock; /* mutex for clients list + of this upcall entry */ + int destroy; + uuid_t gfid; /* gfid of the entry */ }; -typedef struct _upcall_inode_ctx_t upcall_inode_ctx_t; +typedef struct _upcall_inode_ctx upcall_inode_ctx_t; struct upcall_local { - /* XXX: need to check if we can store - * pointers in 'local' which may get freed - * in future by other thread - */ - upcall_inode_ctx_t *upcall_inode_ctx; - inode_t *inode; - loc_t rename_oldloc; + /* XXX: need to check if we can store + * pointers in 'local' which may get freed + * in future by other thread + */ + inode_t *inode; + loc_t rename_oldloc; + loc_t loc; /* required for stat in *xattr_cbk */ + fd_t *fd; /* required for fstat in *xattr_cbk */ + dict_t *xattr; }; typedef struct upcall_local upcall_local_t; -void upcall_local_wipe (xlator_t *this, upcall_local_t *local); -upcall_local_t *upcall_local_init (call_frame_t *frame, xlator_t *this, inode_t *inode); - -upcall_client_t *add_upcall_client (call_frame_t *frame, client_t *client, - upcall_inode_ctx_t *up_inode_ctx); -upcall_client_t *__add_upcall_client (call_frame_t *frame, client_t *client, - upcall_inode_ctx_t *up_inode_ctx); -upcall_client_t *__get_upcall_client (call_frame_t *frame, client_t *client, - upcall_inode_ctx_t *up_inode_ctx); -int __upcall_cleanup_client_entry (upcall_client_t *up_client); -int upcall_cleanup_expired_clients (xlator_t *this, - upcall_inode_ctx_t *up_inode_ctx); - -int __upcall_inode_ctx_set (inode_t *inode, xlator_t *this); -upcall_inode_ctx_t *__upcall_inode_ctx_get (inode_t *inode, xlator_t *this); -upcall_inode_ctx_t *upcall_inode_ctx_get (inode_t *inode, xlator_t *this); -int upcall_cleanup_inode_ctx (xlator_t *this, inode_t *inode); -void upcall_cache_forget (xlator_t *this, inode_t *inode, - upcall_inode_ctx_t *up_inode_ctx); - -void *upcall_reaper_thread (void *data); -int upcall_reaper_thread_init (xlator_t *this); +void +upcall_local_wipe(xlator_t *this, upcall_local_t *local); +upcall_local_t * +upcall_local_init(call_frame_t *frame, xlator_t *this, loc_t *loc, fd_t *fd, + inode_t *inode, dict_t *xattr); + +upcall_inode_ctx_t * +upcall_inode_ctx_get(inode_t *inode, xlator_t *this); +int +upcall_cleanup_inode_ctx(xlator_t *this, inode_t *inode); + +void * +upcall_reaper_thread(void *data); +int +upcall_reaper_thread_init(xlator_t *this); /* Xlator options */ -gf_boolean_t is_upcall_enabled(xlator_t *this); +gf_boolean_t +is_upcall_enabled(xlator_t *this); /* Cache invalidation specific */ -void upcall_cache_invalidate (call_frame_t *frame, xlator_t *this, - client_t *client, inode_t *inode, - uint32_t flags, struct iatt *stbuf, - struct iatt *p_stbuf, - struct iatt *oldp_stbuf); -void upcall_client_cache_invalidate (xlator_t *xl, uuid_t gfid, - upcall_client_t *up_client_entry, - uint32_t flags, struct iatt *stbuf, - struct iatt *p_stbuf, - struct iatt *oldp_stbuf); - +void +upcall_cache_invalidate(call_frame_t *frame, xlator_t *this, client_t *client, + inode_t *inode, uint32_t flags, struct iatt *stbuf, + struct iatt *p_stbuf, struct iatt *oldp_stbuf, + dict_t *xattr); +int +up_filter_xattr(dict_t *xattr, dict_t *regd_xattrs); + +int +up_compare_afr_xattr(dict_t *d, char *k, data_t *v, void *tmp); + +gf_boolean_t +up_invalidate_needed(dict_t *xattrs); #endif /* __UPCALL_H__ */ |
