12a457
From 98b9c42e563651d9ed5d125e275e3616a7009587 Mon Sep 17 00:00:00 2001
12a457
From: N Balachandran <nbalacha@redhat.com>
12a457
Date: Tue, 3 May 2016 11:00:07 +0530
12a457
Subject: [PATCH 109/139] cluster/dht: Handle rmdir failure correctly
12a457
12a457
DHT did not handle rmdir failures on non-hashed subvols
12a457
correctly in a 2x2 dist-rep volume, causing the
12a457
directory do be deleted from the hashed subvol.
12a457
Also fixed an issue where the dht_selfheal_restore
12a457
errcodes were overwriting the rmdir error codes
12a457
12a457
Upstream:
12a457
master      : http://review.gluster.org/#/c/14060/
12a457
release-3.7 : http://review.gluster.org/14123
12a457
12a457
Change-Id: I51f1bfbb93f5c38fe6cfaf62975acd9d8dfa0ce9
12a457
BUG: 1329514
12a457
Signed-off-by: N Balachandran <nbalacha@redhat.com>
12a457
Reviewed-on: https://code.engineering.redhat.com/gerrit/73469
12a457
Reviewed-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
12a457
Tested-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
12a457
---
12a457
 xlators/cluster/dht/src/dht-common.c   |  113 ++++++++++++++++++++++++++++----
12a457
 xlators/cluster/dht/src/dht-selfheal.c |   11 +++-
12a457
 2 files changed, 110 insertions(+), 14 deletions(-)
12a457
12a457
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
12a457
index b3f3774..c5bb9b7 100644
12a457
--- a/xlators/cluster/dht/src/dht-common.c
12a457
+++ b/xlators/cluster/dht/src/dht-common.c
12a457
@@ -7423,17 +7423,23 @@ err:
12a457
 
12a457
 
12a457
 int
12a457
-dht_rmdir_selfheal_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
12a457
+dht_rmdir_selfheal_cbk (call_frame_t *heal_frame, void *cookie, xlator_t *this,
12a457
                         int op_ret, int op_errno, dict_t *xdata)
