3604df
From 63da5ccc4905c89dbd831dbd0efe47d5832cfd50 Mon Sep 17 00:00:00 2001
3604df
From: Poornima G <pgurusid@redhat.com>
3604df
Date: Wed, 16 Dec 2015 05:45:03 -0500
3604df
Subject: [PATCH 112/141] upcall: pass dict with xattrs on xattr invalidation
3604df
3604df
In case of xattr invalidation, return a dict containing
3604df
the updated xattrs.
3604df
3604df
[ndevos: move chunks to change 12995 and only address the xattrs-dict here]
3604df
3604df
Conflicts while backporting:
3604df
        libglusterfs/src/common-utils.c
3604df
        libglusterfs/src/common-utils.h
3604df
        xlators/protocol/server/src/server.c
3604df
3604df
Change-Id: I8733f06a519a9a0f24be1bb4b2c38c9c9dce0ce2
3604df
BUG: 1284873
3604df
Signed-off-by: Poornima G <pgurusid@redhat.com>
3604df
Reviewed-on: http://review.gluster.org/12996
3604df
Smoke: Gluster Build System <jenkins@build.gluster.com>
3604df
CentOS-regression: Gluster Build System <jenkins@build.gluster.com>
3604df
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
3604df
Reviewed-by: Niels de Vos <ndevos@redhat.com>
3604df
Reviewed-by: soumya k <skoduri@redhat.com>
3604df
Tested-by: soumya k <skoduri@redhat.com>
3604df
Reviewed-on: https://code.engineering.redhat.com/gerrit/87025
3604df
Reviewed-by: Rajesh Joseph <rjoseph@redhat.com>
3604df
Tested-by: Rajesh Joseph <rjoseph@redhat.com>
3604df
---
3604df
 libglusterfs/src/common-utils.c               |   34 +++++
3604df
 libglusterfs/src/common-utils.h               |    3 +
3604df
 libglusterfs/src/upcall-utils.h               |    1 +
3604df
 rpc/xdr/src/glusterfs3.h                      |   44 ++++--
3604df
 xlators/features/upcall/src/upcall-internal.c |   23 +++-
3604df
 xlators/features/upcall/src/upcall.c          |  188 ++++++++++++++++---------
3604df
 xlators/features/upcall/src/upcall.h          |   10 +-
3604df
 xlators/protocol/client/src/client-callback.c |   12 ++-
3604df
 xlators/protocol/server/src/server.c          |    9 +-
3604df
 9 files changed, 229 insertions(+), 95 deletions(-)
3604df
3604df
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c
3604df
index 0ee956c..d36069f 100644
3604df
--- a/libglusterfs/src/common-utils.c
3604df
+++ b/libglusterfs/src/common-utils.c
3604df
@@ -36,6 +36,7 @@
3604df
 #endif
3604df
 #include <libgen.h>
3604df
 
3604df
+#include "glusterfs-acl.h"
3604df
 #include "compat-errno.h"
3604df
 #include "logging.h"
3604df
 #include "common-utils.h"
3604df
@@ -4572,3 +4573,36 @@ gf_bits_index (uint64_t n)
3604df
 {
3604df
     return ffsll(n) - 1;
3604df
 }
3604df
+
3604df
+/* This function checks if the input key is a virtual or on disk xattr.
3604df
+ * Its not simple to identify a virtual xattr as there is no common
3604df
+ * format used to identify virtual xattrs. One way is to list each of the
3604df
+ * xattrs in different categories and compare the input against every xattr
3604df
+ * in the list, this is very inefficient as there are 100s of xattrs.
3604df
+ *
3604df
+ * Currently the only consumer of this function is upcall and md-cache,
3604df
+ * hence tailoring this function to their needs; in their case its allowed
3604df
+ * to consider disk xattrs as virtual xattrs, but not vice versa, i.e.
3604df
+ * virtual xattrs should not be considered as on disk xattr. Hence, being
3604df
+ * conservative, we consider anything that starts from user.*, security.*,
3604df
+ * system.* as on disk xattrs. trusted.* and glusterfs.* cannot be considered
3604df
+ * as virtual xattrs as there are some on disk xattrs which start from
3604df
+ * glusterfs.* and trusted.*
3604df
+ *
3604df
+ * Hence, this function could return an on disk xattr as virtual xattr but
3604df
+ * never a virtual xattr as on disk xattr.
3604df
+ */
3604df
+gf_boolean_t
3604df
+is_virtual_xattr (const char *k)
3604df
+{
3604df
+        gf_boolean_t ret = _gf_true;
3604df
+
3604df
+        if ((strncmp (k, "user.", strlen ("user.")) == 0) ||
3604df
+            (strncmp (k, "security.", strlen ("security.")) == 0) ||
3604df
+            (strncmp (k, "system.", strlen ("system.")) == 0) ||
3604df
+            (GF_POSIX_ACL_REQUEST (k))) {
3604df
+                ret = _gf_false;
3604df
+        }
3604df
+
3604df
+        return ret;
3604df
+}
3604df
diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h
3604df
index 3aecc02..56e8b42 100644
3604df
--- a/libglusterfs/src/common-utils.h
3604df
+++ b/libglusterfs/src/common-utils.h
3604df
@@ -844,6 +844,9 @@ void
3604df
 gf_zero_fill_stat (struct iatt *buf);
