]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
staging/lustre/ptlrpc: flock deadlock detection does not work
authorAndriy Skulysh <Andriy_Skulysh@xyratex.com>
Wed, 22 Jan 2014 13:36:19 +0000 (21:36 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 7 Feb 2014 17:44:17 +0000 (09:44 -0800)
Flock deadlocks are checked on the first attempt to grant
the flock only. If we try again to grant it after its
blocking lock is cancelled, we don't check for deadlocks
which also may exist.

Perform deadlock detection during reprocess

Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-1715
Lustre-change: http://review.whamcloud.com/3553
Signed-off-by: Andriy Skulysh <Andriy_Skulysh@xyratex.com>
Reviewed-by: Vitaly Fertman <vitaly_fertman@xyratex.com>
Reviewed-by: Bruce Korb <bruce_korb@xyratex.com>
Reviewed-by: Keith Mannthey <keith.mannthey@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
Signed-off-by: Peng Tao <bergwolf@gmail.com>
Signed-off-by: Andreas Dilger <andreas.dilger@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
drivers/staging/lustre/lustre/include/lustre_dlm_flags.h
drivers/staging/lustre/lustre/ldlm/ldlm_flock.c
drivers/staging/lustre/lustre/llite/llite_lib.c
drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
drivers/staging/lustre/lustre/ptlrpc/wiretest.c

index ac7fb379bf746b1e18190bfee2384b49593243ca..05c77c0b2d75f613b8d1afbdfd7ab6e3c3490b0a 100644 (file)
@@ -1304,6 +1304,8 @@ extern void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb);
 #define OBD_CONNECT_LIGHTWEIGHT 0x1000000000000ULL/* lightweight connection */
 #define OBD_CONNECT_SHORTIO     0x2000000000000ULL/* short io */
 #define OBD_CONNECT_PINGLESS   0x4000000000000ULL/* pings not required */
+#define OBD_CONNECT_FLOCK_DEAD 0x8000000000000ULL/* flock deadlock detection */
+
 /* XXX README XXX:
  * Please DO NOT add flag values here before first ensuring that this same
  * flag value is not in use on some other branch.  Please clear any such
@@ -1341,7 +1343,8 @@ extern void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb);
                                OBD_CONNECT_EINPROGRESS | \
                                OBD_CONNECT_LIGHTWEIGHT | OBD_CONNECT_UMASK | \
                                OBD_CONNECT_LVB_TYPE | OBD_CONNECT_LAYOUTLOCK |\
-                               OBD_CONNECT_PINGLESS | OBD_CONNECT_MAX_EASIZE)
+                               OBD_CONNECT_PINGLESS | OBD_CONNECT_MAX_EASIZE |\
+                               OBD_CONNECT_FLOCK_DEAD)
 #define OST_CONNECT_SUPPORTED  (OBD_CONNECT_SRVLOCK | OBD_CONNECT_GRANT | \
                                OBD_CONNECT_REQPORTAL | OBD_CONNECT_VERSION | \
                                OBD_CONNECT_TRUNCLOCK | OBD_CONNECT_INDEX | \
index 75716f17f64bedc927f80d6e5225924d58e6cc86..73fb38ee0a34ff4ad993bc88f588ea4e4dddade5 100644 (file)
 #ifndef LDLM_ALL_FLAGS_MASK
 
 /** l_flags bits marked as "all_flags" bits */
-#define LDLM_FL_ALL_FLAGS_MASK          0x00FFFFFFC08F132FULL
+#define LDLM_FL_ALL_FLAGS_MASK          0x00FFFFFFC08F932FULL
 
 /** l_flags bits marked as "ast" bits */
-#define LDLM_FL_AST_MASK                0x0000000080000000ULL
+#define LDLM_FL_AST_MASK                0x0000000080008000ULL
 
 /** l_flags bits marked as "blocked" bits */
 #define LDLM_FL_BLOCKED_MASK            0x000000000000000EULL
@@ -56,7 +56,7 @@
 #define LDLM_FL_LOCAL_ONLY_MASK         0x00FFFFFF00000000ULL
 
 /** l_flags bits marked as "on_wire" bits */
