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