3604df
 
3604df
 gf_boolean_t
3604df
+is_virtual_xattr (const char *k);
3604df
+
3604df
+gf_boolean_t
3604df
 gf_is_valid_xattr_namespace (char *k);
3604df
 
3604df
 const char *
3604df
diff --git a/libglusterfs/src/upcall-utils.h b/libglusterfs/src/upcall-utils.h
3604df
index 614276f..f4b15e3 100644
3604df
--- a/libglusterfs/src/upcall-utils.h
3604df
+++ b/libglusterfs/src/upcall-utils.h
3604df
@@ -74,6 +74,7 @@ struct gf_upcall_cache_invalidation {
3604df
         struct iatt stat;
3604df
         struct iatt p_stat; /* parent dir stat */
3604df
         struct iatt oldp_stat; /* oldparent dir stat */
3604df
+        dict_t *dict; /* For xattrs */
3604df
 };
3604df
 
3604df
 struct gf_upcall_recall_lease {
3604df
diff --git a/rpc/xdr/src/glusterfs3.h b/rpc/xdr/src/glusterfs3.h
3604df
index 57a289b..1977b48 100644
3604df
--- a/rpc/xdr/src/glusterfs3.h
3604df
+++ b/rpc/xdr/src/glusterfs3.h
3604df
@@ -341,23 +341,24 @@ gf_stat_from_iatt (struct gf_iatt *gf_stat, struct iatt *iatt)
3604df
 	gf_stat->ia_ctime_nsec = iatt->ia_ctime_nsec ;
3604df
 }
3604df
 
