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:
Andriy Skulysh 2013-07-23 00:06:52 +08:00 committed by Greg Kroah-Hartman
parent 251c4317b3
commit 3fa08ae702

View file

@ -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);