Page MenuHomeFreeBSD

D57793.id180636.diff
No OneTemporary

D57793.id180636.diff

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
@@ -419,19 +419,16 @@
SYSCTL_ULONG(_debug_witness, OID_AUTO, witness_count,
CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &witness_count, 0,
"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.
@@ -489,6 +486,7 @@
static uint8_t **w_rmatrix;
static struct lock_list_entry w_locklistdata[LOCK_CHILDCOUNT];
static struct witness_hash w_hash; /* The witness hash table. */
+static u_long w_sz; /* Witness startup memory allocation size */
/* The lock order data hash */
static struct witness_lock_order_data *w_lodata;
@@ -791,10 +789,10 @@
/*
* Calculate the size of early witness structures.
*/
-int
-witness_startup_count(void)
+static u_long
+witness_startup_calc(void)
{
- int sz;
+ u_long sz;
sz = sizeof(struct witness) * witness_count;
sz += sizeof(*w_rmatrix) * (witness_count + 1);
@@ -803,10 +801,55 @@
sz += sizeof(void *);
sz += sizeof(w_lodata[0]) * witness_lo_data_count;
sz += sizeof(w_lohash.wloh_array[0]) * witness_lo_hash_size;
+ sz = round_page(sz);
return (sz);
}
+u_long
+witness_startup_count(u_long avail)
+{
+
+ /* Tune witness. */
+ TUNABLE_ULONG_FETCH("debug.witness.witness_count", &witness_count);
+ witness_count = ulmax(witness_count, 1);
+ TUNABLE_ULONG_FETCH("debug.witness.lock_order_data_count",
+ &witness_lo_data_count);
+ TUNABLE_ULONG_FETCH("debug.witness.lock_order_hash_size",
+ &witness_lo_hash_size);
+ w_sz = witness_startup_calc();
+ if (w_sz <= avail)
+ return (w_sz);
+
+ /* Memory allocation would be too large, try fallbacks. */
+ printf("WARNING: WITNESS configuration would need %lu KiB, "
+ "with %lu KiB available\n", w_sz / 1024, avail / 1024);
+ witness_count = ulmin(witness_count, WITNESS_COUNT);
+ witness_lo_data_count = ulmin(witness_lo_data_count,
+ WITNESS_LO_DATA_COUNT);
+ witness_lo_hash_size = ulmin(witness_lo_hash_size,
+ WITNESS_LO_HASH_SIZE);
+ w_sz = witness_startup_calc();
+ if (w_sz <= avail) {
+ printf("WARNING: WITNESS configuration reduced to defaults\n");
+ return (w_sz);
+ }
+
+ /* Minimize startup allocations, functionally disabling witness. */
+ witness_count = 1;
+ witness_lo_data_count = 0;
+ witness_lo_hash_size = 1;
+ w_sz = witness_startup_calc();
+ if (w_sz <= avail) {
+ printf("WARNING: WITNESS configuration defaults too large, "
+ "lock order checks disabled\n");
+ return (w_sz);
+ }
+
+ panic("WITNESS unable to initialize with %lu KiB available",
+ avail / 1024);
+}
+
/*
* The WITNESS-enabled diagnostic code. Note that the witness code does
* assume that the early boot is single-threaded at least until after this
@@ -843,6 +886,8 @@
w_lohash.wloh_array = (void *)p;
p += sizeof(w_lohash.wloh_array[0]) * witness_lo_hash_size;
+ MPASS(p <= (uintptr_t)mem + w_sz);
+
badstack_sbuf_size = witness_count * 256;
/*
diff --git a/sys/sys/lock.h b/sys/sys/lock.h
--- a/sys/sys/lock.h
+++ b/sys/sys/lock.h
@@ -247,7 +247,7 @@
void witness_thread_exit(struct thread *);
#ifdef WITNESS
-int witness_startup_count(void);
+u_long witness_startup_count(u_long);
void witness_startup(void *);
/* Flags for witness_warn(). */
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -585,7 +585,7 @@
int biggestone, i, segind;
#ifdef WITNESS
void *mapped;
- int witness_size;
+ u_long witness_size;
#endif
#if defined(__i386__) && defined(VM_PHYSSEG_DENSE)
long ii;
@@ -610,7 +610,14 @@
new_end = end;
#ifdef WITNESS
- witness_size = round_page(witness_startup_count());
+ /*
+ * witness(4) support. Allocate and map memory and initialize.
+ * Advertised available memory is limited in order to avoid witness
+ * misconfiguration consuming memory needed for subsequent essential
+ * allocations.
+ */
+ witness_size = round_page(witness_startup_count(
+ trunc_page((new_end - phys_avail[biggestone]) / 2)));
new_end -= witness_size;
mapped = pmap_map(&vaddr, new_end, new_end + witness_size,
VM_PROT_READ | VM_PROT_WRITE);

File Metadata

Mime Type
text/plain
Expires
Thu, Jul 9, 8:11 AM (17 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34881806
Default Alt Text
D57793.id180636.diff (4 KB)

Event Timeline