3604df
-static inline void
3604df
-gf_proto_cache_invalidation_from_upcall (gfs3_cbk_cache_invalidation_req *gf_c_req,
3604df
+static inline int
3604df
+gf_proto_cache_invalidation_from_upcall (xlator_t *this,
3604df
+                                         gfs3_cbk_cache_invalidation_req *gf_c_req,
3604df
                                          struct gf_upcall *gf_up_data)
3604df
 {
3604df
         struct gf_upcall_cache_invalidation *gf_c_data = NULL;
3604df
         int    is_cache_inval                          = 0;
3604df
         int    ret                                     = -1;
3604df
 
3604df
-        GF_VALIDATE_OR_GOTO(THIS->name, gf_c_req, out);
3604df
-        GF_VALIDATE_OR_GOTO(THIS->name, gf_up_data, out);
3604df
+        GF_VALIDATE_OR_GOTO(this->name, gf_c_req, out);
3604df
+        GF_VALIDATE_OR_GOTO(this->name, gf_up_data, out);
3604df
 
3604df
         is_cache_inval = ((gf_up_data->event_type ==
3604df
                           GF_UPCALL_CACHE_INVALIDATION) ? 1 : 0);
3604df
-        GF_VALIDATE_OR_GOTO(THIS->name, is_cache_inval, out);
3604df
+        GF_VALIDATE_OR_GOTO(this->name, is_cache_inval, out);
3604df
 
3604df
         gf_c_data = (struct gf_upcall_cache_invalidation *)gf_up_data->data;
3604df
-        GF_VALIDATE_OR_GOTO(THIS->name, gf_c_data, out);
3604df
+        GF_VALIDATE_OR_GOTO(this->name, gf_c_data, out);
3604df
 
3604df
         gf_c_req->gfid = uuid_utoa (gf_up_data->gfid);
3604df
         gf_c_req->event_type       = gf_up_data->event_type;
3604df
@@ -367,29 +368,35 @@ gf_proto_cache_invalidation_from_upcall (gfs3_cbk_cache_invalidation_req *gf_c_r
3604df
         gf_stat_from_iatt (&gf_c_req->parent_stat, &gf_c_data->p_stat);
3604df
         gf_stat_from_iatt (&gf_c_req->oldparent_stat, &gf_c_data->oldp_stat);
3604df
 
3604df
+        ret = 0;
3604df
+        GF_PROTOCOL_DICT_SERIALIZE (this, gf_c_data->dict, &(gf_c_req->xdata).xdata_val,
3604df
+                                    (gf_c_req->xdata).xdata_len, ret, out);
3604df
+        if (ret > 0)
3604df
+                ret = -ret;
3604df
 out:
3604df
-        return;
3604df
+        return ret;
3604df
 }
3604df
 
3604df
-static inline void
3604df
-gf_proto_cache_invalidation_to_upcall (gfs3_cbk_cache_invalidation_req *gf_c_req,
3604df
+static inline int
3604df
+gf_proto_cache_invalidation_to_upcall (xlator_t *this,
3604df
+                                       gfs3_cbk_cache_invalidation_req *gf_c_req,
3604df
                                        struct gf_upcall *gf_up_data)
3604df
 {
3604df
         struct gf_upcall_cache_invalidation *gf_c_data = NULL;
3604df
         int    ret                                     = -1;
3604df
 
3604df
-        GF_VALIDATE_OR_GOTO(THIS->name, gf_c_req, out);
3604df
-        GF_VALIDATE_OR_GOTO(THIS->name, gf_up_data, out);
3604df
+        GF_VALIDATE_OR_GOTO(this->name, gf_c_req, out);
3604df
+        GF_VALIDATE_OR_GOTO(this->name, gf_up_data, out);
3604df
 
3604df
         gf_c_data = (struct gf_upcall_cache_invalidation *)gf_up_data->data;
3604df
-        GF_VALIDATE_OR_GOTO(THIS->name, gf_c_data, out);
3604df
+        GF_VALIDATE_OR_GOTO(this->name, gf_c_data, out);
3604df
 
3604df
         ret = gf_uuid_parse (gf_c_req->gfid, gf_up_data->gfid);
3604df
         if (ret) {
3604df
-                gf_log (THIS->name, GF_LOG_WARNING, "gf_uuid_parse(%s) failed",
3604df
+                gf_log (this->name, GF_LOG_WARNING, "gf_uuid_parse(%s) failed",
3604df
                         gf_c_req->gfid);
3604df
                 gf_up_data->event_type = GF_UPCALL_EVENT_NULL;
3604df
-                return;
3604df
+                goto out;
3604df
         }
3604df
 
3604df
         gf_up_data->event_type      = gf_c_req->event_type;
3604df
@@ -400,7 +407,14 @@ gf_proto_cache_invalidation_to_upcall (gfs3_cbk_cache_invalidation_req *gf_c_req
3604df
         gf_stat_to_iatt (&gf_c_req->parent_stat, &gf_c_data->p_stat);
3604df
         gf_stat_to_iatt (&gf_c_req->oldparent_stat, &gf_c_data->oldp_stat);
3604df
 
3604df
+        ret = 0;
3604df
+        GF_PROTOCOL_DICT_UNSERIALIZE (this, gf_c_data->dict,
3604df
+                                      (gf_c_req->xdata).xdata_val,
3604df
+                                      (gf_c_req->xdata).xdata_len, ret,
3604df
+                                      ret, out);
3604df
+        if (ret > 0)
3604df
+                ret = -ret;
3604df
 out:
3604df
-        return;
3604df
+        return ret;
3604df
 }
3604df
 #endif /* !_GLUSTERFS3_H */
3604df
diff --git a/xlators/features/upcall/src/upcall-internal.c b/xlators/features/upcall/src/upcall-internal.c
3604df
index f9005df..f3c81af 100644
3604df
--- a/xlators/features/upcall/src/upcall-internal.c
3604df
+++ b/xlators/features/upcall/src/upcall-internal.c
3604df
@@ -435,6 +435,16 @@ upcall_reaper_thread_init (xlator_t *this)
3604df
         return ret;
3604df
 }
3604df
 
3604df
+int
3604df
+up_filter_virtual_xattr (dict_t *d, char *k, data_t *v, void *tmp)
3604df
+{
3604df
+        if (is_virtual_xattr (k) == _gf_true) {
3604df
+                dict_del (d, k);
3604df
+        }
3604df
+
3604df
+        return 0;
3604df
+}
3604df
+
3604df
 /*
3604df
  * Given a client, first fetch upcall_entry_t from the inode_ctx client list.
3604df
  * Later traverse through the client list of that upcall entry. If this client
3604df
@@ -448,7 +458,8 @@ upcall_reaper_thread_init (xlator_t *this)
3604df
 void
3604df
 upcall_cache_invalidate (call_frame_t *frame, xlator_t *this, client_t *client,
3604df
                          inode_t *inode, uint32_t flags, struct iatt *stbuf,
3604df
-                         struct iatt *p_stbuf, struct iatt *oldp_stbuf)
3604df
+                         struct iatt *p_stbuf, struct iatt *oldp_stbuf,
3604df
+                         dict_t *xattr)
3604df
 {
3604df
         upcall_client_t *up_client       = NULL;
3604df
         upcall_client_t *up_client_entry = NULL;
3604df
@@ -524,11 +535,12 @@ upcall_cache_invalidate (call_frame_t *frame, xlator_t *this, client_t *client,
3604df
                          *  Also if the file is frequently accessed, set
3604df
                          *  expire_time_attr to 0.
3604df
                          */
3604df
-                        upcall_client_cache_invalidate(this,
3604df
+                        upcall_client_cache_invalidate (this,
3604df
                                                        up_inode_ctx->gfid,
3604df
                                                        up_client_entry,
3604df
                                                        flags, stbuf,
3604df
-                                                       p_stbuf, oldp_stbuf);
3604df
+                                                       p_stbuf, oldp_stbuf,
3604df
+                                                       xattr);
3604df
                 }
3604df
 
3604df
                 if (!found) {
3604df
@@ -551,7 +563,7 @@ upcall_client_cache_invalidate (xlator_t *this, uuid_t gfid,
3604df
                                 upcall_client_t *up_client_entry,
3604df
                                 uint32_t flags, struct iatt *stbuf,
3604df
                                 struct iatt *p_stbuf,
3604df
-                                struct iatt *oldp_stbuf)
3604df
+                                struct iatt *oldp_stbuf, dict_t *xattr)
3604df
 {
3604df
         struct gf_upcall                    up_req  = {0,};
3604df
         struct gf_upcall_cache_invalidation ca_req  = {0,};
3604df
@@ -577,6 +589,7 @@ upcall_client_cache_invalidate (xlator_t *this, uuid_t gfid,
3604df
                         ca_req.p_stat = *p_stbuf;
3604df
                 if (oldp_stbuf)
3604df
                         ca_req.oldp_stat = *oldp_stbuf;
3604df
+                ca_req.dict = xattr;
3604df
 
3604df
                 up_req.data = &ca_req;
3604df
                 up_req.event_type = GF_UPCALL_CACHE_INVALIDATION;
3604df
@@ -641,7 +654,7 @@ upcall_cache_forget (xlator_t *this, inode_t *inode, upcall_inode_ctx_t *up_inod
3604df
                                                        up_inode_ctx->gfid,
3604df
                                                        up_client_entry,
3604df
                                                        flags, NULL,
3604df
-                                                       NULL, NULL);
3604df
+                                                       NULL, NULL, NULL);
3604df
                 }
3604df
 
3604df
         }
3604df
diff --git a/xlators/features/upcall/src/upcall.c b/xlators/features/upcall/src/upcall.c
3604df
index ce3bd4e..4ae0ab0 100644
3604df
--- a/xlators/features/upcall/src/upcall.c
3604df
+++ b/xlators/features/upcall/src/upcall.c
3604df
@@ -47,7 +47,7 @@ up_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = UP_UPDATE_CLIENT;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 NULL, NULL, NULL);
3604df
+                                 NULL, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (open, frame, op_ret, op_errno, fd, xdata);
3604df
@@ -65,7 +65,7 @@ up_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, fd->inode);
3604df
+        local = upcall_local_init (frame, this, fd->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -101,7 +101,7 @@ up_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = UP_WRITE_FLAGS;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 postbuf, NULL, NULL);
3604df
+                                 postbuf, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (writev, frame, op_ret, op_errno,
3604df
@@ -121,7 +121,7 @@ up_writev (call_frame_t *frame, xlator_t *this, fd_t *fd,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, fd->inode);
3604df
+        local = upcall_local_init (frame, this, fd->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -161,7 +161,7 @@ up_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = UP_UPDATE_CLIENT;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 stbuf, NULL, NULL);
3604df
+                                 stbuf, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (readv, frame, op_ret, op_errno, vector,
3604df
@@ -180,7 +180,7 @@ up_readv (call_frame_t *frame, xlator_t *this,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, fd->inode);
3604df
+        local = upcall_local_init (frame, this, fd->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -219,7 +219,7 @@ up_lk_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = UP_UPDATE_CLIENT;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 NULL, NULL, NULL);
3604df
+                                 NULL, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (lk, frame, op_ret, op_errno, lock, xdata);
3604df
@@ -236,7 +236,7 @@ up_lk (call_frame_t *frame, xlator_t *this,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, fd->inode);
3604df
+        local = upcall_local_init (frame, this, fd->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -273,7 +273,7 @@ up_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = UP_WRITE_FLAGS;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 postbuf, NULL, NULL);
3604df
+                                 postbuf, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (truncate, frame, op_ret, op_errno,
3604df
@@ -291,7 +291,7 @@ up_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->inode);
3604df
+        local = upcall_local_init (frame, this, loc->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -334,7 +334,7 @@ up_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
          */
3604df
         flags = UP_ATTR_FLAGS;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 statpost, NULL, NULL);
3604df
+                                 statpost, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (setattr, frame, op_ret, op_errno,
3604df
@@ -352,7 +352,7 @@ up_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->inode);
3604df
+        local = upcall_local_init (frame, this, loc->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -393,7 +393,7 @@ up_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = (UP_RENAME_FLAGS | UP_PARENT_DENTRY_FLAGS);
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 stbuf, postnewparent, postoldparent);
3604df
+                                 stbuf, postnewparent, postoldparent, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (rename, frame, op_ret, op_errno,
3604df
@@ -412,7 +412,7 @@ up_rename (call_frame_t *frame, xlator_t *this,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, oldloc->inode);
3604df
+        local = upcall_local_init (frame, this, oldloc->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -453,7 +453,7 @@ up_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = (UP_NLINK_FLAGS | UP_PARENT_DENTRY_FLAGS);
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 NULL, postparent, NULL);
3604df
+                                 NULL, postparent, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (unlink, frame, op_ret, op_errno,
3604df
@@ -471,7 +471,7 @@ up_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->inode);
3604df
+        local = upcall_local_init (frame, this, loc->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -509,7 +509,7 @@ up_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = (UP_NLINK_FLAGS | UP_PARENT_DENTRY_FLAGS);
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 stbuf, postparent, NULL);
3604df
+                                 stbuf, postparent, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (link, frame, op_ret, op_errno,
3604df
@@ -527,7 +527,7 @@ up_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, oldloc->inode);
3604df
+        local = upcall_local_init (frame, this, oldloc->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -567,7 +567,7 @@ up_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
 
3604df
         flags = (UP_NLINK_FLAGS | UP_PARENT_DENTRY_FLAGS);
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 NULL, postparent, NULL);
3604df
+                                 NULL, postparent, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (rmdir, frame, op_ret, op_errno,
3604df
@@ -585,7 +585,7 @@ up_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->inode);
3604df
+        local = upcall_local_init (frame, this, loc->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -626,7 +626,7 @@ up_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         /* invalidate parent's entry too */
3604df
         flags = UP_TIMES;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 postparent, NULL, NULL);
3604df
+                                 postparent, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (mkdir, frame, op_ret, op_errno,
3604df
@@ -644,7 +644,7 @@ up_mkdir (call_frame_t *frame, xlator_t *this,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->parent);
3604df
+        local = upcall_local_init (frame, this, loc->parent, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -687,7 +687,7 @@ up_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         /* However invalidate parent's entry */
3604df
         flags = UP_TIMES;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 postparent, NULL, NULL);
3604df
+                                 postparent, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (create, frame, op_ret, op_errno, fd,
3604df
@@ -706,7 +706,7 @@ up_create (call_frame_t *frame, xlator_t *this,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->parent);
3604df
+        local = upcall_local_init (frame, this, loc->parent, NULL);
3604df
 
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
@@ -747,7 +747,7 @@ up_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = UP_UPDATE_CLIENT;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 stbuf, NULL, NULL);
3604df
+                                 stbuf, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (lookup, frame, op_ret, op_errno, inode, stbuf,
3604df
@@ -765,7 +765,7 @@ up_lookup (call_frame_t *frame, xlator_t *this,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->inode);
3604df
+        local = upcall_local_init (frame, this, loc->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -804,7 +804,7 @@ up_stat_cbk (call_frame_t *frame, void *cookie,
3604df
         }
3604df
         flags = UP_UPDATE_CLIENT;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 buf, NULL, NULL);
3604df
+                                 buf, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (stat, frame, op_ret, op_errno, buf,
3604df
@@ -821,7 +821,7 @@ up_stat (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata)
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->inode);
3604df
+        local = upcall_local_init (frame, this, loc->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -849,7 +849,7 @@ up_fstat (call_frame_t *frame, xlator_t *this,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, fd->inode);
3604df
+        local = upcall_local_init (frame, this, fd->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -877,7 +877,7 @@ up_ftruncate (call_frame_t *frame, xlator_t *this,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, fd->inode);
3604df
+        local = upcall_local_init (frame, this, fd->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -915,7 +915,7 @@ up_access_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = UP_UPDATE_CLIENT;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 NULL, NULL, NULL);
3604df
+                                 NULL, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (access, frame, op_ret, op_errno, xdata);
3604df
@@ -932,7 +932,7 @@ up_access (call_frame_t *frame, xlator_t *this,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->inode);
3604df
+        local = upcall_local_init (frame, this, loc->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -970,7 +970,7 @@ up_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = UP_UPDATE_CLIENT;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 stbuf, NULL, NULL);
3604df
+                                 stbuf, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (readlink, frame, op_ret, op_errno, path, stbuf,
3604df
@@ -988,7 +988,7 @@ up_readlink (call_frame_t *frame, xlator_t *this,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->inode);
3604df
+        local = upcall_local_init (frame, this, loc->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1030,7 +1030,7 @@ up_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         /* invalidate parent's entry too */
3604df
         flags = UP_TIMES;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 postparent, NULL, NULL);
3604df
+                                 postparent, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (mknod, frame, op_ret, op_errno, inode, buf,
3604df
@@ -1048,7 +1048,7 @@ up_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->parent);
3604df
+        local = upcall_local_init (frame, this, loc->parent, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1090,7 +1090,7 @@ up_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         /* invalidate parent's entry too */
3604df
         flags = UP_TIMES;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 postparent, NULL, NULL);
3604df
+                                 postparent, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (symlink, frame, op_ret, op_errno, inode, buf,
3604df
@@ -1109,7 +1109,7 @@ up_symlink (call_frame_t   *frame, xlator_t *this,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->parent);
3604df
+        local = upcall_local_init (frame, this, loc->parent, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1148,7 +1148,7 @@ up_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = UP_UPDATE_CLIENT;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 NULL, NULL, NULL);
3604df
+                                 NULL, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (opendir, frame, op_ret, op_errno, fd, xdata);
3604df
@@ -1165,7 +1165,7 @@ up_opendir (call_frame_t *frame, xlator_t *this,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->inode);
3604df
+        local = upcall_local_init (frame, this, loc->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1203,7 +1203,7 @@ up_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = UP_UPDATE_CLIENT;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 NULL, NULL, NULL);
3604df
+                                 NULL, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (statfs, frame, op_ret, op_errno, buf, xdata);
3604df
@@ -1220,7 +1220,7 @@ up_statfs (call_frame_t *frame, xlator_t *this,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->inode);
3604df
+        local = upcall_local_init (frame, this, loc->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1258,7 +1258,7 @@ up_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = UP_UPDATE_CLIENT;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 NULL, NULL, NULL);
3604df
+                                 NULL, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (readdir, frame, op_ret, op_errno, entries, xdata);
3604df
@@ -1275,7 +1275,7 @@ up_readdir (call_frame_t  *frame, xlator_t *this,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, fd->inode);
3604df
+        local = upcall_local_init (frame, this, fd->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1303,7 +1303,7 @@ up_readdirp (call_frame_t *frame, xlator_t *this,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, fd->inode);
3604df
+        local = upcall_local_init (frame, this, fd->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1331,7 +1331,7 @@ up_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, fd->inode);
3604df
+        local = upcall_local_init (frame, this, fd->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1370,7 +1370,7 @@ up_fallocate_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = UP_WRITE_FLAGS;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 post, NULL, NULL);
3604df
+                                 post, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (fallocate, frame, op_ret, op_errno, pre,
3604df
@@ -1388,7 +1388,7 @@ up_fallocate(call_frame_t *frame, xlator_t *this, fd_t *fd,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, fd->inode);
3604df
+        local = upcall_local_init (frame, this, fd->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1427,7 +1427,7 @@ up_discard_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = UP_WRITE_FLAGS;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 post, NULL, NULL);
3604df
+                                 post, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (discard, frame, op_ret, op_errno, pre,
3604df
@@ -1445,7 +1445,7 @@ up_discard(call_frame_t *frame, xlator_t *this, fd_t *fd,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, fd->inode);
3604df
+        local = upcall_local_init (frame, this, fd->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1484,7 +1484,7 @@ up_zerofill_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = UP_WRITE_FLAGS;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 post, NULL, NULL);
3604df
+                                 post, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (zerofill, frame, op_ret, op_errno, pre,
3604df
@@ -1502,7 +1502,7 @@ up_zerofill(call_frame_t *frame, xlator_t *this, fd_t *fd,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, fd->inode);
3604df
+        local = upcall_local_init (frame, this, fd->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1541,7 +1541,7 @@ up_seek_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int op_ret,
3604df
         }
3604df
         flags = UP_UPDATE_CLIENT;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 NULL, NULL, NULL);
3604df
+                                 NULL, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (seek, frame, op_ret, op_errno, offset, xdata);
3604df
@@ -1559,7 +1559,7 @@ up_seek (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, fd->inode);
3604df
+        local = upcall_local_init (frame, this, fd->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1585,6 +1585,7 @@ up_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         client_t         *client        = NULL;
3604df
         uint32_t         flags          = 0;
3604df
         upcall_local_t   *local         = NULL;
3604df
+        int              ret            = 0;
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
@@ -1596,8 +1597,14 @@ up_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
 
3604df
         flags = UP_XATTR;
3604df
+        /* Remove the virtual xattrs from the dict */
3604df
+        ret = dict_foreach (local->xattr, up_filter_virtual_xattr, NULL);
3604df
+        if (ret < 0) {
3604df
+                op_ret = ret;
3604df
+                goto out;
3604df
+        }
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 NULL, NULL, NULL);
3604df
+                                 NULL, NULL, NULL, local->xattr);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (setxattr, frame, op_ret, op_errno, xdata);
3604df
@@ -1612,10 +1619,17 @@ up_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict,
3604df
 {
3604df
         int32_t          op_errno        = -1;
3604df
         upcall_local_t   *local          = NULL;
3604df
+        dict_t           *xattr          = NULL;
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->inode);
3604df
+        xattr = dict_copy_with_ref (dict, NULL);
3604df
+        if (!xattr) {
3604df
+                op_errno = ENOMEM;
3604df
+                goto err;
3604df
+        }
3604df
+
3604df
+        local = upcall_local_init (frame, this, loc->inode, xattr);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1642,6 +1656,7 @@ up_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         client_t         *client        = NULL;
3604df
         uint32_t         flags          = 0;
3604df
         upcall_local_t   *local         = NULL;
3604df
+        int              ret            = 0;
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
@@ -1653,8 +1668,14 @@ up_fsetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
 
3604df
         flags = UP_XATTR;
3604df
+        /* Remove the virtual xattrs from the dict */
3604df
+        ret = dict_foreach (local->xattr, up_filter_virtual_xattr, NULL);
3604df
+        if (ret < 0) {
3604df
+                op_ret = ret;
3604df
+                goto out;
3604df
+        }
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 NULL, NULL, NULL);
3604df
+                                 NULL, NULL, NULL, local->xattr);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (fsetxattr, frame, op_ret, op_errno, xdata);
3604df
@@ -1669,10 +1690,17 @@ up_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict,
3604df
 {
3604df
         int32_t          op_errno        = -1;
3604df
         upcall_local_t   *local          = NULL;
3604df
+        dict_t           *xattr          = NULL;
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, fd->inode);
3604df
+        xattr = dict_copy_with_ref (dict, NULL);
3604df
+        if (!xattr) {
3604df
+                op_errno = ENOMEM;
3604df
+                goto err;
3604df
+        }
3604df
+
3604df
+        local = upcall_local_init (frame, this, fd->inode, xattr);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1710,7 +1738,7 @@ up_fremovexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = UP_XATTR_RM;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 NULL, NULL, NULL);
3604df
+                                 NULL, NULL, NULL, local->xattr);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (fremovexattr, frame, op_ret, op_errno,
3604df
@@ -1718,16 +1746,24 @@ out:
3604df
         return 0;
3604df
 }
3604df
 
3604df
+
3604df
 int32_t
3604df
 up_fremovexattr (call_frame_t *frame, xlator_t *this, fd_t *fd,
3604df
                  const char *name, dict_t *xdata)
3604df
 {
3604df
         int32_t          op_errno        = -1;
3604df
         upcall_local_t   *local          = NULL;
3604df
+        dict_t           *xattr          = NULL;
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, fd->inode);
3604df
+        xattr = dict_for_key_value (name, "", 1);
3604df
+        if (!xattr) {
3604df
+                op_errno = ENOMEM;
3604df
+                goto err;
3604df
+        }
3604df
+
3604df
+        local = upcall_local_init (frame, this, fd->inode, xattr);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1745,6 +1781,7 @@ err:
3604df
         return 0;
3604df
 }
3604df
 
3604df
+
3604df
 int32_t
3604df
 up_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
                     int32_t op_ret, int32_t op_errno, dict_t *xdata)
3604df
@@ -1763,7 +1800,7 @@ up_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
         }
3604df
         flags = UP_XATTR_RM;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 NULL, NULL, NULL);
3604df
+                                 NULL, NULL, NULL, local->xattr);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (removexattr, frame, op_ret, op_errno,
3604df
@@ -1771,16 +1808,24 @@ out:
3604df
         return 0;
3604df
 }
3604df
 
3604df
+
3604df
 int32_t
3604df
 up_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
3604df
                 const char *name, dict_t *xdata)
3604df
 {
3604df
         int32_t          op_errno        = -1;
3604df
         upcall_local_t   *local          = NULL;
3604df
+        dict_t           *xattr          = NULL;
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->inode);
3604df
+        xattr = dict_for_key_value (name, "", 1);
3604df
+        if (!xattr) {
3604df
+                op_errno = ENOMEM;
3604df
+                goto err;
3604df
+        }
3604df
+
3604df
+        local = upcall_local_init (frame, this, loc->inode, xattr);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1819,7 +1864,7 @@ up_fgetxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
 
3604df
         flags = UP_UPDATE_CLIENT;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 NULL, NULL, NULL);
