1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2020-2023 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_trans_resv.h" 11 #include "xfs_mount.h" 12 #include "xfs_btree.h" 13 #include "xfs_log_format.h" 14 #include "xfs_trans.h" 15 #include "xfs_inode.h" 16 #include "xfs_bit.h" 17 #include "xfs_bmap.h" 18 #include "xfs_bmap_btree.h" 19 #include "scrub/scrub.h" 20 #include "scrub/common.h" 21 #include "scrub/trace.h" 22 #include "scrub/repair.h" 23 #include "scrub/xfile.h" 24 #include "scrub/rtbitmap.h" 25 26 /* Set up to repair the realtime bitmap file metadata. */ 27 int 28 xrep_setup_rtbitmap( 29 struct xfs_scrub *sc, 30 struct xchk_rtbitmap *rtb) 31 { 32 struct xfs_mount *mp = sc->mp; 33 unsigned long long blocks = 0; 34 35 /* 36 * Reserve enough blocks to write out a completely new bmbt for a 37 * maximally fragmented bitmap file. We do not hold the rtbitmap 38 * ILOCK yet, so this is entirely speculative. 39 */ 40 blocks = xfs_bmbt_calc_size(mp, mp->m_sb.sb_rbmblocks); 41 if (blocks > UINT_MAX) 42 return -EOPNOTSUPP; 43 44 rtb->resblks += blocks; 45 return 0; 46 } 47 48 /* 49 * Make sure that the given range of the data fork of the realtime file is 50 * mapped to written blocks. The caller must ensure that the inode is joined 51 * to the transaction. 52 */ 53 STATIC int 54 xrep_rtbitmap_data_mappings( 55 struct xfs_scrub *sc, 56 xfs_filblks_t len) 57 { 58 struct xfs_bmbt_irec map; 59 xfs_fileoff_t off = 0; 60 int error; 61 62 ASSERT(sc->ip != NULL); 63 64 while (off < len) { 65 int nmaps = 1; 66 67 /* 68 * If we have a real extent mapping this block then we're 69 * in ok shape. 70 */ 71 error = xfs_bmapi_read(sc->ip, off, len - off, &map, &nmaps, 72 XFS_DATA_FORK); 73 if (error) 74 return error; 75 if (nmaps == 0) { 76 ASSERT(nmaps != 0); 77 return -EFSCORRUPTED; 78 } 79 80 /* 81 * Written extents are ok. Holes are not filled because we 82 * do not know the freespace information. 83 */ 84 if (xfs_bmap_is_written_extent(&map) || 85 map.br_startblock == HOLESTARTBLOCK) { 86 off = map.br_startoff + map.br_blockcount; 87 continue; 88 } 89 90 /* 91 * If we find a delalloc reservation then something is very 92 * very wrong. Bail out. 93 */ 94 if (map.br_startblock == DELAYSTARTBLOCK) 95 return -EFSCORRUPTED; 96 97 /* Make sure we're really converting an unwritten extent. */ 98 if (map.br_state != XFS_EXT_UNWRITTEN) { 99 ASSERT(map.br_state == XFS_EXT_UNWRITTEN); 100 return -EFSCORRUPTED; 101 } 102 103 /* Make sure this block has a real zeroed extent mapped. */ 104 nmaps = 1; 105 error = xfs_bmapi_write(sc->tp, sc->ip, map.br_startoff, 106 map.br_blockcount, 107 XFS_BMAPI_CONVERT | XFS_BMAPI_ZERO, 108 0, &map, &nmaps); 109 if (error) 110 return error; 111 112 /* Commit new extent and all deferred work. */ 113 error = xrep_defer_finish(sc); 114 if (error) 115 return error; 116 117 off = map.br_startoff + map.br_blockcount; 118 } 119 120 return 0; 121 } 122 123 /* Fix broken rt volume geometry. */ 124 STATIC int 125 xrep_rtbitmap_geometry( 126 struct xfs_scrub *sc, 127 struct xchk_rtbitmap *rtb) 128 { 129 struct xfs_mount *mp = sc->mp; 130 struct xfs_trans *tp = sc->tp; 131 132 /* Superblock fields */ 133 if (mp->m_sb.sb_rextents != rtb->rextents) 134 xfs_trans_mod_sb(sc->tp, XFS_TRANS_SB_REXTENTS, 135 rtb->rextents - mp->m_sb.sb_rextents); 136 137 if (mp->m_sb.sb_rbmblocks != rtb->rbmblocks) 138 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBMBLOCKS, 139 rtb->rbmblocks - mp->m_sb.sb_rbmblocks); 140 141 if (mp->m_sb.sb_rextslog != rtb->rextslog) 142 xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSLOG, 143 rtb->rextslog - mp->m_sb.sb_rextslog); 144 145 /* Fix broken isize */ 146 sc->ip->i_disk_size = roundup_64(sc->ip->i_disk_size, 147 mp->m_sb.sb_blocksize); 148 149 if (sc->ip->i_disk_size < XFS_FSB_TO_B(mp, rtb->rbmblocks)) 150 sc->ip->i_disk_size = XFS_FSB_TO_B(mp, rtb->rbmblocks); 151 152 xfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE); 153 return xrep_roll_trans(sc); 154 } 155 156 /* Repair the realtime bitmap file metadata. */ 157 int 158 xrep_rtbitmap( 159 struct xfs_scrub *sc) 160 { 161 struct xchk_rtbitmap *rtb = sc->buf; 162 struct xfs_mount *mp = sc->mp; 163 unsigned long long blocks = 0; 164 int error; 165 166 /* Impossibly large rtbitmap means we can't touch the filesystem. */ 167 if (rtb->rbmblocks > U32_MAX) 168 return 0; 169 170 /* 171 * If the size of the rt bitmap file is larger than what we reserved, 172 * figure out if we need to adjust the block reservation in the 173 * transaction. 174 */ 175 blocks = xfs_bmbt_calc_size(mp, rtb->rbmblocks); 176 if (blocks > UINT_MAX) 177 return -EOPNOTSUPP; 178 if (blocks > rtb->resblks) { 179 error = xfs_trans_reserve_more(sc->tp, blocks, 0); 180 if (error) 181 return error; 182 183 rtb->resblks += blocks; 184 } 185 186 /* Fix inode core and forks. */ 187 error = xrep_metadata_inode_forks(sc); 188 if (error) 189 return error; 190 191 xfs_trans_ijoin(sc->tp, sc->ip, 0); 192 193 /* Ensure no unwritten extents. */ 194 error = xrep_rtbitmap_data_mappings(sc, rtb->rbmblocks); 195 if (error) 196 return error; 197 198 /* Fix inconsistent bitmap geometry */ 199 return xrep_rtbitmap_geometry(sc, rtb); 200 } 201
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.