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