From fef1020406a0fb99ebb7871d7648bfad7a9d91a6 Mon Sep 17 00:00:00 2001 From: Li Dongyang Date: Wed, 13 Jul 2016 16:17:53 +1000 Subject: [PATCH] LU-8391 ldlm: check double grant race after resource change In ldlm_handle_cp_callback(), we call lock_res_and_lock and then check if the ldlm lock has already been granted. If the lock resource has changed, we release the lock and go ahead allocating new resource, then grabs the lock again before calling ldlm_grant_lock(). However this gives another thread an opportunity to grab the lock and pass the check, while we change the resource. Eventually the other thread calls ldlm_grant_lock() on the same ldlm lock and triggers a LASSERT. Fix the issue by doing double grant race check after changing the lock resource. Signed-off-by: Li Dongyang Change-Id: Ib327b5e6b5f211909db5350de383d470a891e72a Reviewed-on: https://review.whamcloud.com/21275 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin --- lustre/ldlm/ldlm_lockd.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/lustre/ldlm/ldlm_lockd.c b/lustre/ldlm/ldlm_lockd.c index a062e5c..486f53b 100644 --- a/lustre/ldlm/ldlm_lockd.c +++ b/lustre/ldlm/ldlm_lockd.c @@ -1790,6 +1790,21 @@ static void ldlm_handle_cp_callback(struct ptlrpc_request *req, } lock_res_and_lock(lock); + + if (!ldlm_res_eq(&dlm_req->lock_desc.l_resource.lr_name, + &lock->l_resource->lr_name)) { + ldlm_resource_unlink_lock(lock); + unlock_res_and_lock(lock); + rc = ldlm_lock_change_resource(ns, lock, + &dlm_req->lock_desc.l_resource.lr_name); + if (rc < 0) { + LDLM_ERROR(lock, "Failed to allocate resource"); + GOTO(out, rc); + } + LDLM_DEBUG(lock, "completion AST, new resource"); + lock_res_and_lock(lock); + } + if (ldlm_is_destroyed(lock) || lock->l_granted_mode == lock->l_req_mode) { /* bug 11300: the lock has already been granted */ @@ -1813,21 +1828,7 @@ static void ldlm_handle_cp_callback(struct ptlrpc_request *req, LDLM_DEBUG(lock, "completion AST, new policy data"); } - ldlm_resource_unlink_lock(lock); - if (memcmp(&dlm_req->lock_desc.l_resource.lr_name, - &lock->l_resource->lr_name, - sizeof(lock->l_resource->lr_name)) != 0) { - unlock_res_and_lock(lock); - rc = ldlm_lock_change_resource(ns, lock, - &dlm_req->lock_desc.l_resource.lr_name); - if (rc < 0) { - LDLM_ERROR(lock, "Failed to allocate resource"); - GOTO(out, rc); - } - LDLM_DEBUG(lock, "completion AST, new resource"); - CERROR("change resource!\n"); - lock_res_and_lock(lock); - } + ldlm_resource_unlink_lock(lock); if (dlm_req->lock_flags & LDLM_FL_AST_SENT) { /* BL_AST locks are not needed in LRU. -- 1.8.3.1