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