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