Blob Blame History Raw
From ebcd815d4ae36228cf79c393e8d58aa49d5300bb Mon Sep 17 00:00:00 2001
From: Anuradha Talur <atalur@redhat.com>
Date: Fri, 13 May 2016 15:34:06 +0530
Subject: [PATCH 150/158] cluster/afr : Do post-op in case of symmetric errors

        Backport of: http://review.gluster.org/#/c/14310/

In afr_changelog_post_op_now(), if there was any error,
meaning op_ret < 0, post-op was not being done even when
the errors were symmetric and there were no "failed
subvols".

Fix:
When the errors are symmetric, perform post-op.

How was the bug found :
In a 1 X 3 volume with shard and write behind on
when writes were done into a file with one brick down,
the trusted.afr.dirty xattr's value for .shard directory
would keep increasing as post op was not done but pre-op was.
This incorrectly showed .shard to be in split-brain.

RCA:
When WB is on, due to multiple writes being sent on
offset lying in the same shard, chances are that
same shard file will be created more than once
with the second one failing with op_ret < 0
and op_errno = EEXIST.

As op_ret was negative, afr wouldn't do post-op,
leading to no decrement of trusted.afr.dirty xattr.
Thus showing .shard directory to be in split-brain.

        >Change-Id: I711bdeaa1397244e6a7790e96f0c84501798fc59
        >BUG: 1335652
        >Signed-off-by: Anuradha Talur <atalur@redhat.com>

Change-Id: I711bdeaa1397244e6a7790e96f0c84501798fc59
BUG: 1332949
Signed-off-by: Anuradha Talur <atalur@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/74280
Reviewed-by: Ravishankar Narayanankutty <ravishankar@redhat.com>
Tested-by: Ravishankar Narayanankutty <ravishankar@redhat.com>
---
 tests/bugs/replicate/bug-1335652.t        |   29 +++++++++++++++++++++++++++++
 xlators/cluster/afr/src/afr-transaction.c |    8 ++++++--
 2 files changed, 35 insertions(+), 2 deletions(-)
 create mode 100644 tests/bugs/replicate/bug-1335652.t

diff --git a/tests/bugs/replicate/bug-1335652.t b/tests/bugs/replicate/bug-1335652.t
new file mode 100644
index 0000000..653a1b0
--- /dev/null
+++ b/tests/bugs/replicate/bug-1335652.t
@@ -0,0 +1,29 @@
+#!/bin/bash
+. $(dirname $0)/../../include.rc
+. $(dirname $0)/../../volume.rc
+cleanup;
+
+TEST glusterd
+TEST pidof glusterd
+TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2}
+TEST $CLI volume set $V0 shard on
+TEST $CLI volume set $V0 self-heal-daemon off
+TEST $CLI volume set $V0 data-self-heal off
+TEST $CLI volume set $V0 entry-self-heal off
+TEST $CLI volume set $V0 metadata-self-heal off
+TEST $CLI volume start $V0
+
+TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0;
+
+#Kill the zero'th brick so that 1st and 2nd get marked dirty
+TEST kill_brick $V0 $H0 $B0/${V0}0
+
+TEST dd if=/dev/urandom of=$M0/file bs=10MB count=20
+
+#At any point value of dirty should not be greater than 0 on source bricks
+EXPECT "000000000000000000000000" get_hex_xattr trusted.afr.dirty $B0/${V0}1/.shard
+EXPECT "000000000000000000000000" get_hex_xattr trusted.afr.dirty $B0/${V0}2/.shard
+
+rm -rf $M0/file;
+
+cleanup;
diff --git a/xlators/cluster/afr/src/afr-transaction.c b/xlators/cluster/afr/src/afr-transaction.c
index 73de030..d83a45c 100644
--- a/xlators/cluster/afr/src/afr-transaction.c
+++ b/xlators/cluster/afr/src/afr-transaction.c
@@ -580,10 +580,14 @@ afr_handle_symmetric_errors (call_frame_t *frame, xlator_t *this)
 		}
 		i_errno = local->replies[i].op_errno;
 
-		if (i_errno == ENOTCONN) {
+		if (i_errno == ENOTCONN || i_errno == EDQUOT ||
+                    i_errno == ENOSPC) {
 			/* ENOTCONN is not a symmetric error. We do not
 			   know if the operation was performed on the
 			   backend or not.
+			*  Before reaching EDQUOT and ENOSPC, each brick would
+			*  have written some amount of data, hence this is not
+			*  symmetric error.
 			*/
 			matching_errors = _gf_false;
 			break;
@@ -760,7 +764,7 @@ afr_changelog_post_op_now (call_frame_t *frame, xlator_t *this)
 	else
 		need_undirty = _gf_true;
 
-        if (local->op_ret < 0) {
+        if (local->op_ret < 0 && !nothing_failed) {
                 afr_changelog_post_op_done (frame, this);
                 goto out;
         }
-- 
1.7.1