d2787b
From a19fa252942938a308ffa655fca3814d0660c6e2 Mon Sep 17 00:00:00 2001
d2787b
From: Vinayakswami Hariharmath <vharihar@redhat.com>
d2787b
Date: Wed, 3 Jun 2020 18:58:56 +0530
d2787b
Subject: [PATCH 563/584] features/shard: Use fd lookup post file open
d2787b
d2787b
Issue:
d2787b
When a process has the open fd and the same file is
d2787b
unlinked in middle of the operations, then file based
d2787b
lookup fails with ENOENT or stale file
d2787b
d2787b
Solution:
d2787b
When the file already open and fd is available, use fstat
d2787b
to get the file attributes
d2787b
d2787b
Backport of:
d2787b
> Upstream-patch: https://review.gluster.org/#/c/glusterfs/+/24528/
d2787b
> Change-Id: I0e83aee9f11b616dcfe13769ebfcda6742e4e0f4
d2787b
> Fixes: #1281
d2787b
> Signed-off-by: Vinayakswami Hariharmath <vharihar@redhat.com>
d2787b
d2787b
BUG: 1925425
d2787b
Change-Id: I0e83aee9f11b616dcfe13769ebfcda6742e4e0f4
d2787b
Signed-off-by: Vinayakswami Hariharmath <vharihar@redhat.com>
d2787b
Reviewed-on: https://code.engineering.redhat.com/gerrit/c/rhs-glusterfs/+/244957
d2787b
Tested-by: RHGS Build Bot <nigelb@redhat.com>
d2787b
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
d2787b
---
d2787b
 tests/bugs/shard/issue-1281.t      |  34 +++++++++++
d2787b
 xlators/features/shard/src/shard.c | 119 +++++++++++++++++++++++--------------
d2787b
 2 files changed, 110 insertions(+), 43 deletions(-)
d2787b
 create mode 100644 tests/bugs/shard/issue-1281.t
d2787b
d2787b
diff --git a/tests/bugs/shard/issue-1281.t b/tests/bugs/shard/issue-1281.t
d2787b
new file mode 100644
d2787b
index 0000000..9704caa
d2787b
--- /dev/null
d2787b
+++ b/tests/bugs/shard/issue-1281.t
d2787b
@@ -0,0 +1,34 @@
d2787b
+#!/bin/bash
d2787b
+
d2787b
+. $(dirname $0)/../../include.rc
d2787b
+
d2787b
+cleanup;
d2787b
+
d2787b
+TEST glusterd
d2787b
+TEST pidof glusterd
d2787b
+TEST $CLI volume create $V0 $H0:$B0/${V0}{0,1}
d2787b
+TEST $CLI volume set $V0 features.shard on
d2787b
+TEST $CLI volume set $V0 performance.quick-read off
d2787b
+TEST $CLI volume set $V0 performance.io-cache off
d2787b
+TEST $CLI volume set $V0 performance.read-ahead off
d2787b
+TEST $CLI volume set $V0 performance.write-behind off
d2787b
+TEST $CLI volume start $V0
d2787b
+
d2787b
+TEST $GFS --volfile-id=$V0 --volfile-server=$H0 $M0
d2787b
+
d2787b
+#Open a file and store descriptor in fd = 5
d2787b
+exec 5>$M0/foo
d2787b
+
d2787b
+#Unlink the same file which is opened in prev step
d2787b
+TEST unlink $M0/foo
d2787b
+
d2787b
+#Write something on the file using the open fd = 5
d2787b
+echo "issue-1281" >&5
d2787b
+
d2787b
+#Write on the descriptor should be succesful
d2787b
+EXPECT 0 echo $?
d2787b
+
d2787b
+#Close the fd = 5
d2787b
+exec 5>&-
d2787b
+
d2787b
+cleanup
d2787b
diff --git a/xlators/features/shard/src/shard.c b/xlators/features/shard/src/shard.c
d2787b
index c5cc224..2ba4528 100644
d2787b
--- a/xlators/features/shard/src/shard.c
d2787b
+++ b/xlators/features/shard/src/shard.c
d2787b
@@ -1653,26 +1653,24 @@ err:
d2787b
 }
d2787b
 
d2787b
 int
