Commit 3fa08ae7 authored by Andriy Skulysh's avatar Andriy Skulysh Committed by Greg Kroah-Hartman

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/3277Signed-off-by: default avatarAndriy Skulysh <Andriy_Skulysh@xyratex.com>
Reviewed-by: default avatarVitaly Fertman <vitaly_fertman@xyratex.com>
Reviewed-by: default avatarBruce Korb <bruce_korb@xyratex.com>
Reviewed-by: default avatarKeith Mannthey <keith.mannthey@intel.com>
Reviewed-by: default avatarOleg Drokin <oleg.drokin@intel.com>
Signed-off-by: default avatarPeng Tao <tao.peng@emc.com>
Signed-off-by: default avatarAndreas Dilger <andreas.dilger@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 251c4317
...@@ -198,6 +198,7 @@ ldlm_flock_deadlock(struct ldlm_lock *req, struct ldlm_lock *bl_lock) ...@@ -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, ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment