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