d1681e
From 14a8e47839a955cd693616c7497b93ddc9584478 Mon Sep 17 00:00:00 2001
d1681e
From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org>
d1681e
Date: Tue, 25 Jul 2017 11:54:09 +0200
d1681e
Subject: [PATCH 140/148] md-cache: Add additional samba and macOS specific EAs
d1681e
 to mdcache
d1681e
d1681e
Samba ships with a server implementation of the Apple Create Context
d1681e
extension (AAPL) as negotiated by all modern Apple clients. With the
d1681e
support of the AAPL extension, Apple clients will integrate better with
d1681e
Samba servers. The AAPL implementation itself is contained in the Samba
d1681e
vfs_fruit(8) module which has to be activated in Samba. This vfs_fruit
d1681e
module also provides support for macOS alternate data streams which will
d1681e
be represented in EAs. Two standard data streams ("AFP_AfpInfo" and
d1681e
"AFP_Resource") will be stored in the following EAs:
d1681e
d1681e
* user.org.netatalk.Metadata
d1681e
* user.org.netatalk.ResourceFork
d1681e
d1681e
For all other data streams, vfs_fruit relies on another Samba vfs
d1681e
module, vfs_streams_xattr(8), to handle these. Although configurable, by
d1681e
default the vfs_streams_xattr module will build EA keynames with a
d1681e
"user.DosStream." prefix. Please note that we have to deal with only one
d1681e
known prefix key, as macOS will happily compose EA keynames like:
d1681e
d1681e
* user.DosStream.com.apple.diskimages.fsck:$DATA
d1681e
* user.DosStream.com.apple.diskimages.recentcksum:$DATA
d1681e
* user.DosStream.com.apple.metadata:kMDItemWhereFroms:$DATA
d1681e
* user.DosStream.com.apple.quarantine:$DATA
d1681e
* etc.
d1681e
d1681e
Caching of vfs_fruit specific EAs is crucial for SMB performance and is
d1681e
controlled with the same configuration option
d1681e
"performance.cache-samba-metadata".
d1681e
d1681e
> Signed-off-by: Guenther Deschner <gd@samba.org>
d1681e
> Change-Id: Ia7aa341234dc13e1c0057f3d658b7ef711b5d31e
d1681e
> BUG: 1499933
d1681e
> Reviewed-on: https://review.gluster.org/#/c/18455/
d1681e
> Reviewed-by: Jeff Darcy
d1681e
> Reviewed-by: Niels de Vos
d1681e
> Smoke: Gluster Build System <jenkins@build.gluster.org>
d1681e
> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
d1681e
> (cherry picked from commit ae9b006f23b1408ff548348440369d056becdc1d)
d1681e
d1681e
Change-Id: Ia7aa341234dc13e1c0057f3d658b7ef711b5d31e
d1681e
BUG: 1446125
d1681e
Signed-off-by: Guenther Deschner <gd@samba.org>
d1681e
Signed-off-by: Poornima G <pgurusid@redhat.com>
d1681e
Reviewed-on: https://code.engineering.redhat.com/gerrit/128479
d1681e
Tested-by: RHGS Build Bot <nigelb@redhat.com>
d1681e
Reviewed-by: Gunther Deschner <gdeschne@redhat.com>
d1681e
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
d1681e
---
d1681e
 tests/bugs/md-cache/bug-1211863.t           | 16 +++----
d1681e
 xlators/performance/md-cache/src/md-cache.c | 66 ++++++++++++++++++++++++++---
d1681e
 2 files changed, 68 insertions(+), 14 deletions(-)
d1681e
d1681e
diff --git a/tests/bugs/md-cache/bug-1211863.t b/tests/bugs/md-cache/bug-1211863.t
d1681e
index ece42fe..b89d7f5 100755
d1681e
--- a/tests/bugs/md-cache/bug-1211863.t
d1681e
+++ b/tests/bugs/md-cache/bug-1211863.t
d1681e
@@ -26,15 +26,15 @@ TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M1
d1681e
 TEST touch $M0/file1
d1681e
 
d1681e
 ## 9. Setxattr from mount-0
d1681e
-TEST "setfattr -n user.DOSATTRIB -v "abc" $M0/file1"
d1681e
+TEST "setfattr -n user.DosStream.abc -v "abc" $M0/file1"
d1681e
 ## 10. Getxattr from mount-1, this should return the correct value as it is a fresh getxattr
d1681e
-TEST "getfattr -n user.DOSATTRIB $M1/file1 | grep -q abc"
d1681e
+TEST "getfattr -n user.DosStream.abc $M1/file1 | grep -q abc"
d1681e
 
d1681e
 ## 11. Now modify the same xattr from mount-0 again
d1681e
-TEST "setfattr -n user.DOSATTRIB -v "xyz" $M0/file1"
d1681e
+TEST "setfattr -n user.DosStream.abc -v "xyz" $M0/file1"
d1681e
 ## 12. Since the xattr is already cached in mount-1 it returns the old xattr
d1681e
        #value, until the timeout (600)
