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