-#define LDLM_FL_ON_WIRE_MASK            0x00000000C08F132FULL
+#define LDLM_FL_ON_WIRE_MASK            0x00000000C08F932FULL
 
 /** extent, mode, or resource changed */
 #define LDLM_FL_LOCK_CHANGED            0x0000000000000001ULL // bit   0
 #define ldlm_set_has_intent(_l)         LDLM_SET_FLAG((  _l), 1ULL << 12)
 #define ldlm_clear_has_intent(_l)       LDLM_CLEAR_FLAG((_l), 1ULL << 12)
 
+/** flock deadlock detected */
+#define LDLM_FL_FLOCK_DEADLOCK          0x0000000000008000ULL /* bit  15 */
+#define ldlm_is_flock_deadlock(_l)      LDLM_TEST_FLAG((_l), 1ULL << 15)
+#define ldlm_set_flock_deadlock(_l)     LDLM_SET_FLAG((_l), 1ULL << 15)
+#define ldlm_clear_flock_deadlock(_l)   LDLM_CLEAR_FLAG((_l), 1ULL << 15)
+
 /** discard (no writeback) on cancel */
 #define LDLM_FL_DISCARD_DATA            0x0000000000010000ULL // bit  16
 #define ldlm_is_discard_data(_l)        LDLM_TEST_FLAG(( _l), 1ULL << 16)
@@ -390,6 +396,7 @@ static int hf_lustre_ldlm_fl_ast_sent            = -1;
 static int hf_lustre_ldlm_fl_replay              = -1;
 static int hf_lustre_ldlm_fl_intent_only         = -1;
 static int hf_lustre_ldlm_fl_has_intent          = -1;
+static int hf_lustre_ldlm_fl_flock_deadlock      = -1;
 static int hf_lustre_ldlm_fl_discard_data        = -1;
 static int hf_lustre_ldlm_fl_no_timeout          = -1;
 static int hf_lustre_ldlm_fl_block_nowait        = -1;
@@ -431,6 +438,7 @@ const value_string lustre_ldlm_flags_vals[] = {
        {LDLM_FL_REPLAY,              "LDLM_FL_REPLAY"},
        {LDLM_FL_INTENT_ONLY,         "LDLM_FL_INTENT_ONLY"},
        {LDLM_FL_HAS_INTENT,          "LDLM_FL_HAS_INTENT"},
+       {LDLM_FL_FLOCK_DEADLOCK,      "LDLM_FL_FLOCK_DEADLOCK"},
        {LDLM_FL_DISCARD_DATA,        "LDLM_FL_DISCARD_DATA"},
        {LDLM_FL_NO_TIMEOUT,          "LDLM_FL_NO_TIMEOUT"},
        {LDLM_FL_BLOCK_NOWAIT,        "LDLM_FL_BLOCK_NOWAIT"},
index c9aae132f98ae254bd213657a4304a940c9040fc..986bf384bff744621021c211d451583fcfefaa61 100644 (file)
@@ -205,6 +205,26 @@ ldlm_flock_deadlock(struct ldlm_lock *req, struct ldlm_lock *bl_lock)
        return 0;
 }
 
+static void ldlm_flock_cancel_on_deadlock(struct ldlm_lock *lock,
+                                         struct list_head *work_list)
+{
+       CDEBUG(D_INFO, "reprocess deadlock req=%p\n", lock);
+
+       if ((exp_connect_flags(lock->l_export) &
+                               OBD_CONNECT_FLOCK_DEAD) == 0) {
+               CERROR(
+                     "deadlock found, but client doesn't support flock canceliation\n");
+       } else {
+               LASSERT(lock->l_completion_ast);
+               LASSERT((lock->l_flags & LDLM_FL_AST_SENT) == 0);
+               lock->l_flags |= LDLM_FL_AST_SENT | LDLM_FL_CANCEL_ON_BLOCK |
+                       LDLM_FL_FLOCK_DEADLOCK;
+               ldlm_flock_blocking_unlink(lock);
+               ldlm_resource_unlink_lock(lock);
+               ldlm_add_ast_work_item(lock, NULL, work_list);
+       }
+}
+
 /**
  * Process a granting attempt for flock lock.
  * Must be called under ns lock held.
@@ -272,6 +292,7 @@ reprocess:
                        }
                }
        } else {
+               int reprocess_failed = 0;
                lockmode_verify(mode);
 
                /* This loop determines if there are existing locks
@@ -293,8 +314,15 @@ reprocess:
                        if (!ldlm_flocks_overlap(lock, req))
                                continue;
 
-                       if (!first_enq)
-                               return LDLM_ITER_CONTINUE;
+                       if (!first_enq) {
+                               reprocess_failed = 1;
+                               if (ldlm_flock_deadlock(req, lock)) {
+                                       ldlm_flock_cancel_on_deadlock(req,
+                                                       work_list);
+                                       return LDLM_ITER_CONTINUE;
+                               }
+                               continue;
+                       }
 
                        if (*flags & LDLM_FL_BLOCK_NOWAIT) {
                                ldlm_flock_destroy(req, mode, *flags);
@@ -330,6 +358,8 @@ reprocess:
                        *flags |= LDLM_FL_BLOCK_GRANTED;
                        return LDLM_ITER_STOP;
                }
+               if (reprocess_failed)
+                       return LDLM_ITER_CONTINUE;
        }
 
        if (*flags & LDLM_FL_TEST_LOCK) {
@@ -646,7 +676,10 @@ granted:
        /* ldlm_lock_enqueue() has already placed lock on the granted list. */
        list_del_init(&lock->l_res_link);
 
