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