74b1de
From cca418b78ec976aa69eacd56b0e6127ea7e3dd26 Mon Sep 17 00:00:00 2001
74b1de
From: Pranith Kumar K <pkarampu@redhat.com>
74b1de
Date: Thu, 4 Apr 2019 15:31:56 +0530
74b1de
Subject: [PATCH 095/124] cluster/afr: Remove local from owners_list on failure
74b1de
 of lock-acquisition
74b1de
74b1de
	Backport of https://review.gluster.org/c/glusterfs/+/22515
74b1de
74b1de
When eager-lock lock acquisition fails because of say network failures, the
74b1de
local is not being removed from owners_list, this leads to accumulation of
74b1de
waiting frames and the application will hang because the waiting frames are
74b1de
under the assumption that another transaction is in the process of acquiring
74b1de
lock because owner-list is not empty. Handled this case as well in this patch.
74b1de
Added asserts to make it easier to find these problems in future.
74b1de
74b1de
Change-Id: I3101393265e9827755725b1f2d94a93d8709e923
74b1de
fixes: bz#1688395
74b1de
Signed-off-by: Pranith Kumar K <pkarampu@redhat.com>
74b1de
Reviewed-on: https://code.engineering.redhat.com/gerrit/167859
74b1de
Tested-by: RHGS Build Bot <nigelb@redhat.com>
74b1de
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
74b1de
---
74b1de
 tests/bugs/replicate/bug-1696599-io-hang.t | 47 ++++++++++++++++++++++++++++++
74b1de
 xlators/cluster/afr/src/afr-common.c       |  8 ++---
74b1de
 xlators/cluster/afr/src/afr-lk-common.c    |  1 -
74b1de
 xlators/cluster/afr/src/afr-transaction.c  | 19 +++++-------
74b1de
 xlators/cluster/afr/src/afr.h              |  4 +--
74b1de
 5 files changed, 61 insertions(+), 18 deletions(-)
74b1de
 create mode 100755 tests/bugs/replicate/bug-1696599-io-hang.t
74b1de
74b1de
diff --git a/tests/bugs/replicate/bug-1696599-io-hang.t b/tests/bugs/replicate/bug-1696599-io-hang.t
74b1de
new file mode 100755
74b1de
index 0000000..869cdb9
74b1de
--- /dev/null
74b1de
+++ b/tests/bugs/replicate/bug-1696599-io-hang.t
74b1de
@@ -0,0 +1,47 @@
74b1de
+#!/bin/bash
74b1de
+
74b1de
+. $(dirname $0)/../../include.rc
74b1de
+. $(dirname $0)/../../volume.rc
74b1de
+. $(dirname $0)/../../fileio.rc
74b1de
+
74b1de
+#Tests that local structures in afr are removed from granted/blocked list of
74b1de
+#locks when inodelk fails on all bricks
74b1de
+
74b1de
+cleanup;
74b1de
+
74b1de
+TEST glusterd
74b1de
+TEST pidof glusterd
74b1de
+
74b1de
+TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{1..3}
74b1de
+TEST $CLI volume set $V0 performance.quick-read off
74b1de
+TEST $CLI volume set $V0 performance.write-behind off
74b1de
+TEST $CLI volume set $V0 performance.io-cache off
74b1de
+TEST $CLI volume set $V0 performance.stat-prefetch off
74b1de
+TEST $CLI volume set $V0 performance.client-io-threads off
74b1de
+TEST $CLI volume set $V0 delay-gen locks
74b1de
+TEST $CLI volume set $V0 delay-gen.delay-duration 5000000
74b1de
+TEST $CLI volume set $V0 delay-gen.delay-percentage 100
74b1de
+TEST $CLI volume set $V0 delay-gen.enable finodelk
74b1de
+
74b1de
+TEST $CLI volume start $V0
74b1de
+EXPECT 'Started' volinfo_field $V0 'Status'
74b1de
+
74b1de
+TEST $GFS -s $H0 --volfile-id $V0 $M0
74b1de
+TEST touch $M0/file
74b1de
+#Trigger write and stop bricks so inodelks fail on all bricks leading to
74b1de
+#lock failure condition
74b1de
+echo abc >> $M0/file &
74b1de
+
74b1de
+TEST $CLI volume stop $V0
74b1de
+TEST $CLI volume reset $V0 delay-gen
74b1de
+wait
74b1de
+TEST $CLI volume start $V0
74b1de
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_meta $M0 $V0-replicate-0 0
74b1de
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_meta $M0 $V0-replicate-0 1
74b1de
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_meta $M0 $V0-replicate-0 2
74b1de
+#Test that only one write succeeded, this tests that delay-gen worked as
74b1de
+#expected
74b1de
+echo abc >> $M0/file
74b1de
+EXPECT "abc" cat $M0/file
74b1de
+
74b1de
+cleanup;
74b1de
diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c
74b1de
index 45b96e3..47a5d3a 100644
74b1de
--- a/xlators/cluster/afr/src/afr-common.c
74b1de
+++ b/xlators/cluster/afr/src/afr-common.c
74b1de
@@ -5763,6 +5763,10 @@ afr_transaction_local_init(afr_local_t *local, xlator_t *this)
74b1de
     afr_private_t *priv = NULL;
