From 76ed61bb5e3fefb3e4071a24f6dd26f37c950c77 Mon Sep 17 00:00:00 2001 From: Ravishankar N Date: Fri, 25 Mar 2016 18:48:30 +0530 Subject: afr: add mtime based split-brain resolution to CLI Backport of http://review.gluster.org/#/c/13828/ Extended the CLI to include support for split-brain resolution based on mtime. The command syntax is: $:gluster volume heal split-brain latest-mtime where can be either the full file name as seen from the root of the volume (or) the gfid-string representation of the file. Change-Id: I7a16f72ff1a4495aa69f43f22758a9404e958b4f BUG: 1321748 Signed-off-by: Ravishankar N Reviewed-on: http://review.gluster.org/13838 Smoke: Gluster Build System NetBSD-regression: NetBSD Build System Reviewed-by: Anuradha Talur CentOS-regression: Gluster Build System Reviewed-by: Pranith Kumar Karampuri --- xlators/cluster/afr/src/afr-self-heal-common.c | 81 ++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 10 deletions(-) (limited to 'xlators/cluster') diff --git a/xlators/cluster/afr/src/afr-self-heal-common.c b/xlators/cluster/afr/src/afr-self-heal-common.c index fff2a06f927..db9af05a474 100644 --- a/xlators/cluster/afr/src/afr-self-heal-common.c +++ b/xlators/cluster/afr/src/afr-self-heal-common.c @@ -329,6 +329,10 @@ afr_mark_largest_file_as_source (xlator_t *this, unsigned char *sources, for (i = 0; i < priv->child_count; i++) { if (!sources[i]) continue; + if (!replies[i].valid || replies[i].op_ret != 0) { + sources[i] = 0; + continue; + } if (size <= replies[i].poststat.ia_size) { size = replies[i].poststat.ia_size; } @@ -343,6 +347,41 @@ afr_mark_largest_file_as_source (xlator_t *this, unsigned char *sources, } } +void +afr_mark_latest_mtime_file_as_source (xlator_t *this, unsigned char *sources, + struct afr_reply *replies) +{ + int i = 0; + afr_private_t *priv = NULL; + uint32_t mtime = 0; + uint32_t mtime_nsec = 0; + + priv = this->private; + for (i = 0; i < priv->child_count; i++) { + if (!sources[i]) + continue; + if (!replies[i].valid || replies[i].op_ret != 0) { + sources[i] = 0; + continue; + } + if ((mtime < replies[i].poststat.ia_mtime) || + ((mtime == replies[i].poststat.ia_mtime) && + (mtime_nsec < replies[i].poststat.ia_mtime_nsec))) { + mtime = replies[i].poststat.ia_mtime; + mtime_nsec = replies[i].poststat.ia_mtime_nsec; + } + } + for (i = 0; i < priv->child_count; i++) { + if (!sources[i]) + continue; + if ((mtime > replies[i].poststat.ia_mtime) || + ((mtime == replies[i].poststat.ia_mtime) && + (mtime_nsec > replies[i].poststat.ia_mtime_nsec))) { + sources[i] = 0; + } + } +} + void afr_mark_active_sinks (xlator_t *this, unsigned char *sources, unsigned char *locked_on, unsigned char *sinks) @@ -433,6 +472,9 @@ afr_mark_split_brain_source_sinks (call_frame_t *frame, xlator_t *this, } xdata_rsp = local->xdata_rsp; + for (i = 0 ; i < priv->child_count; i++) + if (locked_on[i]) + sources[i] = 1; switch (heal_op) { case GF_SHD_OP_SBRAIN_HEAL_FROM_BIGGER_FILE: if (type == AFR_METADATA_TRANSACTION) { @@ -443,9 +485,6 @@ afr_mark_split_brain_source_sinks (call_frame_t *frame, xlator_t *this, ret = -1; goto out; } - for (i = 0 ; i < priv->child_count; i++) - if (locked_on[i]) - sources[i] = 1; afr_mark_largest_file_as_source (this, sources, replies); if (AFR_COUNT (sources, priv->child_count) != 1) { ret = dict_set_str (xdata_rsp, "sh-fail-msg", @@ -454,11 +493,24 @@ afr_mark_split_brain_source_sinks (call_frame_t *frame, xlator_t *this, ret = -1; goto out; } - for (i = 0 ; i < priv->child_count; i++) - if (sources[i]) - source = i; - sinks[source] = 0; - healed_sinks[source] = 0; + break; + case GF_SHD_OP_SBRAIN_HEAL_FROM_LATEST_MTIME: + if (type == AFR_METADATA_TRANSACTION) { + ret = dict_set_str (xdata_rsp, "sh-fail-msg", + "Use source-brick option to" + " heal metadata split-brain"); + if (!ret) + ret = -1; + goto out; + } + afr_mark_latest_mtime_file_as_source (this, sources, replies); + if (AFR_COUNT (sources, priv->child_count) != 1) { + ret = dict_set_str (xdata_rsp, "sh-fail-msg", + "No difference in mtime"); + if (!ret) + ret = -1; + goto out; + } break; case GF_SHD_OP_SBRAIN_HEAL_FROM_BRICK: ret = dict_get_str (xdata_req, "child-name", &name); @@ -479,16 +531,25 @@ afr_mark_split_brain_source_sinks (call_frame_t *frame, xlator_t *this, ret = -1; goto out; } + memset (sources, 0, sizeof (*sources) * priv->child_count); sources[source] = 1; - sinks[source] = 0; - healed_sinks[source] = 0; break; default: ret = -1; goto out; } + for (i = 0 ; i < priv->child_count; i++) { + if (sources[i]) { + source = i; + break; + } + } + sinks[source] = 0; + healed_sinks[source] = 0; ret = source; out: + if (ret < 0) + memset (sources, 0, sizeof (*sources) * priv->child_count); return ret; } -- cgit