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