Turn WITNESS_COUNT into a tunable and sysctl. This allows adjusting

the value without recompiling the kernel.  This is useful when
recompiling is not possible as an immediate solution. When we run out
of witness objects, witness is completely disabled. Not having an
immediate solution can therefore be problematic.

Submitted by:	Sreekanth Rupavatharam <rupavath@juniper.net>
Obtained from:	Juniper Networks, Inc.
This commit is contained in:
Marcel Moolenaar 2014-10-11 02:02:58 +00:00
parent c57b274d49
commit 90a5222f14
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=272925

View File

@ -135,7 +135,6 @@ __FBSDID("$FreeBSD$");
#ifndef WITNESS_COUNT
#define WITNESS_COUNT 1536
#endif
#define WITNESS_CHILDCOUNT (WITNESS_COUNT * 4)
#define WITNESS_HASH_SIZE 251 /* Prime, gives load factor < 2 */
#define WITNESS_PENDLIST (1024 + MAXCPU)
@ -155,7 +154,6 @@ __FBSDID("$FreeBSD$");
#define MAX_W_NAME 64
#define BADSTACK_SBUF_SIZE (256 * WITNESS_COUNT)
#define FULLGRAPH_SBUF_SIZE 512
/*
@ -184,7 +182,7 @@ __FBSDID("$FreeBSD$");
#define WITNESS_ATOD(x) (((x) & WITNESS_RELATED_MASK) << 2)
#define WITNESS_INDEX_ASSERT(i) \
MPASS((i) > 0 && (i) <= w_max_used_index && (i) < WITNESS_COUNT)
MPASS((i) > 0 && (i) <= w_max_used_index && (i) < witness_count)
static MALLOC_DEFINE(M_WITNESS, "Witness", "Witness");
@ -416,6 +414,13 @@ int witness_skipspin = 0;
#endif
SYSCTL_INT(_debug_witness, OID_AUTO, skipspin, CTLFLAG_RDTUN, &witness_skipspin, 0, "");
/* tunable for Witness count */
int witness_count = WITNESS_COUNT;
int badstack_sbuf_size = WITNESS_COUNT * 256;
SYSCTL_INT(_debug_witness, OID_AUTO, witness_count, CTLFLAG_RDTUN,
&witness_count, 0, "");
/*
* Call this to print out the relations between locks.
*/
@ -450,7 +455,7 @@ SYSCTL_INT(_debug_witness, OID_AUTO, sleep_cnt, CTLFLAG_RD, &w_sleep_cnt, 0,
"");
static struct witness *w_data;
static uint8_t w_rmatrix[WITNESS_COUNT+1][WITNESS_COUNT+1];
static uint8_t **w_rmatrix;
static struct lock_list_entry w_locklistdata[LOCK_CHILDCOUNT];
static struct witness_hash w_hash; /* The witness hash table. */
@ -726,9 +731,18 @@ witness_initialize(void *dummy __unused)
struct witness *w, *w1;
int i;
w_data = malloc(sizeof (struct witness) * WITNESS_COUNT, M_WITNESS,
w_data = malloc(sizeof (struct witness) * witness_count, M_WITNESS,
M_NOWAIT | M_ZERO);
w_rmatrix = malloc(sizeof(uint8_t *) * (witness_count+1),
M_WITNESS, M_NOWAIT | M_ZERO);
for(i = 0; i < witness_count+1; i++) {
w_rmatrix[i] = malloc(sizeof(uint8_t) * (witness_count + 1),
M_WITNESS, M_NOWAIT | M_ZERO);
}
badstack_sbuf_size = witness_count * 256;
/*
* We have to release Giant before initializing its witness
* structure so that WITNESS doesn't get confused.
@ -739,7 +753,7 @@ witness_initialize(void *dummy __unused)
CTR1(KTR_WITNESS, "%s: initializing witness", __func__);
mtx_init(&w_mtx, "witness lock", NULL, MTX_SPIN | MTX_QUIET |
MTX_NOWITNESS | MTX_NOPROFILE);
for (i = WITNESS_COUNT - 1; i >= 0; i--) {
for (i = witness_count - 1; i >= 0; i--) {
w = &w_data[i];
memset(w, 0, sizeof(*w));
w_data[i].w_index = i; /* Witness index never changes. */
@ -752,8 +766,10 @@ witness_initialize(void *dummy __unused)
STAILQ_REMOVE_HEAD(&w_free, w_list);
w_free_cnt--;
memset(w_rmatrix, 0,
(sizeof(**w_rmatrix) * (WITNESS_COUNT+1) * (WITNESS_COUNT+1)));
for(i = 0; i < witness_count; i++) {
memset(w_rmatrix[i], 0, sizeof(uint8_t) *
(witness_count + 1));
}
for (i = 0; i < LOCK_CHILDCOUNT; i++)
witness_lock_list_free(&w_locklistdata[i]);
@ -1196,7 +1212,7 @@ witness_checkorder(struct lock_object *lock, int flags, const char *file,
for (j = 0, lle = lock_list; lle != NULL; lle = lle->ll_next) {
for (i = lle->ll_count - 1; i >= 0; i--, j++) {
MPASS(j < WITNESS_COUNT);
MPASS(j < witness_count);
lock1 = &lle->ll_children[i];
/*
@ -2057,7 +2073,7 @@ witness_get(void)
w_free_cnt--;
index = w->w_index;
MPASS(index > 0 && index == w_max_used_index+1 &&
index < WITNESS_COUNT);
index < witness_count);
bzero(w, sizeof(*w));
w->w_index = index;
if (index > w_max_used_index)
@ -2482,7 +2498,7 @@ sysctl_debug_witness_badstacks(SYSCTL_HANDLER_ARGS)
return (error);
}
error = 0;
sb = sbuf_new(NULL, NULL, BADSTACK_SBUF_SIZE, SBUF_AUTOEXTEND);
sb = sbuf_new(NULL, NULL, badstack_sbuf_size, SBUF_AUTOEXTEND);
if (sb == NULL)
return (ENOMEM);