git: ca8a1c3c27b0 - main - witness: add tunables debug.witness.lock_order_{data_count,hash_size}
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 18 Jun 2026 04:17:17 UTC
The branch main has been updated by rlibby:
URL: https://cgit.FreeBSD.org/src/commit/?id=ca8a1c3c27b0d5915e0dcfd02ea4ef703db4fe9a
commit ca8a1c3c27b0d5915e0dcfd02ea4ef703db4fe9a
Author: Ryan Libby <rlibby@FreeBSD.org>
AuthorDate: 2026-06-18 03:54:26 +0000
Commit: Ryan Libby <rlibby@FreeBSD.org>
CommitDate: 2026-06-18 04:05:43 +0000
witness: add tunables debug.witness.lock_order_{data_count,hash_size}
Add tunable debug.witness.lock_order_data_count to allow adjusting the
number of witness lock order data entries (stacks) without recompiling
the kernel. This may help to display stacks when a lock order reversal
is reported but the number of entries is exhausted before recording the
first lock order, by allowing the user to reboot with an adjusted
tunable and try again.
Tunable debug.witness.lock_order_hash_size is also provided to allow the
hash table load factor to be managed, though that is not required.
Also tweak witness_lock_order_add to avoid computing a hash when it
won't be needed because the lock order data entries are exhausted.
Reviewed by: kib, markj
Sponsored by: Dell Inc.
Differential Revision: https://reviews.freebsd.org/D57600
---
sys/kern/subr_witness.c | 39 ++++++++++++++++++++++++++++++++-------
1 file changed, 32 insertions(+), 7 deletions(-)
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 2bfd8711eed7..21d015c4f381 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -264,7 +264,7 @@ struct witness_lock_order_data {
* (struct witness_lock_order_data).
*/
struct witness_lock_order_hash {
- struct witness_lock_order_data *wloh_array[WITNESS_LO_HASH_SIZE];
+ struct witness_lock_order_data **wloh_array;
u_int wloh_size;
u_int wloh_count;
};
@@ -421,6 +421,18 @@ SYSCTL_ULONG(_debug_witness, OID_AUTO, witness_count,
"Maximum count of lock type entries");
TUNABLE_ULONG("debug.witness.witness_count", &witness_count);
+static u_long witness_lo_data_count = WITNESS_LO_DATA_COUNT;
+SYSCTL_ULONG(_debug_witness, OID_AUTO, lock_order_data_count,
+ CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &witness_lo_data_count, 0,
+ "Maximum count of lock order data (stacks) to track");
+TUNABLE_ULONG("debug.witness.lock_order_data_count", &witness_lo_data_count);
+
+static u_long witness_lo_hash_size = WITNESS_LO_HASH_SIZE;
+SYSCTL_ULONG(_debug_witness, OID_AUTO, lock_order_hash_size,
+ CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &witness_lo_hash_size, 0,
+ "Hash table size for lock order data");
+TUNABLE_ULONG("debug.witness.lock_order_hash_size", &witness_lo_hash_size);
+
/*
* Output channel for witness messages. By default we print to the console.
*/
@@ -479,7 +491,7 @@ static struct lock_list_entry w_locklistdata[LOCK_CHILDCOUNT];
static struct witness_hash w_hash; /* The witness hash table. */
/* The lock order data hash */
-static struct witness_lock_order_data w_lodata[WITNESS_LO_DATA_COUNT];
+static struct witness_lock_order_data *w_lodata;
static struct witness_lock_order_data *w_lofree = NULL;
static struct witness_lock_order_hash w_lohash;
static int w_max_used_index = 0;
@@ -788,6 +800,9 @@ witness_startup_count(void)
sz += sizeof(*w_rmatrix) * (witness_count + 1);
sz += sizeof(*w_rmatrix[0]) * (witness_count + 1) *
(witness_count + 1);
+ sz += sizeof(void *);
+ sz += sizeof(w_lodata[0]) * witness_lo_data_count;
+ sz += sizeof(w_lohash.wloh_array[0]) * witness_lo_hash_size;
return (sz);
}
@@ -818,6 +833,16 @@ witness_startup(void *mem)
w_rmatrix[i] = (void *)p;
p += sizeof(*w_rmatrix[i]) * (witness_count + 1);
}
+
+ /* Fix up alignment */
+ p = roundup2(p, sizeof(void *));
+
+ w_lodata = (void *)p;
+ p += sizeof(w_lodata[0]) * witness_lo_data_count;
+
+ w_lohash.wloh_array = (void *)p;
+ p += sizeof(w_lohash.wloh_array[0]) * witness_lo_hash_size;
+
badstack_sbuf_size = witness_count * 256;
/*
@@ -3300,14 +3325,14 @@ witness_init_hash_tables(void)
/* Initialize the lock order data hash. */
w_lofree = NULL;
- for (i = 0; i < WITNESS_LO_DATA_COUNT; i++) {
+ for (i = 0; i < witness_lo_data_count; i++) {
memset(&w_lodata[i], 0, sizeof(w_lodata[i]));
w_lodata[i].wlod_next = w_lofree;
w_lofree = &w_lodata[i];
}
- w_lohash.wloh_size = WITNESS_LO_HASH_SIZE;
+ w_lohash.wloh_size = witness_lo_hash_size;
w_lohash.wloh_count = 0;
- for (i = 0; i < WITNESS_LO_HASH_SIZE; i++)
+ for (i = 0; i < w_lohash.wloh_size; i++)
w_lohash.wloh_array[i] = NULL;
}
@@ -3414,13 +3439,13 @@ witness_lock_order_add(struct witness *parent, struct witness *child)
& WITNESS_LOCK_ORDER_KNOWN)
return (1);
- hash = witness_hash_djb2((const char *)&key,
- sizeof(key)) % w_lohash.wloh_size;
w_rmatrix[parent->w_index][child->w_index] |= WITNESS_LOCK_ORDER_KNOWN;
data = w_lofree;
if (data == NULL)
return (0);
w_lofree = data->wlod_next;
+ hash = witness_hash_djb2((const char *)&key,
+ sizeof(key)) % w_lohash.wloh_size;
data->wlod_next = w_lohash.wloh_array[hash];
data->wlod_key = key;
w_lohash.wloh_array[hash] = data;