There is a race that if IR shared lock is revoked fastly the
completion ast can be called twice with the lock granted. The
IR lock should be cancelled only once in this case.
Signed-off-by: Jinshan Xiong <jinshan.xiong@whamcloud.com>
Change-Id: Ie1b2742d436fb6f549cfcb25dc50fbbabcd1f008
Reviewed-on: http://review.whamcloud.com/2390
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: James Simmons <uja.ornl@gmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED |
LDLM_FL_BLOCK_CONV))) {
if (!(flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED |
LDLM_FL_BLOCK_CONV))) {
- struct fs_db *fsdb = (struct fs_db *)lock->l_ast_data;
- struct lustre_handle lockh;
- mgs_ir_notify_complete(fsdb);
+ /* l_ast_data is used as a marker to avoid cancel ldlm lock
+ * twice. See LU-1259. */
+ lock_res_and_lock(lock);
+ fsdb = (struct fs_db *)lock->l_ast_data;
+ lock->l_ast_data = NULL;
+ unlock_res_and_lock(lock);
- ldlm_lock2handle(lock, &lockh);
- ldlm_lock_decref_and_cancel(&lockh, LCK_EX);
+ if (fsdb != NULL) {
+ struct lustre_handle lockh;
+
+ mgs_ir_notify_complete(fsdb);
+
+ ldlm_lock2handle(lock, &lockh);
+ ldlm_lock_decref_and_cancel(&lockh, LCK_EX);
+ }
}
RETURN(ldlm_completion_ast(lock, flags, cbdata));
}
RETURN(ldlm_completion_ast(lock, flags, cbdata));