diff options
author | Pranith Kumar K <pranithk@gluster.com> | 2012-06-27 16:42:35 +0530 |
---|---|---|
committer | Anand Avati <avati@redhat.com> | 2012-07-26 10:14:54 -0700 |
commit | f153c835807ac31006ba690b1deb47b20b51bc83 (patch) | |
tree | 563b61874ec5304116d92f39bb6e1f749b1c6d3f /xlators/cluster/afr/src/afr-self-heal-data.c | |
parent | c2a7a22bfe18316eab441d49e515726e53f74582 (diff) |
cluster/afr: Modified split-brain handling
RCA
The bug is observed because the decision to mark
a file in split-brain is taken outside appropriate locks.
Lookup gathers xattrs outside any lock. The xattrs being
in split-brain in lookup should only be taken as a hint.
Appropriate inodelks should be taken before confirming
a split-brain. Self-heal confirms this at the moment.
If data/metadata self-heal is turned off, inspecting of
xattrs could not be performed so split-brain behavior
does not work correctly if the self-heal options are turned off.
Fix
Self-heals are launched to inspect xattrs even when the
data/metadata self-heal options are turned off. The decision
to heal data/metadata after the xattrs are inspected is based
on whether the options are turned on/off. So decision to set/reset
split-brain flag is taken inside appropriate locks.
Testcases:
tests 33-36 in
https://github.com/pranithk/gluster-tests/blob/master/afr/self-heal.sh
Change-Id: Ia8aeab08208b50c06609ad35a9d72f3d553ee343
BUG: 833727
Signed-off-by: Pranith Kumar K <pranithk@gluster.com>
Reviewed-on: http://review.gluster.com/3626
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Anand Avati <avati@redhat.com>
Diffstat (limited to 'xlators/cluster/afr/src/afr-self-heal-data.c')
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-data.c | 63 |
1 files changed, 37 insertions, 26 deletions
diff --git a/xlators/cluster/afr/src/afr-self-heal-data.c b/xlators/cluster/afr/src/afr-self-heal-data.c index 1672b4f282e..6619c1353c7 100644 --- a/xlators/cluster/afr/src/afr-self-heal-data.c +++ b/xlators/cluster/afr/src/afr-self-heal-data.c @@ -688,16 +688,6 @@ afr_sh_data_fxattrop_fstat_done (call_frame_t *frame, xlator_t *this) nsources = afr_build_sources (this, sh->xattr, sh->buf, sh->pending_matrix, sh->sources, sh->success_children, AFR_DATA_TRANSACTION, NULL, _gf_true); - if ((nsources == 0) && !sh->sync_done) { - gf_log (this->name, GF_LOG_DEBUG, - "No self-heal needed for %s", - local->loc.path); - - local->govinda_gOvinda = 0; - afr_sh_data_finish (frame, this); - return 0; - } - if ((nsources == -1) && (priv->favorite_child != -1) && (sh->child_errno[priv->favorite_child] == 0)) { @@ -720,12 +710,12 @@ afr_sh_data_fxattrop_fstat_done (call_frame_t *frame, xlator_t *this) "split-brain). Please delete the file from all but " "the preferred subvolume.", local->loc.path); - local->govinda_gOvinda = 1; + sh->data_spb = _gf_true; afr_sh_data_fail (frame, this); return 0; } - local->govinda_gOvinda = 0; + sh->data_spb = _gf_false; ret = afr_sh_inode_set_read_ctx (sh, this); if (ret) { gf_log (this->name, GF_LOG_DEBUG, @@ -738,7 +728,20 @@ afr_sh_data_fxattrop_fstat_done (call_frame_t *frame, xlator_t *this) if (sh->sync_done) { afr_sh_data_setattr (frame, this); } else { - afr_sh_data_fix (frame, this); + if (nsources == 0) { + gf_log (this->name, GF_LOG_DEBUG, + "No self-heal needed for %s", + local->loc.path); + + afr_sh_data_finish (frame, this); + return 0; + } + + if (sh->do_data_self_heal && + afr_data_self_heal_enabled (priv->data_self_heal)) + afr_sh_data_fix (frame, this); + else + afr_sh_data_finish (frame, this); } return 0; } @@ -764,11 +767,7 @@ afr_lookup_select_read_child_by_txn_type (xlator_t *this, afr_local_t *local, bufs = local->cont.lookup.bufs; success_children = local->cont.lookup.success_children; - pending_matrix = afr_matrix_create (priv->child_count, - priv->child_count); - if (NULL == pending_matrix) - goto out; - + pending_matrix = local->cont.lookup.pending_matrix; sources = local->cont.lookup.sources; memset (sources, 0, sizeof (*sources) * priv->child_count); @@ -780,9 +779,7 @@ afr_lookup_select_read_child_by_txn_type (xlator_t *this, afr_local_t *local, local->loc.path); switch (txn_type) { case AFR_DATA_TRANSACTION: - afr_set_split_brain (this, - local->cont.lookup.inode, - _gf_true); + local->cont.lookup.possible_spb = _gf_true; nsources = 1; sources[success_children[0]] = 1; break; @@ -809,7 +806,6 @@ afr_lookup_select_read_child_by_txn_type (xlator_t *this, afr_local_t *local, sources, priv->hash_mode, gfid); out: - afr_matrix_cleanup (pending_matrix, priv->child_count); gf_log (this->name, GF_LOG_DEBUG, "returning read_child: %d", read_child); return read_child; @@ -1351,6 +1347,17 @@ afr_sh_non_reg_lock_success (call_frame_t *frame, xlator_t *this) return 0; } +gf_boolean_t +afr_can_start_data_self_heal (afr_self_heal_t *sh, afr_private_t *priv) +{ + if (sh->force_confirm_spb) + return _gf_true; + if (sh->do_data_self_heal && + afr_data_self_heal_enabled (priv->data_self_heal)) + return _gf_true; + return _gf_false; +} + int afr_self_heal_data (call_frame_t *frame, xlator_t *this) { @@ -1361,10 +1368,14 @@ afr_self_heal_data (call_frame_t *frame, xlator_t *this) local = frame->local; sh = &local->self_heal; - local->govinda_gOvinda = afr_is_split_brain (this, sh->inode); - - if (sh->do_data_self_heal && - afr_data_self_heal_enabled (priv->data_self_heal)) { + /* Self-heal completion cbk changes inode split-brain status based on + * govinda_gOvinda, mdata_spb, data_spb value. + * Initialize data_spb with current split-brain status. + * If for some reason self-heal fails(locking phase etc), it makes sure + * we retain the split-brain status before this self-heal started. + */ + sh->data_spb = afr_is_split_brain (this, sh->inode); + if (afr_can_start_data_self_heal (sh, priv)) { if (IA_ISREG (sh->type)) { afr_sh_data_open (frame, this); } else { |