xref: /kernel/linux/linux-6.6/fs/xfs/libxfs/xfs_btree.h (revision 62306a36)
162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
462306a36Sopenharmony_ci * All Rights Reserved.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci#ifndef __XFS_BTREE_H__
762306a36Sopenharmony_ci#define	__XFS_BTREE_H__
862306a36Sopenharmony_ci
962306a36Sopenharmony_cistruct xfs_buf;
1062306a36Sopenharmony_cistruct xfs_inode;
1162306a36Sopenharmony_cistruct xfs_mount;
1262306a36Sopenharmony_cistruct xfs_trans;
1362306a36Sopenharmony_cistruct xfs_ifork;
1462306a36Sopenharmony_cistruct xfs_perag;
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/*
1762306a36Sopenharmony_ci * Generic key, ptr and record wrapper structures.
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * These are disk format structures, and are converted where necessary
2062306a36Sopenharmony_ci * by the btree specific code that needs to interpret them.
2162306a36Sopenharmony_ci */
2262306a36Sopenharmony_ciunion xfs_btree_ptr {
2362306a36Sopenharmony_ci	__be32			s;	/* short form ptr */
2462306a36Sopenharmony_ci	__be64			l;	/* long form ptr */
2562306a36Sopenharmony_ci};
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/*
2862306a36Sopenharmony_ci * The in-core btree key.  Overlapping btrees actually store two keys
2962306a36Sopenharmony_ci * per pointer, so we reserve enough memory to hold both.  The __*bigkey
3062306a36Sopenharmony_ci * items should never be accessed directly.
3162306a36Sopenharmony_ci */
3262306a36Sopenharmony_ciunion xfs_btree_key {
3362306a36Sopenharmony_ci	struct xfs_bmbt_key		bmbt;
3462306a36Sopenharmony_ci	xfs_bmdr_key_t			bmbr;	/* bmbt root block */
3562306a36Sopenharmony_ci	xfs_alloc_key_t			alloc;
3662306a36Sopenharmony_ci	struct xfs_inobt_key		inobt;
3762306a36Sopenharmony_ci	struct xfs_rmap_key		rmap;
3862306a36Sopenharmony_ci	struct xfs_rmap_key		__rmap_bigkey[2];
3962306a36Sopenharmony_ci	struct xfs_refcount_key		refc;
4062306a36Sopenharmony_ci};
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ciunion xfs_btree_rec {
4362306a36Sopenharmony_ci	struct xfs_bmbt_rec		bmbt;
4462306a36Sopenharmony_ci	xfs_bmdr_rec_t			bmbr;	/* bmbt root block */
4562306a36Sopenharmony_ci	struct xfs_alloc_rec		alloc;
4662306a36Sopenharmony_ci	struct xfs_inobt_rec		inobt;
4762306a36Sopenharmony_ci	struct xfs_rmap_rec		rmap;
4862306a36Sopenharmony_ci	struct xfs_refcount_rec		refc;
4962306a36Sopenharmony_ci};
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/*
5262306a36Sopenharmony_ci * This nonsense is to make -wlint happy.
5362306a36Sopenharmony_ci */
5462306a36Sopenharmony_ci#define	XFS_LOOKUP_EQ	((xfs_lookup_t)XFS_LOOKUP_EQi)
5562306a36Sopenharmony_ci#define	XFS_LOOKUP_LE	((xfs_lookup_t)XFS_LOOKUP_LEi)
5662306a36Sopenharmony_ci#define	XFS_LOOKUP_GE	((xfs_lookup_t)XFS_LOOKUP_GEi)
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci#define	XFS_BTNUM_BNO	((xfs_btnum_t)XFS_BTNUM_BNOi)
5962306a36Sopenharmony_ci#define	XFS_BTNUM_CNT	((xfs_btnum_t)XFS_BTNUM_CNTi)
6062306a36Sopenharmony_ci#define	XFS_BTNUM_BMAP	((xfs_btnum_t)XFS_BTNUM_BMAPi)
6162306a36Sopenharmony_ci#define	XFS_BTNUM_INO	((xfs_btnum_t)XFS_BTNUM_INOi)
6262306a36Sopenharmony_ci#define	XFS_BTNUM_FINO	((xfs_btnum_t)XFS_BTNUM_FINOi)
6362306a36Sopenharmony_ci#define	XFS_BTNUM_RMAP	((xfs_btnum_t)XFS_BTNUM_RMAPi)
6462306a36Sopenharmony_ci#define	XFS_BTNUM_REFC	((xfs_btnum_t)XFS_BTNUM_REFCi)
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ciuint32_t xfs_btree_magic(int crc, xfs_btnum_t btnum);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/*
6962306a36Sopenharmony_ci * For logging record fields.
7062306a36Sopenharmony_ci */
7162306a36Sopenharmony_ci#define	XFS_BB_MAGIC		(1u << 0)
7262306a36Sopenharmony_ci#define	XFS_BB_LEVEL		(1u << 1)
7362306a36Sopenharmony_ci#define	XFS_BB_NUMRECS		(1u << 2)
7462306a36Sopenharmony_ci#define	XFS_BB_LEFTSIB		(1u << 3)
7562306a36Sopenharmony_ci#define	XFS_BB_RIGHTSIB		(1u << 4)
7662306a36Sopenharmony_ci#define	XFS_BB_BLKNO		(1u << 5)
7762306a36Sopenharmony_ci#define	XFS_BB_LSN		(1u << 6)
7862306a36Sopenharmony_ci#define	XFS_BB_UUID		(1u << 7)
7962306a36Sopenharmony_ci#define	XFS_BB_OWNER		(1u << 8)
8062306a36Sopenharmony_ci#define	XFS_BB_NUM_BITS		5
8162306a36Sopenharmony_ci#define	XFS_BB_ALL_BITS		((1u << XFS_BB_NUM_BITS) - 1)
8262306a36Sopenharmony_ci#define	XFS_BB_NUM_BITS_CRC	9
8362306a36Sopenharmony_ci#define	XFS_BB_ALL_BITS_CRC	((1u << XFS_BB_NUM_BITS_CRC) - 1)
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci/*
8662306a36Sopenharmony_ci * Generic stats interface
8762306a36Sopenharmony_ci */
8862306a36Sopenharmony_ci#define XFS_BTREE_STATS_INC(cur, stat)	\
8962306a36Sopenharmony_ci	XFS_STATS_INC_OFF((cur)->bc_mp, (cur)->bc_statoff + __XBTS_ ## stat)
9062306a36Sopenharmony_ci#define XFS_BTREE_STATS_ADD(cur, stat, val)	\
9162306a36Sopenharmony_ci	XFS_STATS_ADD_OFF((cur)->bc_mp, (cur)->bc_statoff + __XBTS_ ## stat, val)
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cienum xbtree_key_contig {
9462306a36Sopenharmony_ci	XBTREE_KEY_GAP = 0,
9562306a36Sopenharmony_ci	XBTREE_KEY_CONTIGUOUS,
9662306a36Sopenharmony_ci	XBTREE_KEY_OVERLAP,
9762306a36Sopenharmony_ci};
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci/*
10062306a36Sopenharmony_ci * Decide if these two numeric btree key fields are contiguous, overlapping,
10162306a36Sopenharmony_ci * or if there's a gap between them.  @x should be the field from the high
10262306a36Sopenharmony_ci * key and @y should be the field from the low key.
10362306a36Sopenharmony_ci */
10462306a36Sopenharmony_cistatic inline enum xbtree_key_contig xbtree_key_contig(uint64_t x, uint64_t y)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	x++;
10762306a36Sopenharmony_ci	if (x < y)
10862306a36Sopenharmony_ci		return XBTREE_KEY_GAP;
10962306a36Sopenharmony_ci	if (x == y)
11062306a36Sopenharmony_ci		return XBTREE_KEY_CONTIGUOUS;
11162306a36Sopenharmony_ci	return XBTREE_KEY_OVERLAP;
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_cistruct xfs_btree_ops {
11562306a36Sopenharmony_ci	/* size of the key and record structures */
11662306a36Sopenharmony_ci	size_t	key_len;
11762306a36Sopenharmony_ci	size_t	rec_len;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	/* cursor operations */
12062306a36Sopenharmony_ci	struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *);
12162306a36Sopenharmony_ci	void	(*update_cursor)(struct xfs_btree_cur *src,
12262306a36Sopenharmony_ci				 struct xfs_btree_cur *dst);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	/* update btree root pointer */
12562306a36Sopenharmony_ci	void	(*set_root)(struct xfs_btree_cur *cur,
12662306a36Sopenharmony_ci			    const union xfs_btree_ptr *nptr, int level_change);
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	/* block allocation / freeing */
12962306a36Sopenharmony_ci	int	(*alloc_block)(struct xfs_btree_cur *cur,
13062306a36Sopenharmony_ci			       const union xfs_btree_ptr *start_bno,
13162306a36Sopenharmony_ci			       union xfs_btree_ptr *new_bno,
13262306a36Sopenharmony_ci			       int *stat);
13362306a36Sopenharmony_ci	int	(*free_block)(struct xfs_btree_cur *cur, struct xfs_buf *bp);
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	/* update last record information */
13662306a36Sopenharmony_ci	void	(*update_lastrec)(struct xfs_btree_cur *cur,
13762306a36Sopenharmony_ci				  const struct xfs_btree_block *block,
13862306a36Sopenharmony_ci				  const union xfs_btree_rec *rec,
13962306a36Sopenharmony_ci				  int ptr, int reason);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	/* records in block/level */
14262306a36Sopenharmony_ci	int	(*get_minrecs)(struct xfs_btree_cur *cur, int level);
14362306a36Sopenharmony_ci	int	(*get_maxrecs)(struct xfs_btree_cur *cur, int level);
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	/* records on disk.  Matter for the root in inode case. */
14662306a36Sopenharmony_ci	int	(*get_dmaxrecs)(struct xfs_btree_cur *cur, int level);
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	/* init values of btree structures */
14962306a36Sopenharmony_ci	void	(*init_key_from_rec)(union xfs_btree_key *key,
15062306a36Sopenharmony_ci				     const union xfs_btree_rec *rec);
15162306a36Sopenharmony_ci	void	(*init_rec_from_cur)(struct xfs_btree_cur *cur,
15262306a36Sopenharmony_ci				     union xfs_btree_rec *rec);
15362306a36Sopenharmony_ci	void	(*init_ptr_from_cur)(struct xfs_btree_cur *cur,
15462306a36Sopenharmony_ci				     union xfs_btree_ptr *ptr);
15562306a36Sopenharmony_ci	void	(*init_high_key_from_rec)(union xfs_btree_key *key,
15662306a36Sopenharmony_ci					  const union xfs_btree_rec *rec);
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	/* difference between key value and cursor value */
15962306a36Sopenharmony_ci	int64_t (*key_diff)(struct xfs_btree_cur *cur,
16062306a36Sopenharmony_ci			    const union xfs_btree_key *key);
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	/*
16362306a36Sopenharmony_ci	 * Difference between key2 and key1 -- positive if key1 > key2,
16462306a36Sopenharmony_ci	 * negative if key1 < key2, and zero if equal.  If the @mask parameter
16562306a36Sopenharmony_ci	 * is non NULL, each key field to be used in the comparison must
16662306a36Sopenharmony_ci	 * contain a nonzero value.
16762306a36Sopenharmony_ci	 */
16862306a36Sopenharmony_ci	int64_t (*diff_two_keys)(struct xfs_btree_cur *cur,
16962306a36Sopenharmony_ci				 const union xfs_btree_key *key1,
17062306a36Sopenharmony_ci				 const union xfs_btree_key *key2,
17162306a36Sopenharmony_ci				 const union xfs_btree_key *mask);
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	const struct xfs_buf_ops	*buf_ops;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	/* check that k1 is lower than k2 */
17662306a36Sopenharmony_ci	int	(*keys_inorder)(struct xfs_btree_cur *cur,
17762306a36Sopenharmony_ci				const union xfs_btree_key *k1,
17862306a36Sopenharmony_ci				const union xfs_btree_key *k2);
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	/* check that r1 is lower than r2 */
18162306a36Sopenharmony_ci	int	(*recs_inorder)(struct xfs_btree_cur *cur,
18262306a36Sopenharmony_ci				const union xfs_btree_rec *r1,
18362306a36Sopenharmony_ci				const union xfs_btree_rec *r2);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	/*
18662306a36Sopenharmony_ci	 * Are these two btree keys immediately adjacent?
18762306a36Sopenharmony_ci	 *
18862306a36Sopenharmony_ci	 * Given two btree keys @key1 and @key2, decide if it is impossible for
18962306a36Sopenharmony_ci	 * there to be a third btree key K satisfying the relationship
19062306a36Sopenharmony_ci	 * @key1 < K < @key2.  To determine if two btree records are
19162306a36Sopenharmony_ci	 * immediately adjacent, @key1 should be the high key of the first
19262306a36Sopenharmony_ci	 * record and @key2 should be the low key of the second record.
19362306a36Sopenharmony_ci	 * If the @mask parameter is non NULL, each key field to be used in the
19462306a36Sopenharmony_ci	 * comparison must contain a nonzero value.
19562306a36Sopenharmony_ci	 */
19662306a36Sopenharmony_ci	enum xbtree_key_contig (*keys_contiguous)(struct xfs_btree_cur *cur,
19762306a36Sopenharmony_ci			       const union xfs_btree_key *key1,
19862306a36Sopenharmony_ci			       const union xfs_btree_key *key2,
19962306a36Sopenharmony_ci			       const union xfs_btree_key *mask);
20062306a36Sopenharmony_ci};
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci/*
20362306a36Sopenharmony_ci * Reasons for the update_lastrec method to be called.
20462306a36Sopenharmony_ci */
20562306a36Sopenharmony_ci#define LASTREC_UPDATE	0
20662306a36Sopenharmony_ci#define LASTREC_INSREC	1
20762306a36Sopenharmony_ci#define LASTREC_DELREC	2
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ciunion xfs_btree_irec {
21162306a36Sopenharmony_ci	struct xfs_alloc_rec_incore	a;
21262306a36Sopenharmony_ci	struct xfs_bmbt_irec		b;
21362306a36Sopenharmony_ci	struct xfs_inobt_rec_incore	i;
21462306a36Sopenharmony_ci	struct xfs_rmap_irec		r;
21562306a36Sopenharmony_ci	struct xfs_refcount_irec	rc;
21662306a36Sopenharmony_ci};
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci/* Per-AG btree information. */
21962306a36Sopenharmony_cistruct xfs_btree_cur_ag {
22062306a36Sopenharmony_ci	struct xfs_perag		*pag;
22162306a36Sopenharmony_ci	union {
22262306a36Sopenharmony_ci		struct xfs_buf		*agbp;
22362306a36Sopenharmony_ci		struct xbtree_afakeroot	*afake;	/* for staging cursor */
22462306a36Sopenharmony_ci	};
22562306a36Sopenharmony_ci	union {
22662306a36Sopenharmony_ci		struct {
22762306a36Sopenharmony_ci			unsigned int	nr_ops;	/* # record updates */
22862306a36Sopenharmony_ci			unsigned int	shape_changes;	/* # of extent splits */
22962306a36Sopenharmony_ci		} refc;
23062306a36Sopenharmony_ci		struct {
23162306a36Sopenharmony_ci			bool		active;	/* allocation cursor state */
23262306a36Sopenharmony_ci		} abt;
23362306a36Sopenharmony_ci	};
23462306a36Sopenharmony_ci};
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci/* Btree-in-inode cursor information */
23762306a36Sopenharmony_cistruct xfs_btree_cur_ino {
23862306a36Sopenharmony_ci	struct xfs_inode		*ip;
23962306a36Sopenharmony_ci	struct xbtree_ifakeroot		*ifake;	/* for staging cursor */
24062306a36Sopenharmony_ci	int				allocated;
24162306a36Sopenharmony_ci	short				forksize;
24262306a36Sopenharmony_ci	char				whichfork;
24362306a36Sopenharmony_ci	char				flags;
24462306a36Sopenharmony_ci/* We are converting a delalloc reservation */
24562306a36Sopenharmony_ci#define	XFS_BTCUR_BMBT_WASDEL		(1 << 0)
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci/* For extent swap, ignore owner check in verifier */
24862306a36Sopenharmony_ci#define	XFS_BTCUR_BMBT_INVALID_OWNER	(1 << 1)
24962306a36Sopenharmony_ci};
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cistruct xfs_btree_level {
25262306a36Sopenharmony_ci	/* buffer pointer */
25362306a36Sopenharmony_ci	struct xfs_buf		*bp;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	/* key/record number */
25662306a36Sopenharmony_ci	uint16_t		ptr;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	/* readahead info */
25962306a36Sopenharmony_ci#define XFS_BTCUR_LEFTRA	(1 << 0) /* left sibling has been read-ahead */
26062306a36Sopenharmony_ci#define XFS_BTCUR_RIGHTRA	(1 << 1) /* right sibling has been read-ahead */
26162306a36Sopenharmony_ci	uint16_t		ra;
26262306a36Sopenharmony_ci};
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci/*
26562306a36Sopenharmony_ci * Btree cursor structure.
26662306a36Sopenharmony_ci * This collects all information needed by the btree code in one place.
26762306a36Sopenharmony_ci */
26862306a36Sopenharmony_cistruct xfs_btree_cur
26962306a36Sopenharmony_ci{
27062306a36Sopenharmony_ci	struct xfs_trans	*bc_tp;	/* transaction we're in, if any */
27162306a36Sopenharmony_ci	struct xfs_mount	*bc_mp;	/* file system mount struct */
27262306a36Sopenharmony_ci	const struct xfs_btree_ops *bc_ops;
27362306a36Sopenharmony_ci	struct kmem_cache	*bc_cache; /* cursor cache */
27462306a36Sopenharmony_ci	unsigned int		bc_flags; /* btree features - below */
27562306a36Sopenharmony_ci	xfs_btnum_t		bc_btnum; /* identifies which btree type */
27662306a36Sopenharmony_ci	union xfs_btree_irec	bc_rec;	/* current insert/search record value */
27762306a36Sopenharmony_ci	uint8_t			bc_nlevels; /* number of levels in the tree */
27862306a36Sopenharmony_ci	uint8_t			bc_maxlevels; /* maximum levels for this btree type */
27962306a36Sopenharmony_ci	int			bc_statoff; /* offset of btree stats array */
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	/*
28262306a36Sopenharmony_ci	 * Short btree pointers need an agno to be able to turn the pointers
28362306a36Sopenharmony_ci	 * into physical addresses for IO, so the btree cursor switches between
28462306a36Sopenharmony_ci	 * bc_ino and bc_ag based on whether XFS_BTREE_LONG_PTRS is set for the
28562306a36Sopenharmony_ci	 * cursor.
28662306a36Sopenharmony_ci	 */
28762306a36Sopenharmony_ci	union {
28862306a36Sopenharmony_ci		struct xfs_btree_cur_ag	bc_ag;
28962306a36Sopenharmony_ci		struct xfs_btree_cur_ino bc_ino;
29062306a36Sopenharmony_ci	};
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	/* Must be at the end of the struct! */
29362306a36Sopenharmony_ci	struct xfs_btree_level	bc_levels[];
29462306a36Sopenharmony_ci};
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci/*
29762306a36Sopenharmony_ci * Compute the size of a btree cursor that can handle a btree of a given
29862306a36Sopenharmony_ci * height.  The bc_levels array handles node and leaf blocks, so its size
29962306a36Sopenharmony_ci * is exactly nlevels.
30062306a36Sopenharmony_ci */
30162306a36Sopenharmony_cistatic inline size_t
30262306a36Sopenharmony_cixfs_btree_cur_sizeof(unsigned int nlevels)
30362306a36Sopenharmony_ci{
30462306a36Sopenharmony_ci	return struct_size_t(struct xfs_btree_cur, bc_levels, nlevels);
30562306a36Sopenharmony_ci}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci/* cursor flags */
30862306a36Sopenharmony_ci#define XFS_BTREE_LONG_PTRS		(1<<0)	/* pointers are 64bits long */
30962306a36Sopenharmony_ci#define XFS_BTREE_ROOT_IN_INODE		(1<<1)	/* root may be variable size */
31062306a36Sopenharmony_ci#define XFS_BTREE_LASTREC_UPDATE	(1<<2)	/* track last rec externally */
31162306a36Sopenharmony_ci#define XFS_BTREE_CRC_BLOCKS		(1<<3)	/* uses extended btree blocks */
31262306a36Sopenharmony_ci#define XFS_BTREE_OVERLAPPING		(1<<4)	/* overlapping intervals */
31362306a36Sopenharmony_ci/*
31462306a36Sopenharmony_ci * The root of this btree is a fakeroot structure so that we can stage a btree
31562306a36Sopenharmony_ci * rebuild without leaving it accessible via primary metadata.  The ops struct
31662306a36Sopenharmony_ci * is dynamically allocated and must be freed when the cursor is deleted.
31762306a36Sopenharmony_ci */
31862306a36Sopenharmony_ci#define XFS_BTREE_STAGING		(1<<5)
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci#define	XFS_BTREE_NOERROR	0
32162306a36Sopenharmony_ci#define	XFS_BTREE_ERROR		1
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci/*
32462306a36Sopenharmony_ci * Convert from buffer to btree block header.
32562306a36Sopenharmony_ci */
32662306a36Sopenharmony_ci#define	XFS_BUF_TO_BLOCK(bp)	((struct xfs_btree_block *)((bp)->b_addr))
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci/*
32962306a36Sopenharmony_ci * Internal long and short btree block checks.  They return NULL if the
33062306a36Sopenharmony_ci * block is ok or the address of the failed check otherwise.
33162306a36Sopenharmony_ci */
33262306a36Sopenharmony_cixfs_failaddr_t __xfs_btree_check_lblock(struct xfs_btree_cur *cur,
33362306a36Sopenharmony_ci		struct xfs_btree_block *block, int level, struct xfs_buf *bp);
33462306a36Sopenharmony_cixfs_failaddr_t __xfs_btree_check_sblock(struct xfs_btree_cur *cur,
33562306a36Sopenharmony_ci		struct xfs_btree_block *block, int level, struct xfs_buf *bp);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci/*
33862306a36Sopenharmony_ci * Check that block header is ok.
33962306a36Sopenharmony_ci */
34062306a36Sopenharmony_ciint
34162306a36Sopenharmony_cixfs_btree_check_block(
34262306a36Sopenharmony_ci	struct xfs_btree_cur	*cur,	/* btree cursor */
34362306a36Sopenharmony_ci	struct xfs_btree_block	*block,	/* generic btree block pointer */
34462306a36Sopenharmony_ci	int			level,	/* level of the btree block */
34562306a36Sopenharmony_ci	struct xfs_buf		*bp);	/* buffer containing block, if any */
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci/*
34862306a36Sopenharmony_ci * Check that (long) pointer is ok.
34962306a36Sopenharmony_ci */
35062306a36Sopenharmony_cibool					/* error (0 or EFSCORRUPTED) */
35162306a36Sopenharmony_cixfs_btree_check_lptr(
35262306a36Sopenharmony_ci	struct xfs_btree_cur	*cur,	/* btree cursor */
35362306a36Sopenharmony_ci	xfs_fsblock_t		fsbno,	/* btree block disk address */
35462306a36Sopenharmony_ci	int			level);	/* btree block level */
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci/*
35762306a36Sopenharmony_ci * Check that (short) pointer is ok.
35862306a36Sopenharmony_ci */
35962306a36Sopenharmony_cibool					/* error (0 or EFSCORRUPTED) */
36062306a36Sopenharmony_cixfs_btree_check_sptr(
36162306a36Sopenharmony_ci	struct xfs_btree_cur	*cur,	/* btree cursor */
36262306a36Sopenharmony_ci	xfs_agblock_t		agbno,	/* btree block disk address */
36362306a36Sopenharmony_ci	int			level);	/* btree block level */
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci/*
36662306a36Sopenharmony_ci * Delete the btree cursor.
36762306a36Sopenharmony_ci */
36862306a36Sopenharmony_civoid
36962306a36Sopenharmony_cixfs_btree_del_cursor(
37062306a36Sopenharmony_ci	struct xfs_btree_cur	*cur,	/* btree cursor */
37162306a36Sopenharmony_ci	int			error);	/* del because of error */
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci/*
37462306a36Sopenharmony_ci * Duplicate the btree cursor.
37562306a36Sopenharmony_ci * Allocate a new one, copy the record, re-get the buffers.
37662306a36Sopenharmony_ci */
37762306a36Sopenharmony_ciint					/* error */
37862306a36Sopenharmony_cixfs_btree_dup_cursor(
37962306a36Sopenharmony_ci	struct xfs_btree_cur		*cur,	/* input cursor */
38062306a36Sopenharmony_ci	struct xfs_btree_cur		**ncur);/* output cursor */
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci/*
38362306a36Sopenharmony_ci * Compute first and last byte offsets for the fields given.
38462306a36Sopenharmony_ci * Interprets the offsets table, which contains struct field offsets.
38562306a36Sopenharmony_ci */
38662306a36Sopenharmony_civoid
38762306a36Sopenharmony_cixfs_btree_offsets(
38862306a36Sopenharmony_ci	uint32_t		fields,	/* bitmask of fields */
38962306a36Sopenharmony_ci	const short		*offsets,/* table of field offsets */
39062306a36Sopenharmony_ci	int			nbits,	/* number of bits to inspect */
39162306a36Sopenharmony_ci	int			*first,	/* output: first byte offset */
39262306a36Sopenharmony_ci	int			*last);	/* output: last byte offset */
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci/*
39562306a36Sopenharmony_ci * Get a buffer for the block, return it read in.
39662306a36Sopenharmony_ci * Long-form addressing.
39762306a36Sopenharmony_ci */
39862306a36Sopenharmony_ciint					/* error */
39962306a36Sopenharmony_cixfs_btree_read_bufl(
40062306a36Sopenharmony_ci	struct xfs_mount	*mp,	/* file system mount point */
40162306a36Sopenharmony_ci	struct xfs_trans	*tp,	/* transaction pointer */
40262306a36Sopenharmony_ci	xfs_fsblock_t		fsbno,	/* file system block number */
40362306a36Sopenharmony_ci	struct xfs_buf		**bpp,	/* buffer for fsbno */
40462306a36Sopenharmony_ci	int			refval,	/* ref count value for buffer */
40562306a36Sopenharmony_ci	const struct xfs_buf_ops *ops);
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci/*
40862306a36Sopenharmony_ci * Read-ahead the block, don't wait for it, don't return a buffer.
40962306a36Sopenharmony_ci * Long-form addressing.
41062306a36Sopenharmony_ci */
41162306a36Sopenharmony_civoid					/* error */
41262306a36Sopenharmony_cixfs_btree_reada_bufl(
41362306a36Sopenharmony_ci	struct xfs_mount	*mp,	/* file system mount point */
41462306a36Sopenharmony_ci	xfs_fsblock_t		fsbno,	/* file system block number */
41562306a36Sopenharmony_ci	xfs_extlen_t		count,	/* count of filesystem blocks */
41662306a36Sopenharmony_ci	const struct xfs_buf_ops *ops);
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci/*
41962306a36Sopenharmony_ci * Read-ahead the block, don't wait for it, don't return a buffer.
42062306a36Sopenharmony_ci * Short-form addressing.
42162306a36Sopenharmony_ci */
42262306a36Sopenharmony_civoid					/* error */
42362306a36Sopenharmony_cixfs_btree_reada_bufs(
42462306a36Sopenharmony_ci	struct xfs_mount	*mp,	/* file system mount point */
42562306a36Sopenharmony_ci	xfs_agnumber_t		agno,	/* allocation group number */
42662306a36Sopenharmony_ci	xfs_agblock_t		agbno,	/* allocation group block number */
42762306a36Sopenharmony_ci	xfs_extlen_t		count,	/* count of filesystem blocks */
42862306a36Sopenharmony_ci	const struct xfs_buf_ops *ops);
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci/*
43162306a36Sopenharmony_ci * Initialise a new btree block header
43262306a36Sopenharmony_ci */
43362306a36Sopenharmony_civoid
43462306a36Sopenharmony_cixfs_btree_init_block(
43562306a36Sopenharmony_ci	struct xfs_mount *mp,
43662306a36Sopenharmony_ci	struct xfs_buf	*bp,
43762306a36Sopenharmony_ci	xfs_btnum_t	btnum,
43862306a36Sopenharmony_ci	__u16		level,
43962306a36Sopenharmony_ci	__u16		numrecs,
44062306a36Sopenharmony_ci	__u64		owner);
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_civoid
44362306a36Sopenharmony_cixfs_btree_init_block_int(
44462306a36Sopenharmony_ci	struct xfs_mount	*mp,
44562306a36Sopenharmony_ci	struct xfs_btree_block	*buf,
44662306a36Sopenharmony_ci	xfs_daddr_t		blkno,
44762306a36Sopenharmony_ci	xfs_btnum_t		btnum,
44862306a36Sopenharmony_ci	__u16			level,
44962306a36Sopenharmony_ci	__u16			numrecs,
45062306a36Sopenharmony_ci	__u64			owner,
45162306a36Sopenharmony_ci	unsigned int		flags);
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci/*
45462306a36Sopenharmony_ci * Common btree core entry points.
45562306a36Sopenharmony_ci */
45662306a36Sopenharmony_ciint xfs_btree_increment(struct xfs_btree_cur *, int, int *);
45762306a36Sopenharmony_ciint xfs_btree_decrement(struct xfs_btree_cur *, int, int *);
45862306a36Sopenharmony_ciint xfs_btree_lookup(struct xfs_btree_cur *, xfs_lookup_t, int *);
45962306a36Sopenharmony_ciint xfs_btree_update(struct xfs_btree_cur *, union xfs_btree_rec *);
46062306a36Sopenharmony_ciint xfs_btree_new_iroot(struct xfs_btree_cur *, int *, int *);
46162306a36Sopenharmony_ciint xfs_btree_insert(struct xfs_btree_cur *, int *);
46262306a36Sopenharmony_ciint xfs_btree_delete(struct xfs_btree_cur *, int *);
46362306a36Sopenharmony_ciint xfs_btree_get_rec(struct xfs_btree_cur *, union xfs_btree_rec **, int *);
46462306a36Sopenharmony_ciint xfs_btree_change_owner(struct xfs_btree_cur *cur, uint64_t new_owner,
46562306a36Sopenharmony_ci			   struct list_head *buffer_list);
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci/*
46862306a36Sopenharmony_ci * btree block CRC helpers
46962306a36Sopenharmony_ci */
47062306a36Sopenharmony_civoid xfs_btree_lblock_calc_crc(struct xfs_buf *);
47162306a36Sopenharmony_cibool xfs_btree_lblock_verify_crc(struct xfs_buf *);
47262306a36Sopenharmony_civoid xfs_btree_sblock_calc_crc(struct xfs_buf *);
47362306a36Sopenharmony_cibool xfs_btree_sblock_verify_crc(struct xfs_buf *);
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci/*
47662306a36Sopenharmony_ci * Internal btree helpers also used by xfs_bmap.c.
47762306a36Sopenharmony_ci */
47862306a36Sopenharmony_civoid xfs_btree_log_block(struct xfs_btree_cur *, struct xfs_buf *, uint32_t);
47962306a36Sopenharmony_civoid xfs_btree_log_recs(struct xfs_btree_cur *, struct xfs_buf *, int, int);
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci/*
48262306a36Sopenharmony_ci * Helpers.
48362306a36Sopenharmony_ci */
48462306a36Sopenharmony_cistatic inline int xfs_btree_get_numrecs(const struct xfs_btree_block *block)
48562306a36Sopenharmony_ci{
48662306a36Sopenharmony_ci	return be16_to_cpu(block->bb_numrecs);
48762306a36Sopenharmony_ci}
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_cistatic inline void xfs_btree_set_numrecs(struct xfs_btree_block *block,
49062306a36Sopenharmony_ci		uint16_t numrecs)
49162306a36Sopenharmony_ci{
49262306a36Sopenharmony_ci	block->bb_numrecs = cpu_to_be16(numrecs);
49362306a36Sopenharmony_ci}
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_cistatic inline int xfs_btree_get_level(const struct xfs_btree_block *block)
49662306a36Sopenharmony_ci{
49762306a36Sopenharmony_ci	return be16_to_cpu(block->bb_level);
49862306a36Sopenharmony_ci}
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci/*
50262306a36Sopenharmony_ci * Min and max functions for extlen, agblock, fileoff, and filblks types.
50362306a36Sopenharmony_ci */
50462306a36Sopenharmony_ci#define	XFS_EXTLEN_MIN(a,b)	min_t(xfs_extlen_t, (a), (b))
50562306a36Sopenharmony_ci#define	XFS_EXTLEN_MAX(a,b)	max_t(xfs_extlen_t, (a), (b))
50662306a36Sopenharmony_ci#define	XFS_AGBLOCK_MIN(a,b)	min_t(xfs_agblock_t, (a), (b))
50762306a36Sopenharmony_ci#define	XFS_AGBLOCK_MAX(a,b)	max_t(xfs_agblock_t, (a), (b))
50862306a36Sopenharmony_ci#define	XFS_FILEOFF_MIN(a,b)	min_t(xfs_fileoff_t, (a), (b))
50962306a36Sopenharmony_ci#define	XFS_FILEOFF_MAX(a,b)	max_t(xfs_fileoff_t, (a), (b))
51062306a36Sopenharmony_ci#define	XFS_FILBLKS_MIN(a,b)	min_t(xfs_filblks_t, (a), (b))
51162306a36Sopenharmony_ci#define	XFS_FILBLKS_MAX(a,b)	max_t(xfs_filblks_t, (a), (b))
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_cixfs_failaddr_t xfs_btree_sblock_v5hdr_verify(struct xfs_buf *bp);
51462306a36Sopenharmony_cixfs_failaddr_t xfs_btree_sblock_verify(struct xfs_buf *bp,
51562306a36Sopenharmony_ci		unsigned int max_recs);
51662306a36Sopenharmony_cixfs_failaddr_t xfs_btree_lblock_v5hdr_verify(struct xfs_buf *bp,
51762306a36Sopenharmony_ci		uint64_t owner);
51862306a36Sopenharmony_cixfs_failaddr_t xfs_btree_lblock_verify(struct xfs_buf *bp,
51962306a36Sopenharmony_ci		unsigned int max_recs);
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ciunsigned int xfs_btree_compute_maxlevels(const unsigned int *limits,
52262306a36Sopenharmony_ci		unsigned long long records);
52362306a36Sopenharmony_ciunsigned long long xfs_btree_calc_size(const unsigned int *limits,
52462306a36Sopenharmony_ci		unsigned long long records);
52562306a36Sopenharmony_ciunsigned int xfs_btree_space_to_height(const unsigned int *limits,
52662306a36Sopenharmony_ci		unsigned long long blocks);
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci/*
52962306a36Sopenharmony_ci * Return codes for the query range iterator function are 0 to continue
53062306a36Sopenharmony_ci * iterating, and non-zero to stop iterating.  Any non-zero value will be
53162306a36Sopenharmony_ci * passed up to the _query_range caller.  The special value -ECANCELED can be
53262306a36Sopenharmony_ci * used to stop iteration, because _query_range never generates that error
53362306a36Sopenharmony_ci * code on its own.
53462306a36Sopenharmony_ci */
53562306a36Sopenharmony_citypedef int (*xfs_btree_query_range_fn)(struct xfs_btree_cur *cur,
53662306a36Sopenharmony_ci		const union xfs_btree_rec *rec, void *priv);
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ciint xfs_btree_query_range(struct xfs_btree_cur *cur,
53962306a36Sopenharmony_ci		const union xfs_btree_irec *low_rec,
54062306a36Sopenharmony_ci		const union xfs_btree_irec *high_rec,
54162306a36Sopenharmony_ci		xfs_btree_query_range_fn fn, void *priv);
54262306a36Sopenharmony_ciint xfs_btree_query_all(struct xfs_btree_cur *cur, xfs_btree_query_range_fn fn,
54362306a36Sopenharmony_ci		void *priv);
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_citypedef int (*xfs_btree_visit_blocks_fn)(struct xfs_btree_cur *cur, int level,
54662306a36Sopenharmony_ci		void *data);
54762306a36Sopenharmony_ci/* Visit record blocks. */
54862306a36Sopenharmony_ci#define XFS_BTREE_VISIT_RECORDS		(1 << 0)
54962306a36Sopenharmony_ci/* Visit leaf blocks. */
55062306a36Sopenharmony_ci#define XFS_BTREE_VISIT_LEAVES		(1 << 1)
55162306a36Sopenharmony_ci/* Visit all blocks. */
55262306a36Sopenharmony_ci#define XFS_BTREE_VISIT_ALL		(XFS_BTREE_VISIT_RECORDS | \
55362306a36Sopenharmony_ci					 XFS_BTREE_VISIT_LEAVES)
55462306a36Sopenharmony_ciint xfs_btree_visit_blocks(struct xfs_btree_cur *cur,
55562306a36Sopenharmony_ci		xfs_btree_visit_blocks_fn fn, unsigned int flags, void *data);
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ciint xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_extlen_t *blocks);
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ciunion xfs_btree_rec *xfs_btree_rec_addr(struct xfs_btree_cur *cur, int n,
56062306a36Sopenharmony_ci		struct xfs_btree_block *block);
56162306a36Sopenharmony_ciunion xfs_btree_key *xfs_btree_key_addr(struct xfs_btree_cur *cur, int n,
56262306a36Sopenharmony_ci		struct xfs_btree_block *block);
56362306a36Sopenharmony_ciunion xfs_btree_key *xfs_btree_high_key_addr(struct xfs_btree_cur *cur, int n,
56462306a36Sopenharmony_ci		struct xfs_btree_block *block);
56562306a36Sopenharmony_ciunion xfs_btree_ptr *xfs_btree_ptr_addr(struct xfs_btree_cur *cur, int n,
56662306a36Sopenharmony_ci		struct xfs_btree_block *block);
56762306a36Sopenharmony_ciint xfs_btree_lookup_get_block(struct xfs_btree_cur *cur, int level,
56862306a36Sopenharmony_ci		const union xfs_btree_ptr *pp, struct xfs_btree_block **blkp);
56962306a36Sopenharmony_cistruct xfs_btree_block *xfs_btree_get_block(struct xfs_btree_cur *cur,
57062306a36Sopenharmony_ci		int level, struct xfs_buf **bpp);
57162306a36Sopenharmony_cibool xfs_btree_ptr_is_null(struct xfs_btree_cur *cur,
57262306a36Sopenharmony_ci		const union xfs_btree_ptr *ptr);
57362306a36Sopenharmony_ciint64_t xfs_btree_diff_two_ptrs(struct xfs_btree_cur *cur,
57462306a36Sopenharmony_ci				const union xfs_btree_ptr *a,
57562306a36Sopenharmony_ci				const union xfs_btree_ptr *b);
57662306a36Sopenharmony_civoid xfs_btree_get_sibling(struct xfs_btree_cur *cur,
57762306a36Sopenharmony_ci			   struct xfs_btree_block *block,
57862306a36Sopenharmony_ci			   union xfs_btree_ptr *ptr, int lr);
57962306a36Sopenharmony_civoid xfs_btree_get_keys(struct xfs_btree_cur *cur,
58062306a36Sopenharmony_ci		struct xfs_btree_block *block, union xfs_btree_key *key);
58162306a36Sopenharmony_ciunion xfs_btree_key *xfs_btree_high_key_from_key(struct xfs_btree_cur *cur,
58262306a36Sopenharmony_ci		union xfs_btree_key *key);
58362306a36Sopenharmony_citypedef bool (*xfs_btree_key_gap_fn)(struct xfs_btree_cur *cur,
58462306a36Sopenharmony_ci		const union xfs_btree_key *key1,
58562306a36Sopenharmony_ci		const union xfs_btree_key *key2);
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ciint xfs_btree_has_records(struct xfs_btree_cur *cur,
58862306a36Sopenharmony_ci		const union xfs_btree_irec *low,
58962306a36Sopenharmony_ci		const union xfs_btree_irec *high,
59062306a36Sopenharmony_ci		const union xfs_btree_key *mask,
59162306a36Sopenharmony_ci		enum xbtree_recpacking *outcome);
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_cibool xfs_btree_has_more_records(struct xfs_btree_cur *cur);
59462306a36Sopenharmony_cistruct xfs_ifork *xfs_btree_ifork_ptr(struct xfs_btree_cur *cur);
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci/* Key comparison helpers */
59762306a36Sopenharmony_cistatic inline bool
59862306a36Sopenharmony_cixfs_btree_keycmp_lt(
59962306a36Sopenharmony_ci	struct xfs_btree_cur		*cur,
60062306a36Sopenharmony_ci	const union xfs_btree_key	*key1,
60162306a36Sopenharmony_ci	const union xfs_btree_key	*key2)
60262306a36Sopenharmony_ci{
60362306a36Sopenharmony_ci	return cur->bc_ops->diff_two_keys(cur, key1, key2, NULL) < 0;
60462306a36Sopenharmony_ci}
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_cistatic inline bool
60762306a36Sopenharmony_cixfs_btree_keycmp_gt(
60862306a36Sopenharmony_ci	struct xfs_btree_cur		*cur,
60962306a36Sopenharmony_ci	const union xfs_btree_key	*key1,
61062306a36Sopenharmony_ci	const union xfs_btree_key	*key2)
61162306a36Sopenharmony_ci{
61262306a36Sopenharmony_ci	return cur->bc_ops->diff_two_keys(cur, key1, key2, NULL) > 0;
61362306a36Sopenharmony_ci}
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_cistatic inline bool
61662306a36Sopenharmony_cixfs_btree_keycmp_eq(
61762306a36Sopenharmony_ci	struct xfs_btree_cur		*cur,
61862306a36Sopenharmony_ci	const union xfs_btree_key	*key1,
61962306a36Sopenharmony_ci	const union xfs_btree_key	*key2)
62062306a36Sopenharmony_ci{
62162306a36Sopenharmony_ci	return cur->bc_ops->diff_two_keys(cur, key1, key2, NULL) == 0;
62262306a36Sopenharmony_ci}
62362306a36Sopenharmony_ci
62462306a36Sopenharmony_cistatic inline bool
62562306a36Sopenharmony_cixfs_btree_keycmp_le(
62662306a36Sopenharmony_ci	struct xfs_btree_cur		*cur,
62762306a36Sopenharmony_ci	const union xfs_btree_key	*key1,
62862306a36Sopenharmony_ci	const union xfs_btree_key	*key2)
62962306a36Sopenharmony_ci{
63062306a36Sopenharmony_ci	return !xfs_btree_keycmp_gt(cur, key1, key2);
63162306a36Sopenharmony_ci}
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_cistatic inline bool
63462306a36Sopenharmony_cixfs_btree_keycmp_ge(
63562306a36Sopenharmony_ci	struct xfs_btree_cur		*cur,
63662306a36Sopenharmony_ci	const union xfs_btree_key	*key1,
63762306a36Sopenharmony_ci	const union xfs_btree_key	*key2)
63862306a36Sopenharmony_ci{
63962306a36Sopenharmony_ci	return !xfs_btree_keycmp_lt(cur, key1, key2);
64062306a36Sopenharmony_ci}
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_cistatic inline bool
64362306a36Sopenharmony_cixfs_btree_keycmp_ne(
64462306a36Sopenharmony_ci	struct xfs_btree_cur		*cur,
64562306a36Sopenharmony_ci	const union xfs_btree_key	*key1,
64662306a36Sopenharmony_ci	const union xfs_btree_key	*key2)
64762306a36Sopenharmony_ci{
64862306a36Sopenharmony_ci	return !xfs_btree_keycmp_eq(cur, key1, key2);
64962306a36Sopenharmony_ci}
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci/* Masked key comparison helpers */
65262306a36Sopenharmony_cistatic inline bool
65362306a36Sopenharmony_cixfs_btree_masked_keycmp_lt(
65462306a36Sopenharmony_ci	struct xfs_btree_cur		*cur,
65562306a36Sopenharmony_ci	const union xfs_btree_key	*key1,
65662306a36Sopenharmony_ci	const union xfs_btree_key	*key2,
65762306a36Sopenharmony_ci	const union xfs_btree_key	*mask)
65862306a36Sopenharmony_ci{
65962306a36Sopenharmony_ci	return cur->bc_ops->diff_two_keys(cur, key1, key2, mask) < 0;
66062306a36Sopenharmony_ci}
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_cistatic inline bool
66362306a36Sopenharmony_cixfs_btree_masked_keycmp_gt(
66462306a36Sopenharmony_ci	struct xfs_btree_cur		*cur,
66562306a36Sopenharmony_ci	const union xfs_btree_key	*key1,
66662306a36Sopenharmony_ci	const union xfs_btree_key	*key2,
66762306a36Sopenharmony_ci	const union xfs_btree_key	*mask)
66862306a36Sopenharmony_ci{
66962306a36Sopenharmony_ci	return cur->bc_ops->diff_two_keys(cur, key1, key2, mask) > 0;
67062306a36Sopenharmony_ci}
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_cistatic inline bool
67362306a36Sopenharmony_cixfs_btree_masked_keycmp_ge(
67462306a36Sopenharmony_ci	struct xfs_btree_cur		*cur,
67562306a36Sopenharmony_ci	const union xfs_btree_key	*key1,
67662306a36Sopenharmony_ci	const union xfs_btree_key	*key2,
67762306a36Sopenharmony_ci	const union xfs_btree_key	*mask)
67862306a36Sopenharmony_ci{
67962306a36Sopenharmony_ci	return !xfs_btree_masked_keycmp_lt(cur, key1, key2, mask);
68062306a36Sopenharmony_ci}
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci/* Does this cursor point to the last block in the given level? */
68362306a36Sopenharmony_cistatic inline bool
68462306a36Sopenharmony_cixfs_btree_islastblock(
68562306a36Sopenharmony_ci	struct xfs_btree_cur	*cur,
68662306a36Sopenharmony_ci	int			level)
68762306a36Sopenharmony_ci{
68862306a36Sopenharmony_ci	struct xfs_btree_block	*block;
68962306a36Sopenharmony_ci	struct xfs_buf		*bp;
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	block = xfs_btree_get_block(cur, level, &bp);
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
69462306a36Sopenharmony_ci		return block->bb_u.l.bb_rightsib == cpu_to_be64(NULLFSBLOCK);
69562306a36Sopenharmony_ci	return block->bb_u.s.bb_rightsib == cpu_to_be32(NULLAGBLOCK);
69662306a36Sopenharmony_ci}
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_civoid xfs_btree_set_ptr_null(struct xfs_btree_cur *cur,
69962306a36Sopenharmony_ci		union xfs_btree_ptr *ptr);
70062306a36Sopenharmony_ciint xfs_btree_get_buf_block(struct xfs_btree_cur *cur,
70162306a36Sopenharmony_ci		const union xfs_btree_ptr *ptr, struct xfs_btree_block **block,
70262306a36Sopenharmony_ci		struct xfs_buf **bpp);
70362306a36Sopenharmony_civoid xfs_btree_set_sibling(struct xfs_btree_cur *cur,
70462306a36Sopenharmony_ci		struct xfs_btree_block *block, const union xfs_btree_ptr *ptr,
70562306a36Sopenharmony_ci		int lr);
70662306a36Sopenharmony_civoid xfs_btree_init_block_cur(struct xfs_btree_cur *cur,
70762306a36Sopenharmony_ci		struct xfs_buf *bp, int level, int numrecs);
70862306a36Sopenharmony_civoid xfs_btree_copy_ptrs(struct xfs_btree_cur *cur,
70962306a36Sopenharmony_ci		union xfs_btree_ptr *dst_ptr,
71062306a36Sopenharmony_ci		const union xfs_btree_ptr *src_ptr, int numptrs);
71162306a36Sopenharmony_civoid xfs_btree_copy_keys(struct xfs_btree_cur *cur,
71262306a36Sopenharmony_ci		union xfs_btree_key *dst_key,
71362306a36Sopenharmony_ci		const union xfs_btree_key *src_key, int numkeys);
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_cistatic inline struct xfs_btree_cur *
71662306a36Sopenharmony_cixfs_btree_alloc_cursor(
71762306a36Sopenharmony_ci	struct xfs_mount	*mp,
71862306a36Sopenharmony_ci	struct xfs_trans	*tp,
71962306a36Sopenharmony_ci	xfs_btnum_t		btnum,
72062306a36Sopenharmony_ci	uint8_t			maxlevels,
72162306a36Sopenharmony_ci	struct kmem_cache	*cache)
72262306a36Sopenharmony_ci{
72362306a36Sopenharmony_ci	struct xfs_btree_cur	*cur;
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci	cur = kmem_cache_zalloc(cache, GFP_NOFS | __GFP_NOFAIL);
72662306a36Sopenharmony_ci	cur->bc_tp = tp;
72762306a36Sopenharmony_ci	cur->bc_mp = mp;
72862306a36Sopenharmony_ci	cur->bc_btnum = btnum;
72962306a36Sopenharmony_ci	cur->bc_maxlevels = maxlevels;
73062306a36Sopenharmony_ci	cur->bc_cache = cache;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	return cur;
73362306a36Sopenharmony_ci}
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ciint __init xfs_btree_init_cur_caches(void);
73662306a36Sopenharmony_civoid xfs_btree_destroy_cur_caches(void);
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci#endif	/* __XFS_BTREE_H__ */
739