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