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

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: 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
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -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);