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 *iroot, *rnode, *root, *tmp; + int clev, ilevel, level, nalloc, slot; CTR4(KTR_VM, "insert: tree %p, " KFRMT64(index) ", val %p", rtree, @@ -417,59 +415,59 @@ 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; + rnode = root; clev = level; - rnode = root; + nalloc = 0; 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(); - if (rnode->rn_child[slot] == NULL) { - CTR6(KTR_VM, + + /* If the node is already present just bail. */ + if (rnode->rn_child[slot] != NULL) { + 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", + rtree, rnode, rnode->rn_child[slot], + rnode->rn_count); + rnode = rnode->rn_child[slot]; + continue; + } + + /* Add the required intermidiate node. */ + rnode->rn_child[slot] = vm_radix_node_get(); + if (rnode->rn_child[slot] == NULL) { + CTR6(KTR_VM, "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--; + rtree, KSPLT64L(index), KSPLT64H(index), level, + slot, rnode); + while (nalloc--) { + level = clev; + rnode = root; + for (level--; level > 0; 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--; + tmp = rnode->rn_child[slot]; + if (tmp == NULL) + break; + if (tmp->rn_count == 0) { + vm_radix_node_put(tmp); + rnode->rn_count--; + rnode->rn_child[slot] = NULL; + break; } - 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); } - rnode->rn_count++; - allocmsk |= (1 << level); - } + vm_radix_unwind_heightup(rtree, root, iroot, ilevel); + return (ENOMEM); + } + nalloc++; + rnode->rn_count++; 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]; }