Esempio n. 1
0
/*
 * 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;
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
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);
}