Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 21 Jun 2015 00:36:03 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r284653 - stable/10/sys/kern
Message-ID:  <201506210036.t5L0a3Cd073891@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markj
Date: Sun Jun 21 00:36:02 2015
New Revision: 284653
URL: https://svnweb.freebsd.org/changeset/base/284653

Log:
  MFC r284127:
  witness: don't warn about matrix inconsistencies without holding the mutex
  
  Lock order checking is done without the witness mutex held, so multiple
  threads that are racing to establish a new lock order may read matrix
  entries that are in an inconsistent state. Don't print a warning in this
  case, but instead just redo the check after taking the witness lock.

Modified:
  stable/10/sys/kern/subr_witness.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/kern/subr_witness.c
==============================================================================
--- stable/10/sys/kern/subr_witness.c	Sat Jun 20 23:15:57 2015	(r284652)
+++ stable/10/sys/kern/subr_witness.c	Sun Jun 21 00:36:02 2015	(r284653)
@@ -1167,19 +1167,25 @@ witness_checkorder(struct lock_object *l
 	
 	/*
 	 * Try to perform most checks without a lock.  If this succeeds we
-	 * can skip acquiring the lock and return success.
+	 * can skip acquiring the lock and return success.  Otherwise we redo
+	 * the check with the lock held to handle races with concurrent updates.
 	 */
 	w1 = plock->li_lock->lo_witness;
 	if (witness_lock_order_check(w1, w))
 		return;
 
+	mtx_lock_spin(&w_mtx);
+	if (witness_lock_order_check(w1, w)) {
+		mtx_unlock_spin(&w_mtx);
+		return;
+	}
+	witness_lock_order_add(w1, w);
+
 	/*
 	 * Check for duplicate locks of the same type.  Note that we only
 	 * have to check for this on the last lock we just acquired.  Any
 	 * other cases will be caught as lock order violations.
 	 */
-	mtx_lock_spin(&w_mtx);
-	witness_lock_order_add(w1, w);
 	if (w1 == w) {
 		i = w->w_index;
 		if (!(lock->lo_flags & LO_DUPOK) && !(flags & LOP_DUPOK) &&
@@ -1993,7 +1999,10 @@ _isitmyx(struct witness *w1, struct witn
 
 	/* The flags on one better be the inverse of the flags on the other */
 	if (!((WITNESS_ATOD(r1) == r2 && WITNESS_DTOA(r2) == r1) ||
-		(WITNESS_DTOA(r1) == r2 && WITNESS_ATOD(r2) == r1))) {
+	    (WITNESS_DTOA(r1) == r2 && WITNESS_ATOD(r2) == r1))) {
+		/* Don't squawk if we're potentially racing with an update. */
+		if (!mtx_owned(&w_mtx))
+			return (0);
 		printf("%s: rmatrix mismatch between %s (index %d) and %s "
 		    "(index %d): w_rmatrix[%d][%d] == %hhx but "
 		    "w_rmatrix[%d][%d] == %hhx\n",



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201506210036.t5L0a3Cd073891>