From f928dfab3d2e94211d9865ce994ae3a503f2b9a0 Mon Sep 17 00:00:00 2001 From: N Balachandran Date: Mon, 11 Mar 2019 08:06:15 +0530 Subject: [PATCH 536/538] 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. upstream : https://review.gluster.org/#/c/glusterfs/+/22195/ > Change-Id: I812779aaf3d7bcf24aab1cb158cb6ed50d212451 > fixes: bz#1676400 > Signed-off-by: N Balachandran Change-Id: Ic76248ca7dca05d926f48ba84cd5bfa2943fab92 BUG: 1458215 Signed-off-by: N Balachandran Reviewed-on: https://code.engineering.redhat.com/gerrit/164931 Tested-by: RHGS Build Bot Reviewed-by: Mohit Agrawal Reviewed-by: Sunil Kumar Heggodu Gopala Acharya --- xlators/cluster/dht/src/dht-selfheal.c | 36 ++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/xlators/cluster/dht/src/dht-selfheal.c b/xlators/cluster/dht/src/dht-selfheal.c index 035a709..045689b 100644 --- a/xlators/cluster/dht/src/dht-selfheal.c +++ b/xlators/cluster/dht/src/dht-selfheal.c @@ -1366,6 +1366,7 @@ dht_selfheal_dir_mkdir_lookup_cbk (call_frame_t *frame, void *cookie, 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); @@ -1375,32 +1376,47 @@ dht_selfheal_dir_mkdir_lookup_cbk (call_frame_t *frame, void *cookie, prev = cookie; conf = this->private; - 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, prev); + 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; + } } - 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); - } - } 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, -- 1.8.3.1