Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 7 Jun 2015 18:59:48 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r284127 - head/sys/kern
Message-ID:  <201506071859.t57Ixm6T036074@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markj
Date: Sun Jun  7 18:59:47 2015
New Revision: 284127
URL: https://svnweb.freebsd.org/changeset/base/284127

Log:
  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.
  
  Differential Revision:	https://reviews.freebsd.org/D2713
  Reviewed by:	jhb
  MFC after:	2 weeks
  Sponsored by:	EMC / Isilon Storage Division

Modified:
  head/sys/kern/subr_witness.c

Modified: head/sys/kern/subr_witness.c
==============================================================================
--- head/sys/kern/subr_witness.c	Sun Jun  7 15:54:57 2015	(r284126)
+++ head/sys/kern/subr_witness.c	Sun Jun  7 18:59:47 2015	(r284127)
@@ -1170,19 +1170,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) &&
@@ -1996,7 +2002,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?201506071859.t57Ixm6T036074>