From b0f1d782fc45313fce4e1c0e74127401d5342d05 Mon Sep 17 00:00:00 2001 From: N Balachandran Date: Tue, 12 Feb 2019 13:58:54 +0530 Subject: cluster/dht: Fix lookup selfheal and rmdir race A race between the lookup selfheal and rmdir can cause directories to be healed only on non-hashed subvols. This can prevent the directory from being listed from the mount point and in turn causes rm -rf to fail with ENOTEMPTY. Fix: Update the layout information correctly and reduce the call count only after processing the response. Change-Id: I812779aaf3d7bcf24aab1cb158cb6ed50d212451 fixes: bz#1676400 Signed-off-by: N Balachandran --- xlators/cluster/dht/src/dht-selfheal.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) (limited to 'xlators/cluster/dht/src') diff --git a/xlators/cluster/dht/src/dht-selfheal.c b/xlators/cluster/dht/src/dht-selfheal.c index e306943edda..bd1b7eae256 100644 --- a/xlators/cluster/dht/src/dht-selfheal.c +++ b/xlators/cluster/dht/src/dht-selfheal.c @@ -1309,11 +1309,13 @@ dht_selfheal_dir_mkdir_lookup_cbk(call_frame_t *frame, void *cookie, int missing_dirs = 0; dht_layout_t *layout = NULL; dht_conf_t *conf = 0; + xlator_t *prev = 0; loc_t *loc = NULL; int check_mds = 0; int errst = 0; int32_t mds_xattr_val[1] = {0}; char gfid_local[GF_UUID_BUF_SIZE] = {0}; + int index = -1; VALIDATE_OR_GOTO(this->private, err); @@ -1321,32 +1323,46 @@ dht_selfheal_dir_mkdir_lookup_cbk(call_frame_t *frame, void *cookie, layout = local->layout; loc = &local->loc; conf = this->private; + prev = cookie; - if (local->gfid) + if (!gf_uuid_is_null(local->gfid)) gf_uuid_unparse(local->gfid, gfid_local); - this_call_cnt = dht_frame_return(frame); - LOCK(&frame->lock); { + index = dht_layout_index_for_subvol(layout, prev); if ((op_ret < 0) && (op_errno == ENOENT || op_errno == ESTALE)) { local->selfheal.hole_cnt = !local->selfheal.hole_cnt ? 1 : local->selfheal.hole_cnt + 1; + /* the status might have changed. Update the layout with the + * new status + */ + if (index >= 0) { + layout->list[index].err = op_errno; + } } if (!op_ret) { dht_iatt_merge(this, &local->stbuf, stbuf); - } - check_mds = dht_dict_get_array(xattr, conf->mds_xattr_key, - mds_xattr_val, 1, &errst); - if (dict_get(xattr, conf->mds_xattr_key) && check_mds && !errst) { - dict_unref(local->xattr); - local->xattr = dict_ref(xattr); + check_mds = dht_dict_get_array(xattr, conf->mds_xattr_key, + mds_xattr_val, 1, &errst); + if (dict_get(xattr, conf->mds_xattr_key) && check_mds && !errst) { + dict_unref(local->xattr); + local->xattr = dict_ref(xattr); + } + /* the status might have changed. Update the layout with the + * new status + */ + if (index >= 0) { + layout->list[index].err = -1; + } } } UNLOCK(&frame->lock); + this_call_cnt = dht_frame_return(frame); + if (is_last_call(this_call_cnt)) { if (local->selfheal.hole_cnt == layout->cnt) { gf_msg_debug(this->name, op_errno, -- cgit