74b1de
 
74b1de
     priv = this->private;
74b1de
+    INIT_LIST_HEAD(&local->transaction.wait_list);
74b1de
+    INIT_LIST_HEAD(&local->transaction.owner_list);
74b1de
+    INIT_LIST_HEAD(&local->ta_waitq);
74b1de
+    INIT_LIST_HEAD(&local->ta_onwireq);
74b1de
     ret = afr_internal_lock_init(&local->internal_lock, priv->child_count);
74b1de
     if (ret < 0)
74b1de
         goto out;
74b1de
@@ -5800,10 +5804,6 @@ afr_transaction_local_init(afr_local_t *local, xlator_t *this)
74b1de
         goto out;
74b1de
 
74b1de
     ret = 0;
74b1de
-    INIT_LIST_HEAD(&local->transaction.wait_list);
74b1de
-    INIT_LIST_HEAD(&local->transaction.owner_list);
74b1de
-    INIT_LIST_HEAD(&local->ta_waitq);
74b1de
-    INIT_LIST_HEAD(&local->ta_onwireq);
74b1de
 out:
74b1de
     return ret;
74b1de
 }
74b1de
diff --git a/xlators/cluster/afr/src/afr-lk-common.c b/xlators/cluster/afr/src/afr-lk-common.c
74b1de
index 4091671..bc8eabe 100644
74b1de
--- a/xlators/cluster/afr/src/afr-lk-common.c
74b1de
+++ b/xlators/cluster/afr/src/afr-lk-common.c
74b1de
@@ -397,7 +397,6 @@ afr_unlock_now(call_frame_t *frame, xlator_t *this)
74b1de
     int_lock->lk_call_count = call_count;
74b1de
 
74b1de
     if (!call_count) {
74b1de
-        GF_ASSERT(!local->transaction.do_eager_unlock);
74b1de
         gf_msg_trace(this->name, 0, "No internal locks unlocked");
74b1de
         int_lock->lock_cbk(frame, this);
74b1de
         goto out;
74b1de
diff --git a/xlators/cluster/afr/src/afr-transaction.c b/xlators/cluster/afr/src/afr-transaction.c
74b1de
index 229820b..15f3a7e 100644
74b1de
--- a/xlators/cluster/afr/src/afr-transaction.c
74b1de
+++ b/xlators/cluster/afr/src/afr-transaction.c
74b1de
@@ -372,6 +372,8 @@ afr_transaction_done(call_frame_t *frame, xlator_t *this)
74b1de
     }
74b1de
     local->transaction.unwind(frame, this);
74b1de
 
74b1de
+    GF_ASSERT(list_empty(&local->transaction.owner_list));
74b1de
+    GF_ASSERT(list_empty(&local->transaction.wait_list));
74b1de
     AFR_STACK_DESTROY(frame);
74b1de
 
74b1de
     return 0;
