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