diff options
author | Sakshi <sabansal@redhat.com> | 2015-07-16 14:31:03 +0530 |
---|---|---|
committer | Raghavendra G <rgowdapp@redhat.com> | 2016-04-05 22:06:02 -0700 |
commit | c25f88c953215b1bfc135aeafc43dc00a663206d (patch) | |
tree | 63bb8af7f4a2d1b363e5018811fe8d19d423df2c /xlators/cluster/dht/src/dht-helper.c | |
parent | 648357ffad482a1bda8915d42df9d5b055dae44f (diff) |
dht: lock on subvols to prevent lookup vs rmdir race
There is a possibility that while an rmdir is completed on
some non-hashed subvol and proceeding to others, a lookup
selfheal can recreate the same directory on those subvols
for which the rmdir had succeeded. Now the deletion of the
parent directory will fail with an ENOTEMPTY.
To fix this take blocking inodelk on the subvols before
starting rmdir. Selfheal must also take blocking inodelk
before creating the entry.
Change-Id: I168a195c35ac1230ba7124d3b0ca157755b3df96
BUG: 1245065
Signed-off-by: Sakshi <sabansal@redhat.com>
Reviewed-on: http://review.gluster.org/13528
CentOS-regression: Gluster Build System <jenkins@build.gluster.com>
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
Smoke: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
Tested-by: Raghavendra G <rgowdapp@redhat.com>
Diffstat (limited to 'xlators/cluster/dht/src/dht-helper.c')
-rw-r--r-- | xlators/cluster/dht/src/dht-helper.c | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/xlators/cluster/dht/src/dht-helper.c b/xlators/cluster/dht/src/dht-helper.c index 8e82eef697c..8673c1fd83a 100644 --- a/xlators/cluster/dht/src/dht-helper.c +++ b/xlators/cluster/dht/src/dht-helper.c @@ -491,6 +491,7 @@ dht_lock_new (xlator_t *this, xlator_t *xl, loc_t *loc, short type, lock->xl = xl; lock->type = type; + lock->domain = gf_strdup (domain); if (lock->domain == NULL) { dht_lock_free (lock); @@ -1976,21 +1977,41 @@ dht_blocking_inodelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, dict_t *xdata) { int lk_index = 0; + int i = 0; dht_local_t *local = NULL; lk_index = (long) cookie; local = frame->local; - if (op_ret == 0) { local->lock.locks[lk_index]->locked = _gf_true; } else { - local->lock.op_ret = -1; - local->lock.op_errno = op_errno; - goto cleanup; + switch (op_errno) { + case ESTALE: + case ENOENT: + if (local->lock.reaction != IGNORE_ENOENT_ESTALE) { + local->lock.op_ret = -1; + local->lock.op_errno = op_errno; + goto cleanup; + } + break; + default: + local->lock.op_ret = -1; + local->lock.op_errno = op_errno; + goto cleanup; + } } if (lk_index == (local->lock.lk_count - 1)) { + for (i = 0; (i < local->lock.lk_count) && + (!local->lock.locks[i]->locked); i++) + ; + + if (i == local->lock.lk_count) { + local->lock.op_ret = -1; + local->lock.op_errno = op_errno; + } + dht_inodelk_done (frame); } else { dht_blocking_inodelk_rec (frame, ++lk_index); @@ -2064,7 +2085,8 @@ out: int dht_blocking_inodelk (call_frame_t *frame, dht_lock_t **lk_array, - int lk_count, fop_inodelk_cbk_t inodelk_cbk) + int lk_count, dht_reaction_type_t reaction, + fop_inodelk_cbk_t inodelk_cbk) { int ret = -1; call_frame_t *lock_frame = NULL; @@ -2086,6 +2108,7 @@ dht_blocking_inodelk (call_frame_t *frame, dht_lock_t **lk_array, dht_set_lkowner (lk_array, lk_count, &lock_frame->root->lk_owner); local = lock_frame->local; + local->lock.reaction = reaction; local->main_frame = frame; dht_blocking_inodelk_rec (lock_frame, 0); |