summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/ec
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/cluster/ec')
-rw-r--r--xlators/cluster/ec/src/ec-common.c16
-rw-r--r--xlators/cluster/ec/src/ec-generic.c19
2 files changed, 23 insertions, 12 deletions
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);
}