|
|
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 |
|