e7a346
From 43124cc2d3ddb1b3262e254326d8461cdf1f894d Mon Sep 17 00:00:00 2001
e7a346
From: Ravishankar N <ravishankar@redhat.com>
e7a346
Date: Fri, 21 Sep 2018 18:23:34 +0530
e7a346
Subject: [PATCH 385/385] afr: fix incorrect reporting of directory split-brain
e7a346
e7a346
Patch on master: https://review.gluster.org/#/c/glusterfs/+/21135/
e7a346
Problem:
e7a346
When a directory has dirty xattrs due to failed post-ops or when
e7a346
replace/reset brick is performed, AFR does a conservative merge as
e7a346
expected, but heal-info reports it as split-brain because there are no
e7a346
clear sources.
e7a346
e7a346
Fix:
e7a346
Modify pending flag to contain information about pending heals and
e7a346
split-brains. For directories, if spit-brain flag is not set,just show
e7a346
them as needing heal and not being in split-brain.
e7a346
e7a346
Change-Id: I21460bb5375297e421a14efb9ef0f9cea46f7e7c
e7a346
BUG: 1610743
e7a346
Signed-off-by: Ravishankar N <ravishankar@redhat.com>
e7a346
Reviewed-on: https://code.engineering.redhat.com/gerrit/150742
e7a346
Tested-by: RHGS Build Bot <nigelb@redhat.com>
e7a346
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
e7a346
---
e7a346
 tests/afr.rc                                       |  2 +-
e7a346
 .../bugs/replicate/bug-1626994-info-split-brain.t  | 62 ++++++++++++++++++++++
e7a346
 xlators/cluster/afr/src/afr-common.c               | 14 ++---
e7a346
 xlators/cluster/afr/src/afr-self-heal-common.c     |  6 ++-
e7a346
 xlators/cluster/afr/src/afr-self-heal-data.c       |  2 +-
e7a346
 xlators/cluster/afr/src/afr-self-heal-entry.c      |  2 +-
e7a346
 xlators/cluster/afr/src/afr-self-heal-metadata.c   |  3 +-
e7a346
 xlators/cluster/afr/src/afr-self-heal.h            |  8 +--
e7a346
 xlators/cluster/afr/src/afr.h                      |  3 ++
e7a346
 9 files changed, 85 insertions(+), 17 deletions(-)
e7a346
 create mode 100644 tests/bugs/replicate/bug-1626994-info-split-brain.t
e7a346
e7a346
diff --git a/tests/afr.rc b/tests/afr.rc
e7a346
index bdf4075..1fd0310 100644
e7a346
--- a/tests/afr.rc
e7a346
+++ b/tests/afr.rc
e7a346
@@ -2,7 +2,7 @@
e7a346
 