d1681e
-TEST "getfattr -n user.DOSATTRIB $M1/file1 | grep -q abc"
d1681e
+TEST "getfattr -n user.DosStream.abc $M1/file1 | grep -q abc"
d1681e
 
d1681e
 ## 13. Unmount to clean all the cache
d1681e
 EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0
d1681e
@@ -54,14 +54,14 @@ TEST glusterfs --volfile-id=/$V0 --volfile-server=$H0 $M1
d1681e
 
d1681e
 ## 23. Repeat the tests 11-14, but this time since cache invalidation is on,
d1681e
        #the getxattr will reflect the new value
d1681e
-TEST "setfattr -n user.DOSATTRIB -v "abc" $M0/file1"
d1681e
-TEST "getfattr -n user.DOSATTRIB $M1/file1 | grep -q abc"
d1681e
-TEST "setfattr -n user.DOSATTRIB -v "xyz" $M0/file1"
d1681e
+TEST "setfattr -n user.DosStream.abc -v "abc" $M0/file1"
d1681e
+TEST "getfattr -n user.DosStream.abc $M1/file1 | grep -q abc"
d1681e
+TEST "setfattr -n user.DosStream.abc -v "xyz" $M0/file1"
d1681e
 sleep 2; #There can be a very very small window where the next getxattr
d1681e
          #reaches md-cache, before the cache-invalidation caused by previous
d1681e
          #setxattr, reaches md-cache. Hence sleeping for 2 sec.
d1681e
          #Also it should not be > 600.
d1681e
-TEST "getfattr -n user.DOSATTRIB $M1/file1 | grep -q xyz"
d1681e
+TEST "getfattr -n user.DosStream.abc $M1/file1 | grep -q xyz"
d1681e
 
d1681e
 TEST $CLI volume set $V0 cache-samba-metadata off
d1681e
 EXPECT 'off' volinfo_field $V0 'performance.cache-samba-metadata'