12a457
 {
12a457
-        dht_local_t  *local = NULL;
12a457
+        dht_local_t  *local      = NULL;
12a457
+        dht_local_t  *heal_local = NULL;
12a457
+        call_frame_t *main_frame = NULL;
12a457
 
12a457
-        local = frame->local;
12a457
+        heal_local = heal_frame->local;
12a457
+        main_frame = heal_local->main_frame;
12a457
+        local = main_frame->local;
12a457
+
12a457
+        DHT_STACK_DESTROY (heal_frame);
12a457
 
12a457
         dht_set_fixed_dir_stat (&local->preparent);
12a457
         dht_set_fixed_dir_stat (&local->postparent);
12a457
 
12a457
-        DHT_STACK_UNWIND (rmdir, frame, local->op_ret, local->op_errno,
12a457
+        DHT_STACK_UNWIND (rmdir, main_frame, local->op_ret, local->op_errno,
12a457
                           &local->preparent, &local->postparent, NULL);
12a457
 
12a457
         return 0;
12a457
@@ -7446,6 +7452,8 @@ dht_rmdir_hashed_subvol_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
12a457
                              struct iatt *postparent, dict_t *xdata)
12a457
 {
12a457
         dht_local_t  *local = NULL;
12a457
+        dht_local_t  *heal_local = NULL;
12a457
+        call_frame_t *heal_frame = NULL;
12a457
         dht_conf_t   *conf = NULL;
12a457
         int           this_call_cnt = 0;
12a457
         call_frame_t *prev = NULL;
12a457
@@ -7496,8 +7504,33 @@ unlock:
12a457
                         local->stbuf.ia_type = local->loc.inode->ia_type;
12a457
 
12a457
                         gf_uuid_copy (local->gfid, local->loc.inode->gfid);
12a457
-                        dht_selfheal_restore (frame, dht_rmdir_selfheal_cbk,
12a457
-                                              &local->loc, local->layout);
12a457
+
12a457
+                        /* Use a different frame or else the rmdir op_ret is
12a457
+                         * overwritten by that of the selfheal */
12a457
+
12a457
+                        heal_frame = copy_frame (frame);
12a457
+
12a457
+                        if (heal_frame == NULL) {
12a457
+                                goto err;
12a457
+                        }
12a457
+
12a457
+                        heal_local = dht_local_init (heal_frame,
12a457
+                                                     &local->loc,
12a457
+                                                     NULL, 0);
12a457
+                        if (!heal_local) {
12a457
+                                DHT_STACK_DESTROY (heal_frame);
12a457
+                                goto err;
12a457
+                        }
12a457
+
12a457
+                        heal_local->inode = inode_ref (local->loc.inode);
12a457
+                        heal_local->main_frame = frame;
12a457
+                        gf_uuid_copy (heal_local->gfid, local->loc.inode->gfid);
12a457
+
12a457
+                        dht_selfheal_restore (heal_frame,
12a457
+                                              dht_rmdir_selfheal_cbk,
12a457
+                                              &heal_local->loc,
12a457
+                                              heal_local->layout);
12a457
+                        return 0;
12a457
                } else {
12a457
 
12a457
                         if (local->loc.parent) {
12a457
@@ -7523,6 +7556,12 @@ unlock:
12a457
         }
12a457
 
12a457
         return 0;
12a457
+
12a457
+err:
12a457
+        DHT_STACK_UNWIND (rmdir, frame, local->op_ret,
12a457
+                          local->op_errno, NULL, NULL, NULL);
12a457
+        return 0;
12a457
+
12a457
 }
12a457
 
12a457
 
12a457
@@ -7536,6 +7575,9 @@ dht_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
12a457
         call_frame_t *prev = NULL;
12a457
         int           done = 0;
12a457
         char gfid[GF_UUID_BUF_SIZE] ={0};
12a457
+        dht_local_t  *heal_local = NULL;
12a457
+        call_frame_t *heal_frame = NULL;
12a457
+        int           ret        = -1;
12a457
 
12a457
         local = frame->local;
12a457
         prev  = cookie;
12a457
@@ -7592,16 +7634,56 @@ unlock:
12a457
                         local->stbuf.ia_type = local->loc.inode->ia_type;
12a457
 
12a457
                         gf_uuid_copy (local->gfid, local->loc.inode->gfid);
12a457
-                        dht_selfheal_restore (frame, dht_rmdir_selfheal_cbk,
12a457
-                                              &local->loc, local->layout);
12a457
+                        heal_frame = copy_frame (frame);
12a457
+                        if (heal_frame == NULL) {
12a457
+                                goto err;
12a457
+                        }
12a457
+
12a457
+                        heal_local = dht_local_init (heal_frame, &local->loc,
12a457
+                                                     NULL, 0);
12a457
+                        if (!heal_local) {
12a457
+                                DHT_STACK_DESTROY (heal_frame);
12a457
+                                goto err;
12a457
+                        }
12a457
+
12a457
+                        heal_local->inode = inode_ref (local->loc.inode);
12a457
+                        heal_local->main_frame = frame;
12a457
+                        gf_uuid_copy (heal_local->gfid, local->loc.inode->gfid);
12a457
+                        ret = dht_selfheal_restore (heal_frame,
12a457
+                                                    dht_rmdir_selfheal_cbk,
12a457
+                                                    &heal_local->loc,
12a457
+                                                    heal_local->layout);
12a457
+                        if (ret) {
12a457
+                                DHT_STACK_DESTROY (heal_frame);
12a457
+                                goto err;
12a457
+                        }
12a457
+
12a457
                 } else if (this_call_cnt) {
12a457
                         /* If non-hashed subvol's have responded, proceed */
12a457
+                        if (local->op_ret == 0) {
12a457
+                                /* Delete the dir from the hashed subvol if:
12a457
+                                 * The fop succeeded on at least one subvol
12a457
+                                 *  and did not fail on any
12a457
+                                 *  or
12a457
+                                 *  The fop failed with ENOENT/ESTALE on
12a457
+                                 *  all subvols */
12a457
+
12a457
+                                STACK_WIND (frame, dht_rmdir_hashed_subvol_cbk,
12a457
+                                            local->hashed_subvol,
12a457
+                                            local->hashed_subvol->fops->rmdir,
12a457
+                                            &local->loc, local->flags, NULL);
12a457
+                        } else {
12a457
+                         /* hashed-subvol was non-NULL and rmdir failed on
12a457
+                          * all non hashed-subvols. Unwind rmdir with
12a457
+                          * local->op_ret and local->op_errno. */
12a457
+                                dht_rmdir_unlock (frame, this);
12a457
+                                DHT_STACK_UNWIND (rmdir, frame, local->op_ret,
12a457
+                                          local->op_errno, &local->preparent,
12a457
+                                          &local->postparent, NULL);
12a457
 
12a457
-                        local->need_selfheal = 0;
12a457
-                        STACK_WIND (frame, dht_rmdir_hashed_subvol_cbk,
12a457
-                                    local->hashed_subvol,
12a457
-                                    local->hashed_subvol->fops->rmdir,
12a457
-                                    &local->loc, local->flags, NULL);
12a457
+                                return 0;
12a457
+
12a457
+                        }
12a457
                 } else if (!this_call_cnt) {
12a457
                         /* All subvol's have responded, proceed */
12a457
 
12a457
@@ -7630,6 +7712,11 @@ unlock:
12a457
         }
