190130
From 8b11ac1575ef167af2a47a96f7b7ed0f32bb5897 Mon Sep 17 00:00:00 2001
2072c5
From: karthik-us <ksubrahm@redhat.com>
2072c5
Date: Fri, 5 Jun 2020 17:20:04 +0530
190130
Subject: [PATCH 422/449] cluster/afr: Prioritize ENOSPC over other errors
2072c5
2072c5
Backport of: https://review.gluster.org/#/c/glusterfs/+/24477/
2072c5
2072c5
Problem:
2072c5
In a replicate/arbiter volume if file creations or writes fails on
2072c5
quorum number of bricks and on one brick it is due to ENOSPC and
2072c5
on other brick it fails for a different reason, it may fail with
2072c5
errors other than ENOSPC in some cases.
2072c5
2072c5
Fix:
2072c5
Prioritize ENOSPC over other lesser priority errors and do not set
2072c5
op_errno in posix_gfid_set if op_ret is 0 to avoid receiving any
2072c5
error_no which can be misinterpreted by __afr_dir_write_finalize().
2072c5
2072c5
Also removing the function afr_has_arbiter_fop_cbk_quorum() which
2072c5
might consider a successful reply form a single brick as quorum
2072c5
success in some cases, whereas we always need fop to be successful
2072c5
on quorum number of bricks in arbiter configuration.
2072c5
2072c5
Change-Id: I4dd2bff17e6812bc7c8372130976e365e2407d88
2072c5
Signed-off-by: karthik-us <ksubrahm@redhat.com>
190130
BUG: 1837467
190130
Reviewed-on: https://code.engineering.redhat.com/gerrit/202526
2072c5
Tested-by: RHGS Build Bot <nigelb@redhat.com>
2072c5
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
2072c5
---
2072c5
 .../bugs/replicate/issue-1254-prioritize-enospc.t  | 80 ++++++++++++++++++++++
2072c5
 xlators/cluster/afr/src/afr-common.c               |  4 +-
2072c5
 xlators/cluster/afr/src/afr-transaction.c          | 48 +------------
2072c5
 xlators/storage/posix/src/posix-helpers.c          |  2 +-
2072c5
 4 files changed, 86 insertions(+), 48 deletions(-)
2072c5
 create mode 100644 tests/bugs/replicate/issue-1254-prioritize-enospc.t
