From 64d2a5a25b64601958c0f47ec2e6356226f97d4b Mon Sep 17 00:00:00 2001 From: Pranith Kumar K Date: Mon, 18 May 2015 14:46:55 +0530 Subject: cluster/ec: Handle lookup failures while op in progress Change-Id: Ia1834ec23d5de615526d4d4e4d2e32aff155b7f7 BUG: 1211962 Signed-off-by: Pranith Kumar K Reviewed-on: http://review.gluster.org/10806 Tested-by: NetBSD Build System Tested-by: Gluster Build System Reviewed-by: Xavier Hernandez --- xlators/cluster/ec/src/ec-common.c | 16 +++++++++------- xlators/cluster/ec/src/ec-generic.c | 19 ++++++++++++++----- 2 files changed, 23 insertions(+), 12 deletions(-) (limited to 'xlators/cluster') diff --git a/xlators/cluster/ec/src/ec-common.c b/xlators/cluster/ec/src/ec-common.c index 393d9142797..afd46c095f3 100644 --- a/xlators/cluster/ec/src/ec-common.c +++ b/xlators/cluster/ec/src/ec-common.c @@ -1206,14 +1206,16 @@ void ec_get_size_version(ec_fop_data_t * fop) loc.path = NULL; loc.name = NULL; } - /* For normal fops, ec_lookup() must succeed on at least EC_MINIMUM_MIN - * bricks, however when this is called as part of a self-heal operation - * the mask of target bricks (fop->mask) could contain less than - * EC_MINIMUM_MIN bricks, causing the lookup to always fail. Thus we - * always use the same minimum used for the main fop. + /* For normal fops, ec_[f]xattrop() must succeed on at least + * EC_MINIMUM_MIN bricks, however when this is called as part of + * a self-heal operation the mask of target bricks (fop->mask) could + * contain less than EC_MINIMUM_MIN bricks, causing the lookup to + * always fail. Thus we always use the same minimum used for the main + * fop. */ - ec_lookup(fop->frame, fop->xl, fop->mask, fop->minimum, - ec_get_size_version_set, NULL, &loc, xdata); + ec_xattrop (fop->frame, fop->xl, fop->mask, fop->minimum, + ec_prepare_update_cbk, NULL, &loc, + GF_XATTROP_ADD_ARRAY64, xdata, NULL); } else { if (ec_loc_from_fd(fop->xl, &loc, fop->fd) != 0) { goto out; diff --git a/xlators/cluster/ec/src/ec-generic.c b/xlators/cluster/ec/src/ec-generic.c index d957bf6533d..9d64735df55 100644 --- a/xlators/cluster/ec/src/ec-generic.c +++ b/xlators/cluster/ec/src/ec-generic.c @@ -964,9 +964,20 @@ int32_t ec_manager_lookup(ec_fop_data_t * fop, int32_t state) return EC_STATE_PREPARE_ANSWER; case EC_STATE_PREPARE_ANSWER: + /* + * Lookup happens without any lock, so there is a chance that it + * will have answers before modification happened and after + * modification happened in the same response. So choose the next + * best answer when the answers don't match for EC_MINIMUM_MIN + */ + + if (!fop->answer && !list_empty(&fop->cbk_list)) { + fop->answer = list_entry (fop->cbk_list.next, ec_cbk_data_t, + list); + } + cbk = fop->answer; - if (cbk != NULL) - { + if (cbk != NULL) { if (!ec_dict_combine(cbk, EC_COMBINE_XDATA)) { if (cbk->op_ret >= 0) @@ -986,9 +997,7 @@ int32_t ec_manager_lookup(ec_fop_data_t * fop, int32_t state) ec_lookup_rebuild(fop->xl->private, fop, cbk); } - } - else - { + } else { ec_fop_set_error(fop, EIO); } -- cgit