summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-common.c44
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-data.c10
2 files changed, 44 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 5342e2231..1f105fcdd 100644
--- a/xlators/cluster/afr/src/afr-self-heal-common.c
+++ b/xlators/cluster/afr/src/afr-self-heal-common.c
@@ -553,15 +553,25 @@ afr_sh_mark_zero_size_file_as_sink (struct iatt *bufs, int32_t *success_children
int child = 0;
gf_boolean_t sink_exists = _gf_false;
gf_boolean_t source_exists = _gf_false;
+ int source = -1;
for (i = 0; i < child_count; i++) {
child = success_children[i];
if (child < 0)
break;
- if (bufs[child].ia_size)
- source_exists = _gf_true;
- if (!bufs[child].ia_size)
+ if (!bufs[child].ia_size) {
sink_exists = _gf_true;
+ continue;
+ }
+ if (!source_exists) {
+ source_exists = _gf_true;
+ source = child;
+ continue;
+ }
+ if (bufs[source].ia_size != bufs[child].ia_size) {
+ nsources = -1;
+ goto out;
+ }
}
if (!source_exists && !sink_exists) {
nsources = -1;
@@ -764,6 +774,8 @@ afr_mark_sources (xlator_t *this, int32_t *sources, int32_t **pending_matrix,
success_children,
child_count,
sources);
+ if ((nsources < 0) && subvol_status)
+ *subvol_status |= SPLIT_BRAIN;
break;
default:
break;
@@ -1296,6 +1308,9 @@ afr_sh_missing_entries_lookup_done (call_frame_t *frame, xlator_t *this,
ia_type_t ia_type = IA_INVAL;
int32_t nsources = 0;
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;
local = frame->local;
sh = &local->self_heal;
@@ -1311,17 +1326,24 @@ afr_sh_missing_entries_lookup_done (call_frame_t *frame, xlator_t *this,
//now No chance for the ia_type to conflict
ia_type = sh->buf[sh->child_success[0]].ia_type;
+ txn_type = afr_transaction_type_get (ia_type);
nsources = afr_build_sources (this, sh->xattr, sh->buf,
sh->pending_matrix, sh->sources,
- sh->child_success,
- afr_transaction_type_get (ia_type),
- NULL, _gf_false);
+ sh->child_success, txn_type,
+ &subvol_status, _gf_false);
if (nsources < 0) {
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);
- op_errno = EIO;
- goto out;
+ if ((txn_type == AFR_DATA_TRANSACTION) &&
+ (subvol_status & SPLIT_BRAIN)) {
+ data_split_brain = _gf_true;
+ sh->sources[sh->child_success[0]] = 1;
+ nsources = 1;
+ } else {
+ op_errno = EIO;
+ goto out;
+ }
}
afr_get_fresh_children (sh->child_success, sh->sources,
@@ -1337,7 +1359,11 @@ 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);
- sh_missing_entries_create (frame, this);
+ if (data_split_brain) {
+ afr_sh_missing_entries_finish (frame, this);
+ } else {
+ sh_missing_entries_create (frame, this);
+ }
return;
out:
sh->op_failed = 1;
diff --git a/xlators/cluster/afr/src/afr-self-heal-data.c b/xlators/cluster/afr/src/afr-self-heal-data.c
index 7d2c86eed..7e97cf8cb 100644
--- a/xlators/cluster/afr/src/afr-self-heal-data.c
+++ b/xlators/cluster/afr/src/afr-self-heal-data.c
@@ -812,9 +812,17 @@ afr_lookup_select_read_child_by_txn_type (xlator_t *this, afr_local_t *local,
nsources = afr_build_sources (this, xattr, bufs, pending_matrix,
sources, success_children, txn_type,
&subvol_status, _gf_false);
- if (subvol_status & SPLIT_BRAIN)
+ 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,
+ _gf_true);
+ nsources = 1;
+ sources[success_children[0]] = 1;
+ }
+ }
if (nsources < 0) {
ret = -1;
goto out;