e3c68b
From 87d8070f80487322a1736846a78725fd88f8de34 Mon Sep 17 00:00:00 2001
e3c68b
From: Pranith Kumar K <pkarampu@redhat.com>
e3c68b
Date: Tue, 20 Aug 2019 13:27:24 +0530
e3c68b
Subject: [PATCH 291/297] cluster/ec: Mark release only when it is acquired
e3c68b
e3c68b
Problem:
e3c68b
Mount-1                                Mount-2
e3c68b
1)Tries to acquire lock on 'dir1'   1)Tries to acquire lock on 'dir1'
e3c68b
2)Lock is granted on brick-0        2)Lock gets EAGAIN on brick-0 and
e3c68b
				      leads to blocking lock on brick-0
e3c68b
3)Gets a lock-contention            3) Doesn't matter what happens on mount-2
e3c68b
  notification, marks lock->release    from here on.
e3c68b
  to true.
e3c68b
4)New fop comes on 'dir1' which will
e3c68b
  be put in frozen list as lock->release
e3c68b
  is set to true.
e3c68b
5) Lock acquisition from step-2 fails because
e3c68b
3 bricks went down in 4+2 setup.
e3c68b
e3c68b
Fop on mount-1 which is put in frozen list will hang because no codepath will
e3c68b
move it from frozen list to any other list and the lock will not be retried.
e3c68b
e3c68b
Fix:
e3c68b
Don't set lock->release to true if lock is not acquired at the time of
e3c68b
lock-contention-notification
e3c68b
e3c68b
Upstream-patch: https://review.gluster.org/c/glusterfs/+/23272
e3c68b
fixes: bz#1731896
e3c68b
Change-Id: Ie6630db8735ccf372cc54b873a3a3aed7a6082b7
e3c68b
Signed-off-by: Pranith Kumar K <pkarampu@redhat.com>
e3c68b
Reviewed-on: https://code.engineering.redhat.com/gerrit/180870
e3c68b
Tested-by: RHGS Build Bot <nigelb@redhat.com>
e3c68b
Reviewed-by: Ashish Pandey <aspandey@redhat.com>
e3c68b
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
e3c68b
---
e3c68b
 xlators/cluster/ec/src/ec-common.c | 20 ++++++++++++++++++--
e3c68b
 xlators/cluster/ec/src/ec-types.h  |  1 +
e3c68b
 2 files changed, 19 insertions(+), 2 deletions(-)
e3c68b
e3c68b
diff --git a/xlators/cluster/ec/src/ec-common.c b/xlators/cluster/ec/src/ec-common.c
e3c68b
index 2e59180..5cae37b 100644
e3c68b
--- a/xlators/cluster/ec/src/ec-common.c
e3c68b
+++ b/xlators/cluster/ec/src/ec-common.c
e3c68b
@@ -1867,6 +1867,10 @@ ec_lock_acquired(ec_lock_link_t *link)
e3c68b
     LOCK(&lock->loc.inode->lock);
e3c68b
 
e3c68b
     lock->acquired = _gf_true;
e3c68b
+    if (lock->contention) {
e3c68b
+        lock->release = _gf_true;
e3c68b
+        lock->contention = _gf_false;
e3c68b
+    }
e3c68b
 
e3c68b
     ec_lock_update_fd(lock, fop);
e3c68b
     ec_lock_wake_shared(lock, &list);
e3c68b
@@ -1892,15 +1896,20 @@ ec_locked(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
e3c68b
     ec_lock_link_t *link = NULL;
e3c68b
     ec_lock_t *lock = NULL;
e3c68b
 
e3c68b
+    link = fop->data;
e3c68b
+    lock = link->lock;
e3c68b
     if (op_ret >= 0) {
e3c68b
-        link = fop->data;
e3c68b
-        lock = link->lock;
e3c68b
         lock->mask = lock->good_mask = fop->good;
e3c68b
         lock->healing = 0;
e3c68b
 
e3c68b
         ec_lock_acquired(link);
e3c68b
         ec_lock(fop->parent);
e3c68b
     } else {
e3c68b
+        LOCK(&lock->loc.inode->lock);
e3c68b
+        {
e3c68b
+            lock->contention = _gf_false;
e3c68b
+        }
e3c68b
+        UNLOCK(&lock->loc.inode->lock);
e3c68b
         gf_msg(this->name, GF_LOG_WARNING, op_errno, EC_MSG_PREOP_LOCK_FAILED,
e3c68b
                "Failed to complete preop lock");
e3c68b
     }
e3c68b
@@ -2547,6 +2556,13 @@ ec_lock_release(ec_t *ec, inode_t *inode)
e3c68b
     gf_msg_debug(ec->xl->name, 0, "Releasing inode %p due to lock contention",
e3c68b
                  inode);
e3c68b
 
e3c68b
+    if (!lock->acquired) {
e3c68b
+        /* This happens if some bricks already got the lock while inodelk is in
e3c68b
+         * progress.  Set release to true after lock is acquired*/
e3c68b
+        lock->contention = _gf_true;
e3c68b
+        goto done;
e3c68b
+    }
e3c68b
+
e3c68b
     /* The lock is not marked to be released, so the frozen list should be
e3c68b
      * empty. */
e3c68b
     GF_ASSERT(list_empty(&lock->frozen));
e3c68b
diff --git a/xlators/cluster/ec/src/ec-types.h b/xlators/cluster/ec/src/ec-types.h
e3c68b
index ea4f6ad..34a9768 100644
e3c68b
--- a/xlators/cluster/ec/src/ec-types.h
e3c68b
+++ b/xlators/cluster/ec/src/ec-types.h
e3c68b
@@ -267,6 +267,7 @@ struct _ec_lock {
e3c68b
     uint32_t refs_pending;  /* Refs assigned to fops being prepared */
e3c68b
     uint32_t waiting_flags; /*Track xattrop/dirty marking*/
e3c68b
     gf_boolean_t acquired;
e3c68b
+    gf_boolean_t contention;
e3c68b
     gf_boolean_t unlock_now;
e3c68b
     gf_boolean_t release;
e3c68b
     gf_boolean_t query;
e3c68b
-- 
e3c68b
1.8.3.1
e3c68b