e7a346
From e76a777f3820e62948256a45a38d5e97f3eb08a9 Mon Sep 17 00:00:00 2001
e7a346
From: N Balachandran <nbalacha@redhat.com>
e7a346
Date: Tue, 28 Aug 2018 12:00:33 +0530
e7a346
Subject: [PATCH 438/444] cluster/dht: In rename, unlink after creating linkto
e7a346
 file
e7a346
e7a346
The linkto file creation for the dst was done in parallel with
e7a346
the unlink of the old src linkto. If these operations reached
e7a346
the brick out of order, we end up with a dst linkto file without
e7a346
a .glusterfs handle.
e7a346
e7a346
Fixed by unlinking only after the linkto file creation has
e7a346
completed.
e7a346
e7a346
upstream patch: https://review.gluster.org/#/c/glusterfs/+/21023/
e7a346
e7a346
> Change-Id: I4246f7655f5bc180f5ded7fd34d263b7828a8110
e7a346
> fixes: bz#1621981
e7a346
> Signed-off-by: N Balachandran <nbalacha@redhat.com>
e7a346
e7a346
Change-Id: Ia845a68bb314997cadab57887a84dff9373400c4
e7a346
BUG: 1622001
e7a346
Signed-off-by: N Balachandran <nbalacha@redhat.com>
e7a346
Reviewed-on: https://code.engineering.redhat.com/gerrit/154933
e7a346
Tested-by: RHGS Build Bot <nigelb@redhat.com>
e7a346
Reviewed-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
e7a346
---
e7a346
 tests/bugs/posix/bug-1619720.t       |   1 +
e7a346
 xlators/cluster/dht/src/dht-rename.c | 254 ++++++++++++++++++-----------------
e7a346
 2 files changed, 133 insertions(+), 122 deletions(-)
e7a346
e7a346
diff --git a/tests/bugs/posix/bug-1619720.t b/tests/bugs/posix/bug-1619720.t
e7a346
index 5e0d0f7..bfd304d 100755
e7a346
--- a/tests/bugs/posix/bug-1619720.t
e7a346
+++ b/tests/bugs/posix/bug-1619720.t
e7a346
@@ -48,6 +48,7 @@ TEST mv $M0/tmp/file-2 $M0/tmp/file-3
e7a346
 
e7a346
 TEST mv -f $M0/tmp/file-1 $M0/tmp/file-3
e7a346
 
e7a346
+
e7a346
 TEST getfattr -n $pgfid_xattr_name $B0/${V0}0/tmp/file-3
e7a346
 TEST getfattr -n $pgfid_xattr_name $B0/${V0}1/tmp/file-3
e7a346
 
e7a346
diff --git a/xlators/cluster/dht/src/dht-rename.c b/xlators/cluster/dht/src/dht-rename.c
e7a346
index 1d0c2bb..378cb0a 100644
e7a346
--- a/xlators/cluster/dht/src/dht-rename.c
e7a346
+++ b/xlators/cluster/dht/src/dht-rename.c
e7a346
@@ -849,8 +849,8 @@ dht_rename_cleanup (call_frame_t *frame)
e7a346
         if (src_cached == dst_cached)
e7a346
                 goto nolinks;
e7a346
 