e7a346
 function create_brick_xattrop_entry {
e7a346
         local xattrop_dir=$(afr_get_index_path $1)
e7a346
-        local base_entry=`ls $xattrop_dir`
e7a346
+        local base_entry=`ls $xattrop_dir|grep xattrop`
e7a346
         local gfid_str
e7a346
         local params=`echo "$@" | cut -d' ' -f2-`
e7a346
         echo $params
e7a346
diff --git a/tests/bugs/replicate/bug-1626994-info-split-brain.t b/tests/bugs/replicate/bug-1626994-info-split-brain.t
e7a346
new file mode 100644
e7a346
index 0000000..86bfecb
e7a346
--- /dev/null
e7a346
+++ b/tests/bugs/replicate/bug-1626994-info-split-brain.t
e7a346
@@ -0,0 +1,62 @@
e7a346
+#!/bin/bash
e7a346
+
e7a346
+. $(dirname $0)/../../include.rc
e7a346
+. $(dirname $0)/../../volume.rc
e7a346
+. $(dirname $0)/../../afr.rc
e7a346
+
e7a346
+cleanup;
e7a346
+
e7a346
+# Test to check dirs having dirty xattr do not show up in info split-brain.
e7a346
+
e7a346
+TEST glusterd;
e7a346
+TEST pidof glusterd;
e7a346
+TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2};
e7a346
+TEST $CLI volume set $V0 self-heal-daemon off
e7a346
+TEST $CLI volume start $V0;
e7a346
+EXPECT 'Started' volinfo_field $V0 'Status';
e7a346
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}0
e7a346
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}1
e7a346
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" brick_up_status $V0 $H0 $B0/${V0}2
e7a346
+TEST $GFS --volfile-id=/$V0 --volfile-server=$H0 $M0
e7a346
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0
e7a346
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1
e7a346
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 2
e7a346
+
e7a346
+# Create base entry in indices/xattrop
e7a346
+echo "Data" > $M0/FILE
e7a346
+rm -f $M0/FILE
e7a346
+EXPECT "1" count_index_entries $B0/${V0}0
e7a346
+EXPECT "1" count_index_entries $B0/${V0}1
e7a346
+EXPECT "1" count_index_entries $B0/${V0}2
e7a346
+
e7a346
+TEST mkdir $M0/dirty_dir
e7a346
+TEST mkdir $M0/pending_dir
e7a346
+
e7a346
+# Set dirty xattrs on all bricks to simulate the case where entry transaction
e7a346
+# succeeded only the pre-op phase.
e7a346
+TEST setfattr -n trusted.afr.dirty -v 0x000000000000000000000001 $B0/${V0}0/dirty_dir
e7a346
+TEST setfattr -n trusted.afr.dirty -v 0x000000000000000000000001 $B0/${V0}1/dirty_dir
e7a346
+TEST setfattr -n trusted.afr.dirty -v 0x000000000000000000000001 $B0/${V0}2/dirty_dir
e7a346
+create_brick_xattrop_entry $B0/${V0}0  dirty_dir
e7a346
+# Should not show up as split-brain.
e7a346
+EXPECT "0" afr_get_split_brain_count $V0
e7a346
+
e7a346
+# replace/reset brick case where the new brick has dirty and the other 2 bricks
e7a346
+# blame it should not be reported as split-brain.
e7a346
+TEST setfattr -n trusted.afr.$V0-client-2 -v 0x000000000000000000000001 $B0/${V0}0
e7a346
+TEST setfattr -n trusted.afr.$V0-client-2 -v 0x000000000000000000000001 $B0/${V0}1
e7a346
+TEST setfattr -n trusted.afr.dirty -v 0x000000000000000000000001 $B0/${V0}2
e7a346
+create_brick_xattrop_entry $B0/${V0}0 "/"
e7a346
+# Should not show up as split-brain.
e7a346
+EXPECT "0" afr_get_split_brain_count $V0
e7a346
+
e7a346
+# Set pending xattrs on all bricks blaming each other to simulate the case of
e7a346
+# entry split-brain.
e7a346
+TEST setfattr -n trusted.afr.$V0-client-1 -v 0x000000000000000000000001 $B0/${V0}0/pending_dir
e7a346
+TEST setfattr -n trusted.afr.$V0-client-2 -v 0x000000000000000000000001 $B0/${V0}1/pending_dir
e7a346
+TEST setfattr -n trusted.afr.$V0-client-0 -v 0x000000000000000000000001 $B0/${V0}2/pending_dir
e7a346
+create_brick_xattrop_entry $B0/${V0}0 pending_dir
e7a346
+# Should show up as split-brain.
e7a346
+EXPECT "1" afr_get_split_brain_count $V0
e7a346
+
e7a346
+cleanup;
e7a346
diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c
e7a346
index a85549b..bded6a2 100644
e7a346
--- a/xlators/cluster/afr/src/afr-common.c
e7a346
+++ b/xlators/cluster/afr/src/afr-common.c
e7a346
@@ -5472,7 +5472,7 @@ out:
e7a346
 int
