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