summaryrefslogtreecommitdiffstats
path: root/xlators/cluster
diff options
context:
space:
mode:
authorN Balachandran <nbalacha@redhat.com>2016-04-25 16:02:10 +0530
committerRaghavendra G <rgowdapp@redhat.com>2016-05-02 21:40:38 -0700
commit534ca9864907a677551e7aff57e5c021d035303d (patch)
tree9cd24dd40b7881582edd436d8c1bae6f849f624a /xlators/cluster
parenta85e75a111941c50ba1996d70328fe686a34ba07 (diff)
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. Change-Id: If2c6f8dc8ee72e3e6a7e04a04c2108243faca468 BUG: 1331933 Signed-off-by: N Balachandran <nbalacha@redhat.com> Reviewed-on: http://review.gluster.org/14123 Smoke: Gluster Build System <jenkins@build.gluster.com> Tested-by: Raghavendra G <rgowdapp@redhat.com> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> CentOS-regression: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
Diffstat (limited to 'xlators/cluster')
-rw-r--r--xlators/cluster/dht/src/dht-common.c110
-rw-r--r--xlators/cluster/dht/src/dht-selfheal.c11
2 files changed, 108 insertions, 13 deletions
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
index 9a844be435e..b21a4d55464 100644
--- a/xlators/cluster/dht/src/dht-common.c
+++ b/xlators/cluster/dht/src/dht-common.c
@@ -7423,17 +7423,22 @@ 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 *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 +7451,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 +7503,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 +7555,12 @@ unlock:
}
return 0;
+
+err:
+ DHT_STACK_UNWIND (rmdir, frame, local->op_ret,
+ local->op_errno, NULL, NULL, NULL);
+ return 0;
+
}
@@ -7536,6 +7574,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 +7633,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 +7711,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 307116ae618..a70b3f7863c 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);