3604df
From 478e3949c19c7ef60737f170d9f3ee60aa9f59c9 Mon Sep 17 00:00:00 2001
3604df
From: Krutika Dhananjay <kdhananj@redhat.com>
3604df
Date: Fri, 25 Nov 2016 15:54:30 +0530
3604df
Subject: [PATCH 193/206] cluster/afr: Fix deadlock due to compound fops
3604df
3604df
        Backport of: http://review.gluster.org/15929
3604df
3604df
When an afr data transaction is eligible for using
3604df
eager-lock, this information is represented in
3604df
local->transaction.eager_lock_on. However, if non-blocking
3604df
inodelk attempt (which is a full lock) fails, AFR falls back
3604df
to blocking locks which are range locks. At this point,
3604df
local->transaction.eager_lock[] per brick is reset but
3604df
local->transaction.eager_lock_on is still true.
3604df
When AFR decides to compound post-op and unlock, it is after
3604df
confirming that the transaction did not use eager lock (well,
3604df
except for a small bug where local->transaction.locks_acquired[]
3604df
is not considered).
3604df
3604df
But within afr_post_op_unlock_do(), afr again incorrectly sets
3604df
the lock range to full-lock based on local->transaction.eager_lock_on
3604df
value. This is a bug and can lead to deadlock since the locks acquired
3604df
were range locks and a full unlock is being sent leading to unlock failure
3604df
and thereby every other lock request (be it from SHD or other clients or
3604df
glfsheal) getting blocked forever and the user perceives a hang.
3604df
3604df
FIX:
3604df
Unconditionally rely on the range locks in inodelk object for unlocking
3604df
when using compounded post-op + unlock.
3604df
3604df
Big thanks to Pranith for helping with the debugging.
3604df
3604df
Change-Id: Ie5af0de1f1a9dc1821dfde3654bab0e54d753281
3604df
BUG: 1396166
3604df
Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com>
3604df
Reviewed-on: https://code.engineering.redhat.com/gerrit/91332
3604df
Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
3604df
Tested-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
3604df
---
3604df
 xlators/cluster/afr/src/afr-transaction.c | 22 ++++++++--------------
3604df
 1 file changed, 8 insertions(+), 14 deletions(-)
3604df
3604df
diff --git a/xlators/cluster/afr/src/afr-transaction.c b/xlators/cluster/afr/src/afr-transaction.c
3604df
index fe53f49..690062f 100644
3604df
--- a/xlators/cluster/afr/src/afr-transaction.c
3604df
+++ b/xlators/cluster/afr/src/afr-transaction.c
3604df
@@ -838,7 +838,7 @@ afr_changelog_post_op_now (call_frame_t *frame, xlator_t *this)
3604df
         int                     ret             = 0;
3604df
         int                     idx             = 0;
3604df
         int                     nothing_failed  = 1;
3604df
-        int                     piggyback       = 0;
3604df
+        gf_boolean_t            compounded_unlock = _gf_true;
3604df
         gf_boolean_t            need_undirty    = _gf_false;
3604df
 
3604df
         afr_handle_quorum (frame);
3604df
@@ -912,9 +912,11 @@ afr_changelog_post_op_now (call_frame_t *frame, xlator_t *this)
3604df
                                 if (local->transaction.pre_op[i] &&
3604df
                                     local->transaction.eager_lock[i]) {
3604df
                                         if (fd_ctx->lock_piggyback[i])
3604df
-                                                piggyback = 1;
3604df
+                                                compounded_unlock = _gf_false;
3604df
+                                        else if (fd_ctx->lock_acquired[i])
3604df
+                                                compounded_unlock = _gf_false;
3604df
                                 }
3604df
-                                if (piggyback == 1)
3604df
+                                if (compounded_unlock == _gf_false)
3604df
                                         break;
3604df
                         }
3604df
                 }
3604df
@@ -923,7 +925,7 @@ afr_changelog_post_op_now (call_frame_t *frame, xlator_t *this)
3604df
 
3604df
         /* Do not compound if any brick got piggybacked lock as
3604df
          * unlock should not be done for that. */
3604df
-        if (local->compound && !piggyback) {
3604df
+        if (local->compound && compounded_unlock) {
3604df
                 afr_post_op_unlock_do (frame, this, xattr,
3604df
                                        afr_changelog_post_op_done,
3604df
                                        AFR_TRANSACTION_POST_OP);
3604df
@@ -1434,11 +1436,9 @@ afr_post_op_unlock_do (call_frame_t *frame, xlator_t *this, dict_t *xattr,
3604df
         compound_args_t         *args           = NULL;
3604df
         afr_internal_lock_t     *int_lock       = NULL;
3604df
         afr_inodelk_t           *inodelk        = NULL;
3604df
-        struct gf_flock         *flock_use      = NULL;
3604df
 	int                     i               = 0;
3604df
 	int                     call_count      = 0;
3604df
         struct gf_flock         flock           = {0,};
3604df
-        struct gf_flock         full_flock      = {0,};
3604df
         int                     ret             = 0;
3604df
 
3604df
 	local = frame->local;
3604df
@@ -1451,8 +1451,6 @@ afr_post_op_unlock_do (call_frame_t *frame, xlator_t *this, dict_t *xattr,
3604df
                 flock.l_start = inodelk->flock.l_start;
3604df
                 flock.l_len   = inodelk->flock.l_len;
3604df
                 flock.l_type  = F_UNLCK;
3604df
-                full_flock.l_type = F_UNLCK;
3604df
-
3604df
         }
3604df
 
3604df
         ret = afr_changelog_prepare (this, frame, &call_count, changelog_resume,
3604df
@@ -1480,22 +1478,18 @@ afr_post_op_unlock_do (call_frame_t *frame, xlator_t *this, dict_t *xattr,
3604df
                             local->fd, GF_XATTROP_ADD_ARRAY,
3604df
                             xattr, xdata);
3604df
         i++;
3604df
-        if (!local->transaction.eager_lock_on)
3604df
-                flock_use = &flock;
3604df
-        else
3604df
-                flock_use = &full_flock;
3604df
 
3604df
         if (afr_is_inodelk_transaction(local)) {
3604df
                 if (local->fd) {
3604df
                         COMPOUND_PACK_ARGS (finodelk, GF_FOP_FINODELK,
3604df
                                             args, i,
3604df
                                             int_lock->domain, local->fd,
3604df
-                                            F_SETLK, flock_use, NULL);
3604df
+                                            F_SETLK, &flock, NULL);
3604df
                 } else {
3604df
                         COMPOUND_PACK_ARGS (inodelk, GF_FOP_INODELK,
3604df
                                             args, i,
3604df
                                             int_lock->domain, &local->loc,
3604df
-                                            F_SETLK, flock_use, NULL);
3604df
+                                            F_SETLK, &flock, NULL);
3604df
                 }
3604df
         }
3604df
 
3604df
-- 
3604df
2.9.3
3604df