summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libglusterfs/src/glusterfs.h1
-rw-r--r--xlators/cluster/afr/src/afr-common.c134
-rw-r--r--xlators/cluster/afr/src/afr-inode-read.c4
-rw-r--r--xlators/cluster/afr/src/afr.h2
4 files changed, 141 insertions, 0 deletions
diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h
index 8f993b2086a..1302a11d82b 100644
--- a/libglusterfs/src/glusterfs.h
+++ b/libglusterfs/src/glusterfs.h
@@ -139,6 +139,7 @@
#define GF_AFR_HEAL_INFO "glusterfs.heal-info"
#define GF_AFR_HEAL_SBRAIN "glusterfs.heal-sbrain"
+#define GF_AFR_SBRAIN_STATUS "afr.split-brain-status"
#define GF_GFIDLESS_LOOKUP "gfidless-lookup"
/* replace-brick and pump related internal xattrs */
diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c
index 0e321e620f7..333c2bda556 100644
--- a/xlators/cluster/afr/src/afr-common.c
+++ b/xlators/cluster/afr/src/afr-common.c
@@ -4537,6 +4537,140 @@ out:
return ret;
}
+int
+afr_set_split_brain_status (call_frame_t *frame, xlator_t *this,
+ struct afr_reply *replies,
+ afr_transaction_type type,
+ gf_boolean_t *spb)
+{
+ afr_private_t *priv = NULL;
+ uint64_t *witness = NULL;
+ unsigned char *sources = NULL;
+ unsigned char *sinks = NULL;
+ int sources_count = 0;
+ int ret = 0;
+
+ priv = this->private;
+
+ sources = alloca0 (priv->child_count);
+ sinks = alloca0 (priv->child_count);
+ witness = alloca0(priv->child_count * sizeof (*witness));
+
+ ret = afr_selfheal_find_direction (frame, this, replies,
+ type, priv->child_up, sources,
+ sinks, witness);
+ if (ret)
+ return ret;
+
+ sources_count = AFR_COUNT (sources, priv->child_count);
+ if (!sources_count)
+ *spb = _gf_true;
+
+ return ret;
+}
+
+int
+afr_get_split_brain_status (call_frame_t *frame, xlator_t *this, loc_t *loc)
+{
+ gf_boolean_t d_spb = _gf_false;
+ gf_boolean_t m_spb = _gf_false;
+ int ret = -1;
+ int op_errno = 0;
+ int i = 0;
+ char *choices = NULL;
+ char *status = NULL;
+ dict_t *dict = NULL;
+ struct afr_reply *replies = NULL;
+ inode_t *inode = NULL;
+ afr_private_t *priv = NULL;
+ xlator_t **children = NULL;
+
+ priv = this->private;
+ children = priv->children;
+
+ inode = afr_inode_find (this, loc->gfid);
+ if (!inode)
+ goto out;
+ replies = alloca0 (sizeof (*replies) * priv->child_count);
+
+ /* Calculation for string length :
+ * (child_count X length of child-name) + strlen (" Choices :")
+ * child-name consists of :
+ * a) 256 = max characters for volname according to GD_VOLUME_NAME_MAX
+ * b) strlen ("-client-00,") assuming 16 replicas
+ */
+ choices = alloca0 (priv->child_count * (256 + strlen ("-client-00,")) +
+ strlen (" Choices:"));
+ ret = afr_selfheal_unlocked_discover (frame, inode, loc->gfid, replies);
+ if (ret) {
+ op_errno = -ret;
+ ret = -1;
+ goto out;
+ }
+
+ ret = afr_set_split_brain_status (frame, this, replies,
+ AFR_DATA_TRANSACTION, &d_spb);
+ if (ret) {
+ op_errno = -ret;
+ ret = -1;
+ goto out;
+ }
+
+ ret = afr_set_split_brain_status (frame, this, replies,
+ AFR_METADATA_TRANSACTION, &m_spb);
+ if (ret) {
+ op_errno = -ret;
+ ret = -1;
+ goto out;
+ }
+
+ dict = dict_new ();
+ if (!dict) {
+ op_errno = ENOMEM;
+ ret = -1;
+ goto out;
+ }
+
+ if (d_spb || m_spb) {
+ sprintf (choices, " Choices:");
+ for (i = 0; i < priv->child_count; i++) {
+ strcat (choices, children[i]->name);
+ strcat (choices, ",");
+ }
+ choices[strlen (choices) - 1] = '\0';
+
+ ret = gf_asprintf (&status, "data-split-brain:%s "
+ "metadata-split-brain:%s%s",
+ (d_spb) ? "yes" : "no",
+ (m_spb) ? "yes" : "no", choices);
+
+ if (-1 == ret) {
+ op_errno = ENOMEM;
+ goto out;
+ }
+ ret = dict_set_dynstr (dict, GF_AFR_SBRAIN_STATUS, status);
+ if (ret)
+ goto out;
+ } else {
+ ret = dict_set_str (dict, GF_AFR_SBRAIN_STATUS,
+ "The file is not under data or"
+ " metadata split-brain");
+ if (ret)
+ goto out;
+ }
+
+ ret = 0;
+out:
+ AFR_STACK_UNWIND (getxattr, frame, ret, op_errno, dict, NULL);
+ if (dict)
+ dict_unref (dict);
+ if (replies)
+ afr_replies_wipe (replies, priv->child_count);
+ if (inode)
+ inode_unref (inode);
+ return ret;
+}
+
int32_t
afr_heal_splitbrain_file(call_frame_t *frame, xlator_t *this, loc_t *loc)
{
diff --git a/xlators/cluster/afr/src/afr-inode-read.c b/xlators/cluster/afr/src/afr-inode-read.c
index 78dd65f30e7..e773f3284a6 100644
--- a/xlators/cluster/afr/src/afr-inode-read.c
+++ b/xlators/cluster/afr/src/afr-inode-read.c
@@ -1385,6 +1385,10 @@ afr_getxattr (call_frame_t *frame, xlator_t *this,
return 0;
}
+ if (!strcmp (name, GF_AFR_SBRAIN_STATUS)) {
+ afr_get_split_brain_status (frame, this, loc);
+ return 0;
+ }
/*
* if we are doing getxattr with pathinfo as the key then we
* collect information from all childs
diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h
index 09821b724fe..d9233eedadc 100644
--- a/xlators/cluster/afr/src/afr.h
+++ b/xlators/cluster/afr/src/afr.h
@@ -1025,4 +1025,6 @@ afr_get_heal_info (call_frame_t *frame, xlator_t *this, loc_t *loc,
int
afr_heal_splitbrain_file(call_frame_t *frame, xlator_t *this, loc_t *loc);
+int
+afr_get_split_brain_status (call_frame_t *frame, xlator_t *this, loc_t *loc);
#endif /* __AFR_H__ */