summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/cluster/afr/src/afr-common.c2
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-algorithm.c105
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-algorithm.h1
-rw-r--r--xlators/cluster/afr/src/afr.h1
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);