d2787b
-shard_lookup_base_file_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
d2787b
-                           int32_t op_ret, int32_t op_errno, inode_t *inode,
d2787b
-                           struct iatt *buf, dict_t *xdata,
d2787b
-                           struct iatt *postparent)
d2787b
+shard_set_iattr_invoke_post_handler(call_frame_t *frame, xlator_t *this,
d2787b
+                                    inode_t *inode, int32_t op_ret,
d2787b
+                                    int32_t op_errno, struct iatt *buf,
d2787b
+                                    dict_t *xdata)
d2787b
 {
d2787b
     int ret = -1;
d2787b
     int32_t mask = SHARD_INODE_WRITE_MASK;
d2787b
-    shard_local_t *local = NULL;
d2787b
+    shard_local_t *local = frame->local;
d2787b
     shard_inode_ctx_t ctx = {
d2787b
         0,
d2787b
     };
d2787b
 
d2787b
-    local = frame->local;
d2787b
-
d2787b
     if (op_ret < 0) {
d2787b
         gf_msg(this->name, GF_LOG_ERROR, op_errno,
d2787b
                SHARD_MSG_BASE_FILE_LOOKUP_FAILED,
d2787b
                "Lookup on base file"
d2787b
                " failed : %s",
d2787b
-               loc_gfid_utoa(&(local->loc)));
d2787b
+               uuid_utoa(inode->gfid));
d2787b
         local->op_ret = op_ret;
d2787b
         local->op_errno = op_errno;
d2787b
         goto unwind;
d2787b
@@ -1706,18 +1704,57 @@ unwind:
d2787b
 }
d2787b
 
d2787b
 int
