diff options
Diffstat (limited to 'xlators/cluster/afr/src')
| -rw-r--r-- | xlators/cluster/afr/src/afr-common.c | 18 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-common.c | 32 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-entry.c | 4 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr.c | 1 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr.h | 2 |
5 files changed, 43 insertions, 14 deletions
diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c index ebadba99a05..cfea53208c8 100644 --- a/xlators/cluster/afr/src/afr-common.c +++ b/xlators/cluster/afr/src/afr-common.c @@ -1085,7 +1085,8 @@ refresh_done: int afr_inode_refresh_done (call_frame_t *frame, xlator_t *this) { - call_frame_t *heal_frame = NULL; + afr_private_t *priv = NULL; + call_frame_t *heal_frame = NULL; afr_local_t *local = NULL; gf_boolean_t start_heal = _gf_false; afr_local_t *heal_local = NULL; @@ -1094,13 +1095,15 @@ afr_inode_refresh_done (call_frame_t *frame, xlator_t *this) int err = 0; local = frame->local; + priv = this->private; ret = afr_replies_interpret (frame, this, local->refreshinode, &start_heal); err = afr_inode_refresh_err (frame, this); - if (ret && afr_selfheal_enabled (this) && start_heal) { + if (priv->did_discovery == _gf_false || + (afr_selfheal_enabled (this) && start_heal)) { heal_frame = copy_frame (frame); if (!heal_frame) goto refresh_done; @@ -2580,6 +2583,8 @@ unwind: local->op_errno = ENOTCONN; } + priv->did_discovery = _gf_true; + AFR_STACK_UNWIND (lookup, frame, local->op_ret, local->op_errno, local->inode, &local->replies[read_subvol].poststat, local->replies[read_subvol].xdata, @@ -2612,7 +2617,7 @@ afr_discover_cbk (call_frame_t *frame, void *cookie, xlator_t *this, local->replies[child_index].xdata = dict_ref (xdata); } - if (local->do_discovery && (op_ret == 0)) + if (local->do_local_discovery && (op_ret == 0)) afr_attempt_local_discovery (this, child_index); if (xdata) { @@ -2717,12 +2722,12 @@ afr_discover (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xattr_req if (!priv->root_inode) priv->root_inode = inode_ref (loc->inode); - if (priv->choose_local && !priv->did_discovery) { + if (priv->choose_local && !priv->did_local_discovery) { /* Logic to detect which subvolumes of AFR are local, in order to prefer them for reads */ - local->do_discovery = _gf_true; - priv->did_discovery = _gf_true; + local->do_local_discovery = _gf_true; + priv->did_local_discovery = _gf_true; } } @@ -4951,6 +4956,7 @@ afr_notify (xlator_t *this, int32_t event, * that we could end up issuing N lookups to the first subvolume, and * O(N^2) overall, but N is small for AFR so it shouldn't be an issue. */ + priv->did_local_discovery = _gf_false; priv->did_discovery = _gf_false; latency_samples = child_xlator->client_latency.count; diff --git a/xlators/cluster/afr/src/afr-self-heal-common.c b/xlators/cluster/afr/src/afr-self-heal-common.c index c11ca11fdd9..bc3a3ee5ca1 100644 --- a/xlators/cluster/afr/src/afr-self-heal-common.c +++ b/xlators/cluster/afr/src/afr-self-heal-common.c @@ -1763,8 +1763,10 @@ afr_selfheal_unlocked_inspect (call_frame_t *frame, xlator_t *this, afr_is_metadata_set (this, replies[i].xdata)) *metadata_selfheal = _gf_true; - if (entry_selfheal && afr_is_entry_set (this, replies[i].xdata)) - *entry_selfheal = _gf_true; + if (priv->did_discovery == _gf_false || + (entry_selfheal && + afr_is_entry_set (this, replies[i].xdata))) + *entry_selfheal = _gf_true; valid_cnt++; if (valid_cnt == 1) { @@ -1919,6 +1921,7 @@ afr_selfheal_newentry_mark (call_frame_t *frame, xlator_t *this, inode_t *inode, { int ret = 0; int i = 0; + int source_count = 0; afr_private_t *priv = NULL; dict_t *xattr = NULL; int **changelog = NULL; @@ -1937,11 +1940,26 @@ afr_selfheal_newentry_mark (call_frame_t *frame, xlator_t *this, inode_t *inode, if (!changelog) goto out; - for (i = 0; i < priv->child_count; i++) { - if (!sources[i]) - continue; - afr_selfheal_post_op (frame, this, inode, i, xattr, NULL); - } + /* Pre-compute how many sources we have, if we made it in here + * without any sources defined, we are doing a conservative + * merge + */ + for (i = 0; i < priv->child_count; i++) { + if (sources[i]) { + source_count++; + } + } + + for (i = 0; i < priv->child_count; i++) { + /* If there are no sources we are doing a conservative + * merge. In such a case ensure we mark the changelog + * on all replicas. + */ + if (!sources[i] && source_count) { + continue; + } + afr_selfheal_post_op (frame, this, inode, i, xattr, NULL); + } out: if (changelog) afr_matrix_cleanup (changelog, priv->child_count); diff --git a/xlators/cluster/afr/src/afr-self-heal-entry.c b/xlators/cluster/afr/src/afr-self-heal-entry.c index 9ab566b8242..12a5940e7cd 100644 --- a/xlators/cluster/afr/src/afr-self-heal-entry.c +++ b/xlators/cluster/afr/src/afr-self-heal-entry.c @@ -443,7 +443,9 @@ __afr_selfheal_entry_finalize_source (xlator_t *this, unsigned char *sources, sources_count = AFR_COUNT (sources, priv->child_count); if ((AFR_CMP (locked_on, healed_sinks, priv->child_count) == 0) - || !sources_count || afr_does_witness_exist (this, witness)) { + || !sources_count || afr_does_witness_exist (this, witness) + || (sources_count == priv->child_count && + priv->did_discovery == _gf_false)) { memset (sources, 0, sizeof (*sources) * priv->child_count); afr_mark_active_sinks (this, sources, locked_on, healed_sinks); diff --git a/xlators/cluster/afr/src/afr.c b/xlators/cluster/afr/src/afr.c index ae9b28c7fb4..6d4b3c73429 100644 --- a/xlators/cluster/afr/src/afr.c +++ b/xlators/cluster/afr/src/afr.c @@ -292,6 +292,7 @@ reconfigure (xlator_t *this, dict_t *options) if (afr_set_favorite_child_policy (priv, fav_child_policy) == -1) goto out; + priv->did_local_discovery = _gf_false; priv->did_discovery = _gf_false; ret = 0; diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h index aa19f1eeb37..bbb444c7974 100644 --- a/xlators/cluster/afr/src/afr.h +++ b/xlators/cluster/afr/src/afr.h @@ -163,6 +163,7 @@ typedef struct _afr_private { uint32_t event_generation; gf_boolean_t choose_local; + gf_boolean_t did_local_discovery; gf_boolean_t did_discovery; uint64_t sh_readdir_size; gf_boolean_t ensure_durability; @@ -813,6 +814,7 @@ typedef struct _afr_local { mode_t umask; int xflag; gf_boolean_t do_discovery; + gf_boolean_t do_local_discovery; struct afr_reply *replies; /* For client side background heals. */ |
