xref: /linux/fs/xfs/libxfs/xfs_rtrmap_btree.c (revision fc6856c6ff08642e3e8437f0416d70a5e1807010)
1*fc6856c6SDarrick J. Wong // SPDX-License-Identifier: GPL-2.0-or-later
2*fc6856c6SDarrick J. Wong /*
3*fc6856c6SDarrick J. Wong  * Copyright (c) 2018-2024 Oracle.  All Rights Reserved.
4*fc6856c6SDarrick J. Wong  * Author: Darrick J. Wong <djwong@kernel.org>
5*fc6856c6SDarrick J. Wong  */
6*fc6856c6SDarrick J. Wong #include "xfs.h"
7*fc6856c6SDarrick J. Wong #include "xfs_fs.h"
8*fc6856c6SDarrick J. Wong #include "xfs_shared.h"
9*fc6856c6SDarrick J. Wong #include "xfs_format.h"
10*fc6856c6SDarrick J. Wong #include "xfs_log_format.h"
11*fc6856c6SDarrick J. Wong #include "xfs_trans_resv.h"
12*fc6856c6SDarrick J. Wong #include "xfs_bit.h"
13*fc6856c6SDarrick J. Wong #include "xfs_sb.h"
14*fc6856c6SDarrick J. Wong #include "xfs_mount.h"
15*fc6856c6SDarrick J. Wong #include "xfs_defer.h"
16*fc6856c6SDarrick J. Wong #include "xfs_inode.h"
17*fc6856c6SDarrick J. Wong #include "xfs_trans.h"
18*fc6856c6SDarrick J. Wong #include "xfs_alloc.h"
19*fc6856c6SDarrick J. Wong #include "xfs_btree.h"
20*fc6856c6SDarrick J. Wong #include "xfs_btree_staging.h"
21*fc6856c6SDarrick J. Wong #include "xfs_rtrmap_btree.h"
22*fc6856c6SDarrick J. Wong #include "xfs_trace.h"
23*fc6856c6SDarrick J. Wong #include "xfs_cksum.h"
24*fc6856c6SDarrick J. Wong #include "xfs_error.h"
25*fc6856c6SDarrick J. Wong #include "xfs_extent_busy.h"
26*fc6856c6SDarrick J. Wong #include "xfs_rtgroup.h"
27*fc6856c6SDarrick J. Wong 
28*fc6856c6SDarrick J. Wong static struct kmem_cache	*xfs_rtrmapbt_cur_cache;
29*fc6856c6SDarrick J. Wong 
30*fc6856c6SDarrick J. Wong /*
31*fc6856c6SDarrick J. Wong  * Realtime Reverse Map btree.
32*fc6856c6SDarrick J. Wong  *
33*fc6856c6SDarrick J. Wong  * This is a btree used to track the owner(s) of a given extent in the realtime
34*fc6856c6SDarrick J. Wong  * device.  See the comments in xfs_rmap_btree.c for more information.
35*fc6856c6SDarrick J. Wong  *
36*fc6856c6SDarrick J. Wong  * This tree is basically the same as the regular rmap btree except that it
37*fc6856c6SDarrick J. Wong  * is rooted in an inode and does not live in free space.
38*fc6856c6SDarrick J. Wong  */
39*fc6856c6SDarrick J. Wong 
40*fc6856c6SDarrick J. Wong static struct xfs_btree_cur *
41*fc6856c6SDarrick J. Wong xfs_rtrmapbt_dup_cursor(
42*fc6856c6SDarrick J. Wong 	struct xfs_btree_cur	*cur)
43*fc6856c6SDarrick J. Wong {
44*fc6856c6SDarrick J. Wong 	return xfs_rtrmapbt_init_cursor(cur->bc_tp, to_rtg(cur->bc_group));
45*fc6856c6SDarrick J. Wong }
46*fc6856c6SDarrick J. Wong 
47*fc6856c6SDarrick J. Wong static xfs_failaddr_t
48*fc6856c6SDarrick J. Wong xfs_rtrmapbt_verify(
49*fc6856c6SDarrick J. Wong 	struct xfs_buf		*bp)
50*fc6856c6SDarrick J. Wong {
51*fc6856c6SDarrick J. Wong 	struct xfs_mount	*mp = bp->b_target->bt_mount;
52*fc6856c6SDarrick J. Wong 	struct xfs_btree_block	*block = XFS_BUF_TO_BLOCK(bp);
53*fc6856c6SDarrick J. Wong 	xfs_failaddr_t		fa;
54*fc6856c6SDarrick J. Wong 	int			level;
55*fc6856c6SDarrick J. Wong 
56*fc6856c6SDarrick J. Wong 	if (!xfs_verify_magic(bp, block->bb_magic))
57*fc6856c6SDarrick J. Wong 		return __this_address;
58*fc6856c6SDarrick J. Wong 
59*fc6856c6SDarrick J. Wong 	if (!xfs_has_rmapbt(mp))
60*fc6856c6SDarrick J. Wong 		return __this_address;
61*fc6856c6SDarrick J. Wong 	fa = xfs_btree_fsblock_v5hdr_verify(bp, XFS_RMAP_OWN_UNKNOWN);
62*fc6856c6SDarrick J. Wong 	if (fa)
63*fc6856c6SDarrick J. Wong 		return fa;
64*fc6856c6SDarrick J. Wong 	level = be16_to_cpu(block->bb_level);
65*fc6856c6SDarrick J. Wong 	if (level > mp->m_rtrmap_maxlevels)
66*fc6856c6SDarrick J. Wong 		return __this_address;
67*fc6856c6SDarrick J. Wong 
68*fc6856c6SDarrick J. Wong 	return xfs_btree_fsblock_verify(bp, mp->m_rtrmap_mxr[level != 0]);
69*fc6856c6SDarrick J. Wong }
70*fc6856c6SDarrick J. Wong 
71*fc6856c6SDarrick J. Wong static void
72*fc6856c6SDarrick J. Wong xfs_rtrmapbt_read_verify(
73*fc6856c6SDarrick J. Wong 	struct xfs_buf	*bp)
74*fc6856c6SDarrick J. Wong {
75*fc6856c6SDarrick J. Wong 	xfs_failaddr_t	fa;
76*fc6856c6SDarrick J. Wong 
77*fc6856c6SDarrick J. Wong 	if (!xfs_btree_fsblock_verify_crc(bp))
78*fc6856c6SDarrick J. Wong 		xfs_verifier_error(bp, -EFSBADCRC, __this_address);
79*fc6856c6SDarrick J. Wong 	else {
80*fc6856c6SDarrick J. Wong 		fa = xfs_rtrmapbt_verify(bp);
81*fc6856c6SDarrick J. Wong 		if (fa)
82*fc6856c6SDarrick J. Wong 			xfs_verifier_error(bp, -EFSCORRUPTED, fa);
83*fc6856c6SDarrick J. Wong 	}
84*fc6856c6SDarrick J. Wong 
85*fc6856c6SDarrick J. Wong 	if (bp->b_error)
86*fc6856c6SDarrick J. Wong 		trace_xfs_btree_corrupt(bp, _RET_IP_);
87*fc6856c6SDarrick J. Wong }
88*fc6856c6SDarrick J. Wong 
89*fc6856c6SDarrick J. Wong static void
90*fc6856c6SDarrick J. Wong xfs_rtrmapbt_write_verify(
91*fc6856c6SDarrick J. Wong 	struct xfs_buf	*bp)
92*fc6856c6SDarrick J. Wong {
93*fc6856c6SDarrick J. Wong 	xfs_failaddr_t	fa;
94*fc6856c6SDarrick J. Wong 
95*fc6856c6SDarrick J. Wong 	fa = xfs_rtrmapbt_verify(bp);
96*fc6856c6SDarrick J. Wong 	if (fa) {
97*fc6856c6SDarrick J. Wong 		trace_xfs_btree_corrupt(bp, _RET_IP_);
98*fc6856c6SDarrick J. Wong 		xfs_verifier_error(bp, -EFSCORRUPTED, fa);
99*fc6856c6SDarrick J. Wong 		return;
100*fc6856c6SDarrick J. Wong 	}
101*fc6856c6SDarrick J. Wong 	xfs_btree_fsblock_calc_crc(bp);
102*fc6856c6SDarrick J. Wong 
103*fc6856c6SDarrick J. Wong }
104*fc6856c6SDarrick J. Wong 
105*fc6856c6SDarrick J. Wong const struct xfs_buf_ops xfs_rtrmapbt_buf_ops = {
106*fc6856c6SDarrick J. Wong 	.name			= "xfs_rtrmapbt",
107*fc6856c6SDarrick J. Wong 	.magic			= { 0, cpu_to_be32(XFS_RTRMAP_CRC_MAGIC) },
108*fc6856c6SDarrick J. Wong 	.verify_read		= xfs_rtrmapbt_read_verify,
109*fc6856c6SDarrick J. Wong 	.verify_write		= xfs_rtrmapbt_write_verify,
110*fc6856c6SDarrick J. Wong 	.verify_struct		= xfs_rtrmapbt_verify,
111*fc6856c6SDarrick J. Wong };
112*fc6856c6SDarrick J. Wong 
113*fc6856c6SDarrick J. Wong const struct xfs_btree_ops xfs_rtrmapbt_ops = {
114*fc6856c6SDarrick J. Wong 	.name			= "rtrmap",
115*fc6856c6SDarrick J. Wong 	.type			= XFS_BTREE_TYPE_INODE,
116*fc6856c6SDarrick J. Wong 	.geom_flags		= XFS_BTGEO_OVERLAPPING |
117*fc6856c6SDarrick J. Wong 				  XFS_BTGEO_IROOT_RECORDS,
118*fc6856c6SDarrick J. Wong 
119*fc6856c6SDarrick J. Wong 	.rec_len		= sizeof(struct xfs_rmap_rec),
120*fc6856c6SDarrick J. Wong 	/* Overlapping btree; 2 keys per pointer. */
121*fc6856c6SDarrick J. Wong 	.key_len		= 2 * sizeof(struct xfs_rmap_key),
122*fc6856c6SDarrick J. Wong 	.ptr_len		= XFS_BTREE_LONG_PTR_LEN,
123*fc6856c6SDarrick J. Wong 
124*fc6856c6SDarrick J. Wong 	.lru_refs		= XFS_RMAP_BTREE_REF,
125*fc6856c6SDarrick J. Wong 	.statoff		= XFS_STATS_CALC_INDEX(xs_rtrmap_2),
126*fc6856c6SDarrick J. Wong 
127*fc6856c6SDarrick J. Wong 	.dup_cursor		= xfs_rtrmapbt_dup_cursor,
128*fc6856c6SDarrick J. Wong 	.buf_ops		= &xfs_rtrmapbt_buf_ops,
129*fc6856c6SDarrick J. Wong };
130*fc6856c6SDarrick J. Wong 
131*fc6856c6SDarrick J. Wong /* Allocate a new rt rmap btree cursor. */
132*fc6856c6SDarrick J. Wong struct xfs_btree_cur *
133*fc6856c6SDarrick J. Wong xfs_rtrmapbt_init_cursor(
134*fc6856c6SDarrick J. Wong 	struct xfs_trans	*tp,
135*fc6856c6SDarrick J. Wong 	struct xfs_rtgroup	*rtg)
136*fc6856c6SDarrick J. Wong {
137*fc6856c6SDarrick J. Wong 	struct xfs_inode	*ip = NULL;
138*fc6856c6SDarrick J. Wong 	struct xfs_mount	*mp = rtg_mount(rtg);
139*fc6856c6SDarrick J. Wong 	struct xfs_btree_cur	*cur;
140*fc6856c6SDarrick J. Wong 
141*fc6856c6SDarrick J. Wong 	return NULL; /* XXX */
142*fc6856c6SDarrick J. Wong 
143*fc6856c6SDarrick J. Wong 	xfs_assert_ilocked(ip, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL);
144*fc6856c6SDarrick J. Wong 
145*fc6856c6SDarrick J. Wong 	cur = xfs_btree_alloc_cursor(mp, tp, &xfs_rtrmapbt_ops,
146*fc6856c6SDarrick J. Wong 			mp->m_rtrmap_maxlevels, xfs_rtrmapbt_cur_cache);
147*fc6856c6SDarrick J. Wong 
148*fc6856c6SDarrick J. Wong 	cur->bc_ino.ip = ip;
149*fc6856c6SDarrick J. Wong 	cur->bc_group = xfs_group_hold(rtg_group(rtg));
150*fc6856c6SDarrick J. Wong 	cur->bc_ino.whichfork = XFS_DATA_FORK;
151*fc6856c6SDarrick J. Wong 	cur->bc_nlevels = be16_to_cpu(ip->i_df.if_broot->bb_level) + 1;
152*fc6856c6SDarrick J. Wong 	cur->bc_ino.forksize = xfs_inode_fork_size(ip, XFS_DATA_FORK);
153*fc6856c6SDarrick J. Wong 
154*fc6856c6SDarrick J. Wong 	return cur;
155*fc6856c6SDarrick J. Wong }
156*fc6856c6SDarrick J. Wong 
157*fc6856c6SDarrick J. Wong /*
158*fc6856c6SDarrick J. Wong  * Install a new rt reverse mapping btree root.  Caller is responsible for
159*fc6856c6SDarrick J. Wong  * invalidating and freeing the old btree blocks.
160*fc6856c6SDarrick J. Wong  */
161*fc6856c6SDarrick J. Wong void
162*fc6856c6SDarrick J. Wong xfs_rtrmapbt_commit_staged_btree(
163*fc6856c6SDarrick J. Wong 	struct xfs_btree_cur	*cur,
164*fc6856c6SDarrick J. Wong 	struct xfs_trans	*tp)
165*fc6856c6SDarrick J. Wong {
166*fc6856c6SDarrick J. Wong 	struct xbtree_ifakeroot	*ifake = cur->bc_ino.ifake;
167*fc6856c6SDarrick J. Wong 	struct xfs_ifork	*ifp;
168*fc6856c6SDarrick J. Wong 	int			flags = XFS_ILOG_CORE | XFS_ILOG_DBROOT;
169*fc6856c6SDarrick J. Wong 
170*fc6856c6SDarrick J. Wong 	ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
171*fc6856c6SDarrick J. Wong 
172*fc6856c6SDarrick J. Wong 	/*
173*fc6856c6SDarrick J. Wong 	 * Free any resources hanging off the real fork, then shallow-copy the
174*fc6856c6SDarrick J. Wong 	 * staging fork's contents into the real fork to transfer everything
175*fc6856c6SDarrick J. Wong 	 * we just built.
176*fc6856c6SDarrick J. Wong 	 */
177*fc6856c6SDarrick J. Wong 	ifp = xfs_ifork_ptr(cur->bc_ino.ip, XFS_DATA_FORK);
178*fc6856c6SDarrick J. Wong 	xfs_idestroy_fork(ifp);
179*fc6856c6SDarrick J. Wong 	memcpy(ifp, ifake->if_fork, sizeof(struct xfs_ifork));
180*fc6856c6SDarrick J. Wong 
181*fc6856c6SDarrick J. Wong 	cur->bc_ino.ip->i_projid = cur->bc_group->xg_gno;
182*fc6856c6SDarrick J. Wong 	xfs_trans_log_inode(tp, cur->bc_ino.ip, flags);
183*fc6856c6SDarrick J. Wong 	xfs_btree_commit_ifakeroot(cur, tp, XFS_DATA_FORK);
184*fc6856c6SDarrick J. Wong }
185*fc6856c6SDarrick J. Wong 
186*fc6856c6SDarrick J. Wong /* Calculate number of records in a rt reverse mapping btree block. */
187*fc6856c6SDarrick J. Wong static inline unsigned int
188*fc6856c6SDarrick J. Wong xfs_rtrmapbt_block_maxrecs(
189*fc6856c6SDarrick J. Wong 	unsigned int		blocklen,
190*fc6856c6SDarrick J. Wong 	bool			leaf)
191*fc6856c6SDarrick J. Wong {
192*fc6856c6SDarrick J. Wong 	if (leaf)
193*fc6856c6SDarrick J. Wong 		return blocklen / sizeof(struct xfs_rmap_rec);
194*fc6856c6SDarrick J. Wong 	return blocklen /
195*fc6856c6SDarrick J. Wong 		(2 * sizeof(struct xfs_rmap_key) + sizeof(xfs_rtrmap_ptr_t));
196*fc6856c6SDarrick J. Wong }
197*fc6856c6SDarrick J. Wong 
198*fc6856c6SDarrick J. Wong /*
199*fc6856c6SDarrick J. Wong  * Calculate number of records in an rt reverse mapping btree block.
200*fc6856c6SDarrick J. Wong  */
201*fc6856c6SDarrick J. Wong unsigned int
202*fc6856c6SDarrick J. Wong xfs_rtrmapbt_maxrecs(
203*fc6856c6SDarrick J. Wong 	struct xfs_mount	*mp,
204*fc6856c6SDarrick J. Wong 	unsigned int		blocklen,
205*fc6856c6SDarrick J. Wong 	bool			leaf)
206*fc6856c6SDarrick J. Wong {
207*fc6856c6SDarrick J. Wong 	blocklen -= XFS_RTRMAP_BLOCK_LEN;
208*fc6856c6SDarrick J. Wong 	return xfs_rtrmapbt_block_maxrecs(blocklen, leaf);
209*fc6856c6SDarrick J. Wong }
210*fc6856c6SDarrick J. Wong 
211*fc6856c6SDarrick J. Wong /* Compute the max possible height for realtime reverse mapping btrees. */
212*fc6856c6SDarrick J. Wong unsigned int
213*fc6856c6SDarrick J. Wong xfs_rtrmapbt_maxlevels_ondisk(void)
214*fc6856c6SDarrick J. Wong {
215*fc6856c6SDarrick J. Wong 	unsigned int		minrecs[2];
216*fc6856c6SDarrick J. Wong 	unsigned int		blocklen;
217*fc6856c6SDarrick J. Wong 
218*fc6856c6SDarrick J. Wong 	blocklen = XFS_MIN_CRC_BLOCKSIZE - XFS_BTREE_LBLOCK_CRC_LEN;
219*fc6856c6SDarrick J. Wong 
220*fc6856c6SDarrick J. Wong 	minrecs[0] = xfs_rtrmapbt_block_maxrecs(blocklen, true) / 2;
221*fc6856c6SDarrick J. Wong 	minrecs[1] = xfs_rtrmapbt_block_maxrecs(blocklen, false) / 2;
222*fc6856c6SDarrick J. Wong 
223*fc6856c6SDarrick J. Wong 	/* We need at most one record for every block in an rt group. */
224*fc6856c6SDarrick J. Wong 	return xfs_btree_compute_maxlevels(minrecs, XFS_MAX_RGBLOCKS);
225*fc6856c6SDarrick J. Wong }
226*fc6856c6SDarrick J. Wong 
227*fc6856c6SDarrick J. Wong int __init
228*fc6856c6SDarrick J. Wong xfs_rtrmapbt_init_cur_cache(void)
229*fc6856c6SDarrick J. Wong {
230*fc6856c6SDarrick J. Wong 	xfs_rtrmapbt_cur_cache = kmem_cache_create("xfs_rtrmapbt_cur",
231*fc6856c6SDarrick J. Wong 			xfs_btree_cur_sizeof(xfs_rtrmapbt_maxlevels_ondisk()),
232*fc6856c6SDarrick J. Wong 			0, 0, NULL);
233*fc6856c6SDarrick J. Wong 
234*fc6856c6SDarrick J. Wong 	if (!xfs_rtrmapbt_cur_cache)
235*fc6856c6SDarrick J. Wong 		return -ENOMEM;
236*fc6856c6SDarrick J. Wong 	return 0;
237*fc6856c6SDarrick J. Wong }
238*fc6856c6SDarrick J. Wong 
239*fc6856c6SDarrick J. Wong void
240*fc6856c6SDarrick J. Wong xfs_rtrmapbt_destroy_cur_cache(void)
241*fc6856c6SDarrick J. Wong {
242*fc6856c6SDarrick J. Wong 	kmem_cache_destroy(xfs_rtrmapbt_cur_cache);
243*fc6856c6SDarrick J. Wong 	xfs_rtrmapbt_cur_cache = NULL;
244*fc6856c6SDarrick J. Wong }
245*fc6856c6SDarrick J. Wong 
246*fc6856c6SDarrick J. Wong /* Compute the maximum height of an rt reverse mapping btree. */
247*fc6856c6SDarrick J. Wong void
248*fc6856c6SDarrick J. Wong xfs_rtrmapbt_compute_maxlevels(
249*fc6856c6SDarrick J. Wong 	struct xfs_mount	*mp)
250*fc6856c6SDarrick J. Wong {
251*fc6856c6SDarrick J. Wong 	unsigned int		d_maxlevels, r_maxlevels;
252*fc6856c6SDarrick J. Wong 
253*fc6856c6SDarrick J. Wong 	if (!xfs_has_rtrmapbt(mp)) {
254*fc6856c6SDarrick J. Wong 		mp->m_rtrmap_maxlevels = 0;
255*fc6856c6SDarrick J. Wong 		return;
256*fc6856c6SDarrick J. Wong 	}
257*fc6856c6SDarrick J. Wong 
258*fc6856c6SDarrick J. Wong 	/*
259*fc6856c6SDarrick J. Wong 	 * The realtime rmapbt lives on the data device, which means that its
260*fc6856c6SDarrick J. Wong 	 * maximum height is constrained by the size of the data device and
261*fc6856c6SDarrick J. Wong 	 * the height required to store one rmap record for each block in an
262*fc6856c6SDarrick J. Wong 	 * rt group.
263*fc6856c6SDarrick J. Wong 	 */
264*fc6856c6SDarrick J. Wong 	d_maxlevels = xfs_btree_space_to_height(mp->m_rtrmap_mnr,
265*fc6856c6SDarrick J. Wong 				mp->m_sb.sb_dblocks);
266*fc6856c6SDarrick J. Wong 	r_maxlevels = xfs_btree_compute_maxlevels(mp->m_rtrmap_mnr,
267*fc6856c6SDarrick J. Wong 				mp->m_groups[XG_TYPE_RTG].blocks);
268*fc6856c6SDarrick J. Wong 
269*fc6856c6SDarrick J. Wong 	/* Add one level to handle the inode root level. */
270*fc6856c6SDarrick J. Wong 	mp->m_rtrmap_maxlevels = min(d_maxlevels, r_maxlevels) + 1;
271*fc6856c6SDarrick J. Wong }
272