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