ca3909
From 2d7d9165c6a8619eef553859b4b7136b8e9ccb55 Mon Sep 17 00:00:00 2001
ca3909
From: Anoop C S <anoopcs@redhat.com>
ca3909
Date: Sat, 10 Aug 2019 10:30:26 +0530
ca3909
Subject: [PATCH 280/284] performance/md-cache: Do not skip caching of null
ca3909
 character xattr values
ca3909
ca3909
Null character string is a valid xattr value in file system. But for
ca3909
those xattrs processed by md-cache, it does not update its entries if
ca3909
value is null('\0'). This results in ENODATA when those xattrs are
ca3909
queried afterwards via getxattr() causing failures in basic operations
ca3909
like create, copy etc in a specially configured Samba setup for Mac OS
ca3909
clients.
ca3909
ca3909
On the other side snapview-server is internally setting empty string("")
ca3909
as value for xattrs received as part of listxattr() and are not intended
ca3909
to be cached. Therefore we try to maintain that behaviour using an
ca3909
additional dictionary key to prevent updation of entries in getxattr()
ca3909
and fgetxattr() callbacks in md-cache.
ca3909
ca3909
Credits: Poornima G <pgurusid@redhat.com>
ca3909
ca3909
Backport of https://review.gluster.org/c/glusterfs/+/23206
ca3909
ca3909
Change-Id: I7859cbad0a06ca6d788420c2a495e658699c6ff7
ca3909
Fixes: bz#1732376
ca3909
Signed-off-by: Anoop C S <anoopcs@redhat.com>
ca3909
Reviewed-on: https://code.engineering.redhat.com/gerrit/179048
ca3909
Tested-by: RHGS Build Bot <nigelb@redhat.com>
ca3909
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
ca3909
---
ca3909
 tests/bugs/md-cache/bug-1726205.t                  | 22 +++++++++++++++
ca3909
 .../features/snapview-server/src/snapview-server.c | 12 ++++++++-
ca3909
 xlators/performance/md-cache/src/md-cache.c        | 31 +++++++++-------------
ca3909
 3 files changed, 45 insertions(+), 20 deletions(-)
ca3909
 create mode 100644 tests/bugs/md-cache/bug-1726205.t
ca3909
ca3909
diff --git a/tests/bugs/md-cache/bug-1726205.t b/tests/bugs/md-cache/bug-1726205.t
ca3909
new file mode 100644
ca3909
index 0000000..795130e
ca3909
--- /dev/null
ca3909
+++ b/tests/bugs/md-cache/bug-1726205.t
ca3909
@@ -0,0 +1,22 @@
ca3909
+#!/bin/bash
ca3909
+
ca3909
+. $(dirname $0)/../../include.rc
ca3909
+. $(dirname $0)/../../volume.rc
ca3909
+
ca3909
+cleanup;
ca3909
+
ca3909
+TEST glusterd;
ca3909
+
ca3909
+TEST $CLI volume create $V0 $H0:$B0/${V0}{1,2,3};
ca3909
+
ca3909
+TEST $CLI volume start $V0
ca3909
+
ca3909
+TEST $CLI volume set $V0 group samba
ca3909
+
ca3909
+TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0
ca3909
+
ca3909
+TEST touch $M0/file
ca3909
+TEST "setfattr -n "user.DosStream.Zone.Identifier:\$DATA" -v '\0' $M0/file"
ca3909
+TEST "getfattr -n "user.DosStream.Zone.Identifier:\$DATA" -e hex $M0/file | grep -q 0x00"
ca3909
+
ca3909
+cleanup;
ca3909
diff --git a/xlators/features/snapview-server/src/snapview-server.c b/xlators/features/snapview-server/src/snapview-server.c
ca3909
index b4998b8..1d6a5e5 100644
ca3909
--- a/xlators/features/snapview-server/src/snapview-server.c
ca3909
+++ b/xlators/features/snapview-server/src/snapview-server.c
ca3909
@@ -828,7 +828,8 @@ out:
ca3909
  * back into the dict. But to get the values for those xattrs it has to do the
ca3909
  * getxattr operation on each xattr which might turn out to be a costly
ca3909
  * operation. So for each of the xattrs present in the list, a 0 byte value