3604df
+                                 NULL, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (fgetxattr, frame, op_ret, op_errno,
3604df
@@ -1837,7 +1882,7 @@ up_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, fd->inode);
3604df
+        local = upcall_local_init (frame, this, fd->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1875,7 +1920,7 @@ up_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
3604df
 
3604df
         flags = UP_UPDATE_CLIENT;
3604df
         upcall_cache_invalidate (frame, this, client, local->inode, flags,
3604df
-                                 NULL, NULL, NULL);
3604df
+                                 NULL, NULL, NULL, NULL);
3604df
 
3604df
 out:
3604df
         UPCALL_STACK_UNWIND (getxattr, frame, op_ret, op_errno,
3604df
@@ -1892,7 +1937,7 @@ up_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
3604df
 
3604df
         EXIT_IF_UPCALL_OFF (this, out);
3604df
 
3604df
-        local = upcall_local_init (frame, this, loc->inode);
3604df
+        local = upcall_local_init (frame, this, loc->inode, NULL);
3604df
         if (!local) {
3604df
                 op_errno = ENOMEM;
3604df
                 goto err;
3604df
@@ -1935,13 +1980,20 @@ upcall_local_wipe (xlator_t *this, upcall_local_t *local)
3604df
 {
3604df
         if (local) {
3604df
                 inode_unref (local->inode);
3604df
+                if (local->xattr) {
3604df
+                        /* There will be 2 refs at this point, hence dict_destroy:
3604df
+                         * 1. taken by dict_copy_with_ref
3604df
+                         * 2. taken by upcall_local_init ()
3604df
+                         */
3604df
+                        dict_destroy (local->xattr);
3604df
+                }
3604df
                 loc_wipe (&local->rename_oldloc);
3604df
                 mem_put (local);
3604df
         }
3604df
 }
3604df
 
3604df
 upcall_local_t *
3604df
-upcall_local_init (call_frame_t *frame, xlator_t *this, inode_t *inode)
3604df
+upcall_local_init (call_frame_t *frame, xlator_t *this, inode_t *inode, dict_t *xattr)
3604df
 {
3604df
         upcall_local_t *local = NULL;
3604df
 
3604df
@@ -1951,6 +2003,8 @@ upcall_local_init (call_frame_t *frame, xlator_t *this, inode_t *inode)
3604df
                 goto out;
3604df
 
3604df
         local->inode = inode_ref (inode);
3604df
+        if (xattr)
3604df
+                local->xattr = dict_ref (xattr);
3604df
 
3604df
         /* Shall we get inode_ctx and store it here itself? */
3604df
         local->upcall_inode_ctx = upcall_inode_ctx_get (inode, this);
3604df
diff --git a/xlators/features/upcall/src/upcall.h b/xlators/features/upcall/src/upcall.h
3604df
index d53c6a3..788555b 100644
3604df
--- a/xlators/features/upcall/src/upcall.h
3604df
+++ b/xlators/features/upcall/src/upcall.h
3604df
@@ -84,11 +84,13 @@ struct upcall_local {
3604df
         upcall_inode_ctx_t *upcall_inode_ctx;
3604df
         inode_t   *inode;
3604df
         loc_t     rename_oldloc;
3604df
+        dict_t    *xattr;
3604df
 };
3604df
 typedef struct upcall_local upcall_local_t;
3604df
 
3604df
 void upcall_local_wipe (xlator_t *this, upcall_local_t *local);
3604df
-upcall_local_t *upcall_local_init (call_frame_t *frame, xlator_t *this, inode_t *inode);
3604df
+upcall_local_t *upcall_local_init (call_frame_t *frame, xlator_t *this,
3604df
+                                   inode_t *inode, dict_t *xattr);
3604df
 
3604df
 upcall_client_t *add_upcall_client (call_frame_t *frame, client_t *client,
3604df
                                     upcall_inode_ctx_t *up_inode_ctx);
3604df
@@ -118,11 +120,13 @@ void upcall_cache_invalidate (call_frame_t *frame, xlator_t *this,
3604df
                               client_t *client, inode_t *inode,
3604df
                               uint32_t flags, struct iatt *stbuf,
3604df
                               struct iatt *p_stbuf,
3604df
-                              struct iatt *oldp_stbuf);
3604df
+                              struct iatt *oldp_stbuf, dict_t *xattr);
3604df
 void upcall_client_cache_invalidate (xlator_t *xl, uuid_t gfid,
3604df
                                      upcall_client_t *up_client_entry,
3604df
                                      uint32_t flags, struct iatt *stbuf,
3604df
                                      struct iatt *p_stbuf,
3604df
-                                     struct iatt *oldp_stbuf);
3604df
+                                     struct iatt *oldp_stbuf, dict_t *xattr);
3604df
+
3604df
+int up_filter_virtual_xattr (dict_t *d, char *k, data_t *v, void *tmp);
3604df
 
3604df
 #endif /* __UPCALL_H__ */
3604df
diff --git a/xlators/protocol/client/src/client-callback.c b/xlators/protocol/client/src/client-callback.c
3604df
index 09097e9..1340440 100644
3604df
--- a/xlators/protocol/client/src/client-callback.c
3604df
+++ b/xlators/protocol/client/src/client-callback.c
3604df
@@ -112,10 +112,13 @@ client_cbk_cache_invalidation (struct rpc_clnt *rpc, void *mydata, void *data)
3604df
         }
