staging/lustre/ldlm: Fix flock deadlock detection race
Deadlock isn't detected if 2 threads are trying to grant 2 locks which deadlock on each other. They call ldlm_flock_deadlock() simultaneously and deadlock ins't detected. The soulition is to add lock to blocking list before calling ldlm_flock_deadlock() Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-1602 Lustre-change: http://review.whamcloud.com/3277 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 <tao.peng@emc.com> Signed-off-by: Andreas Dilger <andreas.dilger@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
251c4317b3
commit
3fa08ae702
1 changed files with 10 additions and 6 deletions
|
@ -198,6 +198,7 @@ ldlm_flock_deadlock(struct ldlm_lock *req, struct ldlm_lock *bl_lock)
|
||||||
if (lock == NULL)
|
if (lock == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
LASSERT(req != lock);
|
||||||
flock = &lock->l_policy_data.l_flock;
|
flock = &lock->l_policy_data.l_flock;
|
||||||
LASSERT(flock->owner == bl_owner);
|
LASSERT(flock->owner == bl_owner);
|
||||||
bl_owner = flock->blocking_owner;
|
bl_owner = flock->blocking_owner;
|
||||||
|
@ -329,18 +330,21 @@ ldlm_process_flock_lock(struct ldlm_lock *req, __u64 *flags, int first_enq,
|
||||||
RETURN(LDLM_ITER_STOP);
|
RETURN(LDLM_ITER_STOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ldlm_flock_deadlock(req, lock)) {
|
/* add lock to blocking list before deadlock
|
||||||
ldlm_flock_destroy(req, mode, *flags);
|
* check to prevent race */
|
||||||
*err = -EDEADLK;
|
|
||||||
RETURN(LDLM_ITER_STOP);
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ldlm_flock_blocking_link(req, lock);
|
rc = ldlm_flock_blocking_link(req, lock);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ldlm_flock_destroy(req, mode, *flags);
|
ldlm_flock_destroy(req, mode, *flags);
|
||||||
*err = rc;
|
*err = rc;
|
||||||
RETURN(LDLM_ITER_STOP);
|
RETURN(LDLM_ITER_STOP);
|
||||||
}
|
}
|
||||||
|
if (ldlm_flock_deadlock(req, lock)) {
|
||||||
|
ldlm_flock_blocking_unlink(req);
|
||||||
|
ldlm_flock_destroy(req, mode, *flags);
|
||||||
|
*err = -EDEADLK;
|
||||||
|
RETURN(LDLM_ITER_STOP);
|
||||||
|
}
|
||||||
|
|
||||||
ldlm_resource_add_lock(res, &res->lr_waiting, req);
|
ldlm_resource_add_lock(res, &res->lr_waiting, req);
|
||||||
*flags |= LDLM_FL_BLOCK_GRANTED;
|
*flags |= LDLM_FL_BLOCK_GRANTED;
|
||||||
RETURN(LDLM_ITER_STOP);
|
RETURN(LDLM_ITER_STOP);
|
||||||
|
|
Loading…
Reference in a new issue