/* * returns 1 if @node is empty after pruning, 0 otherwise */ static int radix_tree_prune_branch(radix_tree_t *tree, radix_tree_node_t *node, uint32_t now) { int i, empty; radix_tree_link_t *link; empty = 1; if (!node) return empty; for (i = 0; i < RADIX_TREE_NODE_SIZE; i++) { link = node->links + i; if (now - link->time < BLOCK_CACHE_PAGE_IDLETIME) { if (radix_tree_node_contains_leaves(tree, node)) { empty = 0; continue; } if (radix_tree_prune_branch(tree, link->u.next, now)) radix_tree_clear_link(link); else empty = 0; continue; } if (radix_tree_node_contains_leaves(tree, node)) radix_tree_remove_page(tree, link->u.leaf.page); else radix_tree_delete_branch(tree, link->u.next); radix_tree_clear_link(link); } if (empty && !radix_tree_node_is_root(tree, node)) radix_tree_free_node(tree, node); return empty; }
static void radix_tree_delete_branch(radix_tree_t *tree, radix_tree_node_t *node) { int i; radix_tree_link_t *link; if (!node) return; for (i = 0; i < RADIX_TREE_NODE_SIZE; i++) { link = node->links + i; if (radix_tree_node_contains_leaves(tree, node)) radix_tree_remove_page(tree, link->u.leaf.page); else radix_tree_delete_branch(tree, link->u.next); radix_tree_clear_link(link); } radix_tree_free_node(tree, node); }
void * radix_tree_remove_node(struct radix_tree *t, uint64_t idx) { struct radix_tree_path path; void **vpp; void *oldp; int i; vpp = radix_tree_lookup_ptr(t, idx, &path, false, 0); KASSERT(vpp != NULL); oldp = *vpp; KASSERT(oldp != NULL); KASSERT(path.p_lastidx == t->t_height); KASSERT(vpp == path_pptr(t, &path, path.p_lastidx)); *vpp = NULL; for (i = t->t_height - 1; i >= 0; i--) { void *entry; struct radix_tree_node ** const pptr = (struct radix_tree_node **)path_pptr(t, &path, i); struct radix_tree_node *n; KASSERT(pptr != NULL); entry = *pptr; n = entry_ptr(entry); KASSERT(n != NULL); KASSERT(n->n_nptrs > 0); n->n_nptrs--; if (n->n_nptrs > 0) { break; } radix_tree_free_node(n); *pptr = NULL; } /* * fix up height */ if (i < 0) { KASSERT(t->t_root == NULL); t->t_height = 0; } /* * update tags */ for (; i >= 0; i--) { void *entry; struct radix_tree_node ** const pptr = (struct radix_tree_node **)path_pptr(t, &path, i); struct radix_tree_node *n; unsigned int newmask; KASSERT(pptr != NULL); entry = *pptr; n = entry_ptr(entry); KASSERT(n != NULL); KASSERT(n->n_nptrs > 0); newmask = any_children_tagmask(n); if (newmask == entry_tagmask(entry)) { break; } *pptr = entry_compose(n, newmask); } /* * XXX is it worth to try to reduce height? * if we do that, make radix_tree_grow rollback its change as well. */ return entry_ptr(oldp); }