From: Andriy Skulysh Date: Wed, 22 Jan 2014 13:36:19 +0000 (+0800) Subject: staging/lustre/ptlrpc: flock deadlock detection does not work X-Git-Tag: next-20140306~21^2~560 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=69342b7884d6ea1ec97c0a99fe0524a380783e83;p=karo-tx-linux.git staging/lustre/ptlrpc: flock deadlock detection does not work 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 Reviewed-by: Vitaly Fertman Reviewed-by: Bruce Korb Reviewed-by: Keith Mannthey Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index ac7fb379bf74..05c77c0b2d75 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -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 | \ diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h b/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h index 75716f17f64b..73fb38ee0a34 100644 --- a/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h +++ b/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h @@ -35,10 +35,10 @@ #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 @@ -114,6 +114,12 @@ #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"}, diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index c9aae132f98a..986bf384bff7 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -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); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 3e4c292769e6..b0b694138869 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -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; diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index ec3b605dae6b..6e7d2e561067 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -98,6 +98,7 @@ static const char * const obd_connect_names[] = { "lightweight_conn", "short_io", "pingless", + "flock_deadlock", "unknown", NULL }; diff --git a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c index 3aa445952024..3c8846006a7b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/wiretest.c +++ b/drivers/staging/lustre/lustre/ptlrpc/wiretest.c @@ -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",