diff options
author | Mohammed Rafi KC <rkavunga@redhat.com> | 2019-06-02 01:36:33 +0530 |
---|---|---|
committer | Pranith Kumar K <pkarampu@redhat.com> | 2019-06-08 17:50:10 +0530 |
commit | 4cfc5788af2488d173ac033850370c4f9ed7a05e (patch) | |
tree | 98a97731e3c76fca7c6f6c06dd2622fe3228adbe /xlators/cluster/ec/src/ec-heal.c | |
parent | 9e0de2b634b888dd069e908b7745197d20fe7036 (diff) | |
download | glusterfs-4cfc5788af2488d173ac033850370c4f9ed7a05e.tar.gz glusterfs-4cfc5788af2488d173ac033850370c4f9ed7a05e.tar.xz glusterfs-4cfc5788af2488d173ac033850370c4f9ed7a05e.zip |
ec/fini: Fix race between xlator cleanup and on going async fop
Problem:
While we process a cleanup, there is a chance for a race between
async operations, for example ec_launch_replace_heal. So this can
lead to invalid mem access.
Solution:
Just like we track on going heal fops, we can also track fops like
ec_launch_replace_heal, so that we can decide when to send a
PARENT_DOWN request.
Change-Id: I055391c5c6c34d58aef7336847f3b570cb831298
fixes: bz#1703948
Signed-off-by: Mohammed Rafi KC <rkavunga@redhat.com>
Diffstat (limited to 'xlators/cluster/ec/src/ec-heal.c')
-rw-r--r-- | xlators/cluster/ec/src/ec-heal.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/xlators/cluster/ec/src/ec-heal.c b/xlators/cluster/ec/src/ec-heal.c index 8844c292f8..237fea2235 100644 --- a/xlators/cluster/ec/src/ec-heal.c +++ b/xlators/cluster/ec/src/ec-heal.c @@ -2814,8 +2814,20 @@ int ec_replace_heal_done(int ret, call_frame_t *heal, void *opaque) { ec_t *ec = opaque; + gf_boolean_t last_fop = _gf_false; + if (GF_ATOMIC_DEC(ec->async_fop_count) == 0) { + LOCK(&ec->lock); + { + last_fop = __ec_is_last_fop(ec); + } + UNLOCK(&ec->lock); + } gf_msg_debug(ec->xl->name, 0, "getxattr on bricks is done ret %d", ret); + + if (last_fop) + ec_pending_fops_completed(ec); + return 0; } @@ -2869,14 +2881,15 @@ ec_launch_replace_heal(ec_t *ec) { int ret = -1; - if (!ec) - return ret; ret = synctask_new(ec->xl->ctx->env, ec_replace_brick_heal_wrap, ec_replace_heal_done, NULL, ec); + if (ret < 0) { gf_msg_debug(ec->xl->name, 0, "Heal failed for replace brick ret = %d", ret); + ec_replace_heal_done(-1, NULL, ec); } + return ret; } |