From 410b1092e690c4e89d95d8b136884df6fcf5a1a8 Mon Sep 17 00:00:00 2001 From: Pranith Kumar K Date: Wed, 14 Mar 2012 17:05:23 +0530 Subject: cluster/afr: Perform conservative merge on dir with xattr split-brain Change-Id: I314cf7bbc8a451e42b6addf367f55e431ab0a85c BUG: 802637 Signed-off-by: Pranith Kumar K Reviewed-on: http://review.gluster.com/2945 Tested-by: Gluster Build System Reviewed-by: Vijay Bellur --- xlators/cluster/afr/src/afr-self-heal-common.c | 50 ++++++++++++++++++++++---- xlators/cluster/afr/src/afr-self-heal-common.h | 3 ++ xlators/cluster/afr/src/afr-self-heal-data.c | 17 +++++++-- 3 files changed, 60 insertions(+), 10 deletions(-) diff --git a/xlators/cluster/afr/src/afr-self-heal-common.c b/xlators/cluster/afr/src/afr-self-heal-common.c index 1f105fcdd96..06899265074 100644 --- a/xlators/cluster/afr/src/afr-self-heal-common.c +++ b/xlators/cluster/afr/src/afr-self-heal-common.c @@ -544,6 +544,28 @@ out: return nsources; } +int +afr_get_no_xattr_dir_read_child (xlator_t *this, int32_t *success_children, + struct iatt *bufs) +{ + afr_private_t *priv = NULL; + int i = 0; + int child = -1; + int read_child = -1; + + priv = this->private; + for (i = 0; i < priv->child_count; i++) { + child = success_children[i]; + if (child < 0) + break; + if (read_child < 0) + read_child = child; + else if (bufs[read_child].ia_size < bufs[child].ia_size) + read_child = child; + } + return read_child; +} + int afr_sh_mark_zero_size_file_as_sink (struct iatt *bufs, int32_t *success_children, int child_count, int32_t *sources) @@ -1310,7 +1332,8 @@ afr_sh_missing_entries_lookup_done (call_frame_t *frame, xlator_t *this, loc_t *loc = NULL; int32_t subvol_status = 0; afr_transaction_type txn_type = AFR_DATA_TRANSACTION; - gf_boolean_t data_split_brain = _gf_false; + gf_boolean_t split_brain = _gf_false; + int read_child = -1; local = frame->local; sh = &local->self_heal; @@ -1335,11 +1358,24 @@ afr_sh_missing_entries_lookup_done (call_frame_t *frame, xlator_t *this, gf_log (this->name, GF_LOG_INFO, "No sources for dir of %s," " in missing entry self-heal, continuing with the rest" " of the self-heals", local->loc.path); - if ((txn_type == AFR_DATA_TRANSACTION) && - (subvol_status & SPLIT_BRAIN)) { - data_split_brain = _gf_true; - sh->sources[sh->child_success[0]] = 1; - nsources = 1; + if (subvol_status & SPLIT_BRAIN) { + split_brain = _gf_true; + switch (txn_type) { + case AFR_DATA_TRANSACTION: + nsources = 1; + sh->sources[sh->child_success[0]] = 1; + break; + case AFR_ENTRY_TRANSACTION: + read_child = afr_get_no_xattr_dir_read_child (this, + sh->child_success, + sh->buf); + sh->sources[read_child] = 1; + nsources = 1; + break; + default: + op_errno = EIO; + goto out; + } } else { op_errno = EIO; goto out; @@ -1359,7 +1395,7 @@ afr_sh_missing_entries_lookup_done (call_frame_t *frame, xlator_t *this, sh->gfid_sh_success_cbk (frame, this); if (uuid_is_null (loc->inode->gfid)) uuid_copy (loc->gfid, sh->buf[sh->source].ia_gfid); - if (data_split_brain) { + if (split_brain) { afr_sh_missing_entries_finish (frame, this); } else { sh_missing_entries_create (frame, this); diff --git a/xlators/cluster/afr/src/afr-self-heal-common.h b/xlators/cluster/afr/src/afr-self-heal-common.h index 56ab2efd084..6c33d5085db 100644 --- a/xlators/cluster/afr/src/afr-self-heal-common.h +++ b/xlators/cluster/afr/src/afr-self-heal-common.h @@ -115,4 +115,7 @@ afr_impunge_frame_create (call_frame_t *frame, xlator_t *this, call_frame_t **impunge_frame); void afr_sh_reset (call_frame_t *frame, xlator_t *this); +int +afr_get_no_xattr_dir_read_child (xlator_t *this, int32_t *success_children, + struct iatt *bufs); #endif /* __AFR_SELF_HEAL_COMMON_H__ */ diff --git a/xlators/cluster/afr/src/afr-self-heal-data.c b/xlators/cluster/afr/src/afr-self-heal-data.c index 7e97cf8cb42..3762a2742fd 100644 --- a/xlators/cluster/afr/src/afr-self-heal-data.c +++ b/xlators/cluster/afr/src/afr-self-heal-data.c @@ -815,12 +815,23 @@ afr_lookup_select_read_child_by_txn_type (xlator_t *this, afr_local_t *local, if (subvol_status & SPLIT_BRAIN) { gf_log (this->name, GF_LOG_WARNING, "%s: Possible split-brain", local->loc.path); - if (txn_type == AFR_DATA_TRANSACTION) { - //succeed lookup fail open - afr_set_split_brain (this, local->cont.lookup.inode, + switch (txn_type) { + case AFR_DATA_TRANSACTION: + afr_set_split_brain (this, + local->cont.lookup.inode, _gf_true); nsources = 1; sources[success_children[0]] = 1; + break; + case AFR_ENTRY_TRANSACTION: + read_child = afr_get_no_xattr_dir_read_child (this, + success_children, + bufs); + sources[read_child] = 1; + nsources = 1; + break; + default: + break; } } if (nsources < 0) { -- cgit