e7a346
 afr_selfheal_locked_metadata_inspect (call_frame_t *frame, xlator_t *this,
e7a346
                                       inode_t *inode, gf_boolean_t *msh,
e7a346
-                                      gf_boolean_t *pending)
e7a346
+                                      unsigned char *pending)
e7a346
 {
e7a346
         int ret = -1;
e7a346
         unsigned char *locked_on = NULL;
e7a346
@@ -5521,7 +5521,7 @@ out:
e7a346
 int
e7a346
 afr_selfheal_locked_data_inspect (call_frame_t *frame, xlator_t *this,
e7a346
                                   fd_t *fd, gf_boolean_t *dsh,
e7a346
-                                  gf_boolean_t *pflag)
e7a346
+                                  unsigned char *pflag)
e7a346
 {
e7a346
         int ret = -1;
e7a346
         unsigned char *data_lock = NULL;
e7a346
@@ -5568,7 +5568,7 @@ out:
e7a346
 int
e7a346
 afr_selfheal_locked_entry_inspect (call_frame_t *frame, xlator_t *this,
e7a346
                                    inode_t *inode,
e7a346
-                                   gf_boolean_t *esh, gf_boolean_t *pflag)
e7a346
+                                   gf_boolean_t *esh, unsigned char *pflag)
e7a346
 {
e7a346
         int ret = -1;
e7a346
         int source = -1;
e7a346
@@ -5619,7 +5619,7 @@ afr_selfheal_locked_entry_inspect (call_frame_t *frame, xlator_t *this,
e7a346
                                                             sinks, healed_sinks,
e7a346
                                                             locked_replies,
e7a346
                                                             &source, pflag);
e7a346
-                        if ((ret == 0) && source < 0)
e7a346
+                        if ((ret == 0) && (*pflag & PFLAG_SBRAIN))
e7a346
                                 ret = -EIO;
e7a346
                         *esh = afr_decide_heal_info (priv, sources, ret);
e7a346
                 }
e7a346
@@ -5642,7 +5642,7 @@ afr_selfheal_locked_inspect (call_frame_t *frame, xlator_t *this, uuid_t gfid,
e7a346
                              gf_boolean_t *entry_selfheal,
e7a346
                              gf_boolean_t *data_selfheal,
e7a346
                              gf_boolean_t *metadata_selfheal,
e7a346
-                             gf_boolean_t *pending)
e7a346
+                             unsigned char *pending)
e7a346
 
e7a346
 {
e7a346
         int ret             = -1;
e7a346
@@ -5730,7 +5730,7 @@ afr_get_heal_info (call_frame_t *frame, xlator_t *this, loc_t *loc)
e7a346
         gf_boolean_t    data_selfheal     = _gf_false;
e7a346
         gf_boolean_t    metadata_selfheal = _gf_false;
e7a346
         gf_boolean_t    entry_selfheal    = _gf_false;
e7a346
-        gf_boolean_t    pending           = _gf_false;
e7a346
+        unsigned char   pending           = 0;
e7a346
         dict_t         *dict              = NULL;
e7a346
         int             ret               = -1;
e7a346
         int             op_errno          = 0;
e7a346
@@ -5750,7 +5750,7 @@ afr_get_heal_info (call_frame_t *frame, xlator_t *this, loc_t *loc)
e7a346
                 goto out;
e7a346
         }
e7a346
 
