19abe03a0SDarrick J. Wong /* SPDX-License-Identifier: GPL-2.0-or-later */
29abe03a0SDarrick J. Wong /*
39abe03a0SDarrick J. Wong * Copyright (c) 2021-2024 Oracle. All Rights Reserved.
49abe03a0SDarrick J. Wong * Author: Darrick J. Wong <djwong@kernel.org>
59abe03a0SDarrick J. Wong */
69abe03a0SDarrick J. Wong #ifndef __XFS_RTREFCOUNT_BTREE_H__
79abe03a0SDarrick J. Wong #define __XFS_RTREFCOUNT_BTREE_H__
89abe03a0SDarrick J. Wong
99abe03a0SDarrick J. Wong struct xfs_buf;
109abe03a0SDarrick J. Wong struct xfs_btree_cur;
119abe03a0SDarrick J. Wong struct xfs_mount;
129abe03a0SDarrick J. Wong struct xbtree_ifakeroot;
139abe03a0SDarrick J. Wong struct xfs_rtgroup;
149abe03a0SDarrick J. Wong
159abe03a0SDarrick J. Wong /* refcounts only exist on crc enabled filesystems */
169abe03a0SDarrick J. Wong #define XFS_RTREFCOUNT_BLOCK_LEN XFS_BTREE_LBLOCK_CRC_LEN
179abe03a0SDarrick J. Wong
189abe03a0SDarrick J. Wong struct xfs_btree_cur *xfs_rtrefcountbt_init_cursor(struct xfs_trans *tp,
199abe03a0SDarrick J. Wong struct xfs_rtgroup *rtg);
209abe03a0SDarrick J. Wong struct xfs_btree_cur *xfs_rtrefcountbt_stage_cursor(struct xfs_mount *mp,
219abe03a0SDarrick J. Wong struct xfs_rtgroup *rtg, struct xfs_inode *ip,
229abe03a0SDarrick J. Wong struct xbtree_ifakeroot *ifake);
239abe03a0SDarrick J. Wong void xfs_rtrefcountbt_commit_staged_btree(struct xfs_btree_cur *cur,
249abe03a0SDarrick J. Wong struct xfs_trans *tp);
259abe03a0SDarrick J. Wong unsigned int xfs_rtrefcountbt_maxrecs(struct xfs_mount *mp,
269abe03a0SDarrick J. Wong unsigned int blocklen, bool leaf);
279abe03a0SDarrick J. Wong void xfs_rtrefcountbt_compute_maxlevels(struct xfs_mount *mp);
28f0415af6SDarrick J. Wong unsigned int xfs_rtrefcountbt_droot_maxrecs(unsigned int blocklen, bool leaf);
299abe03a0SDarrick J. Wong
309abe03a0SDarrick J. Wong /*
319abe03a0SDarrick J. Wong * Addresses of records, keys, and pointers within an incore rtrefcountbt block.
329abe03a0SDarrick J. Wong *
339abe03a0SDarrick J. Wong * (note that some of these may appear unused, but they are used in userspace)
349abe03a0SDarrick J. Wong */
359abe03a0SDarrick J. Wong static inline struct xfs_refcount_rec *
xfs_rtrefcount_rec_addr(struct xfs_btree_block * block,unsigned int index)369abe03a0SDarrick J. Wong xfs_rtrefcount_rec_addr(
379abe03a0SDarrick J. Wong struct xfs_btree_block *block,
389abe03a0SDarrick J. Wong unsigned int index)
399abe03a0SDarrick J. Wong {
409abe03a0SDarrick J. Wong return (struct xfs_refcount_rec *)
419abe03a0SDarrick J. Wong ((char *)block + XFS_RTREFCOUNT_BLOCK_LEN +
429abe03a0SDarrick J. Wong (index - 1) * sizeof(struct xfs_refcount_rec));
439abe03a0SDarrick J. Wong }
449abe03a0SDarrick J. Wong
459abe03a0SDarrick J. Wong static inline struct xfs_refcount_key *
xfs_rtrefcount_key_addr(struct xfs_btree_block * block,unsigned int index)469abe03a0SDarrick J. Wong xfs_rtrefcount_key_addr(
479abe03a0SDarrick J. Wong struct xfs_btree_block *block,
489abe03a0SDarrick J. Wong unsigned int index)
499abe03a0SDarrick J. Wong {
509abe03a0SDarrick J. Wong return (struct xfs_refcount_key *)
519abe03a0SDarrick J. Wong ((char *)block + XFS_RTREFCOUNT_BLOCK_LEN +
529abe03a0SDarrick J. Wong (index - 1) * sizeof(struct xfs_refcount_key));
539abe03a0SDarrick J. Wong }
549abe03a0SDarrick J. Wong
559abe03a0SDarrick J. Wong static inline xfs_rtrefcount_ptr_t *
xfs_rtrefcount_ptr_addr(struct xfs_btree_block * block,unsigned int index,unsigned int maxrecs)569abe03a0SDarrick J. Wong xfs_rtrefcount_ptr_addr(
579abe03a0SDarrick J. Wong struct xfs_btree_block *block,
589abe03a0SDarrick J. Wong unsigned int index,
599abe03a0SDarrick J. Wong unsigned int maxrecs)
609abe03a0SDarrick J. Wong {
619abe03a0SDarrick J. Wong return (xfs_rtrefcount_ptr_t *)
629abe03a0SDarrick J. Wong ((char *)block + XFS_RTREFCOUNT_BLOCK_LEN +
639abe03a0SDarrick J. Wong maxrecs * sizeof(struct xfs_refcount_key) +
649abe03a0SDarrick J. Wong (index - 1) * sizeof(xfs_rtrefcount_ptr_t));
659abe03a0SDarrick J. Wong }
669abe03a0SDarrick J. Wong
679abe03a0SDarrick J. Wong unsigned int xfs_rtrefcountbt_maxlevels_ondisk(void);
689abe03a0SDarrick J. Wong int __init xfs_rtrefcountbt_init_cur_cache(void);
699abe03a0SDarrick J. Wong void xfs_rtrefcountbt_destroy_cur_cache(void);
709abe03a0SDarrick J. Wong
71bf0b9941SDarrick J. Wong xfs_filblks_t xfs_rtrefcountbt_calc_reserves(struct xfs_mount *mp);
72bf0b9941SDarrick J. Wong unsigned long long xfs_rtrefcountbt_calc_size(struct xfs_mount *mp,
73bf0b9941SDarrick J. Wong unsigned long long len);
74bf0b9941SDarrick J. Wong
75f0415af6SDarrick J. Wong /* Addresses of key, pointers, and records within an ondisk rtrefcount block. */
76f0415af6SDarrick J. Wong
77f0415af6SDarrick J. Wong static inline struct xfs_refcount_rec *
xfs_rtrefcount_droot_rec_addr(struct xfs_rtrefcount_root * block,unsigned int index)78f0415af6SDarrick J. Wong xfs_rtrefcount_droot_rec_addr(
79f0415af6SDarrick J. Wong struct xfs_rtrefcount_root *block,
80f0415af6SDarrick J. Wong unsigned int index)
81f0415af6SDarrick J. Wong {
82f0415af6SDarrick J. Wong return (struct xfs_refcount_rec *)
83f0415af6SDarrick J. Wong ((char *)(block + 1) +
84f0415af6SDarrick J. Wong (index - 1) * sizeof(struct xfs_refcount_rec));
85f0415af6SDarrick J. Wong }
86f0415af6SDarrick J. Wong
87f0415af6SDarrick J. Wong static inline struct xfs_refcount_key *
xfs_rtrefcount_droot_key_addr(struct xfs_rtrefcount_root * block,unsigned int index)88f0415af6SDarrick J. Wong xfs_rtrefcount_droot_key_addr(
89f0415af6SDarrick J. Wong struct xfs_rtrefcount_root *block,
90f0415af6SDarrick J. Wong unsigned int index)
91f0415af6SDarrick J. Wong {
92f0415af6SDarrick J. Wong return (struct xfs_refcount_key *)
93f0415af6SDarrick J. Wong ((char *)(block + 1) +
94f0415af6SDarrick J. Wong (index - 1) * sizeof(struct xfs_refcount_key));
95f0415af6SDarrick J. Wong }
96f0415af6SDarrick J. Wong
97f0415af6SDarrick J. Wong static inline xfs_rtrefcount_ptr_t *
xfs_rtrefcount_droot_ptr_addr(struct xfs_rtrefcount_root * block,unsigned int index,unsigned int maxrecs)98f0415af6SDarrick J. Wong xfs_rtrefcount_droot_ptr_addr(
99f0415af6SDarrick J. Wong struct xfs_rtrefcount_root *block,
100f0415af6SDarrick J. Wong unsigned int index,
101f0415af6SDarrick J. Wong unsigned int maxrecs)
102f0415af6SDarrick J. Wong {
103f0415af6SDarrick J. Wong return (xfs_rtrefcount_ptr_t *)
104f0415af6SDarrick J. Wong ((char *)(block + 1) +
105f0415af6SDarrick J. Wong maxrecs * sizeof(struct xfs_refcount_key) +
106f0415af6SDarrick J. Wong (index - 1) * sizeof(xfs_rtrefcount_ptr_t));
107f0415af6SDarrick J. Wong }
108f0415af6SDarrick J. Wong
109f0415af6SDarrick J. Wong /*
110f0415af6SDarrick J. Wong * Address of pointers within the incore btree root.
111f0415af6SDarrick J. Wong *
112f0415af6SDarrick J. Wong * These are to be used when we know the size of the block and
113f0415af6SDarrick J. Wong * we don't have a cursor.
114f0415af6SDarrick J. Wong */
115f0415af6SDarrick J. Wong static inline xfs_rtrefcount_ptr_t *
xfs_rtrefcount_broot_ptr_addr(struct xfs_mount * mp,struct xfs_btree_block * bb,unsigned int index,unsigned int block_size)116f0415af6SDarrick J. Wong xfs_rtrefcount_broot_ptr_addr(
117f0415af6SDarrick J. Wong struct xfs_mount *mp,
118f0415af6SDarrick J. Wong struct xfs_btree_block *bb,
119f0415af6SDarrick J. Wong unsigned int index,
120f0415af6SDarrick J. Wong unsigned int block_size)
121f0415af6SDarrick J. Wong {
122f0415af6SDarrick J. Wong return xfs_rtrefcount_ptr_addr(bb, index,
123f0415af6SDarrick J. Wong xfs_rtrefcountbt_maxrecs(mp, block_size, false));
124f0415af6SDarrick J. Wong }
125f0415af6SDarrick J. Wong
126f0415af6SDarrick J. Wong /*
127f0415af6SDarrick J. Wong * Compute the space required for the incore btree root containing the given
128f0415af6SDarrick J. Wong * number of records.
129f0415af6SDarrick J. Wong */
130f0415af6SDarrick J. Wong static inline size_t
xfs_rtrefcount_broot_space_calc(struct xfs_mount * mp,unsigned int level,unsigned int nrecs)131f0415af6SDarrick J. Wong xfs_rtrefcount_broot_space_calc(
132f0415af6SDarrick J. Wong struct xfs_mount *mp,
133f0415af6SDarrick J. Wong unsigned int level,
134f0415af6SDarrick J. Wong unsigned int nrecs)
135f0415af6SDarrick J. Wong {
136f0415af6SDarrick J. Wong size_t sz = XFS_RTREFCOUNT_BLOCK_LEN;
137f0415af6SDarrick J. Wong
138f0415af6SDarrick J. Wong if (level > 0)
139f0415af6SDarrick J. Wong return sz + nrecs * (sizeof(struct xfs_refcount_key) +
140f0415af6SDarrick J. Wong sizeof(xfs_rtrefcount_ptr_t));
141f0415af6SDarrick J. Wong return sz + nrecs * sizeof(struct xfs_refcount_rec);
142f0415af6SDarrick J. Wong }
143f0415af6SDarrick J. Wong
144f0415af6SDarrick J. Wong /*
145f0415af6SDarrick J. Wong * Compute the space required for the incore btree root given the ondisk
146f0415af6SDarrick J. Wong * btree root block.
147f0415af6SDarrick J. Wong */
148f0415af6SDarrick J. Wong static inline size_t
xfs_rtrefcount_broot_space(struct xfs_mount * mp,struct xfs_rtrefcount_root * bb)149f0415af6SDarrick J. Wong xfs_rtrefcount_broot_space(struct xfs_mount *mp, struct xfs_rtrefcount_root *bb)
150f0415af6SDarrick J. Wong {
151f0415af6SDarrick J. Wong return xfs_rtrefcount_broot_space_calc(mp, be16_to_cpu(bb->bb_level),
152f0415af6SDarrick J. Wong be16_to_cpu(bb->bb_numrecs));
153f0415af6SDarrick J. Wong }
154f0415af6SDarrick J. Wong
155f0415af6SDarrick J. Wong /* Compute the space required for the ondisk root block. */
156f0415af6SDarrick J. Wong static inline size_t
xfs_rtrefcount_droot_space_calc(unsigned int level,unsigned int nrecs)157f0415af6SDarrick J. Wong xfs_rtrefcount_droot_space_calc(
158f0415af6SDarrick J. Wong unsigned int level,
159f0415af6SDarrick J. Wong unsigned int nrecs)
160f0415af6SDarrick J. Wong {
161f0415af6SDarrick J. Wong size_t sz = sizeof(struct xfs_rtrefcount_root);
162f0415af6SDarrick J. Wong
163f0415af6SDarrick J. Wong if (level > 0)
164f0415af6SDarrick J. Wong return sz + nrecs * (sizeof(struct xfs_refcount_key) +
165f0415af6SDarrick J. Wong sizeof(xfs_rtrefcount_ptr_t));
166f0415af6SDarrick J. Wong return sz + nrecs * sizeof(struct xfs_refcount_rec);
167f0415af6SDarrick J. Wong }
168f0415af6SDarrick J. Wong
169f0415af6SDarrick J. Wong /*
170f0415af6SDarrick J. Wong * Compute the space required for the ondisk root block given an incore root
171f0415af6SDarrick J. Wong * block.
172f0415af6SDarrick J. Wong */
173f0415af6SDarrick J. Wong static inline size_t
xfs_rtrefcount_droot_space(struct xfs_btree_block * bb)174f0415af6SDarrick J. Wong xfs_rtrefcount_droot_space(struct xfs_btree_block *bb)
175f0415af6SDarrick J. Wong {
176f0415af6SDarrick J. Wong return xfs_rtrefcount_droot_space_calc(be16_to_cpu(bb->bb_level),
177f0415af6SDarrick J. Wong be16_to_cpu(bb->bb_numrecs));
178f0415af6SDarrick J. Wong }
179f0415af6SDarrick J. Wong
180f0415af6SDarrick J. Wong int xfs_iformat_rtrefcount(struct xfs_inode *ip, struct xfs_dinode *dip);
181f0415af6SDarrick J. Wong void xfs_rtrefcountbt_to_disk(struct xfs_mount *mp,
182f0415af6SDarrick J. Wong struct xfs_btree_block *rblock, int rblocklen,
183f0415af6SDarrick J. Wong struct xfs_rtrefcount_root *dblock, int dblocklen);
184f0415af6SDarrick J. Wong void xfs_iflush_rtrefcount(struct xfs_inode *ip, struct xfs_dinode *dip);
185f0415af6SDarrick J. Wong
186*4ee3113aSDarrick J. Wong int xfs_rtrefcountbt_create(struct xfs_rtgroup *rtg, struct xfs_inode *ip,
187*4ee3113aSDarrick J. Wong struct xfs_trans *tp, bool init);
188*4ee3113aSDarrick J. Wong
1899abe03a0SDarrick J. Wong #endif /* __XFS_RTREFCOUNT_BTREE_H__ */
190