Blob Blame History Raw
From 41a1392633c23a1e5a6f3963d5e3c337ad0ec518 Mon Sep 17 00:00:00 2001
From: Pranith Kumar K <pkarampu@redhat.com>
Date: Wed, 10 Jun 2015 10:30:03 +0530
Subject: [PATCH 39/57] cluster/ec: Wind unlock fops at all cost

        Backport of http://review.gluster.org/11152

Problem:
While files are being created if more than redundancy number of bricks
go down, then unlock for these fops do not go to the bricks. This will
lead to stale locks leading to hangs.

Fix:
Wind unlock fops at all costs.

BUG: 1224160
Change-Id: I3312b0fe1694ad02af5307bcbaf233ac63058846
Signed-off-by: Pranith Kumar K <pkarampu@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/50467
---
 xlators/cluster/ec/src/ec-common.c |   27 ++++++++++++++++++++++++---
 xlators/cluster/ec/src/ec.c        |   26 +++++++++++++++++++++-----
 2 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/xlators/cluster/ec/src/ec-common.c b/xlators/cluster/ec/src/ec-common.c
index f33384b..d9f3442 100644
--- a/xlators/cluster/ec/src/ec-common.c
+++ b/xlators/cluster/ec/src/ec-common.c
@@ -1421,7 +1421,7 @@ void ec_unlock_lock(ec_lock_link_t *link)
         ec_trace("UNLOCK_INODELK", fop, "lock=%p, inode=%p", lock,
                  lock->loc.inode);
 
-        ec_inodelk(fop->frame, fop->xl, lock->mask, EC_MINIMUM_ALL,
+        ec_inodelk(fop->frame, fop->xl, lock->mask, EC_MINIMUM_ONE,
                    ec_unlocked, link, fop->xl->name, &lock->loc, F_SETLK,
                    &lock->flock, NULL);
     } else {
@@ -1834,6 +1834,24 @@ void ec_lock_reuse(ec_fop_data_t *fop)
     }
 }
 
+/* There could be already granted locks sitting on the bricks, unlock for which
+ * must be wound at all costs*/
+static gf_boolean_t
+ec_must_wind (ec_fop_data_t *fop)
+{
+        if ((fop->id == GF_FOP_INODELK) || (fop->id == GF_FOP_FINODELK) ||
+            (fop->id == GF_FOP_LK)) {
+                if (fop->flock.l_type == F_UNLCK)
+                        return _gf_true;
+        } else if ((fop->id == GF_FOP_ENTRYLK) ||
+                   (fop->id == GF_FOP_FENTRYLK)) {
+                if (fop->entrylk_cmd == ENTRYLK_UNLOCK)
+                        return _gf_true;
+        }
+
+        return _gf_false;
+}
+
 void __ec_manager(ec_fop_data_t * fop, int32_t error)
 {
     ec_t *ec = fop->xl->private;
@@ -1841,9 +1859,12 @@ void __ec_manager(ec_fop_data_t * fop, int32_t error)
     do {
         ec_trace("MANAGER", fop, "error=%d", error);
 
-        if (ec->xl_up_count < ec->fragments) {
-            error = ENOTCONN;
+        if (!ec_must_wind (fop)) {
+                if (ec->xl_up_count < ec->fragments) {
+                    error = ENOTCONN;
+                }
         }
+
         if (error != 0) {
             fop->error = error;
             fop->state = -fop->state;
diff --git a/xlators/cluster/ec/src/ec.c b/xlators/cluster/ec/src/ec.c
index 4028aa4..797c390 100644
--- a/xlators/cluster/ec/src/ec.c
+++ b/xlators/cluster/ec/src/ec.c
@@ -625,7 +625,10 @@ int32_t ec_gf_entrylk(call_frame_t * frame, xlator_t * this,
                       const char * volume, loc_t * loc, const char * basename,
                       entrylk_cmd cmd, entrylk_type type, dict_t * xdata)
 {
-    ec_entrylk(frame, this, -1, EC_MINIMUM_ALL, default_entrylk_cbk, NULL,
+    int32_t minimum = EC_MINIMUM_ALL;
+    if (cmd == ENTRYLK_UNLOCK)
+            minimum = EC_MINIMUM_ONE;
+    ec_entrylk(frame, this, -1, minimum, default_entrylk_cbk, NULL,
                volume, loc, basename, cmd, type, xdata);
 
     return 0;
@@ -635,7 +638,10 @@ int32_t ec_gf_fentrylk(call_frame_t * frame, xlator_t * this,
                        const char * volume, fd_t * fd, const char * basename,
                        entrylk_cmd cmd, entrylk_type type, dict_t * xdata)
 {
-    ec_fentrylk(frame, this, -1, EC_MINIMUM_ALL, default_fentrylk_cbk, NULL,
+    int32_t minimum = EC_MINIMUM_ALL;
+    if (cmd == ENTRYLK_UNLOCK)
+            minimum = EC_MINIMUM_ONE;
+    ec_fentrylk(frame, this, -1, minimum, default_fentrylk_cbk, NULL,
                 volume, fd, basename, cmd, type, xdata);
 
     return 0;
@@ -772,7 +778,11 @@ int32_t ec_gf_inodelk(call_frame_t * frame, xlator_t * this,
                       const char * volume, loc_t * loc, int32_t cmd,
                       struct gf_flock * flock, dict_t * xdata)
 {
-    ec_inodelk(frame, this, -1, EC_MINIMUM_ALL, default_inodelk_cbk, NULL,
+    int32_t minimum = EC_MINIMUM_ALL;
+    if (flock->l_type == F_UNLCK)
+            minimum = EC_MINIMUM_ONE;
+
+    ec_inodelk(frame, this, -1, minimum, default_inodelk_cbk, NULL,
                volume, loc, cmd, flock, xdata);
 
     return 0;
@@ -782,7 +792,10 @@ int32_t ec_gf_finodelk(call_frame_t * frame, xlator_t * this,
                        const char * volume, fd_t * fd, int32_t cmd,
                        struct gf_flock * flock, dict_t * xdata)
 {
-    ec_finodelk(frame, this, -1, EC_MINIMUM_ALL, default_finodelk_cbk, NULL,
+    int32_t minimum = EC_MINIMUM_ALL;
+    if (flock->l_type == F_UNLCK)
+            minimum = EC_MINIMUM_ONE;
+    ec_finodelk(frame, this, -1, minimum, default_finodelk_cbk, NULL,
                 volume, fd, cmd, flock, xdata);
 
     return 0;
@@ -800,7 +813,10 @@ int32_t ec_gf_link(call_frame_t * frame, xlator_t * this, loc_t * oldloc,
 int32_t ec_gf_lk(call_frame_t * frame, xlator_t * this, fd_t * fd,
                  int32_t cmd, struct gf_flock * flock, dict_t * xdata)
 {
-    ec_lk(frame, this, -1, EC_MINIMUM_ALL, default_lk_cbk, NULL, fd, cmd,
+    int32_t minimum = EC_MINIMUM_ALL;
+    if (flock->l_type == F_UNLCK)
+            minimum = EC_MINIMUM_ONE;
+    ec_lk(frame, this, -1, minimum, default_lk_cbk, NULL, fd, cmd,
           flock, xdata);
 
     return 0;
-- 
1.7.1