diff options
Diffstat (limited to 'xlators/cluster/ec')
-rw-r--r-- | xlators/cluster/ec/src/ec-data.h | 1 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-heal.c | 9 |
2 files changed, 10 insertions, 0 deletions
diff --git a/xlators/cluster/ec/src/ec-data.h b/xlators/cluster/ec/src/ec-data.h index 285f71e702d..8a48a7ca824 100644 --- a/xlators/cluster/ec/src/ec-data.h +++ b/xlators/cluster/ec/src/ec-data.h @@ -283,6 +283,7 @@ struct _ec_heal fd_t *fd; int32_t partial; int32_t done; + int32_t error; gf_boolean_t nameheal; uintptr_t available; uintptr_t good; diff --git a/xlators/cluster/ec/src/ec-heal.c b/xlators/cluster/ec/src/ec-heal.c index d095aceec00..f76839db38f 100644 --- a/xlators/cluster/ec/src/ec-heal.c +++ b/xlators/cluster/ec/src/ec-heal.c @@ -1777,6 +1777,7 @@ ec_heal_block_done (call_frame_t *frame, void *cookie, xlator_t *this, fop->heal = NULL; heal->fop = NULL; + heal->error = op_ret < 0 ? op_errno : 0; syncbarrier_wake (heal->data); return 0; } @@ -1787,6 +1788,9 @@ ec_sync_heal_block (call_frame_t *frame, xlator_t *this, ec_heal_t *heal) ec_heal_block (frame, this, heal->bad|heal->good, EC_MINIMUM_ONE, ec_heal_block_done, heal); syncbarrier_wait (heal->data, 1); + if (heal->error != 0) { + return -heal->error; + } if (heal->bad == 0) return -ENOTCONN; return 0; @@ -1812,6 +1816,11 @@ ec_rebuild_data (call_frame_t *frame, ec_t *ec, fd_t *fd, uint64_t size, pool = ec->xl->ctx->iobuf_pool; heal->total_size = size; heal->size = iobpool_default_pagesize (pool); + /* We need to adjust the size to a multiple of the stripe size of the + * volume. Otherwise writes would need to fill gaps (head and/or tail) + * with existent data from the bad bricks. This could be garbage on a + * damaged file or it could fail if there aren't enough bricks. */ + heal->size -= heal->size % ec->stripe_size; heal->bad = ec_char_array_to_mask (healed_sinks, ec->nodes); heal->good = ec_char_array_to_mask (sources, ec->nodes); heal->iatt.ia_type = IA_IFREG; |