diff options
author | Andriy Skulysh <Andriy_Skulysh@xyratex.com> | 2013-07-22 16:06:52 (GMT) |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-07-23 20:39:13 (GMT) |
commit | 3fa08ae702b15ad17b394361e53abf80b5e267fd (patch) | |
tree | d49025e994d77a9ba42de80a3a5d2efdbde64965 | |
parent | 251c4317b3219eeacd800d167c105121ed9be188 (diff) | |
download | linux-fsl-qoriq-3fa08ae702b15ad17b394361e53abf80b5e267fd.tar.xz |
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>
-rw-r--r-- | drivers/staging/lustre/lustre/ldlm/ldlm_flock.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index aca1073..39973cb 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -198,6 +198,7 @@ ldlm_flock_deadlock(struct ldlm_lock *req, struct ldlm_lock *bl_lock) if (lock == NULL) break; + LASSERT(req != lock); flock = &lock->l_policy_data.l_flock; LASSERT(flock->owner == bl_owner); bl_owner = flock->blocking_owner; @@ -329,18 +330,21 @@ reprocess: RETURN(LDLM_ITER_STOP); } - if (ldlm_flock_deadlock(req, lock)) { - ldlm_flock_destroy(req, mode, *flags); - *err = -EDEADLK; - RETURN(LDLM_ITER_STOP); - } - + /* add lock to blocking list before deadlock + * check to prevent race */ rc = ldlm_flock_blocking_link(req, lock); if (rc) { ldlm_flock_destroy(req, mode, *flags); *err = rc; 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); *flags |= LDLM_FL_BLOCK_GRANTED; RETURN(LDLM_ITER_STOP); |