Enable witness(4) blessings.

witness has long had a facility to "bless" designated lock pairs.  Lock
order reversals between a pair of blessed locks are not reported upon.
We have a number of long-standing false positive LOR reports; start
marking well-understood LORs as blessed.

This change hides reports about UFS vnode locks and the UFS dirhash
lock, and UFS vnode locks and buffer locks, since those are the two that
I observe most often.  In the long term it would be preferable to be
able to limit blessings to a specific site where a lock is acquired,
and/or extend witness to understand why some lock order reversals are
valid (for example, if code paths with conflicting lock orders are
serialized by a third lock), but in the meantime the false positives
frequently confuse users and generate bug reports.

Reviewed by:	cem, kib, mckusick
MFC after:	2 weeks
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D21039
This commit is contained in:
Mark Johnston 2019-07-30 17:09:58 +00:00
parent 98197770c9
commit 49c3e8c8d1

View File

@ -132,9 +132,6 @@ __FBSDID("$FreeBSD$");
#define LI_EXCLUSIVE 0x00010000 /* Exclusive lock instance. */ #define LI_EXCLUSIVE 0x00010000 /* Exclusive lock instance. */
#define LI_NORELEASE 0x00020000 /* Lock not allowed to be released. */ #define LI_NORELEASE 0x00020000 /* Lock not allowed to be released. */
/* Define this to check for blessed mutexes */
#undef BLESSING
#ifndef WITNESS_COUNT #ifndef WITNESS_COUNT
#define WITNESS_COUNT 1536 #define WITNESS_COUNT 1536
#endif #endif
@ -278,12 +275,10 @@ struct witness_lock_order_hash {
u_int wloh_count; u_int wloh_count;
}; };
#ifdef BLESSING
struct witness_blessed { struct witness_blessed {
const char *b_lock1; const char *b_lock1;
const char *b_lock2; const char *b_lock2;
}; };
#endif
struct witness_pendhelp { struct witness_pendhelp {
const char *wh_type; const char *wh_type;
@ -318,9 +313,7 @@ witness_lock_order_key_equal(const struct witness_lock_order_key *a,
static int _isitmyx(struct witness *w1, struct witness *w2, int rmask, static int _isitmyx(struct witness *w1, struct witness *w2, int rmask,
const char *fname); const char *fname);
static void adopt(struct witness *parent, struct witness *child); static void adopt(struct witness *parent, struct witness *child);
#ifdef BLESSING
static int blessed(struct witness *, struct witness *); static int blessed(struct witness *, struct witness *);
#endif
static void depart(struct witness *w); static void depart(struct witness *w);
static struct witness *enroll(const char *description, static struct witness *enroll(const char *description,
struct lock_class *lock_class); struct lock_class *lock_class);
@ -726,14 +719,25 @@ static struct witness_order_list_entry order_lists[] = {
{ NULL, NULL } { NULL, NULL }
}; };
#ifdef BLESSING
/* /*
* Pairs of locks which have been blessed * Pairs of locks which have been blessed. Witness does not complain about
* Don't complain about order problems with blessed locks * order problems with blessed lock pairs. Please do not add an entry to the
* table without an explanatory comment.
*/ */
static struct witness_blessed blessed_list[] = { static struct witness_blessed blessed_list[] = {
/*
* See the comment in ufs_dirhash.c. Basically, a vnode lock serializes
* both lock orders, so a deadlock cannot happen as a result of this
* LOR.
*/
{ "dirhash", "bufwait" },
/*
* A UFS vnode may be locked in vget() while a buffer belonging to the
* parent directory vnode is locked.
*/
{ "ufs", "bufwait" },
}; };
#endif
/* /*
* This global is set to 0 once it becomes safe to use the witness code. * This global is set to 0 once it becomes safe to use the witness code.
@ -1339,7 +1343,6 @@ witness_checkorder(struct lock_object *lock, int flags, const char *file,
* We have a lock order violation, check to see if it * We have a lock order violation, check to see if it
* is allowed or has already been yelled about. * is allowed or has already been yelled about.
*/ */
#ifdef BLESSING
/* /*
* If the lock order is blessed, just bail. We don't * If the lock order is blessed, just bail. We don't
@ -1348,7 +1351,6 @@ witness_checkorder(struct lock_object *lock, int flags, const char *file,
*/ */
if (blessed(w, w1)) if (blessed(w, w1))
goto out; goto out;
#endif
/* Bail if this violation is known */ /* Bail if this violation is known */
if (w_rmatrix[w1->w_index][w->w_index] & WITNESS_REVERSAL) if (w_rmatrix[w1->w_index][w->w_index] & WITNESS_REVERSAL)
@ -2084,7 +2086,6 @@ isitmydescendant(struct witness *ancestor, struct witness *descendant)
__func__)); __func__));
} }
#ifdef BLESSING
static int static int
blessed(struct witness *w1, struct witness *w2) blessed(struct witness *w1, struct witness *w2)
{ {
@ -2104,7 +2105,6 @@ blessed(struct witness *w1, struct witness *w2)
} }
return (0); return (0);
} }
#endif
static struct witness * static struct witness *
witness_get(void) witness_get(void)