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