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