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