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