d2787b
-shard_lookup_base_file(call_frame_t *frame, xlator_t *this, loc_t *loc,
d2787b
-                       shard_post_fop_handler_t handler)
d2787b
+shard_fstat_base_file_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
d2787b
+                          int32_t op_ret, int32_t op_errno, struct iatt *buf,
d2787b
+                          dict_t *xdata)
d2787b
+{
d2787b
+    shard_local_t *local = frame->local;
d2787b
+
d2787b
+    shard_set_iattr_invoke_post_handler(frame, this, local->fd->inode, op_ret,
d2787b
+                                        op_errno, buf, xdata);
d2787b
+    return 0;
d2787b
+}
d2787b
+
d2787b
+int
d2787b
+shard_lookup_base_file_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
d2787b
+                           int32_t op_ret, int32_t op_errno, inode_t *inode,
d2787b
+                           struct iatt *buf, dict_t *xdata,
d2787b
+                           struct iatt *postparent)
d2787b
+{
d2787b
+    /* In case of op_ret < 0, inode passed to this function will be NULL
d2787b
+       ex: in case of op_errno = ENOENT. So refer prefilled inode data
d2787b
+       which is part of local.
d2787b
+       Note: Reassigning/overriding the inode passed to this cbk with inode
d2787b
+       which is part of *struct shard_local_t* won't cause any issue as
d2787b
+       both inodes have same reference/address as of the inode passed */
d2787b
+    inode = ((shard_local_t *)frame->local)->loc.inode;
d2787b
+
d2787b
+    shard_set_iattr_invoke_post_handler(frame, this, inode, op_ret, op_errno,
d2787b
+                                        buf, xdata);
d2787b
+    return 0;
d2787b
+}
d2787b
+
d2787b
+/* This function decides whether to make file based lookup or
d2787b
+ * fd based lookup (fstat) depending on the 3rd and 4th arg.
d2787b
+ * If fd != NULL and loc == NULL then call is for fstat
d2787b
+ * If fd == NULL and loc != NULL then call is for file based
d2787b
+ * lookup. Please pass args based on the requirement.
d2787b
+ */
d2787b
+int
d2787b
+shard_refresh_base_file(call_frame_t *frame, xlator_t *this, loc_t *loc,
d2787b
+                        fd_t *fd, shard_post_fop_handler_t handler)
d2787b
 {
d2787b
     int ret = -1;
d2787b
+    inode_t *inode = NULL;
d2787b
     shard_local_t *local = NULL;
d2787b
     dict_t *xattr_req = NULL;
d2787b
     gf_boolean_t need_refresh = _gf_false;
d2787b
 
d2787b
     local = frame->local;
d2787b
     local->handler = handler;
d2787b
+    inode = fd ? fd->inode : loc->inode;
d2787b
 
d2787b
-    ret = shard_inode_ctx_fill_iatt_from_cache(loc->inode, this, &local->prebuf,
d2787b
+    ret = shard_inode_ctx_fill_iatt_from_cache(inode, this, &local->prebuf,
d2787b
                                                &need_refresh);
d2787b
     /* By this time, inode ctx should have been created either in create,
d2787b
      * mknod, readdirp or lookup. If not it is a bug!
d2787b
@@ -1726,7 +1763,7 @@ shard_lookup_base_file(call_frame_t *frame, xlator_t *this, loc_t *loc,
d2787b
         gf_msg_debug(this->name, 0,
d2787b
                      "Skipping lookup on base file: %s"
d2787b
                      "Serving prebuf off the inode ctx cache",
d2787b
-                     uuid_utoa(loc->gfid));
d2787b
+                     uuid_utoa(inode->gfid));
d2787b
         goto out;
d2787b
     }
d2787b
 
d2787b
@@ -1737,10 +1774,14 @@ shard_lookup_base_file(call_frame_t *frame, xlator_t *this, loc_t *loc,
d2787b
         goto out;
d2787b
     }
d2787b
 
d2787b
-    SHARD_MD_READ_FOP_INIT_REQ_DICT(this, xattr_req, loc->gfid, local, out);
d2787b
+    SHARD_MD_READ_FOP_INIT_REQ_DICT(this, xattr_req, inode->gfid, local, out);
d2787b
 
d2787b
-    STACK_WIND(frame, shard_lookup_base_file_cbk, FIRST_CHILD(this),
d2787b
-               FIRST_CHILD(this)->fops->lookup, loc, xattr_req);
d2787b
+    if (fd)
d2787b
+        STACK_WIND(frame, shard_fstat_base_file_cbk, FIRST_CHILD(this),
d2787b
+                   FIRST_CHILD(this)->fops->fstat, fd, xattr_req);
d2787b
+    else
d2787b
+        STACK_WIND(frame, shard_lookup_base_file_cbk, FIRST_CHILD(this),
d2787b
+                   FIRST_CHILD(this)->fops->lookup, loc, xattr_req);
d2787b
 
d2787b
     dict_unref(xattr_req);
d2787b
     return 0;
d2787b
@@ -2718,8 +2759,8 @@ shard_truncate(call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset,
d2787b
     local->resolver_base_inode = loc->inode;
d2787b
     GF_ATOMIC_INIT(local->delta_blocks, 0);
d2787b
 
d2787b
-    shard_lookup_base_file(frame, this, &local->loc,
d2787b
-                           shard_post_lookup_truncate_handler);
d2787b
+    shard_refresh_base_file(frame, this, &local->loc, NULL,
d2787b
+                            shard_post_lookup_truncate_handler);
d2787b
     return 0;
d2787b
 
d2787b
 err:
d2787b
@@ -2774,8 +2815,8 @@ shard_ftruncate(call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset,
d2787b
     local->resolver_base_inode = fd->inode;
d2787b
     GF_ATOMIC_INIT(local->delta_blocks, 0);
d2787b
 
d2787b
-    shard_lookup_base_file(frame, this, &local->loc,
d2787b
-                           shard_post_lookup_truncate_handler);
d2787b
+    shard_refresh_base_file(frame, this, NULL, fd,
d2787b
+                            shard_post_lookup_truncate_handler);
d2787b
     return 0;
d2787b
 err:
d2787b
     shard_common_failure_unwind(GF_FOP_FTRUNCATE, frame, -1, ENOMEM);
d2787b
@@ -2919,8 +2960,8 @@ shard_link(call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc,
d2787b
     if (!local->xattr_req)
d2787b
         goto err;
d2787b
 
d2787b
-    shard_lookup_base_file(frame, this, &local->loc,
d2787b
-                           shard_post_lookup_link_handler);
d2787b
+    shard_refresh_base_file(frame, this, &local->loc, NULL,
d2787b
+                            shard_post_lookup_link_handler);
d2787b
     return 0;
d2787b
 err:
d2787b
     shard_common_failure_unwind(GF_FOP_LINK, frame, -1, ENOMEM);
d2787b
@@ -4249,8 +4290,8 @@ shard_post_inodelk_fop_handler(call_frame_t *frame, xlator_t *this)
d2787b
     switch (local->fop) {
d2787b
         case GF_FOP_UNLINK:
d2787b
         case GF_FOP_RENAME:
d2787b
-            shard_lookup_base_file(frame, this, &local->int_inodelk.loc,
d2787b
-                                   shard_post_lookup_base_shard_rm_handler);
d2787b
+            shard_refresh_base_file(frame, this, &local->int_inodelk.loc, NULL,
d2787b
+                                    shard_post_lookup_base_shard_rm_handler);
d2787b
             break;
d2787b
         default:
d2787b
             gf_msg(this->name, GF_LOG_WARNING, 0, SHARD_MSG_INVALID_FOP,
d2787b
@@ -4505,8 +4546,8 @@ shard_rename_src_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
d2787b
     if (local->block_size) {
d2787b
         local->tmp_loc.inode = inode_new(this->itable);
d2787b
         gf_uuid_copy(local->tmp_loc.gfid, (local->loc.inode)->gfid);
d2787b
-        shard_lookup_base_file(frame, this, &local->tmp_loc,
d2787b
-                               shard_post_rename_lookup_handler);
d2787b
+        shard_refresh_base_file(frame, this, &local->tmp_loc, NULL,
d2787b
+                                shard_post_rename_lookup_handler);
d2787b
     } else {
d2787b
         shard_rename_cbk(frame, this);
d2787b
     }
d2787b
@@ -5242,8 +5283,8 @@ shard_readv(call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size,
d2787b
     local->loc.inode = inode_ref(fd->inode);
d2787b
     gf_uuid_copy(local->loc.gfid, fd->inode->gfid);
d2787b
 
d2787b
-    shard_lookup_base_file(frame, this, &local->loc,
d2787b
-                           shard_post_lookup_readv_handler);
d2787b
+    shard_refresh_base_file(frame, this, NULL, fd,
d2787b
+                            shard_post_lookup_readv_handler);
d2787b
     return 0;
d2787b
 err:
d2787b
     shard_common_failure_unwind(GF_FOP_READ, frame, -1, ENOMEM);
d2787b
@@ -6046,8 +6087,8 @@ shard_fsync(call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t datasync,
d2787b
     local->loc.inode = inode_ref(fd->inode);
d2787b
     gf_uuid_copy(local->loc.gfid, fd->inode->gfid);
d2787b
 
d2787b
-    shard_lookup_base_file(frame, this, &local->loc,
d2787b
-                           shard_post_lookup_fsync_handler);
d2787b
+    shard_refresh_base_file(frame, this, NULL, fd,
d2787b
+                            shard_post_lookup_fsync_handler);
d2787b
     return 0;
d2787b
 err:
d2787b
     shard_common_failure_unwind(GF_FOP_FSYNC, frame, -1, ENOMEM);
d2787b
@@ -6420,12 +6461,8 @@ shard_common_remove_xattr(call_frame_t *frame, xlator_t *this,
d2787b
     if (xdata)
d2787b
         local->xattr_req = dict_ref(xdata);
d2787b
 
d2787b
-    /* To-Do: Switch from LOOKUP which is path-based, to FSTAT if the fop is
d2787b
-     * on an fd. This comes under a generic class of bugs in shard tracked by
d2787b
-     * bz #1782428.
d2787b
-     */
d2787b
-    shard_lookup_base_file(frame, this, &local->loc,
d2787b
-                           shard_post_lookup_remove_xattr_handler);
d2787b
+    shard_refresh_base_file(frame, this, loc, fd,
d2787b
+                            shard_post_lookup_remove_xattr_handler);
d2787b
     return 0;
d2787b
 err:
d2787b
     shard_common_failure_unwind(fop, frame, -1, op_errno);
d2787b
@@ -6662,12 +6699,8 @@ shard_common_set_xattr(call_frame_t *frame, xlator_t *this, glusterfs_fop_t fop,
d2787b
     if (xdata)
d2787b
         local->xattr_rsp = dict_ref(xdata);
d2787b
 
d2787b
-    /* To-Do: Switch from LOOKUP which is path-based, to FSTAT if the fop is
d2787b
-     * on an fd. This comes under a generic class of bugs in shard tracked by
d2787b
-     * bz #1782428.
d2787b
-     */
d2787b
-    shard_lookup_base_file(frame, this, &local->loc,
d2787b
-                           shard_post_lookup_set_xattr_handler);
d2787b
+    shard_refresh_base_file(frame, this, loc, fd,
d2787b
+                            shard_post_lookup_set_xattr_handler);
d2787b
     return 0;
d2787b
 err:
d2787b
     shard_common_failure_unwind(fop, frame, -1, op_errno);
d2787b
@@ -6951,8 +6984,8 @@ shard_common_inode_write_begin(call_frame_t *frame, xlator_t *this,
d2787b
     local->loc.inode = inode_ref(fd->inode);
d2787b
     gf_uuid_copy(local->loc.gfid, fd->inode->gfid);
d2787b
 
d2787b
-    shard_lookup_base_file(frame, this, &local->loc,
d2787b
-                           shard_common_inode_write_post_lookup_handler);
d2787b
+    shard_refresh_base_file(frame, this, NULL, fd,
d2787b
+                            shard_common_inode_write_post_lookup_handler);
d2787b
     return 0;
d2787b
 out:
d2787b
     shard_common_failure_unwind(fop, frame, -1, ENOMEM);
d2787b
-- 
d2787b
1.8.3.1
d2787b