2072c5
2072c5
diff --git a/tests/bugs/replicate/issue-1254-prioritize-enospc.t b/tests/bugs/replicate/issue-1254-prioritize-enospc.t
2072c5
new file mode 100644
2072c5
index 0000000..fab94b7
2072c5
--- /dev/null
2072c5
+++ b/tests/bugs/replicate/issue-1254-prioritize-enospc.t
2072c5
@@ -0,0 +1,80 @@
2072c5
+#!/bin/bash
2072c5
+
2072c5
+. $(dirname $0)/../../include.rc
2072c5
+. $(dirname $0)/../../volume.rc
2072c5
+
2072c5
+cleanup
2072c5
+
2072c5
+function create_bricks {
2072c5
+    TEST truncate -s 100M $B0/brick0
2072c5
+    TEST truncate -s 100M $B0/brick1
2072c5
+    TEST truncate -s 20M $B0/brick2
2072c5
+    LO1=`SETUP_LOOP $B0/brick0`
2072c5
+    TEST [ $? -eq 0 ]
2072c5
+    TEST MKFS_LOOP $LO1
2072c5
+    LO2=`SETUP_LOOP $B0/brick1`
2072c5
+    TEST [ $? -eq 0 ]
2072c5
+    TEST MKFS_LOOP $LO2
2072c5
+    LO3=`SETUP_LOOP $B0/brick2`
2072c5
+    TEST [ $? -eq 0 ]
2072c5
+    TEST MKFS_LOOP $LO3
2072c5
+    TEST mkdir -p $B0/${V0}0 $B0/${V0}1 $B0/${V0}2
2072c5
+    TEST MOUNT_LOOP $LO1 $B0/${V0}0
2072c5
+    TEST MOUNT_LOOP $LO2 $B0/${V0}1
2072c5
+    TEST MOUNT_LOOP $LO3 $B0/${V0}2
2072c5
+}
2072c5
+
2072c5
+function create_files {
2072c5
+        local i=1
2072c5
+        while (true)
2072c5
+        do
2072c5
+                touch $M0/file$i
2072c5
+                if [ -e $B0/${V0}2/file$i ];
2072c5
+                then
2072c5
+                        ((i++))
2072c5
+                else
2072c5
+                        break
2072c5
+                fi
2072c5
+        done
2072c5
+}
2072c5
+
2072c5
+TESTS_EXPECTED_IN_LOOP=13
2072c5
+
2072c5
+#Arbiter volume: Check for ENOSPC when arbiter brick becomes full#
2072c5
+TEST glusterd
2072c5
+create_bricks
2072c5
+TEST $CLI volume create $V0 replica 3 arbiter 1 $H0:$B0/${V0}{0,1,2}
2072c5
+TEST $CLI volume start $V0
2072c5
+TEST $CLI volume set $V0 performance.write-behind off
2072c5
+TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0
2072c5
+
2072c5
+create_files
2072c5
+TEST kill_brick $V0 $H0 $B0/${V0}1
2072c5
+error1=$(touch $M0/file-1 2>&1)
2072c5
+EXPECT "No space left on device" echo $error1
2072c5
+error2=$(mkdir $M0/dir-1 2>&1)
2072c5
+EXPECT "No space left on device" echo $error2
2072c5
+error3=$((echo "Test" > $M0/file-3) 2>&1)
2072c5
+EXPECT "No space left on device" echo $error3
2072c5
+
2072c5
+cleanup
2072c5
+
2072c5
+#Replica-3 volume: Check for ENOSPC when one of the brick becomes full#
2072c5
+#Keeping the third brick of lower size to simulate disk full scenario#
2072c5
+TEST glusterd
2072c5
+create_bricks
2072c5
+TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2}
2072c5
+TEST $CLI volume start $V0
2072c5
+TEST $CLI volume set $V0 performance.write-behind off
2072c5
+TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0
2072c5
+
2072c5
+create_files
2072c5
+TEST kill_brick $V0 $H0 $B0/${V0}1
2072c5
+error1=$(touch $M0/file-1 2>&1)
2072c5
+EXPECT "No space left on device" echo $error1
2072c5
+error2=$(mkdir $M0/dir-1 2>&1)
2072c5
+EXPECT "No space left on device" echo $error2
2072c5
+error3=$((cat /dev/zero > $M0/file1) 2>&1)
2072c5
+EXPECT "No space left on device" echo $error3
2072c5
+
2072c5
+cleanup
2072c5
diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c
190130
index 5806556..59710aa 100644
2072c5
--- a/xlators/cluster/afr/src/afr-common.c
2072c5
+++ b/xlators/cluster/afr/src/afr-common.c
190130
@@ -2464,7 +2464,7 @@ error:
2072c5
  * others in that they must be given higher priority while
2072c5
  * returning to the user.
2072c5
  *
2072c5
- * The hierarchy is ENODATA > ENOENT > ESTALE > others
2072c5
+ * The hierarchy is ENODATA > ENOENT > ESTALE > ENOSPC others
2072c5
  */
2072c5
 
2072c5
 int
190130
@@ -2476,6 +2476,8 @@ afr_higher_errno(int32_t old_errno, int32_t new_errno)
2072c5
         return ENOENT;
2072c5
     if (old_errno == ESTALE || new_errno == ESTALE)
2072c5
         return ESTALE;
2072c5
+    if (old_errno == ENOSPC || new_errno == ENOSPC)
2072c5
+        return ENOSPC;
2072c5
 
2072c5
     return new_errno;
2072c5
 }
2072c5
diff --git a/xlators/cluster/afr/src/afr-transaction.c b/xlators/cluster/afr/src/afr-transaction.c
2072c5
index 15f3a7e..8e65ae2 100644
2072c5
--- a/xlators/cluster/afr/src/afr-transaction.c
2072c5
+++ b/xlators/cluster/afr/src/afr-transaction.c
2072c5
@@ -514,42 +514,6 @@ afr_compute_pre_op_sources(call_frame_t *frame, xlator_t *this)
2072c5
                 local->transaction.pre_op_sources[j] = 0;
