diff options
Diffstat (limited to 'xlators/cluster/afr/src/afr-self-heal-algorithm.c')
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-algorithm.c | 42 |
1 files changed, 35 insertions, 7 deletions
diff --git a/xlators/cluster/afr/src/afr-self-heal-algorithm.c b/xlators/cluster/afr/src/afr-self-heal-algorithm.c index 6bd0adcd8..99a210836 100644 --- a/xlators/cluster/afr/src/afr-self-heal-algorithm.c +++ b/xlators/cluster/afr/src/afr-self-heal-algorithm.c @@ -456,6 +456,35 @@ sh_loop_write_cbk (call_frame_t *loop_frame, void *cookie, xlator_t *this, return 0; } +static void +sh_prune_writes_needed (call_frame_t *sh_frame, call_frame_t *loop_frame, + afr_private_t *priv) +{ + afr_local_t *sh_local = NULL; + afr_self_heal_t *sh = NULL; + afr_local_t *loop_local = NULL; + afr_self_heal_t *loop_sh = NULL; + int i = 0; + + sh_local = sh_frame->local; + sh = &sh_local->self_heal; + + if (!strcmp (sh->algo->name, "diff")) + return; + + loop_local = loop_frame->local; + loop_sh = &loop_local->self_heal; + + /* full self-heal guarantees there exists atleast 1 file with size 0 + * That means for other files we can preserve holes that come after + * its size before 'trim' + */ + for (i = 0; i < priv->child_count; i++) { + if (loop_sh->write_needed[i] && + ((loop_sh->offset + 1) > sh->buf[i].ia_size)) + loop_sh->write_needed[i] = 0; + } +} static int sh_loop_read_cbk (call_frame_t *loop_frame, void *cookie, @@ -499,16 +528,15 @@ sh_loop_read_cbk (call_frame_t *loop_frame, void *cookie, goto out; } - if (loop_sh->file_has_holes && iov_0filled (vector, count) == 0) { - gf_log (this->name, GF_LOG_DEBUG, "0 filled block"); - sh_loop_return (sh_frame, this, loop_frame, - op_ret, op_errno); - goto out; - } + if (loop_sh->file_has_holes && iov_0filled (vector, count) == 0) + sh_prune_writes_needed (sh_frame, loop_frame, priv); call_count = sh_number_of_writes_needed (loop_sh->write_needed, priv->child_count); - GF_ASSERT (call_count > 0); + if (call_count == 0) { + sh_loop_return (sh_frame, this, loop_frame, 0, 0); + goto out; + } loop_local->call_count = call_count; for (i = 0; i < priv->child_count; i++) { |