Blob Blame History Raw
From 98b9c42e563651d9ed5d125e275e3616a7009587 Mon Sep 17 00:00:00 2001
From: N Balachandran <nbalacha@redhat.com>
Date: Tue, 3 May 2016 11:00:07 +0530
Subject: [PATCH 109/139] cluster/dht: Handle rmdir failure correctly

DHT did not handle rmdir failures on non-hashed subvols
correctly in a 2x2 dist-rep volume, causing the
directory do be deleted from the hashed subvol.
Also fixed an issue where the dht_selfheal_restore
errcodes were overwriting the rmdir error codes

Upstream:
master      : http://review.gluster.org/#/c/14060/
release-3.7 : http://review.gluster.org/14123

Change-Id: I51f1bfbb93f5c38fe6cfaf62975acd9d8dfa0ce9
BUG: 1329514
Signed-off-by: N Balachandran <nbalacha@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/73469
Reviewed-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
Tested-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
---
 xlators/cluster/dht/src/dht-common.c   |  113 ++++++++++++++++++++++++++++----
 xlators/cluster/dht/src/dht-selfheal.c |   11 +++-
 2 files changed, 110 insertions(+), 14 deletions(-)

diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
index b3f3774..c5bb9b7 100644
--- a/xlators/cluster/dht/src/dht-common.c
+++ b/xlators/cluster/dht/src/dht-common.c
@@ -7423,17 +7423,23 @@ err:
 
 
 int
-dht_rmdir_selfheal_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+dht_rmdir_selfheal_cbk (call_frame_t *heal_frame, void *cookie, xlator_t *this,
                         int op_ret, int op_errno, dict_t *xdata)
 {
-        dht_local_t  *local = NULL;
+        dht_local_t  *local      = NULL;
+        dht_local_t  *heal_local = NULL;
+        call_frame_t *main_frame = NULL;
 
-        local = frame->local;
+        heal_local = heal_frame->local;
+        main_frame = heal_local->main_frame;
+        local = main_frame->local;
+
+        DHT_STACK_DESTROY (heal_frame);
 
         dht_set_fixed_dir_stat (&local->preparent);
         dht_set_fixed_dir_stat (&local->postparent);
 
-        DHT_STACK_UNWIND (rmdir, frame, local->op_ret, local->op_errno,
+        DHT_STACK_UNWIND (rmdir, main_frame, local->op_ret, local->op_errno,
                           &local->preparent, &local->postparent, NULL);
 
         return 0;
@@ -7446,6 +7452,8 @@ dht_rmdir_hashed_subvol_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
                              struct iatt *postparent, dict_t *xdata)
 {
         dht_local_t  *local = NULL;
+        dht_local_t  *heal_local = NULL;
+        call_frame_t *heal_frame = NULL;
         dht_conf_t   *conf = NULL;
         int           this_call_cnt = 0;
         call_frame_t *prev = NULL;
@@ -7496,8 +7504,33 @@ unlock:
                         local->stbuf.ia_type = local->loc.inode->ia_type;
 
                         gf_uuid_copy (local->gfid, local->loc.inode->gfid);
-                        dht_selfheal_restore (frame, dht_rmdir_selfheal_cbk,
-                                              &local->loc, local->layout);
+
+                        /* Use a different frame or else the rmdir op_ret is
+                         * overwritten by that of the selfheal */
+
+                        heal_frame = copy_frame (frame);
+
+                        if (heal_frame == NULL) {
+                                goto err;
+                        }
+
+                        heal_local = dht_local_init (heal_frame,
+                                                     &local->loc,
+                                                     NULL, 0);
+                        if (!heal_local) {
+                                DHT_STACK_DESTROY (heal_frame);
+                                goto err;
+                        }
+
+                        heal_local->inode = inode_ref (local->loc.inode);
+                        heal_local->main_frame = frame;
+                        gf_uuid_copy (heal_local->gfid, local->loc.inode->gfid);
+
+                        dht_selfheal_restore (heal_frame,
+                                              dht_rmdir_selfheal_cbk,
+                                              &heal_local->loc,
+                                              heal_local->layout);
+                        return 0;
                } else {
 
                         if (local->loc.parent) {
@@ -7523,6 +7556,12 @@ unlock:
         }
 
         return 0;
+
+err:
+        DHT_STACK_UNWIND (rmdir, frame, local->op_ret,
+                          local->op_errno, NULL, NULL, NULL);
+        return 0;
+
 }
 
 
@@ -7536,6 +7575,9 @@ dht_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
         call_frame_t *prev = NULL;
         int           done = 0;
         char gfid[GF_UUID_BUF_SIZE] ={0};
+        dht_local_t  *heal_local = NULL;
+        call_frame_t *heal_frame = NULL;
+        int           ret        = -1;
 
         local = frame->local;
         prev  = cookie;
@@ -7592,16 +7634,56 @@ unlock:
                         local->stbuf.ia_type = local->loc.inode->ia_type;
 
                         gf_uuid_copy (local->gfid, local->loc.inode->gfid);
-                        dht_selfheal_restore (frame, dht_rmdir_selfheal_cbk,
-                                              &local->loc, local->layout);
+                        heal_frame = copy_frame (frame);
+                        if (heal_frame == NULL) {
+                                goto err;
+                        }
+
+                        heal_local = dht_local_init (heal_frame, &local->loc,
+                                                     NULL, 0);
+                        if (!heal_local) {
+                                DHT_STACK_DESTROY (heal_frame);
+                                goto err;
+                        }
+
+                        heal_local->inode = inode_ref (local->loc.inode);
+                        heal_local->main_frame = frame;
+                        gf_uuid_copy (heal_local->gfid, local->loc.inode->gfid);
+                        ret = dht_selfheal_restore (heal_frame,
+                                                    dht_rmdir_selfheal_cbk,
+                                                    &heal_local->loc,
+                                                    heal_local->layout);
+                        if (ret) {
+                                DHT_STACK_DESTROY (heal_frame);
+                                goto err;
+                        }
+
                 } else if (this_call_cnt) {
                         /* If non-hashed subvol's have responded, proceed */
+                        if (local->op_ret == 0) {
+                                /* Delete the dir from the hashed subvol if:
+                                 * The fop succeeded on at least one subvol
+                                 *  and did not fail on any
+                                 *  or
+                                 *  The fop failed with ENOENT/ESTALE on
+                                 *  all subvols */
+
+                                STACK_WIND (frame, dht_rmdir_hashed_subvol_cbk,
+                                            local->hashed_subvol,
+                                            local->hashed_subvol->fops->rmdir,
+                                            &local->loc, local->flags, NULL);
+                        } else {
+                         /* hashed-subvol was non-NULL and rmdir failed on
+                          * all non hashed-subvols. Unwind rmdir with
+                          * local->op_ret and local->op_errno. */
+                                dht_rmdir_unlock (frame, this);
+                                DHT_STACK_UNWIND (rmdir, frame, local->op_ret,
+                                          local->op_errno, &local->preparent,
+                                          &local->postparent, NULL);
 
-                        local->need_selfheal = 0;
-                        STACK_WIND (frame, dht_rmdir_hashed_subvol_cbk,
-                                    local->hashed_subvol,
-                                    local->hashed_subvol->fops->rmdir,
-                                    &local->loc, local->flags, NULL);
+                                return 0;
+
+                        }
                 } else if (!this_call_cnt) {
                         /* All subvol's have responded, proceed */
 
@@ -7630,6 +7712,11 @@ unlock:
         }
 
         return 0;
