Index: sys/vm/vm_radix.c =================================================================== --- sys/vm/vm_radix.c (revision 253399) +++ sys/vm/vm_radix.c (working copy) @@ -103,30 +103,21 @@ struct vm_radix_node { static uma_zone_t vm_radix_node_zone; /* - * Allocate a radix node. Pre-allocation should ensure that the request - * will always be satisfied. + * Allocate a radix node. */ static __inline struct vm_radix_node * vm_radix_node_get(vm_pindex_t owner, uint16_t count, uint16_t clevel) { struct vm_radix_node *rnode; + u_int i; - rnode = uma_zalloc(vm_radix_node_zone, M_NOWAIT); - - /* - * The required number of nodes should already be pre-allocated - * by vm_radix_prealloc(). However, UMA can hold a few nodes - * in per-CPU buckets, which will not be accessible by the - * current CPU. Thus, the allocation could return NULL when - * the pre-allocated pool is close to exhaustion. Anyway, - * in practice this should never occur because a new node - * is not always required for insert. Thus, the pre-allocated - * pool should have some extra pages that prevent this from - * becoming a problem. - */ + rnode = uma_zalloc(vm_radix_node_zone, M_NOWAIT | M_ZERO); if (rnode == NULL) - panic("%s: uma_zalloc() returned NULL for a new node", - __func__); + panic("a fess d mammt"); + for (i = 0; i < VM_RADIX_COUNT; i++) + KASSERT(rnode->rn_child[i] == NULL, + ("vm_radix_node_put: rnode %p has child %d %p", rnode, + i, rnode->rn_child[i])); rnode->rn_owner = owner; rnode->rn_count = count; rnode->rn_clev = clevel; @@ -295,20 +286,8 @@ vm_radix_node_zone_dtor(void *mem, int size __unus } #endif +#if 0 /* - * Radix node zone initializer. - */ -static int -vm_radix_node_zone_init(void *mem, int size __unused, int flags __unused) -{ - struct vm_radix_node *rnode; - - rnode = mem; - memset(rnode->rn_child, 0, sizeof(rnode->rn_child)); - return (0); -} - -/* * Pre-allocate intermediate nodes from the UMA slab zone. */ static void @@ -328,6 +307,7 @@ vm_radix_prealloc(void *arg __unused) } SYSINIT(vm_radix_prealloc, SI_SUB_KMEM, SI_ORDER_SECOND, vm_radix_prealloc, NULL); +#endif /* * Initialize the UMA slab zone. @@ -345,7 +325,7 @@ vm_radix_init(void) #else NULL, #endif - vm_radix_node_zone_init, NULL, VM_RADIX_PAD, UMA_ZONE_VM | + NULL, NULL, VM_RADIX_PAD, UMA_ZONE_VM | UMA_ZONE_NOFREE); } @@ -360,7 +340,7 @@ vm_radix_insert(struct vm_radix *rtree, vm_page_t void **parentp; struct vm_radix_node *rnode, *tmp; vm_page_t m; - int slot; + int i, slot; uint16_t clev; index = page->pindex; @@ -387,6 +367,17 @@ vm_radix_insert(struct vm_radix *rtree, vm_page_t *parentp = tmp; vm_radix_addpage(tmp, index, clev, page); vm_radix_addpage(tmp, m->pindex, clev, m); + for (i = 0, slot = 0; slot < VM_RADIX_COUNT; slot++) + if (tmp->rn_child[slot] != NULL) + i++; + if (i != tmp->rn_count) { + printf("count: %d\n", tmp->rn_count); + for (slot = 0; slot < VM_RADIX_COUNT; slot++) + if (tmp->rn_child[slot] != NULL) + printf("%p %d\n", + tmp->rn_child[slot], slot); + panic("i %d, count %d", i, tmp->rn_count); + } return; } else if (vm_radix_keybarr(rnode, index)) break; @@ -394,6 +385,18 @@ vm_radix_insert(struct vm_radix *rtree, vm_page_t if (rnode->rn_child[slot] == NULL) { rnode->rn_count++; vm_radix_addpage(rnode, index, rnode->rn_clev, page); + for (i = 0, slot = 0; slot < VM_RADIX_COUNT; slot++) + if (rnode->rn_child[slot] != NULL) + i++; + if (i != rnode->rn_count) { + printf("count: %d\n", rnode->rn_count); + for (slot = 0; slot < VM_RADIX_COUNT; slot++) + if (rnode->rn_child[slot] != NULL) + printf("%p %d\n", + rnode->rn_child[slot], + slot); + panic("i %d, count %d", i, rnode->rn_count); + } return; } parentp = &rnode->rn_child[slot]; @@ -413,6 +416,16 @@ vm_radix_insert(struct vm_radix *rtree, vm_page_t vm_radix_addpage(tmp, index, clev, page); slot = vm_radix_slot(newind, clev); tmp->rn_child[slot] = rnode; + for (i = 0, slot = 0; slot < VM_RADIX_COUNT; slot++) + if (tmp->rn_child[slot] != NULL) + i++; + if (i != tmp->rn_count) { + printf("count: %d\n", tmp->rn_count); + for (slot = 0; slot < VM_RADIX_COUNT; slot++) + if (tmp->rn_child[slot] != NULL) + printf("%p %d\n", tmp->rn_child[slot], slot); + panic("i %d, count %d", i, tmp->rn_count); + } } /* @@ -675,7 +688,7 @@ vm_radix_remove(struct vm_radix *rtree, vm_pindex_ { struct vm_radix_node *rnode, *parent; vm_page_t m; - int i, slot; + int i, slot, x; rnode = vm_radix_getroot(rtree); if (vm_radix_isleaf(rnode)) { @@ -696,8 +709,21 @@ vm_radix_remove(struct vm_radix *rtree, vm_pindex_ panic("%s: invalid key found", __func__); rnode->rn_child[slot] = NULL; rnode->rn_count--; - if (rnode->rn_count > 1) + if (rnode->rn_count > 1) { + for (x = 0, slot = 0; slot < VM_RADIX_COUNT; + slot++) + if (rnode->rn_child[slot] != NULL) + x++; + if (x != rnode->rn_count) { + printf("count: %d\n", rnode->rn_count); + for (slot = 0; slot < VM_RADIX_COUNT; slot++) + if (rnode->rn_child[slot] != NULL) + printf("%p %d\n", rnode->rn_child[slot], slot); + panic("x %d, count %d", x, + rnode->rn_count); + } break; + } for (i = 0; i < VM_RADIX_COUNT; i++) if (rnode->rn_child[i] != NULL) break; @@ -713,6 +739,16 @@ vm_radix_remove(struct vm_radix *rtree, vm_pindex_ } rnode->rn_count--; rnode->rn_child[i] = NULL; + for (x = 0, slot = 0; slot < VM_RADIX_COUNT; slot++) + if (rnode->rn_child[slot] != NULL) + x++; + if (x != rnode->rn_count) { + printf("count: %d\n", rnode->rn_count); + for (slot = 0; slot < VM_RADIX_COUNT; slot++) + if (rnode->rn_child[slot] != NULL) + printf("%p %d\n", rnode->rn_child[slot], slot); + panic("x %d, count %d", x, rnode->rn_count); + } vm_radix_node_put(rnode); break; } Index: sys/vm/vm_page.c =================================================================== --- sys/vm/vm_page.c (revision 253399) +++ sys/vm/vm_page.c (working copy) @@ -316,7 +316,8 @@ vm_page_startup(vm_offset_t vaddr) /* * Initialize the page and queue locks. */ - mtx_init(&vm_page_queue_free_mtx, "vm page free queue", NULL, MTX_DEF); + mtx_init(&vm_page_queue_free_mtx, "vm page free queue", NULL, MTX_DEF | + MTX_RECURSE); for (i = 0; i < PA_LOCK_COUNT; i++) mtx_init(&pa_lock[i], "vm page", NULL, MTX_DEF); for (i = 0; i < PQ_COUNT; i++) Index: sys/amd64/conf/GENERIC =================================================================== --- sys/amd64/conf/GENERIC (revision 253399) +++ sys/amd64/conf/GENERIC (working copy) @@ -82,8 +82,8 @@ options GDB # Support remote GDB. options DEADLKRES # Enable the deadlock resolver options INVARIANTS # Enable calls of extra sanity checking options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS -options WITNESS # Enable checks to detect deadlocks and cycles -options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed +#options WITNESS # Enable checks to detect deadlocks and cycles +#options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones # Make an SMP-capable kernel by default