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