2072c5
 }
2072c5
 
2072c5
-gf_boolean_t
2072c5
-afr_has_arbiter_fop_cbk_quorum(call_frame_t *frame)
2072c5
-{
2072c5
-    afr_local_t *local = NULL;
2072c5
-    afr_private_t *priv = NULL;
2072c5
-    xlator_t *this = NULL;
2072c5
-    gf_boolean_t fop_failed = _gf_false;
2072c5
-    unsigned char *pre_op_sources = NULL;
2072c5
-    int i = 0;
2072c5
-
2072c5
-    local = frame->local;
2072c5
-    this = frame->this;
2072c5
-    priv = this->private;
2072c5
-    pre_op_sources = local->transaction.pre_op_sources;
2072c5
-
2072c5
-    /* If the fop failed on the brick, it is not a source. */
2072c5
-    for (i = 0; i < priv->child_count; i++)
2072c5
-        if (local->transaction.failed_subvols[i])
2072c5
-            pre_op_sources[i] = 0;
2072c5
-
2072c5
-    switch (AFR_COUNT(pre_op_sources, priv->child_count)) {
2072c5
-        case 1:
2072c5
-            if (pre_op_sources[ARBITER_BRICK_INDEX])
2072c5
-                fop_failed = _gf_true;
2072c5
-            break;
2072c5
-        case 0:
2072c5
-            fop_failed = _gf_true;
2072c5
-            break;
2072c5
-    }
2072c5
-
2072c5
-    if (fop_failed)
2072c5
-        return _gf_false;
2072c5
-
2072c5
-    return _gf_true;
2072c5
-}
2072c5
-
2072c5
 void
2072c5
 afr_txn_arbitrate_fop(call_frame_t *frame, xlator_t *this)
2072c5
 {
2072c5
@@ -968,12 +932,8 @@ afr_need_dirty_marking(call_frame_t *frame, xlator_t *this)
2072c5
         priv->child_count)
2072c5
         return _gf_false;
2072c5
 
2072c5
-    if (priv->arbiter_count) {
2072c5
-        if (!afr_has_arbiter_fop_cbk_quorum(frame))
2072c5
-            need_dirty = _gf_true;
2072c5
-    } else if (!afr_has_fop_cbk_quorum(frame)) {
2072c5
+    if (!afr_has_fop_cbk_quorum(frame))
2072c5
         need_dirty = _gf_true;
2072c5
-    }
2072c5
 
2072c5
     return need_dirty;
2072c5
 }
2072c5
@@ -1023,12 +983,8 @@ afr_handle_quorum(call_frame_t *frame, xlator_t *this)
2072c5
      * no split-brain with the fix. The problem is eliminated completely.
2072c5
      */
2072c5
 
2072c5
-    if (priv->arbiter_count) {
2072c5
-        if (afr_has_arbiter_fop_cbk_quorum(frame))
2072c5
-            return;
2072c5
-    } else if (afr_has_fop_cbk_quorum(frame)) {
2072c5
+    if (afr_has_fop_cbk_quorum(frame))
2072c5
         return;
2072c5
-    }
2072c5
 
2072c5
     if (afr_need_dirty_marking(frame, this))
2072c5
         goto set_response;
2072c5
diff --git a/xlators/storage/posix/src/posix-helpers.c b/xlators/storage/posix/src/posix-helpers.c
190130
index 2c27d22..949c799 100644
2072c5
--- a/xlators/storage/posix/src/posix-helpers.c
2072c5
+++ b/xlators/storage/posix/src/posix-helpers.c
2072c5
@@ -1059,7 +1059,7 @@ verify_handle:
2072c5
         ret = posix_handle_soft(this, path, loc, uuid_curr, &stat;;
2072c5
 
2072c5
 out:
2072c5
-    if (!(*op_errno))
2072c5
+    if (ret && !(*op_errno))
2072c5
         *op_errno = errno;
2072c5
     return ret;
2072c5
 }
2072c5
-- 
2072c5
1.8.3.1
2072c5