Index: sys/vm/vm_radix.c =================================================================== --- sys/vm/vm_radix.c (revisione 235748) +++ sys/vm/vm_radix.c (copia locale) @@ -228,6 +228,9 @@ vm_radix_slot(vm_pindex_t index, int level) return ((index >> (level * VM_RADIX_WIDTH)) & VM_RADIX_MASK); } +static void vm_radix_sweep(struct vm_radix *rtree, vm_pindex_t index, + int color, int hard); + /* * Initialize the radix node submap (for architectures not supporting * direct-mapping) and the radix node zone. @@ -363,8 +366,7 @@ 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; + int ilevel, level, slot; CTR4(KTR_VM, "insert: tree %p, " KFRMT64(index) ", val %p", rtree, @@ -417,8 +419,6 @@ 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; for (level = level - 1; level > 0; level--) { slot = vm_radix_slot(index, level); @@ -434,35 +434,12 @@ vm_radix_insert(struct vm_radix *rtree, vm_pindex_ "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--; - } - 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_sweep(rtree, index, VM_RADIX_BLACK, 0); vm_radix_unwind_heightup(rtree, root, iroot, ilevel); return (ENOMEM); } rnode->rn_count++; - allocmsk |= (1 << level); } CTR6(KTR_VM, "insert: tree %p, " KFRMT64(index) ", level %d, slot %d, rnode %p", @@ -816,21 +793,19 @@ restart: * tree is adjusted after deletion. The value stored at index is returned * panics if the key is not present. */ -void * -vm_radix_remove(struct vm_radix *rtree, vm_pindex_t index, int color) +static void +vm_radix_sweep(struct vm_radix *rtree, vm_pindex_t index, int color, int hard) { struct vm_radix_node *stack[VM_RADIX_LIMIT]; struct vm_radix_node *rnode, *root; - void *val; int level; int slot; level = vm_radix_height(rtree, &root); KASSERT(index <= VM_RADIX_MAX(level), - ("vm_radix_remove: %p index out of range %jd.", rtree, + ("vm_radix_sweep: %p index out of range %jd.", rtree, VM_RADIX_MAX(level))); rnode = root; - val = NULL; level--; /* * Find the node and record the path in stack. @@ -847,13 +822,25 @@ restart: rnode = rnode->rn_child[slot]; level--; } - KASSERT(rnode != NULL, - ("vm_radix_remove: index not present in the tree.\n")); - slot = vm_radix_slot(index, 0); - val = vm_radix_match(rnode->rn_child[slot], color); - KASSERT(val != NULL, - ("vm_radix_remove: index not present in the tree.\n")); + if (hard) { + if (rnode == NULL) + panic("vm_radix_sweep: index not present.\n"); + slot = vm_radix_slot(index, 0); + if (vm_radix_match(rnode->rn_child[slot], color) == NULL) + panic("vm_radix_sweep: index not present as leaf.\n"); + } else { + /* + * Almost certainly it got an half-constructed tree it was + * expected. + */ + KASSERT(level < (VM_RADIX_LIMIT - 1), + ("vm_radix_sweep: level %d not consistent.\n", level)); + ++level; + rnode = stack[level]; + slot = vm_radix_slot(index, level); + } + for (;;) { CTR6(KTR_VM, "remove: resetting tree %p, " KFRMT64(index) ", level %d, slot %d, rnode %p", @@ -873,10 +860,14 @@ restart: * Concurrent black removal, infact, may want to reclaim * the radix node itself before to read it. */ - if (level == 0) - atomic_add_rel_32(&rnode->rn_count, -1); - else - rnode->rn_count--; + if (rnode->rn_count != 0) { + if (level == 0) + atomic_add_rel_32(&rnode->rn_count, -1); + else + rnode->rn_count--; + } else if (hard) + panic("vm_radix_sweep: empty node midway.\n"); + /* * Only allow black removes to prune the tree. */ @@ -891,9 +882,15 @@ restart: slot = vm_radix_slot(index, level); } - return (val); } +void +vm_radix_remove(struct vm_radix *rtree, vm_pindex_t index, int color) +{ + + vm_radix_sweep(rtree, index, color, 1); +} + /* * Remove and free all the nodes from the radix tree. * This function is recrusive but there is a tight control on it as the Index: sys/vm/vm_radix.h =================================================================== --- sys/vm/vm_radix.h (revisione 235748) +++ sys/vm/vm_radix.h (copia locale) @@ -63,7 +63,7 @@ int vm_radix_lookupn(struct vm_radix *, vm_pindex_ void **, int, vm_pindex_t *); void *vm_radix_lookup_le(struct vm_radix *, vm_pindex_t, int); void vm_radix_reclaim_allnodes(struct vm_radix *); -void *vm_radix_remove(struct vm_radix *, vm_pindex_t, int); +void vm_radix_remove(struct vm_radix *, vm_pindex_t, int); /* * Look up any entry at a position greater or equal to index.