74b1de
@@ -393,7 +395,7 @@ afr_lock_fail_shared(afr_local_t *local, struct list_head *list)
74b1de
 }
74b1de
 
74b1de
 static void
74b1de
-afr_handle_lock_acquire_failure(afr_local_t *local, gf_boolean_t locked)
74b1de
+afr_handle_lock_acquire_failure(afr_local_t *local)
74b1de
 {
74b1de
     struct list_head shared;
74b1de
     afr_lock_t *lock = NULL;
74b1de
@@ -414,13 +416,8 @@ afr_handle_lock_acquire_failure(afr_local_t *local, gf_boolean_t locked)
74b1de
     afr_lock_fail_shared(local, &shared);
74b1de
     local->transaction.do_eager_unlock = _gf_true;
74b1de
 out:
74b1de
-    if (locked) {
74b1de
-        local->internal_lock.lock_cbk = afr_transaction_done;
74b1de
-        afr_unlock(local->transaction.frame, local->transaction.frame->this);
74b1de
-    } else {
74b1de
-        afr_transaction_done(local->transaction.frame,
74b1de
-                             local->transaction.frame->this);
74b1de
-    }
74b1de
+    local->internal_lock.lock_cbk = afr_transaction_done;
74b1de
+    afr_unlock(local->transaction.frame, local->transaction.frame->this);
74b1de
 }
74b1de
 
74b1de
 call_frame_t *
74b1de
@@ -619,7 +616,7 @@ afr_transaction_perform_fop(call_frame_t *frame, xlator_t *this)
74b1de
     failure_count = AFR_COUNT(local->transaction.failed_subvols,
74b1de
                               priv->child_count);
74b1de
     if (failure_count == priv->child_count) {
74b1de
-        afr_handle_lock_acquire_failure(local, _gf_true);
74b1de
+        afr_handle_lock_acquire_failure(local);
74b1de
         return 0;
74b1de
     } else {
74b1de
         lock = &local->inode_ctx->lock[local->transaction.type];
74b1de
@@ -2092,7 +2089,7 @@ err:
74b1de
     local->op_ret = -1;
74b1de
     local->op_errno = op_errno;
74b1de
 
74b1de
-    afr_handle_lock_acquire_failure(local, _gf_true);
74b1de
+    afr_handle_lock_acquire_failure(local);
74b1de
 
74b1de
     if (xdata_req)
74b1de
         dict_unref(xdata_req);
74b1de
@@ -2361,7 +2358,7 @@ afr_internal_lock_finish(call_frame_t *frame, xlator_t *this)
74b1de
     } else {
74b1de
         lock = &local->inode_ctx->lock[local->transaction.type];
74b1de
         if (local->internal_lock.lock_op_ret < 0) {
74b1de
-            afr_handle_lock_acquire_failure(local, _gf_false);
74b1de
+            afr_handle_lock_acquire_failure(local);
74b1de
         } else {
74b1de
             lock->event_generation = local->event_generation;
74b1de
             afr_changelog_pre_op(frame, this);
74b1de
diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h
74b1de
index 2cc3797..e731cfa 100644
74b1de
--- a/xlators/cluster/afr/src/afr.h
74b1de
+++ b/xlators/cluster/afr/src/afr.h
74b1de
@@ -1091,8 +1091,8 @@ afr_cleanup_fd_ctx(xlator_t *this, fd_t *fd);
74b1de
 #define AFR_FRAME_INIT(frame, op_errno)                                        \
74b1de
     ({                                                                         \
74b1de
         frame->local = mem_get0(THIS->local_pool);                             \
74b1de
-        if (afr_local_init(frame->local, THIS->private, &op_errno)) {          \
74b1de
-            afr_local_cleanup(frame->local, THIS);                             \
74b1de
+        if (afr_local_init(frame->local, frame->this->private, &op_errno)) {   \
74b1de
+            afr_local_cleanup(frame->local, frame->this);                      \
74b1de
             mem_put(frame->local);                                             \
74b1de
             frame->local = NULL;                                               \
74b1de
         };                                                                     \
74b1de
-- 
74b1de
1.8.3.1
74b1de