3604df
 
3604df
         upcall_data.data = &ca_data;
3604df
-        gf_proto_cache_invalidation_to_upcall (&ca_req, &upcall_data);
3604df
+        ret = gf_proto_cache_invalidation_to_upcall (THIS, &ca_req,
3604df
+                                                     &upcall_data);
3604df
+        if (ret < 0)
3604df
+                goto out;
3604df
 
3604df
-        gf_msg_trace (THIS->name, 0, "Upcall gfid = %s, ret = %d",
3604df
-                      ca_req.gfid, ret);
3604df
+        gf_msg_trace (THIS->name, 0, "Cache invalidation cbk recieved for gfid:"
3604df
+                      " %s, ret = %d", ca_req.gfid, ret);
3604df
 
3604df
         default_notify (THIS, GF_EVENT_UPCALL, &upcall_data);
3604df
 
3604df
@@ -126,6 +129,9 @@ out:
3604df
         if (ca_req.xdata.xdata_val)
3604df
                 free (ca_req.xdata.xdata_val);
3604df
 
3604df
+        if (ca_data.dict)
3604df
+                dict_unref (ca_data.dict);
3604df
+
3604df
         return 0;
3604df
 }
3604df
 
3604df
diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c
3604df
index 457f3d6..726ab69 100644
3604df
--- a/xlators/protocol/server/src/server.c
3604df
+++ b/xlators/protocol/server/src/server.c
3604df
@@ -1251,8 +1251,10 @@ server_process_event_upcall (xlator_t *this, void *data)
3604df
 
3604df
         switch (upcall_data->event_type) {
3604df
         case GF_UPCALL_CACHE_INVALIDATION:
3604df
-                gf_proto_cache_invalidation_from_upcall (&gf_c_req,
3604df
-                                                         upcall_data);
3604df
+                ret = gf_proto_cache_invalidation_from_upcall (this, &gf_c_req,
3604df
+                                                               upcall_data);
3604df
+                if (ret < 0)
3604df
+                        goto out;
3604df
 
3604df
                 up_req = &gf_c_req;
3604df
                 cbk_procnum = GF_CBK_CACHE_INVALIDATION;
3604df
@@ -1301,6 +1303,9 @@ out:
3604df
         if ((gf_recall_lease.xdata).xdata_val)
3604df
                 GF_FREE ((gf_recall_lease.xdata).xdata_val);
3604df
 
3604df
+        if ((gf_c_req.xdata).xdata_val)
3604df
+                GF_FREE ((gf_c_req.xdata).xdata_val);
3604df
+
3604df
         return ret;
3604df
 }
3604df
 
3604df
-- 
3604df
1.7.1
3604df