ca3909
- * ("") is set into the dict before unwinding. This can be treated as an
ca3909
+ * ("") is set into the dict before unwinding. Since ("") is also a valid xattr
ca3909
+ * value(in a file system) we use an extra key in the same dictionary as an
ca3909
  * indicator to other xlators which want to cache the xattrs (as of now,
ca3909
  * md-cache which caches acl and selinux related xattrs) to not to cache the
ca3909
  * values of the xattrs present in the dict.
ca3909
@@ -871,6 +872,15 @@ svs_add_xattrs_to_dict(xlator_t *this, dict_t *dict, char *list, ssize_t size)
ca3909
         list_offset += strlen(keybuffer) + 1;
ca3909
     } /* while (remaining_size > 0) */
ca3909
 
ca3909
+    /* Add an additional key to indicate that we don't need to cache these
ca3909
+     * xattrs(with value "") */
ca3909
+    ret = dict_set_str(dict, "glusterfs.skip-cache", "");
ca3909
+    if (ret < 0) {
ca3909
+        gf_msg(this->name, GF_LOG_ERROR, 0, SVS_MSG_DICT_SET_FAILED,
ca3909
+               "dict set operation for the key glusterfs.skip-cache failed.");
ca3909
+        goto out;
ca3909
+    }
ca3909
+
ca3909
     ret = 0;
ca3909
 
ca3909
 out:
ca3909
diff --git a/xlators/performance/md-cache/src/md-cache.c b/xlators/performance/md-cache/src/md-cache.c
ca3909
index 6e0468f..a6b363f 100644
ca3909
--- a/xlators/performance/md-cache/src/md-cache.c
ca3909
+++ b/xlators/performance/md-cache/src/md-cache.c
ca3909
@@ -698,25 +698,6 @@ updatefn(dict_t *dict, char *key, data_t *value, void *data)
ca3909
             }
ca3909
         }
ca3909
 
ca3909
-        /* posix xlator as part of listxattr will send both names
ca3909
-         * and values of the xattrs in the dict. But as per man page
ca3909
-         * listxattr is mainly supposed to send names of the all the
ca3909
-         * xattrs. gfapi, as of now will put all the keys it obtained
ca3909
-         * in the dict (sent by posix) into a buffer provided by the
ca3909
-         * caller (thus the values of those xattrs are lost). If some
ca3909
-         * xlator makes gfapi based calls (ex: snapview-server), then
ca3909
-         * it has to unwind the calls by putting those names it got
ca3909
-         * in the buffer again into the dict. But now it would not be
ca3909
-         * having the values for those xattrs. So it might just put
ca3909
-         * a 0 byte value ("") into the dict for each xattr and unwind
ca3909
-         * the call. So the xlators which cache the xattrs (as of now
ca3909
-         * md-cache caches the acl and selinux related xattrs), should
ca3909
-         * not update their cache if the value of a xattr is a 0 byte
ca3909
-         * data (i.e. "").
ca3909
-         */
ca3909
-        if (value->len == 1 && value->data[0] == '\0')
ca3909
-            return 0;
ca3909
-
ca3909
         if (dict_set(u->dict, key, value) < 0) {
ca3909
             u->ret = -1;
ca3909
             return -1;
ca3909
@@ -2406,6 +2387,12 @@ mdc_getxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
ca3909
         goto out;
ca3909
     }
ca3909
 
ca3909
+    if (dict_get(xattr, "glusterfs.skip-cache")) {
ca3909
+        gf_msg(this->name, GF_LOG_DEBUG, 0, 0,
ca3909
+               "Skipping xattr update due to empty value");
ca3909
+        goto out;
ca3909
+    }
ca3909
+
ca3909
     mdc_inode_xatt_set(this, local->loc.inode, xdata);
ca3909
 
ca3909
 out:
ca3909
@@ -2488,6 +2475,12 @@ mdc_fgetxattr_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
ca3909
         goto out;
ca3909
     }
ca3909
 
ca3909
+    if (dict_get(xattr, "glusterfs.skip-cache")) {
ca3909
+        gf_msg(this->name, GF_LOG_DEBUG, 0, 0,
ca3909
+               "Skipping xattr update due to empty value");
ca3909
+        goto out;
ca3909
+    }
ca3909
+
ca3909
     mdc_inode_xatt_set(this, local->fd->inode, xdata);
ca3909
 
ca3909
 out:
ca3909
-- 
ca3909
1.8.3.1
ca3909