e7a346
-        if (pending) {
e7a346
+        if (pending & PFLAG_PENDING) {
e7a346
                 size = strlen ("-pending") + 1;
e7a346
                 gf_asprintf (&substr, "-pending");
e7a346
                 if (!substr)
e7a346
diff --git a/xlators/cluster/afr/src/afr-self-heal-common.c b/xlators/cluster/afr/src/afr-self-heal-common.c
e7a346
index 7e6a691..d04f11d 100644
e7a346
--- a/xlators/cluster/afr/src/afr-self-heal-common.c
e7a346
+++ b/xlators/cluster/afr/src/afr-self-heal-common.c
e7a346
@@ -1545,7 +1545,7 @@ afr_selfheal_find_direction (call_frame_t *frame, xlator_t *this,
e7a346
                              afr_transaction_type type,
e7a346
                              unsigned char *locked_on, unsigned char *sources,
e7a346
                              unsigned char *sinks, uint64_t *witness,
e7a346
-                             gf_boolean_t *pflag)
e7a346
+                             unsigned char *pflag)
e7a346
 {
e7a346
         afr_private_t *priv = NULL;
e7a346
         int i = 0;
e7a346
@@ -1573,7 +1573,7 @@ afr_selfheal_find_direction (call_frame_t *frame, xlator_t *this,
e7a346
                 for (i = 0; i < priv->child_count; i++) {
e7a346
                         for (j = 0; j < priv->child_count; j++)
e7a346
                                 if (matrix[i][j])
e7a346
-                                        *pflag = _gf_true;
e7a346
+                                        *pflag |= PFLAG_PENDING;
e7a346
                         if (*pflag)
e7a346
                                 break;
e7a346
                 }
e7a346
@@ -1655,6 +1655,8 @@ afr_selfheal_find_direction (call_frame_t *frame, xlator_t *this,
e7a346
                         if (locked_on[i])
e7a346
                                 sinks[i] = 1;
e7a346
                 }
e7a346
+                if (pflag)
e7a346
+                        *pflag |= PFLAG_SBRAIN;
e7a346
         }
e7a346
 
e7a346
         /* One more class of witness similar to dirty in v2 is where no pending
e7a346
diff --git a/xlators/cluster/afr/src/afr-self-heal-data.c b/xlators/cluster/afr/src/afr-self-heal-data.c
e7a346
index 556a8f9..d3deb8f 100644
e7a346
--- a/xlators/cluster/afr/src/afr-self-heal-data.c
e7a346
+++ b/xlators/cluster/afr/src/afr-self-heal-data.c
e7a346
@@ -624,7 +624,7 @@ __afr_selfheal_data_prepare (call_frame_t *frame, xlator_t *this,
e7a346
                              unsigned char *sources, unsigned char *sinks,
e7a346
                              unsigned char *healed_sinks,
e7a346
                              unsigned char *undid_pending,
e7a346
-			     struct afr_reply *replies, gf_boolean_t *pflag)
e7a346
+			     struct afr_reply *replies, unsigned char *pflag)
e7a346
 {
e7a346
 	int ret = -1;
e7a346
 	int source = -1;
e7a346
diff --git a/xlators/cluster/afr/src/afr-self-heal-entry.c b/xlators/cluster/afr/src/afr-self-heal-entry.c
e7a346
index f6d3a8a..9f597af 100644
e7a346
--- a/xlators/cluster/afr/src/afr-self-heal-entry.c
e7a346
+++ b/xlators/cluster/afr/src/afr-self-heal-entry.c
e7a346
@@ -496,7 +496,7 @@ __afr_selfheal_entry_prepare (call_frame_t *frame, xlator_t *this,
e7a346
                               unsigned char *sources, unsigned char *sinks,
e7a346
                               unsigned char *healed_sinks,
e7a346
 			      struct afr_reply *replies, int *source_p,
e7a346
-                              gf_boolean_t *pflag)
e7a346
+                              unsigned char *pflag)
e7a346
 {
e7a346
 	int ret = -1;
e7a346
 	int source = -1;
e7a346
diff --git a/xlators/cluster/afr/src/afr-self-heal-metadata.c b/xlators/cluster/afr/src/afr-self-heal-metadata.c
e7a346
index 199f896..50f8888 100644
e7a346
--- a/xlators/cluster/afr/src/afr-self-heal-metadata.c
e7a346
+++ b/xlators/cluster/afr/src/afr-self-heal-metadata.c
e7a346
@@ -318,7 +318,8 @@ __afr_selfheal_metadata_prepare (call_frame_t *frame, xlator_t *this, inode_t *i
e7a346
 				 unsigned char *locked_on, unsigned char *sources,
e7a346
 				 unsigned char *sinks, unsigned char *healed_sinks,
e7a346
                                  unsigned char *undid_pending,
e7a346
-				 struct afr_reply *replies, gf_boolean_t *pflag)
e7a346
+				 struct afr_reply *replies,
e7a346
+                                 unsigned char *pflag)
e7a346
 {
e7a346
 	int ret = -1;
e7a346
 	int source = -1;
e7a346
diff --git a/xlators/cluster/afr/src/afr-self-heal.h b/xlators/cluster/afr/src/afr-self-heal.h
e7a346
index cc99d9e..7e6fb42 100644
e7a346
--- a/xlators/cluster/afr/src/afr-self-heal.h
e7a346
+++ b/xlators/cluster/afr/src/afr-self-heal.h
e7a346
@@ -172,7 +172,7 @@ afr_selfheal_find_direction (call_frame_t *frame, xlator_t *this,
e7a346
                              afr_transaction_type type,
e7a346
                              unsigned char *locked_on, unsigned char *sources,
e7a346
                              unsigned char *sinks, uint64_t *witness,
e7a346
-                             gf_boolean_t *flag);
e7a346
+                             unsigned char *flag);
e7a346
 int
e7a346
 afr_selfheal_fill_matrix (xlator_t *this, int **matrix, int subvol, int idx,
e7a346
                           dict_t *xdata);
e7a346
@@ -286,7 +286,7 @@ __afr_selfheal_data_prepare (call_frame_t *frame, xlator_t *this,
e7a346
                              unsigned char *sources,
e7a346
                              unsigned char *sinks, unsigned char *healed_sinks,
e7a346
                              unsigned char *undid_pending,
e7a346
-                             struct afr_reply *replies, gf_boolean_t *flag);
e7a346
+                             struct afr_reply *replies, unsigned char *flag);
e7a346
 
e7a346
 int
e7a346
 __afr_selfheal_metadata_prepare (call_frame_t *frame, xlator_t *this,
e7a346
@@ -296,7 +296,7 @@ __afr_selfheal_metadata_prepare (call_frame_t *frame, xlator_t *this,
e7a346
                                  unsigned char *healed_sinks,
e7a346
                                  unsigned char *undid_pending,
e7a346
                                  struct afr_reply *replies,
e7a346
-                                 gf_boolean_t *flag);
e7a346
+                                 unsigned char *flag);
e7a346
 int
e7a346
 __afr_selfheal_entry_prepare (call_frame_t *frame, xlator_t *this,
e7a346
                               inode_t *inode, unsigned char *locked_on,
e7a346
@@ -304,7 +304,7 @@ __afr_selfheal_entry_prepare (call_frame_t *frame, xlator_t *this,
e7a346
                               unsigned char *sinks,
e7a346
                               unsigned char *healed_sinks,
e7a346
                               struct afr_reply *replies, int *source_p,
e7a346
-                              gf_boolean_t *flag);
e7a346
+                              unsigned char *flag);
e7a346
 
e7a346
 int
e7a346
 afr_selfheal_unlocked_inspect (call_frame_t *frame, xlator_t *this,
e7a346
diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h
e7a346
index afe4a73..2e6d995 100644
e7a346
--- a/xlators/cluster/afr/src/afr.h
e7a346
+++ b/xlators/cluster/afr/src/afr.h
e7a346
@@ -36,6 +36,9 @@
e7a346
 
e7a346
 #define ARBITER_BRICK_INDEX 2
e7a346
 
e7a346
+#define PFLAG_PENDING (1 << 0)
e7a346
+#define PFLAG_SBRAIN (1 << 1)
e7a346
+
e7a346
 typedef int (*afr_lock_cbk_t) (call_frame_t *frame, xlator_t *this);
e7a346
 
e7a346
 typedef int (*afr_read_txn_wind_t) (call_frame_t *frame, xlator_t *this, int subvol);
e7a346
-- 
e7a346
1.8.3.1
e7a346