+
+err:
+        DHT_STACK_UNWIND (rmdir, frame, -1, local->op_errno, NULL, NULL, NULL);
+        return 0;
+
 }
 
 
diff --git a/xlators/cluster/dht/src/dht-selfheal.c b/xlators/cluster/dht/src/dht-selfheal.c
index 307116a..a70b3f7 100644
--- a/xlators/cluster/dht/src/dht-selfheal.c
+++ b/xlators/cluster/dht/src/dht-selfheal.c
@@ -1314,20 +1314,29 @@ dht_selfheal_dir_mkdir_lookup_cbk (call_frame_t *frame, void *cookie,
         int           missing_dirs = 0;
         dht_layout_t  *layout = NULL;
         loc_t         *loc    = NULL;
+        call_frame_t *prev    = NULL;
 
         VALIDATE_OR_GOTO (this->private, err);
 
         local = frame->local;
         layout = local->layout;
         loc = &local->loc;
+        prev  = cookie;
 
         this_call_cnt = dht_frame_return (frame);
 
         LOCK (&frame->lock);
         {
-                if ((op_ret < 0) && (op_errno == ENOENT || op_errno == ESTALE))
+                if ((op_ret < 0) &&
+                    (op_errno == ENOENT || op_errno == ESTALE)) {
                         local->selfheal.hole_cnt = !local->selfheal.hole_cnt ? 1
                                                 : local->selfheal.hole_cnt + 1;
+                }
+
+                if (!op_ret) {
+                        dht_iatt_merge (this, &local->stbuf, stbuf, prev->this);
+                }
+
         }
         UNLOCK (&frame->lock);
 
-- 
1.7.1