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