summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/afr/src
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/cluster/afr/src')
-rw-r--r--xlators/cluster/afr/src/afr-common.c18
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-common.c32
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-entry.c4
-rw-r--r--xlators/cluster/afr/src/afr.c1
-rw-r--r--xlators/cluster/afr/src/afr.h2
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. */