17b94a
From 36b0bd86321436a951f225fcf2e921390ed8dc33 Mon Sep 17 00:00:00 2001
17b94a
From: Michael Adam <obnox@samba.org>
17b94a
Date: Thu, 20 Jun 2019 13:09:37 +0200
17b94a
Subject: [PATCH 223/255] change get_real_filename implementation to use
17b94a
 ENOATTR instead of ENOENT
17b94a
17b94a
get_real_filename is implemented as a virtual extended attribute to help
17b94a
Samba implement the case-insensitive but case preserving SMB protocol
17b94a
more efficiently. It is implemented as a getxattr call on the parent directory
17b94a
with the virtual key of "get_real_filename:<entryname>" by looking for a
17b94a
spelling with different case for the provided file/dir name (<entryname>)
17b94a
and returning this correct spelling as a result if the entry is found.
17b94a
Originally (05aaec645a6262d431486eb5ac7cd702646cfcfb), the
17b94a
implementation used the ENOENT errno to return the authoritative answer
17b94a
that <entryname> does not exist in any case folding.
17b94a
17b94a
Now this implementation is actually a violation or misuse of the defined
17b94a
API for the getxattr call which returns ENOENT for the case that the dir
17b94a
that the call is made against does not exist and ENOATTR (or the synonym
17b94a
ENODATA) for the case that the xattr does not exist.
17b94a
17b94a
This was not a problem until the gluster fuse-bridge was changed
17b94a
to do map ENOENT to ESTALE in 59629f1da9dca670d5dcc6425f7f89b3e96b46bf,
17b94a
after which we the getxattr call for get_real_filename returned an
17b94a
ESTALE instead of ENOENT breaking the expectation in Samba.
17b94a
17b94a
It is an independent problem that ESTALE should not leak out to user
17b94a
space but is intended to trigger retries between fuse and gluster.
17b94a
But nevertheless, the semantics seem to be incorrect here and should
17b94a
be changed.
17b94a
17b94a
This patch changes the implementation of the get_real_filename virtual
17b94a
xattr to correctly return ENOATTR instead of ENOENT if the file/directory
17b94a
being looked up is not found.
17b94a
17b94a
The Samba glusterfs_fuse vfs module which takes advantage of the
17b94a
get_real_filename over a fuse mount will receive a corresponding change
17b94a
to map ENOATTR to ENOENT. Without this change, it will still work
17b94a
correctly, but the performance optimization for nonexisting files is
17b94a
lost. On the other hand side, this change removes the distinction
17b94a
between the old not-implemented case and the implemented case.
17b94a
So Samba changed to treat ENOATTR like ENOENT will not work correctly
17b94a
any more against old servers that don't implement get_real_filename.
17b94a
I.e. existing files will be reported as non-existing
17b94a
17b94a
Backport of https://review.gluster.org/c/glusterfs/+/22925
17b94a
17b94a
Change-Id: I971b427ab8410636d5d201157d9af70e0d075b67
17b94a
fixes: bz#1724089
17b94a
Signed-off-by: Michael Adam <obnox@samba.org>
17b94a
Reviewed-on: https://code.engineering.redhat.com/gerrit/175012
17b94a
Tested-by: RHGS Build Bot <nigelb@redhat.com>
17b94a
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
17b94a
---
17b94a
 xlators/cluster/dht/src/dht-common.c           | 8 ++++----
17b94a
 xlators/storage/posix/src/posix-inode-fd-ops.c | 4 ++--
17b94a
 2 files changed, 6 insertions(+), 6 deletions(-)
17b94a
17b94a
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
17b94a
index 9a6ea5b..219b072 100644
17b94a
--- a/xlators/cluster/dht/src/dht-common.c
17b94a
+++ b/xlators/cluster/dht/src/dht-common.c
17b94a
@@ -4618,7 +4618,7 @@ dht_getxattr_get_real_filename_cbk(call_frame_t *frame, void *cookie,
17b94a
 
17b94a
     LOCK(&frame->lock);
17b94a
     {
17b94a
-        if (local->op_errno == ENODATA || local->op_errno == EOPNOTSUPP) {
17b94a
+        if (local->op_errno == EOPNOTSUPP) {
17b94a
             /* Nothing to do here, we have already found
17b94a
              * a subvol which does not have the get_real_filename
17b94a
              * optimization. If condition is for simple logic.
17b94a
@@ -4627,7 +4627,7 @@ dht_getxattr_get_real_filename_cbk(call_frame_t *frame, void *cookie,
17b94a
         }
17b94a
 
17b94a
         if (op_ret == -1) {
17b94a
-            if (op_errno == ENODATA || op_errno == EOPNOTSUPP) {
17b94a
+            if (op_errno == EOPNOTSUPP) {
17b94a
                 /* This subvol does not have the optimization.
17b94a
                  * Better let the user know we don't support it.
17b94a
                  * Remove previous results if any.
17b94a
@@ -4655,7 +4655,7 @@ dht_getxattr_get_real_filename_cbk(call_frame_t *frame, void *cookie,
17b94a
                 goto post_unlock;
17b94a
             }
17b94a
 
17b94a
-            if (op_errno == ENOENT) {
17b94a
+            if (op_errno == ENOATTR) {
17b94a
                 /* Do nothing, our defaults are set to this.
17b94a
                  */
17b94a
                 goto unlock;
17b94a
@@ -4723,7 +4723,7 @@ dht_getxattr_get_real_filename(call_frame_t *frame, xlator_t *this, loc_t *loc,
17b94a
     cnt = local->call_cnt = layout->cnt;
17b94a
 
17b94a
     local->op_ret = -1;
17b94a
-    local->op_errno = ENOENT;
17b94a
+    local->op_errno = ENOATTR;
17b94a
 
17b94a
     for (i = 0; i < cnt; i++) {
17b94a
         subvol = layout->list[i].xlator;
17b94a
diff --git a/xlators/storage/posix/src/posix-inode-fd-ops.c b/xlators/storage/posix/src/posix-inode-fd-ops.c
17b94a
index c949f68..ea3b69c 100644
17b94a
--- a/xlators/storage/posix/src/posix-inode-fd-ops.c
17b94a
+++ b/xlators/storage/posix/src/posix-inode-fd-ops.c
17b94a
@@ -2954,7 +2954,7 @@ posix_xattr_get_real_filename(call_frame_t *frame, xlator_t *this, loc_t *loc,
17b94a
     (void)sys_closedir(fd);
17b94a
 
17b94a
     if (!found)
17b94a
-        return -ENOENT;
17b94a
+        return -ENOATTR;
17b94a
 
17b94a
     ret = dict_set_dynstr(dict, (char *)key, found);
17b94a
     if (ret) {
17b94a
@@ -3422,7 +3422,7 @@ posix_getxattr(call_frame_t *frame, xlator_t *this, loc_t *loc,
17b94a
         if (ret < 0) {
17b94a
             op_ret = -1;
17b94a
             op_errno = -ret;
17b94a
-            if (op_errno == ENOENT) {
17b94a
+            if (op_errno == ENOATTR) {
17b94a
                 gf_msg_debug(this->name, 0,
17b94a
                              "Failed to get "
17b94a
                              "real filename (%s, %s)",
17b94a
-- 
17b94a
1.8.3.1
17b94a