summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarkj <markj@FreeBSD.org>2015-06-21 00:36:02 +0000
committermarkj <markj@FreeBSD.org>2015-06-21 00:36:02 +0000
commit93e43c433dd31d17afecc5a78db42aec66e02b95 (patch)
treef7af9e7a2bba52068b518c8141057552d0d1a1dc
parent80271ba17a0de5498c2a73d03702f58804fd814b (diff)
downloadFreeBSD-src-93e43c433dd31d17afecc5a78db42aec66e02b95.zip
FreeBSD-src-93e43c433dd31d17afecc5a78db42aec66e02b95.tar.gz
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.
-rw-r--r--sys/kern/subr_witness.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 1fa3020..8b1e3a0 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -1167,19 +1167,25 @@ witness_checkorder(struct lock_object *lock, int flags, const char *file,
/*
* 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 witness *w2, int rmask, const char *fname)
/* 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",
OpenPOWER on IntegriCloud