e7a346
-        if (local->linked && (dst_hashed != src_hashed )&&
e7a346
-                (dst_hashed != src_cached)) {
e7a346
+        if (local->linked && (dst_hashed != src_hashed) &&
e7a346
+            (dst_hashed != src_cached)) {
e7a346
                 call_cnt++;
e7a346
         }
e7a346
 
e7a346
@@ -935,6 +935,120 @@ nolinks:
e7a346
 
e7a346
 
e7a346
 int
e7a346
+dht_rename_unlink (call_frame_t *frame, xlator_t *this)
e7a346
+{
e7a346
+        dht_local_t  *local = NULL;
e7a346
+        xlator_t     *src_hashed = NULL;
e7a346
+        xlator_t     *src_cached = NULL;
e7a346
+        xlator_t     *dst_hashed = NULL;
e7a346
+        xlator_t     *dst_cached = NULL;
e7a346
+        xlator_t     *rename_subvol = NULL;
e7a346
+        dict_t       *xattr     = NULL;
e7a346
+
e7a346
+        local = frame->local;
e7a346
+
e7a346
+        src_hashed = local->src_hashed;
e7a346
+        src_cached = local->src_cached;
e7a346
+        dst_hashed = local->dst_hashed;
e7a346
+        dst_cached = local->dst_cached;
e7a346
+
e7a346
+        local->call_cnt = 0;
e7a346
+
e7a346
+        /* NOTE: rename_subvol is the same subvolume from which dht_rename_cbk
e7a346
+         * is called. since rename has already happened on rename_subvol,
e7a346
+         * unlink shouldn't be sent for oldpath (either linkfile or cached-file)
e7a346
+         * on rename_subvol. */
e7a346
+        if (src_cached == dst_cached)
e7a346
+                rename_subvol = src_cached;
e7a346
+        else
e7a346
+                rename_subvol = dst_hashed;
e7a346
+
e7a346
+        /* TODO: delete files in background */
e7a346
+
e7a346
+        if (src_cached != dst_hashed && src_cached != dst_cached)
e7a346
+                local->call_cnt++;
e7a346
+
e7a346
+        if (src_hashed != rename_subvol && src_hashed != src_cached)
e7a346
+                local->call_cnt++;
e7a346
+
e7a346
+        if (dst_cached && dst_cached != dst_hashed && dst_cached != src_cached)
e7a346
+                local->call_cnt++;
e7a346
+
e7a346
+        if (local->call_cnt == 0)
e7a346
+                goto unwind;
e7a346
+
e7a346
+        DHT_MARK_FOP_INTERNAL (xattr);
e7a346
+
e7a346
+        if (src_cached != dst_hashed && src_cached != dst_cached) {
e7a346
+                dict_t *xattr_new = NULL;
e7a346
+
e7a346
+                xattr_new = dict_copy_with_ref (xattr, NULL);
e7a346
+
e7a346
+                gf_msg_trace (this->name, 0,
e7a346
+                              "deleting old src datafile %s @ %s",
e7a346
+                              local->loc.path, src_cached->name);
e7a346
+
e7a346
+                if (gf_uuid_compare (local->loc.pargfid,
e7a346
+                                     local->loc2.pargfid) == 0) {
e7a346
+                        DHT_MARKER_DONT_ACCOUNT(xattr_new);
e7a346
+                }
e7a346
+
e7a346
+                DHT_CHANGELOG_TRACK_AS_RENAME(xattr_new, &local->loc,
e7a346
+                                              &local->loc2);
e7a346
+                STACK_WIND_COOKIE (frame, dht_rename_unlink_cbk, src_cached,
e7a346
+                                   src_cached, src_cached->fops->unlink,
e7a346
+                                   &local->loc, 0, xattr_new);
e7a346
+
e7a346
+                dict_unref (xattr_new);
e7a346
+                xattr_new = NULL;
e7a346
+        }
e7a346
+
e7a346
+        if (src_hashed != rename_subvol && src_hashed != src_cached) {
e7a346
+                dict_t *xattr_new = NULL;
e7a346
+
e7a346
+                xattr_new = dict_copy_with_ref (xattr, NULL);
e7a346
+
e7a346
+                gf_msg_trace (this->name, 0,
e7a346
+                              "deleting old src linkfile %s @ %s",
e7a346
+                              local->loc.path, src_hashed->name);
e7a346
+
e7a346
+                DHT_MARKER_DONT_ACCOUNT(xattr_new);
e7a346
+
e7a346
+                STACK_WIND_COOKIE (frame, dht_rename_unlink_cbk, src_hashed,
e7a346
+                                   src_hashed, src_hashed->fops->unlink,
e7a346
+                                   &local->loc, 0, xattr_new);
e7a346
+
e7a346
+                dict_unref (xattr_new);
e7a346
+                xattr_new = NULL;
e7a346
+        }
e7a346
+
e7a346
+        if (dst_cached &&
e7a346
+            (dst_cached != dst_hashed) &&
e7a346
+            (dst_cached != src_cached)) {
e7a346
+                gf_msg_trace (this->name, 0,
e7a346
+                              "deleting old dst datafile %s @ %s",
e7a346
+                              local->loc2.path, dst_cached->name);
e7a346
+
e7a346
+                STACK_WIND_COOKIE (frame, dht_rename_unlink_cbk, dst_cached,
e7a346
+                                   dst_cached, dst_cached->fops->unlink,
e7a346
+                                   &local->loc2, 0, xattr);
e7a346
+        }
e7a346
+        if (xattr)
e7a346
+                dict_unref (xattr);
e7a346
+        return 0;
e7a346
+
e7a346
+unwind:
e7a346
+        WIPE (&local->preoldparent);
e7a346
+        WIPE (&local->postoldparent);
e7a346
+        WIPE (&local->preparent);
e7a346
+        WIPE (&local->postparent);
e7a346
+
e7a346
+        dht_rename_done (frame, this);
e7a346
+
e7a346
+        return 0;
e7a346
+}
e7a346
+
e7a346
+int
e7a346
 dht_rename_links_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
e7a346
                              int32_t op_ret, int32_t op_errno,
e7a346
                              inode_t *inode, struct iatt *stbuf,
e7a346
@@ -947,6 +1061,7 @@ dht_rename_links_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
e7a346
         prev = cookie;
e7a346
         local = frame->local;
e7a346
 
e7a346
+        /* TODO: Handle this case in lookup-optimize */
e7a346
         if (op_ret == -1) {
e7a346
                 gf_msg (this->name, GF_LOG_WARNING, op_errno,
e7a346
                         DHT_MSG_CREATE_LINK_FAILED,
e7a346
@@ -958,8 +1073,8 @@ dht_rename_links_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
e7a346
                 local->linked = _gf_false;
e7a346
                 dht_linkfile_attr_heal (frame, this);
e7a346
         }
e7a346
-        DHT_STACK_DESTROY (frame);
e7a346
 
e7a346
+        dht_rename_unlink (frame, this);
e7a346
         return 0;
e7a346
 }
e7a346
 
e7a346
@@ -973,19 +1088,14 @@ dht_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
e7a346
 {
e7a346
         dht_local_t  *local = NULL;
e7a346
         xlator_t     *prev = NULL;
e7a346
-        xlator_t     *src_hashed = NULL;
e7a346
         xlator_t     *src_cached = NULL;
e7a346
         xlator_t     *dst_hashed = NULL;
e7a346
         xlator_t     *dst_cached = NULL;
e7a346
-        xlator_t     *rename_subvol = NULL;
e7a346
-        call_frame_t *link_frame = NULL;
e7a346
-        dht_local_t *link_local = NULL;
e7a346
-        dict_t       *xattr     = NULL;
e7a346
+        loc_t         link_loc  = {0};
e7a346
 
e7a346
         local = frame->local;
e7a346
         prev = cookie;
e7a346
 
e7a346
-        src_hashed = local->src_hashed;
e7a346
         src_cached = local->src_cached;
e7a346
         dst_hashed = local->dst_hashed;
e7a346
         dst_cached = local->dst_cached;
e7a346
@@ -1043,31 +1153,6 @@ dht_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
e7a346
                         local->xattr = dict_copy_with_ref (xdata, local->xattr);
e7a346
         }
e7a346
 
e7a346
-        if ((src_cached == dst_cached) && (dst_hashed != dst_cached)) {
e7a346
-                link_frame = copy_frame (frame);
e7a346
-                if (!link_frame) {
e7a346
-                        goto err;
e7a346
-                }
e7a346
-
e7a346
-                /* fop value sent as maxvalue because it is not used
e7a346
-                   anywhere in this case */
e7a346
-                link_local = dht_local_init (link_frame, &local->loc2, NULL,
e7a346
-                                             GF_FOP_MAXVALUE);
e7a346
-                if (!link_local) {
e7a346
-                        goto err;
e7a346
-                }
e7a346
-
e7a346
-                if (link_local->loc.inode)
e7a346
-                        inode_unref (link_local->loc.inode);
e7a346
-                link_local->loc.inode = inode_ref (local->loc.inode);
e7a346
-                gf_uuid_copy (link_local->gfid, local->loc.inode->gfid);
e7a346
-
e7a346
-                dht_linkfile_create (link_frame, dht_rename_links_create_cbk,
e7a346
-                                     this, src_cached, dst_hashed,
e7a346
-                                     &link_local->loc);
e7a346
-        }
e7a346
-
e7a346
-err:
e7a346
         /* Merge attrs only from src_cached. In case there of src_cached !=
e7a346
          * dst_hashed, this ignores linkfile attrs. */
e7a346
         if (prev == src_cached) {
e7a346
@@ -1080,98 +1165,23 @@ err:
e7a346
                 dht_iatt_merge (this, &local->postparent, postnewparent, prev);
e7a346
         }
e7a346
 
e7a346
+        /* Create the linkto file for the dst file */
e7a346
+        if ((src_cached == dst_cached) && (dst_hashed != dst_cached)) {
e7a346
 
e7a346
-        /* NOTE: rename_subvol is the same subvolume from which dht_rename_cbk
e7a346
-         *       is called. since rename has already happened on rename_subvol,
e7a346
-         *       unlink should not be sent for oldpath (either linkfile or cached-file)
e7a346
-         *       on rename_subvol. */
e7a346
-        if (src_cached == dst_cached)
e7a346
-                rename_subvol = src_cached;
e7a346
-        else
e7a346
-                rename_subvol = dst_hashed;
e7a346
-
e7a346
-        /* TODO: delete files in background */
e7a346
-
e7a346
-        if (src_cached != dst_hashed && src_cached != dst_cached)
e7a346
-                local->call_cnt++;
e7a346
-
e7a346
-        if (src_hashed != rename_subvol && src_hashed != src_cached)
e7a346
-                local->call_cnt++;
e7a346
-
e7a346
-        if (dst_cached && dst_cached != dst_hashed && dst_cached != src_cached)
e7a346
-                local->call_cnt++;
e7a346
-
e7a346
-        if (local->call_cnt == 0)
e7a346
-                goto unwind;
e7a346
-
e7a346
-        DHT_MARK_FOP_INTERNAL (xattr);
e7a346
-
e7a346
-        if (src_cached != dst_hashed && src_cached != dst_cached) {
e7a346
-                dict_t *xattr_new = NULL;
e7a346
-
e7a346
-                xattr_new = dict_copy_with_ref (xattr, NULL);
e7a346
-
e7a346
-                gf_msg_trace (this->name, 0,
e7a346
-                              "deleting old src datafile %s @ %s",
e7a346
-                              local->loc.path, src_cached->name);
e7a346
-
e7a346
-                if (gf_uuid_compare (local->loc.pargfid,
e7a346
-                                  local->loc2.pargfid) == 0) {
e7a346
-                        DHT_MARKER_DONT_ACCOUNT(xattr_new);
e7a346
-                }
e7a346
-
e7a346
-                DHT_CHANGELOG_TRACK_AS_RENAME(xattr_new, &local->loc,
e7a346
-                                              &local->loc2);
e7a346
-                STACK_WIND_COOKIE (frame, dht_rename_unlink_cbk, src_cached,
e7a346
-                                   src_cached, src_cached->fops->unlink,
e7a346
-                                   &local->loc, 0, xattr_new);
e7a346
-
e7a346
-                dict_unref (xattr_new);
e7a346
-                xattr_new = NULL;
e7a346
-        }
e7a346
-
e7a346
-        if (src_hashed != rename_subvol && src_hashed != src_cached) {
e7a346
-                dict_t *xattr_new = NULL;
e7a346
-
e7a346
-                xattr_new = dict_copy_with_ref (xattr, NULL);
e7a346
-
e7a346
-                gf_msg_trace (this->name, 0,
e7a346
-                              "deleting old src linkfile %s @ %s",
e7a346
-                              local->loc.path, src_hashed->name);
e7a346
-
e7a346
-                DHT_MARKER_DONT_ACCOUNT(xattr_new);
e7a346
-
e7a346
-                STACK_WIND_COOKIE (frame, dht_rename_unlink_cbk, src_hashed,
e7a346
-                                   src_hashed, src_hashed->fops->unlink,
e7a346
-                                   &local->loc, 0, xattr_new);
e7a346
-
e7a346
-                dict_unref (xattr_new);
e7a346
-                xattr_new = NULL;
e7a346
-        }
e7a346
+                loc_copy (&link_loc, &local->loc2);
e7a346
+                if (link_loc.inode)
e7a346
+                        inode_unref (link_loc.inode);
e7a346
+                link_loc.inode = inode_ref (local->loc.inode);
e7a346
+                gf_uuid_copy (local->gfid, local->loc.inode->gfid);
e7a346
+                gf_uuid_copy (link_loc.gfid, local->loc.inode->gfid);
e7a346
 
e7a346
-        if (dst_cached
e7a346
-            && (dst_cached != dst_hashed)
e7a346
-            && (dst_cached != src_cached)) {
e7a346
-                gf_msg_trace (this->name, 0,
e7a346
-                              "deleting old dst datafile %s @ %s",
e7a346
-                              local->loc2.path, dst_cached->name);
e7a346
-
e7a346
-                STACK_WIND_COOKIE (frame, dht_rename_unlink_cbk, dst_cached,
e7a346
-                                   dst_cached, dst_cached->fops->unlink,
e7a346
-                                   &local->loc2, 0, xattr);
e7a346
+                dht_linkfile_create (frame, dht_rename_links_create_cbk,
e7a346
+                                     this, src_cached, dst_hashed,
e7a346
+                                     &link_loc);
e7a346
+                return 0;
e7a346
         }
e7a346
-        if (xattr)
e7a346
-                dict_unref (xattr);
e7a346
-        return 0;
e7a346
-
e7a346
-unwind:
e7a346
-        WIPE (&local->preoldparent);
e7a346
-        WIPE (&local->postoldparent);
e7a346
-        WIPE (&local->preparent);
e7a346
-        WIPE (&local->postparent);
e7a346
-
e7a346
-        dht_rename_done (frame, this);
e7a346
 
e7a346
+        dht_rename_unlink (frame, this);
e7a346
         return 0;
e7a346
 
e7a346
 cleanup:
e7a346
-- 
e7a346
1.8.3.1
e7a346