-       if (flags & LDLM_FL_TEST_LOCK) {
+       if (lock->l_flags & LDLM_FL_FLOCK_DEADLOCK) {
+               LDLM_DEBUG(lock, "client-side enqueue deadlock received");
+               rc = -EDEADLK;
+       } else if (flags & LDLM_FL_TEST_LOCK) {
                /* fcntl(F_GETLK) request */
                /* The old mode was saved in getlk->fl_type so that if the mode
                 * in the lock changes we can decref the appropriate refcount.*/
@@ -672,7 +705,7 @@ granted:
                ldlm_process_flock_lock(lock, &noreproc, 1, &err, NULL);
        }
        unlock_res_and_lock(lock);
-       return 0;
+       return rc;
 }
 EXPORT_SYMBOL(ldlm_flock_completion_ast);
 
index 3e4c292769e6b0df65ad42cfb9b7978c772fd1cf..b0b69413886918dd84c234bde02ccdc94b37e2cd 100644 (file)
@@ -206,7 +206,9 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
                                  OBD_CONNECT_EINPROGRESS |
                                  OBD_CONNECT_JOBSTATS | OBD_CONNECT_LVB_TYPE |
                                  OBD_CONNECT_LAYOUTLOCK |
-                                 OBD_CONNECT_PINGLESS | OBD_CONNECT_MAX_EASIZE;
+                                 OBD_CONNECT_PINGLESS |
+                                 OBD_CONNECT_MAX_EASIZE |
+                                 OBD_CONNECT_FLOCK_DEAD;
 
        if (sbi->ll_flags & LL_SBI_SOM_PREVIEW)
                data->ocd_connect_flags |= OBD_CONNECT_SOM;
index ec3b605dae6b95553a384e34c3fd9571a5151d50..6e7d2e5610674964de9cc6d0b7a8a9128c2e04ed 100644 (file)
@@ -98,6 +98,7 @@ static const char * const obd_connect_names[] = {
        "lightweight_conn",
        "short_io",
        "pingless",
+       "flock_deadlock",
        "unknown",
        NULL
 };
index 3aa445952024aa9fd44f9569ce588da180883e6a..3c8846006a7b0256bf68476fd25601a387745429 100644 (file)
@@ -1152,6 +1152,8 @@ void lustre_assert_wire_constants(void)
                 OBD_CONNECT_SHORTIO);
        LASSERTF(OBD_CONNECT_PINGLESS == 0x4000000000000ULL, "found 0x%.16llxULL\n",
                 OBD_CONNECT_PINGLESS);
+       LASSERTF(OBD_CONNECT_FLOCK_DEAD == 0x8000000000000ULL,
+                "found 0x%.16llxULL\n", OBD_CONNECT_FLOCK_DEAD);
        LASSERTF(OBD_CKSUM_CRC32 == 0x00000001UL, "found 0x%.8xUL\n",
                (unsigned)OBD_CKSUM_CRC32);
        LASSERTF(OBD_CKSUM_ADLER == 0x00000002UL, "found 0x%.8xUL\n",