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