From 2533d2b56be0f61b498a62478714036310704a25 Mon Sep 17 00:00:00 2001 From: Pranith Kumar K Date: Thu, 7 Jun 2012 10:57:53 +0530 Subject: cluster/afr: Handle self-heal of files with holes Change-Id: I7a560b3633151c9c1e5a787d1c808d8a396ee754 BUG: 765424 Signed-off-by: Pranith Kumar K Reviewed-on: http://review.gluster.com/3540 Tested-by: Gluster Build System Reviewed-by: Vijay Bellur --- xlators/cluster/afr/src/afr-common.c | 2 + xlators/cluster/afr/src/afr-self-heal-algorithm.c | 105 +++++++++++++--------- xlators/cluster/afr/src/afr-self-heal-algorithm.h | 1 - xlators/cluster/afr/src/afr.h | 1 + 4 files changed, 65 insertions(+), 44 deletions(-) diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c index f0fd6ffd0..d9c42cbcd 100644 --- a/xlators/cluster/afr/src/afr-common.c +++ b/xlators/cluster/afr/src/afr-common.c @@ -515,6 +515,8 @@ afr_local_sh_cleanup (afr_local_t *local, xlator_t *this) if (sh->fresh_parent_dirs) GF_FREE (sh->fresh_parent_dirs); + if (sh->write_needed) + GF_FREE (sh->write_needed); loc_wipe (&sh->parent_loc); loc_wipe (&sh->lookup_loc); diff --git a/xlators/cluster/afr/src/afr-self-heal-algorithm.c b/xlators/cluster/afr/src/afr-self-heal-algorithm.c index 89deefea4..0909ce877 100644 --- a/xlators/cluster/afr/src/afr-self-heal-algorithm.c +++ b/xlators/cluster/afr/src/afr-self-heal-algorithm.c @@ -178,6 +178,32 @@ sh_full_write_cbk (call_frame_t *rw_frame, void *cookie, xlator_t *this, return 0; } +static void +sh_prune_writes_needed (call_frame_t *sh_frame, call_frame_t *rw_frame, + afr_private_t *priv) +{ + afr_local_t *sh_local = NULL; + afr_self_heal_t *sh = NULL; + afr_local_t *rw_local = NULL; + afr_self_heal_t *rw_sh = NULL; + int i = 0; + + sh_local = sh_frame->local; + sh = &sh_local->self_heal; + + rw_local = rw_frame->local; + rw_sh = &rw_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 + */ + for (i = 0; i < priv->child_count; i++) { + if (rw_sh->write_needed[i] && + ((rw_sh->offset + 1) > sh->buf[i].ia_size)) + rw_sh->write_needed[i] = 0; + } +} static int sh_full_read_cbk (call_frame_t *rw_frame, void *cookie, @@ -203,10 +229,7 @@ sh_full_read_cbk (call_frame_t *rw_frame, void *cookie, sh_local = sh_frame->local; sh = &sh_local->self_heal; - call_count = sh->active_sinks; - offset = rw_sh->offset; - rw_local->call_count = call_count; gf_log (this->name, GF_LOG_TRACE, "read %d bytes of data from %s, offset %"PRId64"", @@ -223,27 +246,26 @@ sh_full_read_cbk (call_frame_t *rw_frame, void *cookie, return 0; } + if (sh->file_has_holes && iov_0filled (vector, count) == 0) + sh_prune_writes_needed (sh_frame, rw_frame, priv); + + for (i = 0; i < priv->child_count; i++) + if (rw_sh->write_needed[i]) + call_count++; + rw_sh->offset += op_ret; - if (sh->file_has_holes) { - if (iov_0filled (vector, count) == 0) { - /* the iter function depends on the - sh->offset already being updated - above - */ - gf_log (this->name, GF_LOG_DEBUG, - "block has all 0 filled"); - sh_full_loop_return (rw_frame, this, offset); - goto out; - } + rw_local->call_count = call_count; + if (call_count == 0) { + gf_log (this->name, GF_LOG_DEBUG, "block has all 0 filled"); + sh_full_loop_return (rw_frame, this, offset); + goto out; } for (i = 0; i < priv->child_count; i++) { - if (sh->sources[i] || !sh_local->child_up[i]) + if (!rw_sh->write_needed[i]) continue; - /* this is a sink, so write to it */ - STACK_WIND_COOKIE (rw_frame, sh_full_write_cbk, (void *) (long) i, priv->children[i], @@ -270,6 +292,7 @@ sh_full_read_write (call_frame_t *frame, xlator_t *this, off_t offset) afr_self_heal_t *sh = NULL; call_frame_t *rw_frame = NULL; int32_t op_errno = 0; + int i = 0; priv = this->private; local = frame->local; @@ -283,6 +306,16 @@ sh_full_read_write (call_frame_t *frame, xlator_t *this, off_t offset) rw_frame->local = rw_local; rw_sh = &rw_local->self_heal; + rw_sh->write_needed = GF_CALLOC (priv->child_count, + sizeof (*rw_sh->write_needed), + gf_afr_mt_char); + if (!rw_sh->write_needed) + goto out; + for (i = 0; i < priv->child_count; i++) { + if (sh->sources[i] || !local->child_up[i]) + continue; + rw_sh->write_needed[i] = 1; + } rw_sh->offset = offset; rw_sh->sh_frame = frame; @@ -297,6 +330,8 @@ sh_full_read_write (call_frame_t *frame, xlator_t *this, off_t offset) out: sh->op_failed = 1; + if (rw_frame) + AFR_STACK_DESTROY (rw_frame); sh_full_loop_driver (frame, this, _gf_false); @@ -417,9 +452,6 @@ sh_diff_private_cleanup (call_frame_t *frame, xlator_t *this) for (i = 0; i < priv->data_self_heal_window_size; i++) { if (sh_priv->loops[i]) { - if (sh_priv->loops[i]->write_needed) - GF_FREE (sh_priv->loops[i]->write_needed); - if (sh_priv->loops[i]->checksum) GF_FREE (sh_priv->loops[i]->checksum); @@ -466,9 +498,6 @@ sh_diff_loop_state_reset (struct sh_diff_loop_state *loop_state, int child_count loop_state->active = _gf_false; // loop_state->offset = 0; - memset (loop_state->write_needed, - 0, sizeof (*loop_state->write_needed) * child_count); - memset (loop_state->checksum, 0, MD5_DIGEST_LEN * child_count); } @@ -654,7 +683,7 @@ sh_diff_read_cbk (call_frame_t *rw_frame, void *cookie, loop_index = __loop_index ((uint32_t) (long) cookie); loop_state = sh_priv->loops[loop_index]; - call_count = sh_diff_number_of_writes_needed (loop_state->write_needed, + call_count = sh_diff_number_of_writes_needed (rw_sh->write_needed, priv->child_count); rw_local->call_count = call_count; @@ -670,16 +699,8 @@ sh_diff_read_cbk (call_frame_t *rw_frame, void *cookie, return 0; } - if (sh->file_has_holes) { - if (iov_0filled (vector, count) == 0) { - gf_log (this->name, GF_LOG_DEBUG, "0 filled block"); - sh_diff_loop_return (rw_frame, this, loop_state); - goto out; - } - } - for (i = 0; i < priv->child_count; i++) { - if (loop_state->write_needed[i]) { + if (rw_sh->write_needed[i]) { wcookie = __make_cookie (loop_index, i); STACK_WIND_COOKIE (rw_frame, sh_diff_write_cbk, @@ -694,7 +715,6 @@ sh_diff_read_cbk (call_frame_t *rw_frame, void *cookie, } } -out: return 0; } @@ -805,7 +825,7 @@ sh_diff_checksum_cbk (call_frame_t *rw_frame, void *cookie, xlator_t *this, PRId64" differs from that on source", priv->children[i]->name, loop_state->offset); - write_needed = loop_state->write_needed[i] = 1; + write_needed = rw_sh->write_needed[i] = 1; } } @@ -887,6 +907,11 @@ sh_diff_checksum (call_frame_t *frame, xlator_t *this, off_t offset) rw_frame->local = rw_local; rw_sh = &rw_local->self_heal; + rw_sh->write_needed = GF_CALLOC (priv->child_count, + sizeof (*rw_sh->write_needed), + gf_afr_mt_char); + if (!rw_sh->write_needed) + goto out; rw_sh->offset = sh->offset; rw_sh->sh_frame = frame; @@ -934,6 +959,8 @@ sh_diff_checksum (call_frame_t *frame, xlator_t *this, off_t offset) out: sh->op_failed = 1; + if (rw_frame) + AFR_STACK_DESTROY (rw_frame); sh_diff_loop_driver (frame, this, _gf_false, loop_state); return 0; @@ -1052,12 +1079,6 @@ afr_sh_algo_diff (call_frame_t *frame, xlator_t *this) if (!sh_priv->loops[i]->checksum) goto err; - sh_priv->loops[i]->write_needed = GF_CALLOC (priv->child_count, - sizeof (*sh_priv->loops[i]->write_needed), - gf_afr_mt_char); - if (!sh_priv->loops[i]->write_needed) - goto err; - } sh_diff_loop_driver (frame, this, _gf_true, NULL); @@ -1067,8 +1088,6 @@ err: if (sh_priv) { if (sh_priv->loops) { for (i = 0; i < priv->data_self_heal_window_size; i++) { - if (sh_priv->loops[i]->write_needed) - GF_FREE (sh_priv->loops[i]->write_needed); if (sh_priv->loops[i]->checksum) GF_FREE (sh_priv->loops[i]->checksum); if (sh_priv->loops[i]) diff --git a/xlators/cluster/afr/src/afr-self-heal-algorithm.h b/xlators/cluster/afr/src/afr-self-heal-algorithm.h index 2790dbc6a..59c928d9f 100644 --- a/xlators/cluster/afr/src/afr-self-heal-algorithm.h +++ b/xlators/cluster/afr/src/afr-self-heal-algorithm.h @@ -39,7 +39,6 @@ typedef struct { struct sh_diff_loop_state { off_t offset; - unsigned char *write_needed; uint8_t *checksum; gf_boolean_t active; }; diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h index 1e3592f65..97a4a710c 100644 --- a/xlators/cluster/afr/src/afr.h +++ b/xlators/cluster/afr/src/afr.h @@ -210,6 +210,7 @@ typedef struct { /* private data for the particular self-heal algorithm */ void *private; + unsigned char *write_needed; int (*flush_self_heal_cbk) (call_frame_t *frame, xlator_t *this); -- cgit