162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2018-2023 Oracle.  All Rights Reserved.
462306a36Sopenharmony_ci * Author: Darrick J. Wong <djwong@kernel.org>
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci#include "xfs.h"
762306a36Sopenharmony_ci#include "xfs_fs.h"
862306a36Sopenharmony_ci#include "xfs_shared.h"
962306a36Sopenharmony_ci#include "xfs_bit.h"
1062306a36Sopenharmony_ci#include "xfs_format.h"
1162306a36Sopenharmony_ci#include "xfs_trans_resv.h"
1262306a36Sopenharmony_ci#include "xfs_mount.h"
1362306a36Sopenharmony_ci#include "xfs_btree.h"
1462306a36Sopenharmony_ci#include "scrub/scrub.h"
1562306a36Sopenharmony_ci#include "scrub/bitmap.h"
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include <linux/interval_tree_generic.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistruct xbitmap_node {
2062306a36Sopenharmony_ci	struct rb_node	bn_rbnode;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	/* First set bit of this interval and subtree. */
2362306a36Sopenharmony_ci	uint64_t	bn_start;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	/* Last set bit of this interval. */
2662306a36Sopenharmony_ci	uint64_t	bn_last;
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	/* Last set bit of this subtree.  Do not touch this. */
2962306a36Sopenharmony_ci	uint64_t	__bn_subtree_last;
3062306a36Sopenharmony_ci};
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/* Define our own interval tree type with uint64_t parameters. */
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define START(node) ((node)->bn_start)
3562306a36Sopenharmony_ci#define LAST(node)  ((node)->bn_last)
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/*
3862306a36Sopenharmony_ci * These functions are defined by the INTERVAL_TREE_DEFINE macro, but we'll
3962306a36Sopenharmony_ci * forward-declare them anyway for clarity.
4062306a36Sopenharmony_ci */
4162306a36Sopenharmony_cistatic inline void
4262306a36Sopenharmony_cixbitmap_tree_insert(struct xbitmap_node *node, struct rb_root_cached *root);
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic inline void
4562306a36Sopenharmony_cixbitmap_tree_remove(struct xbitmap_node *node, struct rb_root_cached *root);
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic inline struct xbitmap_node *
4862306a36Sopenharmony_cixbitmap_tree_iter_first(struct rb_root_cached *root, uint64_t start,
4962306a36Sopenharmony_ci			uint64_t last);
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistatic inline struct xbitmap_node *
5262306a36Sopenharmony_cixbitmap_tree_iter_next(struct xbitmap_node *node, uint64_t start,
5362306a36Sopenharmony_ci		       uint64_t last);
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ciINTERVAL_TREE_DEFINE(struct xbitmap_node, bn_rbnode, uint64_t,
5662306a36Sopenharmony_ci		__bn_subtree_last, START, LAST, static inline, xbitmap_tree)
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci/* Iterate each interval of a bitmap.  Do not change the bitmap. */
5962306a36Sopenharmony_ci#define for_each_xbitmap_extent(bn, bitmap) \
6062306a36Sopenharmony_ci	for ((bn) = rb_entry_safe(rb_first(&(bitmap)->xb_root.rb_root), \
6162306a36Sopenharmony_ci				   struct xbitmap_node, bn_rbnode); \
6262306a36Sopenharmony_ci	     (bn) != NULL; \
6362306a36Sopenharmony_ci	     (bn) = rb_entry_safe(rb_next(&(bn)->bn_rbnode), \
6462306a36Sopenharmony_ci				   struct xbitmap_node, bn_rbnode))
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci/* Clear a range of this bitmap. */
6762306a36Sopenharmony_ciint
6862306a36Sopenharmony_cixbitmap_clear(
6962306a36Sopenharmony_ci	struct xbitmap		*bitmap,
7062306a36Sopenharmony_ci	uint64_t		start,
7162306a36Sopenharmony_ci	uint64_t		len)
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	struct xbitmap_node	*bn;
7462306a36Sopenharmony_ci	struct xbitmap_node	*new_bn;
7562306a36Sopenharmony_ci	uint64_t		last = start + len - 1;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	while ((bn = xbitmap_tree_iter_first(&bitmap->xb_root, start, last))) {
7862306a36Sopenharmony_ci		if (bn->bn_start < start && bn->bn_last > last) {
7962306a36Sopenharmony_ci			uint64_t	old_last = bn->bn_last;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci			/* overlaps with the entire clearing range */
8262306a36Sopenharmony_ci			xbitmap_tree_remove(bn, &bitmap->xb_root);
8362306a36Sopenharmony_ci			bn->bn_last = start - 1;
8462306a36Sopenharmony_ci			xbitmap_tree_insert(bn, &bitmap->xb_root);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci			/* add an extent */
8762306a36Sopenharmony_ci			new_bn = kmalloc(sizeof(struct xbitmap_node),
8862306a36Sopenharmony_ci					XCHK_GFP_FLAGS);
8962306a36Sopenharmony_ci			if (!new_bn)
9062306a36Sopenharmony_ci				return -ENOMEM;
9162306a36Sopenharmony_ci			new_bn->bn_start = last + 1;
9262306a36Sopenharmony_ci			new_bn->bn_last = old_last;
9362306a36Sopenharmony_ci			xbitmap_tree_insert(new_bn, &bitmap->xb_root);
9462306a36Sopenharmony_ci		} else if (bn->bn_start < start) {
9562306a36Sopenharmony_ci			/* overlaps with the left side of the clearing range */
9662306a36Sopenharmony_ci			xbitmap_tree_remove(bn, &bitmap->xb_root);
9762306a36Sopenharmony_ci			bn->bn_last = start - 1;
9862306a36Sopenharmony_ci			xbitmap_tree_insert(bn, &bitmap->xb_root);
9962306a36Sopenharmony_ci		} else if (bn->bn_last > last) {
10062306a36Sopenharmony_ci			/* overlaps with the right side of the clearing range */
10162306a36Sopenharmony_ci			xbitmap_tree_remove(bn, &bitmap->xb_root);
10262306a36Sopenharmony_ci			bn->bn_start = last + 1;
10362306a36Sopenharmony_ci			xbitmap_tree_insert(bn, &bitmap->xb_root);
10462306a36Sopenharmony_ci			break;
10562306a36Sopenharmony_ci		} else {
10662306a36Sopenharmony_ci			/* in the middle of the clearing range */
10762306a36Sopenharmony_ci			xbitmap_tree_remove(bn, &bitmap->xb_root);
10862306a36Sopenharmony_ci			kfree(bn);
10962306a36Sopenharmony_ci		}
11062306a36Sopenharmony_ci	}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	return 0;
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci/* Set a range of this bitmap. */
11662306a36Sopenharmony_ciint
11762306a36Sopenharmony_cixbitmap_set(
11862306a36Sopenharmony_ci	struct xbitmap		*bitmap,
11962306a36Sopenharmony_ci	uint64_t		start,
12062306a36Sopenharmony_ci	uint64_t		len)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	struct xbitmap_node	*left;
12362306a36Sopenharmony_ci	struct xbitmap_node	*right;
12462306a36Sopenharmony_ci	uint64_t		last = start + len - 1;
12562306a36Sopenharmony_ci	int			error;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	/* Is this whole range already set? */
12862306a36Sopenharmony_ci	left = xbitmap_tree_iter_first(&bitmap->xb_root, start, last);
12962306a36Sopenharmony_ci	if (left && left->bn_start <= start && left->bn_last >= last)
13062306a36Sopenharmony_ci		return 0;
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	/* Clear out everything in the range we want to set. */
13362306a36Sopenharmony_ci	error = xbitmap_clear(bitmap, start, len);
13462306a36Sopenharmony_ci	if (error)
13562306a36Sopenharmony_ci		return error;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	/* Do we have a left-adjacent extent? */
13862306a36Sopenharmony_ci	left = xbitmap_tree_iter_first(&bitmap->xb_root, start - 1, start - 1);
13962306a36Sopenharmony_ci	ASSERT(!left || left->bn_last + 1 == start);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	/* Do we have a right-adjacent extent? */
14262306a36Sopenharmony_ci	right = xbitmap_tree_iter_first(&bitmap->xb_root, last + 1, last + 1);
14362306a36Sopenharmony_ci	ASSERT(!right || right->bn_start == last + 1);
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	if (left && right) {
14662306a36Sopenharmony_ci		/* combine left and right adjacent extent */
14762306a36Sopenharmony_ci		xbitmap_tree_remove(left, &bitmap->xb_root);
14862306a36Sopenharmony_ci		xbitmap_tree_remove(right, &bitmap->xb_root);
14962306a36Sopenharmony_ci		left->bn_last = right->bn_last;
15062306a36Sopenharmony_ci		xbitmap_tree_insert(left, &bitmap->xb_root);
15162306a36Sopenharmony_ci		kfree(right);
15262306a36Sopenharmony_ci	} else if (left) {
15362306a36Sopenharmony_ci		/* combine with left extent */
15462306a36Sopenharmony_ci		xbitmap_tree_remove(left, &bitmap->xb_root);
15562306a36Sopenharmony_ci		left->bn_last = last;
15662306a36Sopenharmony_ci		xbitmap_tree_insert(left, &bitmap->xb_root);
15762306a36Sopenharmony_ci	} else if (right) {
15862306a36Sopenharmony_ci		/* combine with right extent */
15962306a36Sopenharmony_ci		xbitmap_tree_remove(right, &bitmap->xb_root);
16062306a36Sopenharmony_ci		right->bn_start = start;
16162306a36Sopenharmony_ci		xbitmap_tree_insert(right, &bitmap->xb_root);
16262306a36Sopenharmony_ci	} else {
16362306a36Sopenharmony_ci		/* add an extent */
16462306a36Sopenharmony_ci		left = kmalloc(sizeof(struct xbitmap_node), XCHK_GFP_FLAGS);
16562306a36Sopenharmony_ci		if (!left)
16662306a36Sopenharmony_ci			return -ENOMEM;
16762306a36Sopenharmony_ci		left->bn_start = start;
16862306a36Sopenharmony_ci		left->bn_last = last;
16962306a36Sopenharmony_ci		xbitmap_tree_insert(left, &bitmap->xb_root);
17062306a36Sopenharmony_ci	}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	return 0;
17362306a36Sopenharmony_ci}
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci/* Free everything related to this bitmap. */
17662306a36Sopenharmony_civoid
17762306a36Sopenharmony_cixbitmap_destroy(
17862306a36Sopenharmony_ci	struct xbitmap		*bitmap)
17962306a36Sopenharmony_ci{
18062306a36Sopenharmony_ci	struct xbitmap_node	*bn;
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	while ((bn = xbitmap_tree_iter_first(&bitmap->xb_root, 0, -1ULL))) {
18362306a36Sopenharmony_ci		xbitmap_tree_remove(bn, &bitmap->xb_root);
18462306a36Sopenharmony_ci		kfree(bn);
18562306a36Sopenharmony_ci	}
18662306a36Sopenharmony_ci}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci/* Set up a per-AG block bitmap. */
18962306a36Sopenharmony_civoid
19062306a36Sopenharmony_cixbitmap_init(
19162306a36Sopenharmony_ci	struct xbitmap		*bitmap)
19262306a36Sopenharmony_ci{
19362306a36Sopenharmony_ci	bitmap->xb_root = RB_ROOT_CACHED;
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci/*
19762306a36Sopenharmony_ci * Remove all the blocks mentioned in @sub from the extents in @bitmap.
19862306a36Sopenharmony_ci *
19962306a36Sopenharmony_ci * The intent is that callers will iterate the rmapbt for all of its records
20062306a36Sopenharmony_ci * for a given owner to generate @bitmap; and iterate all the blocks of the
20162306a36Sopenharmony_ci * metadata structures that are not being rebuilt and have the same rmapbt
20262306a36Sopenharmony_ci * owner to generate @sub.  This routine subtracts all the extents
20362306a36Sopenharmony_ci * mentioned in sub from all the extents linked in @bitmap, which leaves
20462306a36Sopenharmony_ci * @bitmap as the list of blocks that are not accounted for, which we assume
20562306a36Sopenharmony_ci * are the dead blocks of the old metadata structure.  The blocks mentioned in
20662306a36Sopenharmony_ci * @bitmap can be reaped.
20762306a36Sopenharmony_ci *
20862306a36Sopenharmony_ci * This is the logical equivalent of bitmap &= ~sub.
20962306a36Sopenharmony_ci */
21062306a36Sopenharmony_ciint
21162306a36Sopenharmony_cixbitmap_disunion(
21262306a36Sopenharmony_ci	struct xbitmap		*bitmap,
21362306a36Sopenharmony_ci	struct xbitmap		*sub)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci	struct xbitmap_node	*bn;
21662306a36Sopenharmony_ci	int			error;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	if (xbitmap_empty(bitmap) || xbitmap_empty(sub))
21962306a36Sopenharmony_ci		return 0;
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	for_each_xbitmap_extent(bn, sub) {
22262306a36Sopenharmony_ci		error = xbitmap_clear(bitmap, bn->bn_start,
22362306a36Sopenharmony_ci				bn->bn_last - bn->bn_start + 1);
22462306a36Sopenharmony_ci		if (error)
22562306a36Sopenharmony_ci			return error;
22662306a36Sopenharmony_ci	}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	return 0;
22962306a36Sopenharmony_ci}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci/*
23262306a36Sopenharmony_ci * Record all btree blocks seen while iterating all records of a btree.
23362306a36Sopenharmony_ci *
23462306a36Sopenharmony_ci * We know that the btree query_all function starts at the left edge and walks
23562306a36Sopenharmony_ci * towards the right edge of the tree.  Therefore, we know that we can walk up
23662306a36Sopenharmony_ci * the btree cursor towards the root; if the pointer for a given level points
23762306a36Sopenharmony_ci * to the first record/key in that block, we haven't seen this block before;
23862306a36Sopenharmony_ci * and therefore we need to remember that we saw this block in the btree.
23962306a36Sopenharmony_ci *
24062306a36Sopenharmony_ci * So if our btree is:
24162306a36Sopenharmony_ci *
24262306a36Sopenharmony_ci *    4
24362306a36Sopenharmony_ci *  / | \
24462306a36Sopenharmony_ci * 1  2  3
24562306a36Sopenharmony_ci *
24662306a36Sopenharmony_ci * Pretend for this example that each leaf block has 100 btree records.  For
24762306a36Sopenharmony_ci * the first btree record, we'll observe that bc_levels[0].ptr == 1, so we
24862306a36Sopenharmony_ci * record that we saw block 1.  Then we observe that bc_levels[1].ptr == 1, so
24962306a36Sopenharmony_ci * we record block 4.  The list is [1, 4].
25062306a36Sopenharmony_ci *
25162306a36Sopenharmony_ci * For the second btree record, we see that bc_levels[0].ptr == 2, so we exit
25262306a36Sopenharmony_ci * the loop.  The list remains [1, 4].
25362306a36Sopenharmony_ci *
25462306a36Sopenharmony_ci * For the 101st btree record, we've moved onto leaf block 2.  Now
25562306a36Sopenharmony_ci * bc_levels[0].ptr == 1 again, so we record that we saw block 2.  We see that
25662306a36Sopenharmony_ci * bc_levels[1].ptr == 2, so we exit the loop.  The list is now [1, 4, 2].
25762306a36Sopenharmony_ci *
25862306a36Sopenharmony_ci * For the 102nd record, bc_levels[0].ptr == 2, so we continue.
25962306a36Sopenharmony_ci *
26062306a36Sopenharmony_ci * For the 201st record, we've moved on to leaf block 3.
26162306a36Sopenharmony_ci * bc_levels[0].ptr == 1, so we add 3 to the list.  Now it is [1, 4, 2, 3].
26262306a36Sopenharmony_ci *
26362306a36Sopenharmony_ci * For the 300th record we just exit, with the list being [1, 4, 2, 3].
26462306a36Sopenharmony_ci */
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci/* Mark a btree block to the agblock bitmap. */
26762306a36Sopenharmony_ciSTATIC int
26862306a36Sopenharmony_cixagb_bitmap_visit_btblock(
26962306a36Sopenharmony_ci	struct xfs_btree_cur	*cur,
27062306a36Sopenharmony_ci	int			level,
27162306a36Sopenharmony_ci	void			*priv)
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	struct xagb_bitmap	*bitmap = priv;
27462306a36Sopenharmony_ci	struct xfs_buf		*bp;
27562306a36Sopenharmony_ci	xfs_fsblock_t		fsbno;
27662306a36Sopenharmony_ci	xfs_agblock_t		agbno;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	xfs_btree_get_block(cur, level, &bp);
27962306a36Sopenharmony_ci	if (!bp)
28062306a36Sopenharmony_ci		return 0;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, xfs_buf_daddr(bp));
28362306a36Sopenharmony_ci	agbno = XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	return xagb_bitmap_set(bitmap, agbno, 1);
28662306a36Sopenharmony_ci}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci/* Mark all (per-AG) btree blocks in the agblock bitmap. */
28962306a36Sopenharmony_ciint
29062306a36Sopenharmony_cixagb_bitmap_set_btblocks(
29162306a36Sopenharmony_ci	struct xagb_bitmap	*bitmap,
29262306a36Sopenharmony_ci	struct xfs_btree_cur	*cur)
29362306a36Sopenharmony_ci{
29462306a36Sopenharmony_ci	return xfs_btree_visit_blocks(cur, xagb_bitmap_visit_btblock,
29562306a36Sopenharmony_ci			XFS_BTREE_VISIT_ALL, bitmap);
29662306a36Sopenharmony_ci}
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci/*
29962306a36Sopenharmony_ci * Record all the buffers pointed to by the btree cursor.  Callers already
30062306a36Sopenharmony_ci * engaged in a btree walk should call this function to capture the list of
30162306a36Sopenharmony_ci * blocks going from the leaf towards the root.
30262306a36Sopenharmony_ci */
30362306a36Sopenharmony_ciint
30462306a36Sopenharmony_cixagb_bitmap_set_btcur_path(
30562306a36Sopenharmony_ci	struct xagb_bitmap	*bitmap,
30662306a36Sopenharmony_ci	struct xfs_btree_cur	*cur)
30762306a36Sopenharmony_ci{
30862306a36Sopenharmony_ci	int			i;
30962306a36Sopenharmony_ci	int			error;
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	for (i = 0; i < cur->bc_nlevels && cur->bc_levels[i].ptr == 1; i++) {
31262306a36Sopenharmony_ci		error = xagb_bitmap_visit_btblock(cur, i, bitmap);
31362306a36Sopenharmony_ci		if (error)
31462306a36Sopenharmony_ci			return error;
31562306a36Sopenharmony_ci	}
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	return 0;
31862306a36Sopenharmony_ci}
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci/* How many bits are set in this bitmap? */
32162306a36Sopenharmony_ciuint64_t
32262306a36Sopenharmony_cixbitmap_hweight(
32362306a36Sopenharmony_ci	struct xbitmap		*bitmap)
32462306a36Sopenharmony_ci{
32562306a36Sopenharmony_ci	struct xbitmap_node	*bn;
32662306a36Sopenharmony_ci	uint64_t		ret = 0;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	for_each_xbitmap_extent(bn, bitmap)
32962306a36Sopenharmony_ci		ret += bn->bn_last - bn->bn_start + 1;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	return ret;
33262306a36Sopenharmony_ci}
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci/* Call a function for every run of set bits in this bitmap. */
33562306a36Sopenharmony_ciint
33662306a36Sopenharmony_cixbitmap_walk(
33762306a36Sopenharmony_ci	struct xbitmap		*bitmap,
33862306a36Sopenharmony_ci	xbitmap_walk_fn		fn,
33962306a36Sopenharmony_ci	void			*priv)
34062306a36Sopenharmony_ci{
34162306a36Sopenharmony_ci	struct xbitmap_node	*bn;
34262306a36Sopenharmony_ci	int			error = 0;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	for_each_xbitmap_extent(bn, bitmap) {
34562306a36Sopenharmony_ci		error = fn(bn->bn_start, bn->bn_last - bn->bn_start + 1, priv);
34662306a36Sopenharmony_ci		if (error)
34762306a36Sopenharmony_ci			break;
34862306a36Sopenharmony_ci	}
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	return error;
35162306a36Sopenharmony_ci}
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci/* Does this bitmap have no bits set at all? */
35462306a36Sopenharmony_cibool
35562306a36Sopenharmony_cixbitmap_empty(
35662306a36Sopenharmony_ci	struct xbitmap		*bitmap)
35762306a36Sopenharmony_ci{
35862306a36Sopenharmony_ci	return bitmap->xb_root.rb_root.rb_node == NULL;
35962306a36Sopenharmony_ci}
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci/* Is the start of the range set or clear?  And for how long? */
36262306a36Sopenharmony_cibool
36362306a36Sopenharmony_cixbitmap_test(
36462306a36Sopenharmony_ci	struct xbitmap		*bitmap,
36562306a36Sopenharmony_ci	uint64_t		start,
36662306a36Sopenharmony_ci	uint64_t		*len)
36762306a36Sopenharmony_ci{
36862306a36Sopenharmony_ci	struct xbitmap_node	*bn;
36962306a36Sopenharmony_ci	uint64_t		last = start + *len - 1;
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	bn = xbitmap_tree_iter_first(&bitmap->xb_root, start, last);
37262306a36Sopenharmony_ci	if (!bn)
37362306a36Sopenharmony_ci		return false;
37462306a36Sopenharmony_ci	if (bn->bn_start <= start) {
37562306a36Sopenharmony_ci		if (bn->bn_last < last)
37662306a36Sopenharmony_ci			*len = bn->bn_last - start + 1;
37762306a36Sopenharmony_ci		return true;
37862306a36Sopenharmony_ci	}
37962306a36Sopenharmony_ci	*len = bn->bn_start - start;
38062306a36Sopenharmony_ci	return false;
38162306a36Sopenharmony_ci}
382