summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--heal/src/glfs-heal.c114
-rw-r--r--tests/basic/afr/gfid-mismatch-resolution-with-cli.t168
-rw-r--r--tests/basic/afr/gfid-mismatch-resolution-with-fav-child-policy.t3
-rw-r--r--xlators/cluster/afr/src/afr-common.c18
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-common.c250
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-entry.c107
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-name.c65
-rw-r--r--xlators/cluster/afr/src/afr-self-heal.h8
-rw-r--r--xlators/cluster/afr/src/afr-self-heald.c2
9 files changed, 584 insertions, 151 deletions
diff --git a/heal/src/glfs-heal.c b/heal/src/glfs-heal.c
index fb997948f57..27115f3ca6c 100644
--- a/heal/src/glfs-heal.c
+++ b/heal/src/glfs-heal.c
@@ -21,6 +21,7 @@
#include <string.h>
#include <time.h>
#include "glusterfs.h"
+#include <libgen.h>
#if (HAVE_LIB_XML)
#include <libxml/encoding.h>
@@ -1031,26 +1032,43 @@ _validate_directory (dict_t *xattr_req, char *file)
int
glfsh_heal_splitbrain_file (glfs_t *fs, xlator_t *top_subvol, loc_t *rootloc,
- char *file, dict_t *xattr_req)
+ char *file, dict_t *xattr_req)
{
- int ret = -1;
- int reval = 0;
- loc_t loc = {0, };
- char *path = NULL;
- char *filename = NULL;
- struct iatt iatt = {0, };
- xlator_t *xl = top_subvol;
- dict_t *xattr_rsp = NULL;
- char *sh_fail_msg = NULL;
- int32_t op_errno = 0;
+ int ret = -1;
+ int reval = 0;
+ loc_t loc = {0, };
+ char *path = NULL;
+ char *path1 = NULL;
+ char *path2 = NULL;
+ char *filename = NULL;
+ char *filename1 = NULL;
+ struct iatt iatt = {0, };
+ xlator_t *xl = top_subvol;
+ dict_t *xattr_rsp = NULL;
+ char *sh_fail_msg = NULL;
+ char *gfid_heal_msg = NULL;
+ int32_t op_errno = 0;
+ gf_boolean_t flag = _gf_false;
if (!strncmp (file, "gfid:", 5)) {
filename = gf_strdup(file);
+ if (!filename) {
+ printf ("Error allocating memory to filename\n");
+ goto out;
+ }
path = strtok (filename, ":");
path = strtok (NULL, ";");
gf_uuid_parse (path, loc.gfid);
loc.path = gf_strdup (uuid_utoa (loc.gfid));
+ if (!loc.path) {
+ printf ("Error allocating memory to path\n");
+ goto out;
+ }
loc.inode = inode_new (rootloc->inode->table);
+ if (!loc.inode) {
+ printf ("Error getting inode\n");
+ goto out;
+ }
ret = syncop_lookup (xl, &loc, &iatt, 0, xattr_req, &xattr_rsp);
if (ret) {
op_errno = -ret;
@@ -1065,9 +1083,72 @@ glfsh_heal_splitbrain_file (glfs_t *fs, xlator_t *top_subvol, loc_t *rootloc,
ret = -1;
goto out;
}
-retry:
+ path1 = gf_strdup (file);
+ if (!path1) {
+ printf ("Error allocating memory to path\n");
+ ret = -1;
+ goto out;
+ }
+ path2 = gf_strdup (file);
+ if (!path2) {
+ printf ("Error allocating memory to path\n");
+ ret = -1;
+ goto out;
+ }
+ path = dirname (path1);
+ filename1 = basename (path2);
+retry1:
+ ret = glfs_resolve (fs, xl, path, &loc, &iatt, reval);
+ ESTALE_RETRY (ret, errno, reval, &loc, retry1);
+ if (ret) {
+ printf("Lookup failed on %s:%s\n",
+ path, strerror (errno));
+ goto out;
+ }
+ GF_FREE ((char *)loc.path);
+ loc.path = gf_strdup (file);
+ if (!loc.path) {
+ printf ("Error allocating memory for path\n");
+ ret = -1;
+ goto out;
+ }
+ loc.parent = inode_unref (loc.parent);
+ loc.parent = inode_ref (loc.inode);
+ loc.inode = inode_unref (loc.inode);
+ loc.inode = inode_new (rootloc->inode->table);
+ if (!loc.inode) {
+ printf ("Error getting inode\n");
+ ret = -1;
+ goto out;
+ }
+ loc.name = filename1;
+ gf_uuid_copy (loc.pargfid, loc.gfid);
+ gf_uuid_clear (loc.gfid);
+
+ ret = syncop_lookup (xl, &loc, &iatt, 0, xattr_req, &xattr_rsp);
+ if (ret) {
+ op_errno = -ret;
+ printf ("Lookup failed on %s:%s.\n", file,
+ strerror(op_errno));
+ flag = _gf_true;
+ }
+
+ ret = dict_get_str (xattr_rsp, "gfid-heal-msg", &gfid_heal_msg);
+ if (!ret) {
+ printf ("%s for file %s\n", gfid_heal_msg, file);
+ loc_wipe (&loc);
+ goto out;
+ }
+ if (flag)
+ goto out;
+
+ reval = 0;
+ loc_wipe (&loc);
+ memset (&iatt, 0, sizeof(iatt));
+
+retry2:
ret = glfs_resolve (fs, xl, file, &loc, &iatt, reval);
- ESTALE_RETRY (ret, errno, reval, &loc, retry);
+ ESTALE_RETRY (ret, errno, reval, &loc, retry2);
if (ret) {
printf("Lookup failed on %s:%s\n",
file, strerror (errno));
@@ -1098,6 +1179,13 @@ retry:
out:
if (xattr_rsp)
dict_unref (xattr_rsp);
+ if (path1)
+ GF_FREE (path1);
+ if (path2)
+ GF_FREE (path2);
+ if (filename)
+ GF_FREE (filename);
+ loc_wipe (&loc);
return ret;
}
diff --git a/tests/basic/afr/gfid-mismatch-resolution-with-cli.t b/tests/basic/afr/gfid-mismatch-resolution-with-cli.t
new file mode 100644
index 00000000000..b739ddc49cc
--- /dev/null
+++ b/tests/basic/afr/gfid-mismatch-resolution-with-cli.t
@@ -0,0 +1,168 @@
+#!/bin/bash
+
+. $(dirname $0)/../../include.rc
+. $(dirname $0)/../../volume.rc
+
+cleanup;
+
+TEST glusterd
+TEST pidof glusterd
+TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1}
+TEST $CLI volume start $V0
+TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0
+TEST $CLI volume set $V0 self-heal-daemon off
+TEST $CLI volume set $V0 cluster.entry-self-heal off
+TEST $CLI volume set $V0 cluster.metadata-self-heal off
+TEST $CLI volume set $V0 cluster.data-self-heal off
+cd $M0
+
+##### Healing from latest mtime ######
+
+TEST kill_brick $V0 $H0 $B0/${V0}0
+echo "Sink based on mtime" > f1
+TEST $CLI volume start $V0 force
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0
+TEST kill_brick $V0 $H0 $B0/${V0}1
+echo "Source based on mtime" > f1
+
+gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/f1)
+gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/f1)
+TEST [ "$gfid_0" != "$gfid_1" ]
+
+TEST $CLI volume start $V0 force
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1
+
+#We know that first brick has the latest mtime
+LATEST_MTIME_MD5=$(md5sum $B0/${V0}0/f1 | awk '{print $1}')
+
+TEST $CLI volume heal $V0 split-brain latest-mtime /f1
+
+#gfid split-brain should be resolved
+gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/f1)
+TEST [ "$gfid_0" == "$gfid_1" ]
+
+#Heal the data and check the md5sum
+TEST $CLI volume set $V0 self-heal-daemon on
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1
+TEST $CLI volume heal $V0
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0
+HEALED_MD5=$(md5sum $B0/${V0}1/f1 | awk '{print $1}')
+TEST [ "$LATEST_MTIME_MD5" == "$HEALED_MD5" ]
+
+
+##### Healing from bigger file ######
+
+TEST mkdir test
+TEST $CLI volume set $V0 self-heal-daemon off
+TEST kill_brick $V0 $H0 $B0/${V0}0
+echo "Bigger file" > test/f2
+TEST $CLI volume start $V0 force
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0
+TEST kill_brick $V0 $H0 $B0/${V0}1
+echo "Small file" > test/f2
+
+gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/test/f2)
+gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/test/f2)
+TEST [ "$gfid_0" != "$gfid_1" ]
+
+TEST $CLI volume start $V0 force
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1
+
+#We know that second brick has the bigger file
+BIGGER_FILE_MD5=$(md5sum $B0/${V0}1/test/f2 | awk '{print $1}')
+
+TEST $CLI volume heal $V0 split-brain bigger-file /test/f2
+
+#gfid split-brain should be resolved
+gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/test/f2)
+TEST [ "$gfid_0" == "$gfid_1" ]
+
+#Heal the data and check the md5sum
+TEST $CLI volume set $V0 self-heal-daemon on
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1
+TEST $CLI volume heal $V0
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0
+HEALED_MD5=$(md5sum $B0/${V0}0/test/f2 | awk '{print $1}')
+TEST [ "$BIGGER_FILE_MD5" == "$HEALED_MD5" ]
+
+
+#Add one more brick, and heal.
+TEST $CLI volume add-brick $V0 replica 3 $H0:$B0/${V0}2
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}2
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 2
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 2
+
+TEST $CLI volume heal $V0
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0
+
+
+##### Healing from source brick ######
+
+TEST $CLI volume set $V0 self-heal-daemon off
+TEST $CLI volume set $V0 cluster.quorum-type none
+TEST kill_brick $V0 $H0 $B0/${V0}0
+echo "We will consider these as sinks" > test/f3
+TEST $CLI volume start $V0 force
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 0
+TEST kill_brick $V0 $H0 $B0/${V0}1
+TEST kill_brick $V0 $H0 $B0/${V0}2
+echo "We will take this as source" > test/f3
+
+gfid_0=$(gf_get_gfid_xattr $B0/${V0}0/test/f3)
+gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/test/f3)
+gfid_2=$(gf_get_gfid_xattr $B0/${V0}2/test/f3)
+TEST [ "$gfid_0" != "$gfid_1" ]
+TEST [ "$gfid_1" == "$gfid_2" ]
+
+TEST $CLI volume start $V0 force
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}2
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 2
+
+#We will try to heal the split-brain with bigger file option.
+#It should fail, since we have same file size in bricks 1 & 2.
+EXPECT "No bigger file for file /test/f3" $CLI volume heal $V0 split-brain bigger-file /test/f3
+
+#Now heal from taking the brick 0 as the source
+SOURCE_MD5=$(md5sum $B0/${V0}0/test/f3 | awk '{print $1}')
+
+TEST $CLI volume heal $V0 split-brain source-brick $H0:$B0/${V0}0 /test/f3
+
+#gfid split-brain should be resolved
+gfid_1=$(gf_get_gfid_xattr $B0/${V0}1/test/f3)
+gfid_2=$(gf_get_gfid_xattr $B0/${V0}2/test/f3)
+TEST [ "$gfid_0" == "$gfid_1" ]
+TEST [ "$gfid_0" == "$gfid_2" ]
+
+#Heal the data and check the md5sum
+TEST $CLI volume set $V0 self-heal-daemon on
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 2
+TEST $CLI volume heal $V0
+EXPECT_WITHIN $HEAL_TIMEOUT "^0$" get_pending_heal_count $V0
+HEALED_MD5_1=$(md5sum $B0/${V0}1/test/f3 | awk '{print $1}')
+HEALED_MD5_2=$(md5sum $B0/${V0}2/test/f3 | awk '{print $1}')
+TEST [ "$SOURCE_MD5" == "$HEALED_MD5_1" ]
+TEST [ "$SOURCE_MD5" == "$HEALED_MD5_2" ]
+
+cd -
+cleanup;
diff --git a/tests/basic/afr/gfid-mismatch-resolution-with-fav-child-policy.t b/tests/basic/afr/gfid-mismatch-resolution-with-fav-child-policy.t
index 9f1347bbb44..2f14f838e49 100644
--- a/tests/basic/afr/gfid-mismatch-resolution-with-fav-child-policy.t
+++ b/tests/basic/afr/gfid-mismatch-resolution-with-fav-child-policy.t
@@ -226,6 +226,3 @@ HEALED_MD5=$(md5sum $B0/${V0}2/f4 | cut -d\ -f1)
TEST [ "$MAJORITY_MD5" == "$HEALED_MD5" ]
cleanup;
-
-#G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=1450730
-#G_TESTDEF_TEST_STATUS_NETBSD7=BAD_TEST,BUG=1450730
diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c
index 064320441b7..cba18b2ff8f 100644
--- a/xlators/cluster/afr/src/afr-common.c
+++ b/xlators/cluster/afr/src/afr-common.c
@@ -2114,6 +2114,7 @@ afr_lookup_done (call_frame_t *frame, xlator_t *this)
int op_errno = 0;
int read_subvol = 0;
int par_read_subvol = 0;
+ int ret = -1;
unsigned char *readable = NULL;
int event = 0;
struct afr_reply *replies = NULL;
@@ -2124,6 +2125,7 @@ afr_lookup_done (call_frame_t *frame, xlator_t *this)
int spb_choice = -1;
ia_type_t ia_type = IA_INVAL;
afr_read_subvol_args_t args = {0,};
+ char *gfid_heal_msg = NULL;
priv = this->private;
local = frame->local;
@@ -2258,6 +2260,19 @@ unwind:
local->op_errno = ENOTCONN;
}
+ ret = dict_get_str (local->xattr_req, "gfid-heal-msg", &gfid_heal_msg);
+ if (!ret) {
+ ret = dict_set_str (local->replies[read_subvol].xdata,
+ "gfid-heal-msg", gfid_heal_msg);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ AFR_MSG_DICT_SET_FAILED,
+ "Error setting gfid-heal-msg dict");
+ local->op_ret = -1;
+ local->op_errno = ENOMEM;
+ }
+ }
+
AFR_STACK_UNWIND (lookup, frame, local->op_ret, local->op_errno,
local->inode, &local->replies[read_subvol].poststat,
local->replies[read_subvol].xdata,
@@ -2520,7 +2535,7 @@ afr_lookup_selfheal_wrap (void *opaque)
loc_pargfid (&local->loc, pargfid);
ret = afr_selfheal_name (frame->this, pargfid, local->loc.name,
- &local->cont.lookup.gfid_req);
+ &local->cont.lookup.gfid_req, local->xattr_req);
if (ret == -EIO)
goto unwind;
@@ -2581,6 +2596,7 @@ afr_lookup_entry_heal (call_frame_t *frame, xlator_t *this)
}
if (need_heal) {
+
heal = copy_frame (frame);
if (heal)
heal->root->pid = GF_CLIENT_PID_SELF_HEALD;
diff --git a/xlators/cluster/afr/src/afr-self-heal-common.c b/xlators/cluster/afr/src/afr-self-heal-common.c
index 6b5e50d6c56..9ecd63ce10c 100644
--- a/xlators/cluster/afr/src/afr-self-heal-common.c
+++ b/xlators/cluster/afr/src/afr-self-heal-common.c
@@ -20,6 +20,256 @@ void
afr_heal_synctask (xlator_t *this, afr_local_t *local);
int
+afr_gfid_sbrain_source_from_src_brick (xlator_t *this,
+ struct afr_reply *replies,
+ char *src_brick)
+{
+ int i = 0;
+ afr_private_t *priv = NULL;
+
+ priv = this->private;
+ for (i = 0; i < priv->child_count; i++) {
+ if (!replies[i].valid || replies[i].op_ret == -1)
+ continue;
+ if (strcmp (priv->children[i]->name, src_brick) == 0)
+ return i;
+ }
+ return -1;
+}
+
+int
+afr_selfheal_gfid_mismatch_by_majority (struct afr_reply *replies,
+ int child_count)
+{
+ int j = 0;
+ int i = 0;
+ int src = -1;
+ int votes[child_count];
+
+ for (i = 0; i < child_count; i++) {
+ if (!replies[i].valid || replies[i].op_ret == -1)
+ continue;
+
+ votes[i] = 1;
+ for (j = i+1; j < child_count; j++) {
+ if ((!gf_uuid_compare (replies[i].poststat.ia_gfid,
+ replies[j].poststat.ia_gfid)))
+ votes[i]++;
+ if (votes[i] > child_count / 2) {
+ src = i;
+ goto out;
+ }
+ }
+ }
+
+out:
+ return src;
+}
+
+int afr_gfid_sbrain_source_from_bigger_file (struct afr_reply *replies,
+ int child_count)
+{
+ int i = 0;
+ int src = -1;
+ uint64_t size = 0;
+
+ for (i = 0; i < child_count; i++) {
+ if (!replies[i].valid || replies[i].op_ret == -1)
+ continue;
+ if (size < replies[i].poststat.ia_size) {
+ src = i;
+ size = replies[i].poststat.ia_size;
+ } else if (replies[i].poststat.ia_size == size) {
+ src = -1;
+ }
+ }
+ return src;
+}
+
+int afr_gfid_sbrain_source_from_latest_mtime (struct afr_reply *replies,
+ int child_count)
+{
+ int i = 0;
+ int src = -1;
+ uint32_t mtime = 0;
+ uint32_t mtime_nsec = 0;
+
+ for (i = 0; i < child_count; i++) {
+ if (!replies[i].valid || replies[i].op_ret != 0)
+ continue;
+ if ((mtime < replies[i].poststat.ia_mtime) ||
+ ((mtime == replies[i].poststat.ia_mtime) &&
+ (mtime_nsec < replies[i].poststat.ia_mtime_nsec))) {
+ src = i;
+ mtime = replies[i].poststat.ia_mtime;
+ mtime_nsec = replies[i].poststat.ia_mtime_nsec;
+ } else if ((mtime == replies[i].poststat.ia_mtime) &&
+ (mtime_nsec == replies[i].poststat.ia_mtime_nsec)) {
+ src = -1;
+ }
+ }
+ return src;
+}
+
+int
+afr_gfid_split_brain_source (xlator_t *this, struct afr_reply *replies,
+ inode_t *inode, uuid_t pargfid, const char *bname,
+ int src_idx, int child_idx,
+ unsigned char *locked_on, int *src, dict_t *xdata)
+{
+ afr_private_t *priv = NULL;
+ char g1[64] = {0,};
+ char g2[64] = {0,};
+ int up_count = 0;
+ int heal_op = -1;
+ int ret = -1;
+ char *src_brick = NULL;
+
+ *src = -1;
+ priv = this->private;
+ up_count = AFR_COUNT (locked_on, priv->child_count);
+ if (up_count != priv->child_count) {
+ gf_msg (this->name, GF_LOG_ERROR, 0, AFR_MSG_SPLIT_BRAIN,
+ "All the bricks should be up to resolve the gfid split "
+ "barin");
+ if (xdata) {
+ ret = dict_set_str (xdata, "gfid-heal-msg", "All the "
+ "bricks should be up to resolve the"
+ " gfid split barin");
+ if (ret)
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ AFR_MSG_DICT_SET_FAILED, "Error setting"
+ " gfid-heal-msg dict");
+ }
+ goto out;
+ }
+
+ if (xdata) {
+ ret = dict_get_int32 (xdata, "heal-op", &heal_op);
+ if (ret)
+ goto fav_child;
+ } else {
+ goto fav_child;
+ }
+
+ switch (heal_op) {
+ case GF_SHD_OP_SBRAIN_HEAL_FROM_BIGGER_FILE:
+ *src = afr_gfid_sbrain_source_from_bigger_file (replies,
+ priv->child_count);
+ if (*src == -1) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ AFR_MSG_SPLIT_BRAIN, "No bigger file");
+ if (xdata) {
+ ret = dict_set_str (xdata, "gfid-heal-msg",
+ "No bigger file");
+ if (ret)
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ AFR_MSG_DICT_SET_FAILED, "Error"
+ " setting gfid-heal-msg dict");
+ }
+ }
+ break;
+
+ case GF_SHD_OP_SBRAIN_HEAL_FROM_LATEST_MTIME:
+ *src = afr_gfid_sbrain_source_from_latest_mtime (replies,
+ priv->child_count);
+ if (*src == -1) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ AFR_MSG_SPLIT_BRAIN, "No difference in mtime");
+ if (xdata) {
+ ret = dict_set_str (xdata, "gfid-heal-msg",
+ "No difference in mtime");
+ if (ret)
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ AFR_MSG_DICT_SET_FAILED, "Error"
+ "setting gfid-heal-msg dict");
+ }
+ }
+ break;
+
+ case GF_SHD_OP_SBRAIN_HEAL_FROM_BRICK:
+ ret = dict_get_str (xdata, "child-name", &src_brick);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ AFR_MSG_SPLIT_BRAIN, "Error getting the source "
+ "brick");
+ break;
+ }
+ *src = afr_gfid_sbrain_source_from_src_brick (this, replies,
+ src_brick);
+ if (*src == -1) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ AFR_MSG_SPLIT_BRAIN, "Error getting the source "
+ "brick");
+ if (xdata) {
+ ret = dict_set_str (xdata, "gfid-heal-msg",
+ "Error getting the source "
+ "brick");
+ if (ret)
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ AFR_MSG_DICT_SET_FAILED, "Error"
+ " setting gfid-heal-msg dict");
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ goto out;
+
+fav_child:
+ switch (priv->fav_child_policy) {
+ case AFR_FAV_CHILD_BY_SIZE:
+ *src = afr_sh_fav_by_size (this, replies, inode);
+ break;
+ case AFR_FAV_CHILD_BY_MTIME:
+ *src = afr_sh_fav_by_mtime (this, replies, inode);
+ break;
+ case AFR_FAV_CHILD_BY_CTIME:
+ *src = afr_sh_fav_by_ctime(this, replies, inode);
+ break;
+ case AFR_FAV_CHILD_BY_MAJORITY:
+ if (priv->child_count != 2)
+ *src = afr_selfheal_gfid_mismatch_by_majority (replies,
+ priv->child_count);
+ else
+ *src = -1;
+
+ if (*src == -1) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ AFR_MSG_SPLIT_BRAIN, "No majority to resolve "
+ "gfid split brain");
+ }
+ break;
+ default:
+ break;
+ }
+
+out:
+ if (*src == -1) {
+ gf_msg (this->name, GF_LOG_ERROR, 0, AFR_MSG_SPLIT_BRAIN,
+ "Gfid mismatch detected for <gfid:%s>/%s>, %s on %s and"
+ " %s on %s.", uuid_utoa (pargfid), bname,
+ uuid_utoa_r (replies[child_idx].poststat.ia_gfid, g1),
+ priv->children[child_idx]->name,
+ uuid_utoa_r (replies[src_idx].poststat.ia_gfid, g2),
+ priv->children[src_idx]->name);
+ gf_event (EVENT_AFR_SPLIT_BRAIN, "subvol=%s;type=gfid;file="
+ "<gfid:%s>/%s>;count=2;child-%d=%s;gfid-%d=%s;"
+ "child-%d=%s;gfid-%d=%s", this->name,
+ uuid_utoa (pargfid), bname, child_idx,
+ priv->children[child_idx]->name, child_idx,
+ uuid_utoa_r (replies[child_idx].poststat.ia_gfid, g1),
+ src_idx, priv->children[src_idx]->name, src_idx,
+ uuid_utoa_r (replies[src_idx].poststat.ia_gfid, g2));
+ return -1;
+ }
+ return 0;
+}
+
+
+int
afr_selfheal_post_op_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int op_ret, int op_errno, dict_t *xattr, dict_t *xdata)
{
diff --git a/xlators/cluster/afr/src/afr-self-heal-entry.c b/xlators/cluster/afr/src/afr-self-heal-entry.c
index 82ae6432d7d..d7e9e60a7bf 100644
--- a/xlators/cluster/afr/src/afr-self-heal-entry.c
+++ b/xlators/cluster/afr/src/afr-self-heal-entry.c
@@ -17,105 +17,6 @@
#include "syncop-utils.h"
#include "events.h"
-int
-afr_selfheal_gfid_mismatch_by_majority (struct afr_reply *replies,
- int child_count)
-{
- int j = 0;
- int i = 0;
- int src = -1;
- int votes[child_count];
-
- for (i = 0; i < child_count; i++) {
- if (!replies[i].valid || replies[i].op_ret == -1)
- continue;
-
- votes[i] = 1;
- for (j = i+1; j < child_count; j++) {
- if ((!gf_uuid_compare (replies[i].poststat.ia_gfid,
- replies[j].poststat.ia_gfid)))
- votes[i]++;
- if (votes[i] > child_count / 2) {
- src = i;
- goto out;
- }
- }
- }
-
-out:
- return src;
-}
-
-int
-afr_gfid_split_brain_source (xlator_t *this, struct afr_reply *replies,
- inode_t *inode, uuid_t pargfid, char *bname,
- int src_idx, int child_idx,
- unsigned char *locked_on, int *src)
-{
- afr_private_t *priv = NULL;
- char g1[64] = {0,};
- char g2[64] = {0,};
- int up_count = 0;
-
- priv = this->private;
- up_count = AFR_COUNT (locked_on, priv->child_count);
- if (up_count != priv->child_count) {
- gf_msg (this->name, GF_LOG_ERROR, 0,
- AFR_MSG_SPLIT_BRAIN,
- "All the bricks should be up to resolve the gfid split "
- "brain");
- goto out;
- }
- switch (priv->fav_child_policy) {
- case AFR_FAV_CHILD_BY_SIZE:
- *src = afr_sh_fav_by_size (this, replies, inode);
- break;
- case AFR_FAV_CHILD_BY_MTIME:
- *src = afr_sh_fav_by_mtime (this, replies, inode);
- break;
- case AFR_FAV_CHILD_BY_CTIME:
- *src = afr_sh_fav_by_ctime(this, replies, inode);
- break;
- case AFR_FAV_CHILD_BY_MAJORITY:
- if (priv->child_count != 2)
- *src = afr_selfheal_gfid_mismatch_by_majority (replies,
- priv->child_count);
- else
- *src = -1;
-
- if (*src == -1) {
- gf_msg (this->name, GF_LOG_ERROR, 0,
- AFR_MSG_SPLIT_BRAIN, "No majority to resolve "
- "gfid split brain");
- }
- break;
- default:
- break;
- }
-
-out:
- if (*src == -1) {
- gf_msg (this->name, GF_LOG_ERROR, 0, AFR_MSG_SPLIT_BRAIN,
- "Gfid mismatch detected for <gfid:%s>/%s>, %s on %s and"
- " %s on %s. Skipping conservative merge on the file.",
- uuid_utoa (pargfid), bname,
- uuid_utoa_r (replies[child_idx].poststat.ia_gfid, g1),
- priv->children[child_idx]->name,
- uuid_utoa_r (replies[src_idx].poststat.ia_gfid, g2),
- priv->children[src_idx]->name);
- gf_event (EVENT_AFR_SPLIT_BRAIN, "subvol=%s;type=gfid;file="
- "<gfid:%s>/%s>;count=2;child-%d=%s;gfid-%d=%s;"
- "child-%d=%s;gfid-%d=%s", this->name,
- uuid_utoa (pargfid), bname, child_idx,
- priv->children[child_idx]->name, child_idx,
- uuid_utoa_r (replies[child_idx].poststat.ia_gfid, g1),
- src_idx, priv->children[src_idx]->name, src_idx,
- uuid_utoa_r (replies[src_idx].poststat.ia_gfid, g2));
- return -1;
- }
- return 0;
-}
-
static int
afr_selfheal_entry_delete (xlator_t *this, inode_t *dir, const char *name,
inode_t *inode, int child, struct afr_reply *replies)
@@ -332,7 +233,13 @@ afr_selfheal_detect_gfid_and_type_mismatch (xlator_t *this,
ret = afr_gfid_split_brain_source (this, replies, inode,
pargfid, bname,
src_idx, i,
- locked_on, src);
+ locked_on, src,
+ NULL);
+ if (ret)
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ AFR_MSG_SPLIT_BRAIN,
+ "Skipping conservative merge on the "
+ "file.");
return ret;
}
diff --git a/xlators/cluster/afr/src/afr-self-heal-name.c b/xlators/cluster/afr/src/afr-self-heal-name.c
index 8372cb6e376..1d198a8883e 100644
--- a/xlators/cluster/afr/src/afr-self-heal-name.c
+++ b/xlators/cluster/afr/src/afr-self-heal-name.c
@@ -330,14 +330,15 @@ static int
afr_selfheal_name_gfid_mismatch_check (xlator_t *this, struct afr_reply *replies,
int source, unsigned char *sources,
int *gfid_idx, uuid_t pargfid,
- const char *bname)
+ const char *bname, inode_t *inode,
+ unsigned char *locked_on, dict_t *xdata)
{
int i = 0;
int gfid_idx_iter = -1;
+ int ret = -1;
void *gfid = NULL;
void *gfid1 = NULL;
afr_private_t *priv = NULL;
- char g1[64], g2[64];
priv = this->private;
@@ -358,31 +359,29 @@ afr_selfheal_name_gfid_mismatch_check (xlator_t *this, struct afr_reply *replies
if (sources[i] || source == -1) {
if ((sources[gfid_idx_iter] || source == -1) &&
gf_uuid_compare (gfid, gfid1)) {
- gf_msg (this->name, GF_LOG_WARNING, 0,
- AFR_MSG_SPLIT_BRAIN,
- "GFID mismatch for <gfid:%s>/%s "
- "%s on %s and %s on %s",
- uuid_utoa (pargfid), bname,
- uuid_utoa_r (gfid1, g1),
- priv->children[i]->name,
- uuid_utoa_r (gfid, g2),
- priv->children[gfid_idx_iter]->name);
- gf_event (EVENT_AFR_SPLIT_BRAIN,
- "subvol=%s;type=gfid;"
- "file=<gfid:%s>/%s;count=2;"
- "child-%d=%s;gfid-%d=%s;child-%d=%s;"
- "gfid-%d=%s", this->name,
- uuid_utoa (pargfid), bname, i,
- priv->children[i]->name, i,
- uuid_utoa_r (gfid1, g1),
- gfid_idx_iter,
- priv->children[gfid_idx_iter]->name,
- gfid_idx_iter,
- uuid_utoa_r (gfid, g2));
-
- return -EIO;
+ ret = afr_gfid_split_brain_source (this,
+ replies,
+ inode,
+ pargfid,
+ bname,
+ gfid_idx_iter,
+ i, locked_on,
+ gfid_idx,
+ xdata);
+ if (!ret && *gfid_idx >= 0) {
+ ret = dict_set_str (xdata,
+ "gfid-heal-msg",
+ "GFID split-brain "
+ "resolved");
+ if (ret)
+ gf_msg (this->name,
+ GF_LOG_ERROR, 0,
+ AFR_MSG_DICT_SET_FAILED,
+ "Error setting gfid-"
+ "heal-msg dict");
+ }
+ return ret;
}
-
gfid = &replies[i].poststat.ia_gfid;
gfid_idx_iter = i;
}
@@ -427,7 +426,7 @@ __afr_selfheal_name_do (call_frame_t *frame, xlator_t *this, inode_t *parent,
unsigned char *sources, unsigned char *sinks,
unsigned char *healed_sinks, int source,
unsigned char *locked_on, struct afr_reply *replies,
- void *gfid_req)
+ void *gfid_req, dict_t *xdata)
{
int gfid_idx = -1;
int ret = -1;
@@ -458,7 +457,8 @@ __afr_selfheal_name_do (call_frame_t *frame, xlator_t *this, inode_t *parent,
ret = afr_selfheal_name_gfid_mismatch_check (this, replies, source,
sources, &gfid_idx,
- pargfid, bname);
+ pargfid, bname, inode,
+ locked_on, xdata);
if (ret)
return ret;
@@ -583,7 +583,8 @@ out:
int
afr_selfheal_name_do (call_frame_t *frame, xlator_t *this, inode_t *parent,
- uuid_t pargfid, const char *bname, void *gfid_req)
+ uuid_t pargfid, const char *bname, void *gfid_req,
+ dict_t *xdata)
{
afr_private_t *priv = NULL;
unsigned char *sources = NULL;
@@ -640,7 +641,7 @@ afr_selfheal_name_do (call_frame_t *frame, xlator_t *this, inode_t *parent,
ret = __afr_selfheal_name_do (frame, this, parent, pargfid,
bname, inode, sources, sinks,
healed_sinks, source, locked_on,
- replies, gfid_req);
+ replies, gfid_req, xdata);
}
unlock:
afr_selfheal_unentrylk (frame, this, parent, this->name, bname,
@@ -707,7 +708,7 @@ afr_selfheal_name_unlocked_inspect (call_frame_t *frame, xlator_t *this,
int
afr_selfheal_name (xlator_t *this, uuid_t pargfid, const char *bname,
- void *gfid_req)
+ void *gfid_req, dict_t *xdata)
{
inode_t *parent = NULL;
call_frame_t *frame = NULL;
@@ -729,7 +730,7 @@ afr_selfheal_name (xlator_t *this, uuid_t pargfid, const char *bname,
if (need_heal) {
ret = afr_selfheal_name_do (frame, this, parent, pargfid, bname,
- gfid_req);
+ gfid_req, xdata);
if (ret)
goto out;
}
diff --git a/xlators/cluster/afr/src/afr-self-heal.h b/xlators/cluster/afr/src/afr-self-heal.h
index 2e22ac2d7a1..36f081ec354 100644
--- a/xlators/cluster/afr/src/afr-self-heal.h
+++ b/xlators/cluster/afr/src/afr-self-heal.h
@@ -99,7 +99,7 @@ afr_throttled_selfheal (call_frame_t *frame, xlator_t *this);
int
afr_selfheal_name (xlator_t *this, uuid_t gfid, const char *name,
- void *gfid_req);
+ void *gfid_req, dict_t *xdata);
int
afr_selfheal_data (call_frame_t *frame, xlator_t *this, inode_t *inode);
@@ -330,4 +330,10 @@ int
afr_sh_fav_by_ctime (xlator_t *this, struct afr_reply *replies,
inode_t *inode);
+int
+afr_gfid_split_brain_source (xlator_t *this, struct afr_reply *replies,
+ inode_t *inode, uuid_t pargfid, const char *bname,
+ int src_idx, int child_idx,
+ unsigned char *locked_on, int *src, dict_t *xdata);
+
#endif /* !_AFR_SELFHEAL_H */
diff --git a/xlators/cluster/afr/src/afr-self-heald.c b/xlators/cluster/afr/src/afr-self-heald.c
index e1a40521709..08817202b33 100644
--- a/xlators/cluster/afr/src/afr-self-heald.c
+++ b/xlators/cluster/afr/src/afr-self-heald.c
@@ -301,7 +301,7 @@ afr_shd_selfheal_name (struct subvol_healer *healer, int child, uuid_t parent,
{
int ret = -1;
- ret = afr_selfheal_name (THIS, parent, bname, NULL);
+ ret = afr_selfheal_name (THIS, parent, bname, NULL, NULL);
return ret;
}