12a457
 
12a457
         return 0;
12a457
+
12a457
+err:
12a457
+        DHT_STACK_UNWIND (rmdir, frame, -1, local->op_errno, NULL, NULL, NULL);
12a457
+        return 0;
12a457
+
12a457
 }
12a457
 
12a457
 
12a457
diff --git a/xlators/cluster/dht/src/dht-selfheal.c b/xlators/cluster/dht/src/dht-selfheal.c
12a457
index 307116a..a70b3f7 100644
12a457
--- a/xlators/cluster/dht/src/dht-selfheal.c
12a457
+++ b/xlators/cluster/dht/src/dht-selfheal.c
12a457
@@ -1314,20 +1314,29 @@ dht_selfheal_dir_mkdir_lookup_cbk (call_frame_t *frame, void *cookie,
12a457
         int           missing_dirs = 0;
12a457
         dht_layout_t  *layout = NULL;
12a457
         loc_t         *loc    = NULL;
12a457
+        call_frame_t *prev    = NULL;
12a457
 
12a457
         VALIDATE_OR_GOTO (this->private, err);
12a457
 
12a457
         local = frame->local;
12a457
         layout = local->layout;
12a457
         loc = &local->loc;
12a457
+        prev  = cookie;
12a457
 
12a457
         this_call_cnt = dht_frame_return (frame);
12a457
 
12a457
         LOCK (&frame->lock);
12a457
         {
12a457
-                if ((op_ret < 0) && (op_errno == ENOENT || op_errno == ESTALE))
12a457
+                if ((op_ret < 0) &&
12a457
+                    (op_errno == ENOENT || op_errno == ESTALE)) {
12a457
                         local->selfheal.hole_cnt = !local->selfheal.hole_cnt ? 1
12a457
                                                 : local->selfheal.hole_cnt + 1;
12a457
+                }
12a457
+
12a457
+                if (!op_ret) {
12a457
+                        dht_iatt_merge (this, &local->stbuf, stbuf, prev->this);
12a457
+                }
12a457
+
12a457
         }
12a457
         UNLOCK (&frame->lock);
12a457
 
12a457
-- 
12a457
1.7.1
12a457