Index: sys/vm/vm_radix.c =================================================================== --- sys/vm/vm_radix.c (revisione 235748) +++ sys/vm/vm_radix.c (copia locale) @@ -100,7 +100,6 @@ #endif CTASSERT(VM_RADIX_HEIGHT >= VM_RADIX_LIMIT); -CTASSERT((sizeof(u_int) * NBBY) >= VM_RADIX_LIMIT); struct vm_radix_node { void *rn_child[VM_RADIX_COUNT]; /* Child nodes. */ @@ -362,9 +361,8 @@ vm_radix_reclaim_allnodes_internal(struct vm_radix int vm_radix_insert(struct vm_radix *rtree, vm_pindex_t index, void *val) { - struct vm_radix_node *iroot, *rnode, *root; - u_int allocmsk; - int clev, ilevel, level, slot; + struct vm_radix_node *stack[VM_RADIX_LIMIT], *iroot, *rnode, *root; + int ilevel, level, slot; CTR4(KTR_VM, "insert: tree %p, " KFRMT64(index) ", val %p", rtree, @@ -417,11 +415,11 @@ vm_radix_insert(struct vm_radix *rtree, vm_pindex_ } /* Now that the tree is tall enough, fill in the path to the index. */ - allocmsk = 0; - clev = level; rnode = root; + stack[level - 1] = rnode; for (level = level - 1; level > 0; level--) { slot = vm_radix_slot(index, level); + /* Add the required intermidiate nodes. */ if (rnode->rn_child[slot] == NULL) { rnode->rn_child[slot] = vm_radix_node_get(); @@ -430,46 +428,39 @@ vm_radix_insert(struct vm_radix *rtree, vm_pindex_ "insert: tree %p, " KFRMT64(index) ", level %d, slot %d, rnode %p ENOMEM", rtree, KSPLT64L(index), KSPLT64H(index), level, slot, rnode); - CTR4(KTR_VM, - "insert: tree %p, rnode %p, child %p, count %u ENOMEM", - rtree, rnode, rnode->rn_child[slot], - rnode->rn_count); - MPASS(level != clev || allocmsk == 0); - while (allocmsk != 0) { - rnode = root; - level = clev; - level--; - slot = vm_radix_slot(index, level); - CTR4(KTR_VM, - "insert: unwind root %p, level %d, slot %d, allocmsk: 0x%x", - root, level, slot, allocmsk); - MPASS(level >= (ffs(allocmsk) - 1)); - while (level > (ffs(allocmsk) - 1)) { - MPASS(level > 0); - slot = vm_radix_slot(index, - level); - rnode = rnode->rn_child[slot]; - level--; + + /* + * We can safely exclude the first item as + * root was already allocated, thus check + * below VM_RADIX_LIMIT is fine. + */ + for (level++; level < VM_RADIX_LIMIT; level++) { + MPASS(stack[level] != root); + if ((uintptr_t)stack[level] & 1) { + stack[level + 1]->rn_count--; + vm_radix_node_put(stack[level]); } - MPASS((allocmsk & (1 << level)) != 0); - allocmsk &= ~(1 << level); - rnode->rn_count--; - vm_radix_node_put(rnode->rn_child[slot]); - rnode->rn_child[slot] = NULL; } vm_radix_unwind_heightup(rtree, root, iroot, ilevel); - return (ENOMEM); + return (ENOMEM); } rnode->rn_count++; - allocmsk |= (1 << level); - } + + /* + * The LSB can be used to signal the node was + * allocated during this path building and needs to be + * destructed now. + */ + stack[level - 1] = + (void *)((uintptr_t)rnode->rn_child[slot] + 1); + } else + stack[level - 1] = rnode->rn_child[slot]; CTR6(KTR_VM, "insert: tree %p, " KFRMT64(index) ", level %d, slot %d, rnode %p", rtree, KSPLT64L(index), KSPLT64H(index), level, slot, rnode); - CTR4(KTR_VM, - "insert: tree %p, rnode %p, child %p, count %u", + CTR4(KTR_VM, "insert: tree %p, rnode %p, child %p, count %u", rtree, rnode, rnode->rn_child[slot], rnode->rn_count); rnode = rnode->rn_child[slot]; }