diff --git a/sys/fs/tarfs/tarfs_subr.c b/sys/fs/tarfs/tarfs_subr.c --- a/sys/fs/tarfs/tarfs_subr.c +++ b/sys/fs/tarfs/tarfs_subr.c @@ -48,6 +48,8 @@ #include #include +WITNESS_BLESSED(tarfs, "tarfs", "bufwait"); + MALLOC_DEFINE(M_TARFSNAME, "tarfs name", "tarfs file names"); MALLOC_DEFINE(M_TARFSBLK, "tarfs blk", "tarfs block maps"); diff --git a/sys/fs/tarfs/tarfs_vfsops.c b/sys/fs/tarfs/tarfs_vfsops.c --- a/sys/fs/tarfs/tarfs_vfsops.c +++ b/sys/fs/tarfs/tarfs_vfsops.c @@ -1246,3 +1246,9 @@ VFS_SET(tarfs_vfsops, tarfs, VFCF_READONLY); MODULE_VERSION(tarfs, 1); MODULE_DEPEND(tarfs, xz, 1, 1, 1); + +/* + * The tarfs decompression stream vnode may be locked while a + * buffer belonging to a tarfs data vnode is locked. + */ +WITNESS_BLESSED(tarfs_bufwait, "tarfs", "bufwait"); diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c --- a/sys/kern/subr_witness.c +++ b/sys/kern/subr_witness.c @@ -274,11 +274,6 @@ u_int wloh_count; }; -struct witness_blessed { - const char *b_lock1; - const char *b_lock2; -}; - struct witness_pendhelp { const char *wh_type; struct lock_object *wh_lock; @@ -723,28 +718,17 @@ /* * Pairs of locks which have been blessed. Witness does not complain about * order problems with blessed lock pairs. Please do not add an entry to the - * table without an explanatory comment. + * linker set without an explanatory comment. */ -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" }, +WITNESS_BLESSED(null, NULL, NULL); +SET_DECLARE(witness_blessed_set, struct witness_blessed); - /* - * The tarfs decompression stream vnode may be locked while a - * buffer belonging to a tarfs data vnode is locked. - */ - { "tarfs", "bufwait" }, -}; +/* + * 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. + */ +WITNESS_BLESSED(dirhash_bufwait, "dirhash", "bufwait"); /* * This global is set to 0 once it becomes safe to use the witness code. @@ -2143,11 +2127,12 @@ static int blessed(struct witness *w1, struct witness *w2) { - int i; - struct witness_blessed *b; + struct witness_blessed *b, **list; - for (i = 0; i < nitems(blessed_list); i++) { - b = &blessed_list[i]; + SET_FOREACH(list, witness_blessed_set) { + b = *list; + if (b->b_lock1 == NULL || b->b_lock2 == NULL) + continue; if (strcmp(w1->w_name, b->b_lock1) == 0) { if (strcmp(w2->w_name, b->b_lock2) == 0) return (1); diff --git a/sys/sys/lock.h b/sys/sys/lock.h --- a/sys/sys/lock.h +++ b/sys/sys/lock.h @@ -249,6 +249,19 @@ int witness_startup_count(void); void witness_startup(void *); +struct witness_blessed { + const char *b_lock1; + const char *b_lock2; +}; + +#include + +#define WITNESS_BLESSED(uniquifier, lock1, lock2) \ + static struct witness_blessed _wit_bless_##uniquifier = { \ + lock1, lock2 \ + }; \ + DATA_SET(witness_blessed_set, _wit_bless_##uniquifier) + /* Flags for witness_warn(). */ #define WARN_GIANTOK 0x01 /* Giant is exempt from this check. */ #define WARN_PANIC 0x02 /* Panic if check fails. */ @@ -325,6 +338,7 @@ #define WITNESS_RELEASEOK(lock) (void)0 #define WITNESS_FILE(lock) ("?") #define WITNESS_LINE(lock) (0) +#define WITNESS_BLESSED(uniquifier, lock1, lock2) #endif /* WITNESS */ #endif /* _KERNEL */ diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c --- a/sys/ufs/ffs/ffs_subr.c +++ b/sys/ufs/ffs/ffs_subr.c @@ -68,6 +68,12 @@ #include #include +/* + * A UFS vnode may be locked in vget() while a buffer belonging to the + * parent directory vnode is locked. + */ +WITNESS_BLESSED(ufs, "ufs", "bufwait"); + #define UFS_MALLOC(size, type, flags) malloc(size, type, flags) #define UFS_FREE(ptr, type) free(ptr, type)