d1681e
diff --git a/xlators/performance/md-cache/src/md-cache.c b/xlators/performance/md-cache/src/md-cache.c
d1681e
index 1ca7727..feab357 100644
d1681e
--- a/xlators/performance/md-cache/src/md-cache.c
d1681e
+++ b/xlators/performance/md-cache/src/md-cache.c
d1681e
@@ -72,56 +72,85 @@ static struct mdc_key {
d1681e
 	const char *name;
d1681e
 	int         load;
d1681e
 	int         check;
d1681e
+	int         prefix_match;
d1681e
 } mdc_keys[] = {
d1681e
 	{
d1681e
 		.name = POSIX_ACL_ACCESS_XATTR,
d1681e
 		.load = 0,
d1681e
 		.check = 1,
d1681e
+		.prefix_match = 0,
d1681e
 	},
d1681e
 	{
d1681e
 		.name = POSIX_ACL_DEFAULT_XATTR,
d1681e
 		.load = 0,
d1681e
 		.check = 1,
d1681e
+		.prefix_match = 0,
d1681e
 	},
d1681e
 	{
d1681e
 		.name = GF_POSIX_ACL_ACCESS,
d1681e
 		.load = 0,
d1681e
 		.check = 1,
d1681e
+		.prefix_match = 0,
d1681e
 	},
d1681e
 	{
d1681e
 		.name = GF_POSIX_ACL_DEFAULT,
d1681e
 		.load = 0,
d1681e
 		.check = 1,
d1681e
+		.prefix_match = 0,
d1681e
 	},
d1681e
 	{
d1681e
 		.name = GF_SELINUX_XATTR_KEY,
d1681e
 		.load = 0,
d1681e
 		.check = 1,
d1681e
+		.prefix_match = 0,
d1681e
 	},
d1681e
         {
d1681e
                 .name = "user.swift.metadata",
d1681e
                 .load = 0,
d1681e
                 .check = 1,
d1681e
+                .prefix_match = 0,
d1681e
         },
d1681e
         {
d1681e
                 .name = "user.DOSATTRIB",
d1681e
                 .load = 0,
d1681e
                 .check = 1,
d1681e
+                .prefix_match = 0,
d1681e
+        },
d1681e
+        {
d1681e
+                .name = "user.DosStream.*",
d1681e
+                .load = 0,
d1681e
+                .check = 1,
d1681e
+                .prefix_match = 1,
d1681e
+        },
d1681e
+        {
d1681e
+                .name = "user.org.netatalk.Metadata",
d1681e
+                .load = 0,
d1681e
+                .check = 1,
d1681e
+                .prefix_match = 0,
d1681e
+        },
d1681e
+        {
d1681e
+                .name = "user.org.netatalk.ResourceFork",
d1681e
+                .load = 0,
d1681e
+                .check = 1,
d1681e
+                .prefix_match = 0,
d1681e
         },
d1681e
         {
d1681e
                 .name = "security.NTACL",
d1681e
                 .load = 0,
d1681e
                 .check = 1,
d1681e
+                .prefix_match = 0,
d1681e
         },
d1681e
 	{
d1681e
 		.name = "security.capability",
d1681e
 		.load = 0,
d1681e
 		.check = 1,
d1681e
+		.prefix_match = 0,
d1681e
 	},
d1681e
 	{
d1681e
 		.name = "gfid-req",
d1681e
 		.load = 0,
d1681e
 		.check = 1,
d1681e
+		.prefix_match = 0,
d1681e
 	},
d1681e
         {
d1681e
                 .name = "security.ima",
d1681e
@@ -132,6 +161,7 @@ static struct mdc_key {
d1681e
                 .name = NULL,
d1681e
                 .load = 0,
d1681e
                 .check = 0,
d1681e
+                .prefix_match = 0,
d1681e
         }
d1681e
 };
d1681e
 
d1681e
@@ -606,8 +636,14 @@ updatefn(dict_t *dict, char *key, data_t *value, void *data)
d1681e
 	for (mdc_key = mdc_keys[i].name; (mdc_key = mdc_keys[i].name); i++) {
d1681e
 		if (!mdc_keys[i].check)
d1681e
 			continue;
d1681e
-		if (strcmp(mdc_key, key))
d1681e
-			continue;
d1681e
+
d1681e
+		if (mdc_keys[i].prefix_match) {
d1681e
+			if (strncmp (mdc_key, key, (strlen(mdc_key) - 1)))
d1681e
+				continue;
d1681e
+		} else {
d1681e
+			if (strcmp(mdc_key, key))
d1681e
+				continue;
d1681e
+		}
d1681e
 
d1681e
 		if (!u->dict) {
d1681e
 			u->dict = dict_new();
d1681e
@@ -986,8 +1022,13 @@ is_mdc_key_satisfied (const char *key)
d1681e
 	for (mdc_key = mdc_keys[i].name; (mdc_key = mdc_keys[i].name); i++) {
d1681e
 		if (!mdc_keys[i].load)
d1681e
 			continue;
d1681e
-		if (strcmp (mdc_key, key) == 0)
d1681e
-			return 1;
d1681e
+		if (mdc_keys[i].prefix_match) {
d1681e
+			if (strncmp (mdc_key, key, (strlen(mdc_key) - 1)) == 0)
d1681e
+				return 1;
d1681e
+		} else {
d1681e
+			if (strcmp (mdc_key, key) == 0)
d1681e
+				return 1;
d1681e
+		}
d1681e
 	}
d1681e
 
d1681e
         gf_msg_trace ("md-cache", 0, "xattr key %s doesn't satisfy "
d1681e
@@ -2902,6 +2943,12 @@ reconfigure (xlator_t *this, dict_t *options)
d1681e
                           options, bool, out);
d1681e
         mdc_key_load_set (mdc_keys, "user.DOSATTRIB",
d1681e
                           conf->cache_samba_metadata);
d1681e
+        mdc_key_load_set (mdc_keys, "user.DosStream.",
d1681e
+                          conf->cache_samba_metadata);
d1681e
+        mdc_key_load_set (mdc_keys, "user.org.netatalk.Metadata",
d1681e
+                          conf->cache_samba_metadata);
d1681e
+        mdc_key_load_set (mdc_keys, "user.org.netatalk.ResourceFork",
d1681e
+                          conf->cache_samba_metadata);
d1681e
         mdc_key_load_set (mdc_keys, "security.NTACL",
d1681e
                           conf->cache_samba_metadata);
d1681e
 
d1681e
@@ -2973,6 +3020,12 @@ init (xlator_t *this)
d1681e
                         bool, out);
d1681e
         mdc_key_load_set (mdc_keys, "user.DOSATTRIB",
d1681e
                           conf->cache_samba_metadata);
d1681e
+        mdc_key_load_set (mdc_keys, "user.DosStream.",
d1681e
+                          conf->cache_samba_metadata);
d1681e
+        mdc_key_load_set (mdc_keys, "user.org.netatalk.Metadata",
d1681e
+                          conf->cache_samba_metadata);
d1681e
+        mdc_key_load_set (mdc_keys, "user.org.netatalk.ResourceFork",
d1681e
+                          conf->cache_samba_metadata);
d1681e
         mdc_key_load_set (mdc_keys, "security.NTACL",
d1681e
                           conf->cache_samba_metadata);
d1681e
 
d1681e
@@ -3131,8 +3184,9 @@ struct volume_options options[] = {
d1681e
         { .key = {"cache-samba-metadata"},
d1681e
           .type = GF_OPTION_TYPE_BOOL,
d1681e
           .default_value = "false",
d1681e
-          .description = "Cache samba metadata (user.DOSATTRIB, security.NTACL"
d1681e
-                         " xattrs)",
d1681e
+          .description = "Cache samba metadata (user.DOSATTRIB, security.NTACL,"
d1681e
+                         " org.netatalk.Metadata, org.netatalk.ResourceFork, "
d1681e
+                         "and user.DosStream. xattrs)",
d1681e
         },
d1681e
 	{ .key = {"cache-posix-acl"},
d1681e
 	  .type = GF_OPTION_TYPE_BOOL,
d1681e
-- 
d1681e
1.8.3.1
d1681e