diff options
Diffstat (limited to 'xlators')
| -rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-data.c | 77 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr.c | 2 | 
2 files changed, 66 insertions, 13 deletions
diff --git a/xlators/cluster/afr/src/afr-self-heal-data.c b/xlators/cluster/afr/src/afr-self-heal-data.c index 2118fd66df5..8c092522c9e 100644 --- a/xlators/cluster/afr/src/afr-self-heal-data.c +++ b/xlators/cluster/afr/src/afr-self-heal-data.c @@ -492,28 +492,81 @@ afr_sh_data_trim_sinks (call_frame_t *frame, xlator_t *this)  } -struct afr_sh_algorithm * -afr_sh_data_pick_algo (call_frame_t *frame, xlator_t *this) +static struct afr_sh_algorithm * +sh_algo_from_name (xlator_t *this, char *name)  { -        afr_private_t *priv = NULL;          int i = 0; -        priv = this->private; -          while (afr_self_heal_algorithms[i].name) { -                if (!strcmp (priv->data_self_heal_algorithm, -                             afr_self_heal_algorithms[i].name)) { -                        goto out; +                if (!strcmp (name, afr_self_heal_algorithms[i].name)) { +                        return &afr_self_heal_algorithms[i];                  }                  i++;          } -        /* No match found, so fall back on "full" */ +        return NULL; +} + + +static int +sh_zero_byte_files_exist (afr_self_heal_t *sh, int child_count) +{ +        int i; +        int ret = 0; + +        for (i = 0; i < child_count; i++) { +                if (sh->buf[i].st_size == 0) { +                        ret = 1; +                        break; +                } +        } + +        return ret; +} + + +struct afr_sh_algorithm * +afr_sh_data_pick_algo (call_frame_t *frame, xlator_t *this) +{ +        afr_private_t *           priv  = NULL; +        struct afr_sh_algorithm * algo  = NULL; +        afr_local_t *             local = NULL; +        afr_self_heal_t *         sh    = NULL; + +        priv  = this->private; +        local = frame->local; +        sh    = &local->self_heal; +        algo  = sh_algo_from_name (this, priv->data_self_heal_algorithm); + +        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) +                    || (sh->file_size <= (priv->data_self_heal_window_size * this->ctx->page_size))) { + +                        /* +                         * If the file does not exist on one of the subvolumes, +                         * or a zero-byte file exists (created by entry self-heal) +                         * the entire content has to be copied anyway, so there +                         * is no benefit from using the "diff" algorithm. +                         * +                         * If the file size is about the same as page size, +                         * the entire file can be read and written with a few +                         * (pipelined) STACK_WINDs, which will be faster +                         * than "diff" which has to read checksums and then +                         * read and write. +                         */ + +                        algo = sh_algo_from_name (this, "full"); + +                } else { +                        algo = sh_algo_from_name (this, "diff"); +                } +        } -        i = 0; -out: -        return &afr_self_heal_algorithms[i]; +        return algo;  } diff --git a/xlators/cluster/afr/src/afr.c b/xlators/cluster/afr/src/afr.c index cf4b8d3bca4..433f73b7d26 100644 --- a/xlators/cluster/afr/src/afr.c +++ b/xlators/cluster/afr/src/afr.c @@ -2400,7 +2400,7 @@ init (xlator_t *this)  		}   	} -        priv->data_self_heal_algorithm = "full"; +        priv->data_self_heal_algorithm = "";          dict_ret = dict_get_str (this->options, "data-self-heal-algorithm",                                   &algo);  | 
