diff options
author | markj <markj@FreeBSD.org> | 2015-06-21 00:36:02 +0000 |
---|---|---|
committer | markj <markj@FreeBSD.org> | 2015-06-21 00:36:02 +0000 |
commit | 93e43c433dd31d17afecc5a78db42aec66e02b95 (patch) | |
tree | f7af9e7a2bba52068b518c8141057552d0d1a1dc | |
parent | 80271ba17a0de5498c2a73d03702f58804fd814b (diff) | |
download | FreeBSD-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.c | 17 |
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", |