summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-algorithm.c42
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-algorithm.h1
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-data.c16
-rw-r--r--xlators/cluster/afr/src/afr.h1
4 files changed, 45 insertions, 15 deletions
diff --git a/xlators/cluster/afr/src/afr-self-heal-algorithm.c b/xlators/cluster/afr/src/afr-self-heal-algorithm.c
index 6bd0adcd851..99a2108361c 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++) {
diff --git a/xlators/cluster/afr/src/afr-self-heal-algorithm.h b/xlators/cluster/afr/src/afr-self-heal-algorithm.h
index 04d8e8a6ce7..27d3d171bb9 100644
--- a/xlators/cluster/afr/src/afr-self-heal-algorithm.h
+++ b/xlators/cluster/afr/src/afr-self-heal-algorithm.h
@@ -20,7 +20,6 @@
#ifndef __AFR_SELF_HEAL_ALGORITHM_H__
#define __AFR_SELF_HEAL_ALGORITHM_H__
-
typedef int (*afr_sh_algo_fn) (call_frame_t *frame,
xlator_t *this);
diff --git a/xlators/cluster/afr/src/afr-self-heal-data.c b/xlators/cluster/afr/src/afr-self-heal-data.c
index bf37729fe82..d362d5add6f 100644
--- a/xlators/cluster/afr/src/afr-self-heal-data.c
+++ b/xlators/cluster/afr/src/afr-self-heal-data.c
@@ -492,12 +492,16 @@ sh_algo_from_name (xlator_t *this, char *name)
static int
-sh_zero_byte_files_exist (afr_self_heal_t *sh, int child_count)
+sh_zero_byte_files_exist (afr_local_t *local, int child_count)
{
- int i;
- int ret = 0;
+ int i = 0;
+ int ret = 0;
+ afr_self_heal_t *sh = NULL;
+ sh = &local->self_heal;
for (i = 0; i < child_count; i++) {
+ if (!local->child_up[i] || sh->child_errno[i])
+ continue;
if (sh->buf[i].ia_size == 0) {
ret = 1;
break;
@@ -524,8 +528,7 @@ afr_sh_data_pick_algo (call_frame_t *frame, xlator_t *this)
if (algo == NULL) {
/* option not set, so fall back on heuristics */
- if ((local->enoent_count != 0)
- || sh_zero_byte_files_exist (sh, priv->child_count)
+ if (sh_zero_byte_files_exist (local, priv->child_count)
|| (sh->file_size <= (priv->data_self_heal_window_size *
this->ctx->page_size))) {
@@ -568,6 +571,7 @@ afr_sh_data_sync_prepare (call_frame_t *frame, xlator_t *this)
sh_algo = afr_sh_data_pick_algo (frame, this);
+ sh->algo = sh_algo;
sh_algo->fn (frame, this);
return 0;
@@ -944,8 +948,6 @@ afr_sh_data_fstat (call_frame_t *frame, xlator_t *this)
local->call_count = call_count;
afr_reset_children (sh->success_children, priv->child_count);
- memset (sh->child_errno, 0,
- sizeof (*sh->child_errno) * priv->child_count);
sh->success_count = 0;
for (i = 0; i < priv->child_count; i++) {
child = fstat_children[i];
diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h
index 918e44d7d92..815f4667c0b 100644
--- a/xlators/cluster/afr/src/afr.h
+++ b/xlators/cluster/afr/src/afr.h
@@ -261,6 +261,7 @@ typedef struct {
afr_sh_algo_private_t *private;
+ struct afr_sh_algorithm *algo;
afr_lock_cbk_t data_lock_success_handler;
afr_lock_cbk_t data_lock_failure_handler;
int (*completion_cbk) (call_frame_t *frame, xlator_t *this);