162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci#include <linux/interval_tree.h>
362306a36Sopenharmony_ci#include <linux/interval_tree_generic.h>
462306a36Sopenharmony_ci#include <linux/compiler.h>
562306a36Sopenharmony_ci#include <linux/export.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#define START(node) ((node)->start)
862306a36Sopenharmony_ci#define LAST(node)  ((node)->last)
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ciINTERVAL_TREE_DEFINE(struct interval_tree_node, rb,
1162306a36Sopenharmony_ci		     unsigned long, __subtree_last,
1262306a36Sopenharmony_ci		     START, LAST,, interval_tree)
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(interval_tree_insert);
1562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(interval_tree_remove);
1662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(interval_tree_iter_first);
1762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(interval_tree_iter_next);
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#ifdef CONFIG_INTERVAL_TREE_SPAN_ITER
2062306a36Sopenharmony_ci/*
2162306a36Sopenharmony_ci * Roll nodes[1] into nodes[0] by advancing nodes[1] to the end of a contiguous
2262306a36Sopenharmony_ci * span of nodes. This makes nodes[0]->last the end of that contiguous used span
2362306a36Sopenharmony_ci * indexes that started at the original nodes[1]->start. nodes[1] is now the
2462306a36Sopenharmony_ci * first node starting the next used span. A hole span is between nodes[0]->last
2562306a36Sopenharmony_ci * and nodes[1]->start. nodes[1] must be !NULL.
2662306a36Sopenharmony_ci */
2762306a36Sopenharmony_cistatic void
2862306a36Sopenharmony_ciinterval_tree_span_iter_next_gap(struct interval_tree_span_iter *state)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	struct interval_tree_node *cur = state->nodes[1];
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	state->nodes[0] = cur;
3362306a36Sopenharmony_ci	do {
3462306a36Sopenharmony_ci		if (cur->last > state->nodes[0]->last)
3562306a36Sopenharmony_ci			state->nodes[0] = cur;
3662306a36Sopenharmony_ci		cur = interval_tree_iter_next(cur, state->first_index,
3762306a36Sopenharmony_ci					      state->last_index);
3862306a36Sopenharmony_ci	} while (cur && (state->nodes[0]->last >= cur->start ||
3962306a36Sopenharmony_ci			 state->nodes[0]->last + 1 == cur->start));
4062306a36Sopenharmony_ci	state->nodes[1] = cur;
4162306a36Sopenharmony_ci}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_civoid interval_tree_span_iter_first(struct interval_tree_span_iter *iter,
4462306a36Sopenharmony_ci				   struct rb_root_cached *itree,
4562306a36Sopenharmony_ci				   unsigned long first_index,
4662306a36Sopenharmony_ci				   unsigned long last_index)
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	iter->first_index = first_index;
4962306a36Sopenharmony_ci	iter->last_index = last_index;
5062306a36Sopenharmony_ci	iter->nodes[0] = NULL;
5162306a36Sopenharmony_ci	iter->nodes[1] =
5262306a36Sopenharmony_ci		interval_tree_iter_first(itree, first_index, last_index);
5362306a36Sopenharmony_ci	if (!iter->nodes[1]) {
5462306a36Sopenharmony_ci		/* No nodes intersect the span, whole span is hole */
5562306a36Sopenharmony_ci		iter->start_hole = first_index;
5662306a36Sopenharmony_ci		iter->last_hole = last_index;
5762306a36Sopenharmony_ci		iter->is_hole = 1;
5862306a36Sopenharmony_ci		return;
5962306a36Sopenharmony_ci	}
6062306a36Sopenharmony_ci	if (iter->nodes[1]->start > first_index) {
6162306a36Sopenharmony_ci		/* Leading hole on first iteration */
6262306a36Sopenharmony_ci		iter->start_hole = first_index;
6362306a36Sopenharmony_ci		iter->last_hole = iter->nodes[1]->start - 1;
6462306a36Sopenharmony_ci		iter->is_hole = 1;
6562306a36Sopenharmony_ci		interval_tree_span_iter_next_gap(iter);
6662306a36Sopenharmony_ci		return;
6762306a36Sopenharmony_ci	}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	/* Starting inside a used */
7062306a36Sopenharmony_ci	iter->start_used = first_index;
7162306a36Sopenharmony_ci	iter->is_hole = 0;
7262306a36Sopenharmony_ci	interval_tree_span_iter_next_gap(iter);
7362306a36Sopenharmony_ci	iter->last_used = iter->nodes[0]->last;
7462306a36Sopenharmony_ci	if (iter->last_used >= last_index) {
7562306a36Sopenharmony_ci		iter->last_used = last_index;
7662306a36Sopenharmony_ci		iter->nodes[0] = NULL;
7762306a36Sopenharmony_ci		iter->nodes[1] = NULL;
7862306a36Sopenharmony_ci	}
7962306a36Sopenharmony_ci}
8062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(interval_tree_span_iter_first);
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_civoid interval_tree_span_iter_next(struct interval_tree_span_iter *iter)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	if (!iter->nodes[0] && !iter->nodes[1]) {
8562306a36Sopenharmony_ci		iter->is_hole = -1;
8662306a36Sopenharmony_ci		return;
8762306a36Sopenharmony_ci	}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	if (iter->is_hole) {
9062306a36Sopenharmony_ci		iter->start_used = iter->last_hole + 1;
9162306a36Sopenharmony_ci		iter->last_used = iter->nodes[0]->last;
9262306a36Sopenharmony_ci		if (iter->last_used >= iter->last_index) {
9362306a36Sopenharmony_ci			iter->last_used = iter->last_index;
9462306a36Sopenharmony_ci			iter->nodes[0] = NULL;
9562306a36Sopenharmony_ci			iter->nodes[1] = NULL;
9662306a36Sopenharmony_ci		}
9762306a36Sopenharmony_ci		iter->is_hole = 0;
9862306a36Sopenharmony_ci		return;
9962306a36Sopenharmony_ci	}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	if (!iter->nodes[1]) {
10262306a36Sopenharmony_ci		/* Trailing hole */
10362306a36Sopenharmony_ci		iter->start_hole = iter->nodes[0]->last + 1;
10462306a36Sopenharmony_ci		iter->last_hole = iter->last_index;
10562306a36Sopenharmony_ci		iter->nodes[0] = NULL;
10662306a36Sopenharmony_ci		iter->is_hole = 1;
10762306a36Sopenharmony_ci		return;
10862306a36Sopenharmony_ci	}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	/* must have both nodes[0] and [1], interior hole */
11162306a36Sopenharmony_ci	iter->start_hole = iter->nodes[0]->last + 1;
11262306a36Sopenharmony_ci	iter->last_hole = iter->nodes[1]->start - 1;
11362306a36Sopenharmony_ci	iter->is_hole = 1;
11462306a36Sopenharmony_ci	interval_tree_span_iter_next_gap(iter);
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(interval_tree_span_iter_next);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci/*
11962306a36Sopenharmony_ci * Advance the iterator index to a specific position. The returned used/hole is
12062306a36Sopenharmony_ci * updated to start at new_index. This is faster than calling
12162306a36Sopenharmony_ci * interval_tree_span_iter_first() as it can avoid full searches in several
12262306a36Sopenharmony_ci * cases where the iterator is already set.
12362306a36Sopenharmony_ci */
12462306a36Sopenharmony_civoid interval_tree_span_iter_advance(struct interval_tree_span_iter *iter,
12562306a36Sopenharmony_ci				     struct rb_root_cached *itree,
12662306a36Sopenharmony_ci				     unsigned long new_index)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	if (iter->is_hole == -1)
12962306a36Sopenharmony_ci		return;
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	iter->first_index = new_index;
13262306a36Sopenharmony_ci	if (new_index > iter->last_index) {
13362306a36Sopenharmony_ci		iter->is_hole = -1;
13462306a36Sopenharmony_ci		return;
13562306a36Sopenharmony_ci	}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	/* Rely on the union aliasing hole/used */
13862306a36Sopenharmony_ci	if (iter->start_hole <= new_index && new_index <= iter->last_hole) {
13962306a36Sopenharmony_ci		iter->start_hole = new_index;
14062306a36Sopenharmony_ci		return;
14162306a36Sopenharmony_ci	}
14262306a36Sopenharmony_ci	if (new_index == iter->last_hole + 1)
14362306a36Sopenharmony_ci		interval_tree_span_iter_next(iter);
14462306a36Sopenharmony_ci	else
14562306a36Sopenharmony_ci		interval_tree_span_iter_first(iter, itree, new_index,
14662306a36Sopenharmony_ci					      iter->last_index);
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(interval_tree_span_iter_advance);
14962306a36Sopenharmony_ci#endif
150