1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2017-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_inode.h" 14 #include "xfs_log_format.h" 15 #include "xfs_trans.h" 16 #include "xfs_rtbitmap.h" 17 #include "xfs_bit.h" 18 #include "xfs_bmap.h" 19 #include "xfs_sb.h" 20 #include "xfs_exchmaps.h" 21 #include "scrub/scrub.h" 22 #include "scrub/common.h" 23 #include "scrub/trace.h" 24 #include "scrub/xfile.h" 25 #include "scrub/repair.h" 26 #include "scrub/tempexch.h" 27 #include "scrub/rtsummary.h" 28 29 /* 30 * Realtime Summary 31 * ================ 32 * 33 * We check the realtime summary by scanning the realtime bitmap file to create 34 * a new summary file incore, and then we compare the computed version against 35 * the ondisk version. We use the 'xfile' functionality to store this 36 * (potentially large) amount of data in pageable memory. 37 */ 38 39 /* Set us up to check the rtsummary file. */ 40 int 41 xchk_setup_rtsummary( 42 struct xfs_scrub *sc) 43 { 44 struct xfs_mount *mp = sc->mp; 45 char *descr; 46 struct xchk_rtsummary *rts; 47 int error; 48 49 rts = kvzalloc(struct_size(rts, words, mp->m_blockwsize), 50 XCHK_GFP_FLAGS); 51 if (!rts) 52 return -ENOMEM; 53 sc->buf = rts; 54 55 if (xchk_could_repair(sc)) { 56 error = xrep_setup_rtsummary(sc, rts); 57 if (error) 58 return error; 59 } 60 61 /* 62 * Create an xfile to construct a new rtsummary file. The xfile allows 63 * us to avoid pinning kernel memory for this purpose. 64 */ 65 descr = xchk_xfile_descr(sc, "realtime summary file"); 66 error = xfile_create(descr, XFS_FSB_TO_B(mp, mp->m_rsumblocks), 67 &sc->xfile); 68 kfree(descr); 69 if (error) 70 return error; 71 72 error = xchk_trans_alloc(sc, rts->resblks); 73 if (error) 74 return error; 75 76 error = xchk_install_live_inode(sc, mp->m_rsumip); 77 if (error) 78 return error; 79 80 error = xchk_ino_dqattach(sc); 81 if (error) 82 return error; 83 84 /* 85 * Locking order requires us to take the rtbitmap first. We must be 86 * careful to unlock it ourselves when we are done with the rtbitmap 87 * file since the scrub infrastructure won't do that for us. Only 88 * then we can lock the rtsummary inode. 89 */ 90 xfs_ilock(mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP); 91 xchk_ilock(sc, XFS_ILOCK_EXCL | XFS_ILOCK_RTSUM); 92 93 /* 94 * Now that we've locked the rtbitmap and rtsummary, we can't race with 95 * growfsrt trying to expand the summary or change the size of the rt 96 * volume. Hence it is safe to compute and check the geometry values. 97 */ 98 if (mp->m_sb.sb_rblocks) { 99 int rextslog; 100 101 rts->rextents = xfs_rtb_to_rtx(mp, mp->m_sb.sb_rblocks); 102 rextslog = xfs_compute_rextslog(rts->rextents); 103 rts->rsumlevels = rextslog + 1; 104 rts->rbmblocks = xfs_rtbitmap_blockcount(mp, rts->rextents); 105 rts->rsumblocks = xfs_rtsummary_blockcount(mp, rts->rsumlevels, 106 rts->rbmblocks); 107 } 108 return 0; 109 } 110 111 /* Helper functions to record suminfo words in an xfile. */ 112 113 static inline int 114 xfsum_load( 115 struct xfs_scrub *sc, 116 xfs_rtsumoff_t sumoff, 117 union xfs_suminfo_raw *rawinfo) 118 { 119 return xfile_load(sc->xfile, rawinfo, 120 sizeof(union xfs_suminfo_raw), 121 sumoff << XFS_WORDLOG); 122 } 123 124 static inline int 125 xfsum_store( 126 struct xfs_scrub *sc, 127 xfs_rtsumoff_t sumoff, 128 const union xfs_suminfo_raw rawinfo) 129 { 130 return xfile_store(sc->xfile, &rawinfo, 131 sizeof(union xfs_suminfo_raw), 132 sumoff << XFS_WORDLOG); 133 } 134 135 inline int 136 xfsum_copyout( 137 struct xfs_scrub *sc, 138 xfs_rtsumoff_t sumoff, 139 union xfs_suminfo_raw *rawinfo, 140 unsigned int nr_words) 141 { 142 return xfile_load(sc->xfile, rawinfo, nr_words << XFS_WORDLOG, 143 sumoff << XFS_WORDLOG); 144 } 145 146 static inline xfs_suminfo_t 147 xchk_rtsum_inc( 148 struct xfs_mount *mp, 149 union xfs_suminfo_raw *v) 150 { 151 v->old += 1; 152 return v->old; 153 } 154 155 /* Update the summary file to reflect the free extent that we've accumulated. */ 156 STATIC int 157 xchk_rtsum_record_free( 158 struct xfs_mount *mp, 159 struct xfs_trans *tp, 160 const struct xfs_rtalloc_rec *rec, 161 void *priv) 162 { 163 struct xfs_scrub *sc = priv; 164 xfs_fileoff_t rbmoff; 165 xfs_rtblock_t rtbno; 166 xfs_filblks_t rtlen; 167 xfs_rtsumoff_t offs; 168 unsigned int lenlog; 169 union xfs_suminfo_raw v; 170 xfs_suminfo_t value; 171 int error = 0; 172 173 if (xchk_should_terminate(sc, &error)) 174 return error; 175 176 /* Compute the relevant location in the rtsum file. */ 177 rbmoff = xfs_rtx_to_rbmblock(mp, rec->ar_startext); 178 lenlog = xfs_highbit64(rec->ar_extcount); 179 offs = xfs_rtsumoffs(mp, lenlog, rbmoff); 180 181 rtbno = xfs_rtx_to_rtb(mp, rec->ar_startext); 182 rtlen = xfs_rtx_to_rtb(mp, rec->ar_extcount); 183 184 if (!xfs_verify_rtbext(mp, rtbno, rtlen)) { 185 xchk_ino_xref_set_corrupt(sc, mp->m_rbmip->i_ino); 186 return -EFSCORRUPTED; 187 } 188 189 /* Bump the summary count. */ 190 error = xfsum_load(sc, offs, &v); 191 if (error) 192 return error; 193 194 value = xchk_rtsum_inc(sc->mp, &v); 195 trace_xchk_rtsum_record_free(mp, rec->ar_startext, rec->ar_extcount, 196 lenlog, offs, value); 197 198 return xfsum_store(sc, offs, v); 199 } 200 201 /* Compute the realtime summary from the realtime bitmap. */ 202 STATIC int 203 xchk_rtsum_compute( 204 struct xfs_scrub *sc) 205 { 206 struct xfs_mount *mp = sc->mp; 207 unsigned long long rtbmp_blocks; 208 209 /* If the bitmap size doesn't match the computed size, bail. */ 210 rtbmp_blocks = xfs_rtbitmap_blockcount(mp, mp->m_sb.sb_rextents); 211 if (XFS_FSB_TO_B(mp, rtbmp_blocks) != mp->m_rbmip->i_disk_size) 212 return -EFSCORRUPTED; 213 214 return xfs_rtalloc_query_all(sc->mp, sc->tp, xchk_rtsum_record_free, 215 sc); 216 } 217 218 /* Compare the rtsummary file against the one we computed. */ 219 STATIC int 220 xchk_rtsum_compare( 221 struct xfs_scrub *sc) 222 { 223 struct xfs_bmbt_irec map; 224 struct xfs_iext_cursor icur; 225 226 struct xfs_mount *mp = sc->mp; 227 struct xfs_inode *ip = sc->ip; 228 struct xchk_rtsummary *rts = sc->buf; 229 xfs_fileoff_t off = 0; 230 xfs_fileoff_t endoff; 231 xfs_rtsumoff_t sumoff = 0; 232 int error = 0; 233 234 rts->args.mp = sc->mp; 235 rts->args.tp = sc->tp; 236 237 /* Mappings may not cross or lie beyond EOF. */ 238 endoff = XFS_B_TO_FSB(mp, ip->i_disk_size); 239 if (xfs_iext_lookup_extent(ip, &ip->i_df, endoff, &icur, &map)) { 240 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, endoff); 241 return 0; 242 } 243 244 while (off < endoff) { 245 int nmap = 1; 246 247 if (xchk_should_terminate(sc, &error)) 248 return error; 249 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 250 return 0; 251 252 /* Make sure we have a written extent. */ 253 error = xfs_bmapi_read(ip, off, endoff - off, &map, &nmap, 254 XFS_DATA_FORK); 255 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, off, &error)) 256 return error; 257 258 if (nmap != 1 || !xfs_bmap_is_written_extent(&map)) { 259 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, off); 260 return 0; 261 } 262 263 off += map.br_blockcount; 264 } 265 266 for (off = 0; off < endoff; off++) { 267 union xfs_suminfo_raw *ondisk_info; 268 269 /* Read a block's worth of ondisk rtsummary file. */ 270 error = xfs_rtsummary_read_buf(&rts->args, off); 271 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, off, &error)) 272 return error; 273 274 /* Read a block's worth of computed rtsummary file. */ 275 error = xfsum_copyout(sc, sumoff, rts->words, mp->m_blockwsize); 276 if (error) { 277 xfs_rtbuf_cache_relse(&rts->args); 278 return error; 279 } 280 281 ondisk_info = xfs_rsumblock_infoptr(&rts->args, 0); 282 if (memcmp(ondisk_info, rts->words, 283 mp->m_blockwsize << XFS_WORDLOG) != 0) { 284 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, off); 285 xfs_rtbuf_cache_relse(&rts->args); 286 return error; 287 } 288 289 xfs_rtbuf_cache_relse(&rts->args); 290 sumoff += mp->m_blockwsize; 291 } 292 293 return 0; 294 } 295 296 /* Scrub the realtime summary. */ 297 int 298 xchk_rtsummary( 299 struct xfs_scrub *sc) 300 { 301 struct xfs_mount *mp = sc->mp; 302 struct xchk_rtsummary *rts = sc->buf; 303 int error = 0; 304 305 /* Is sb_rextents correct? */ 306 if (mp->m_sb.sb_rextents != rts->rextents) { 307 xchk_ino_set_corrupt(sc, mp->m_rbmip->i_ino); 308 goto out_rbm; 309 } 310 311 /* Is m_rsumlevels correct? */ 312 if (mp->m_rsumlevels != rts->rsumlevels) { 313 xchk_ino_set_corrupt(sc, mp->m_rsumip->i_ino); 314 goto out_rbm; 315 } 316 317 /* Is m_rsumsize correct? */ 318 if (mp->m_rsumblocks != rts->rsumblocks) { 319 xchk_ino_set_corrupt(sc, mp->m_rsumip->i_ino); 320 goto out_rbm; 321 } 322 323 /* The summary file length must be aligned to an fsblock. */ 324 if (mp->m_rsumip->i_disk_size & mp->m_blockmask) { 325 xchk_ino_set_corrupt(sc, mp->m_rsumip->i_ino); 326 goto out_rbm; 327 } 328 329 /* 330 * Is the summary file itself large enough to handle the rt volume? 331 * growfsrt expands the summary file before updating sb_rextents, so 332 * the file can be larger than rsumsize. 333 */ 334 if (mp->m_rsumip->i_disk_size < XFS_FSB_TO_B(mp, rts->rsumblocks)) { 335 xchk_ino_set_corrupt(sc, mp->m_rsumip->i_ino); 336 goto out_rbm; 337 } 338 339 /* Invoke the fork scrubber. */ 340 error = xchk_metadata_inode_forks(sc); 341 if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) 342 goto out_rbm; 343 344 /* Construct the new summary file from the rtbitmap. */ 345 error = xchk_rtsum_compute(sc); 346 if (error == -EFSCORRUPTED) { 347 /* 348 * EFSCORRUPTED means the rtbitmap is corrupt, which is an xref 349 * error since we're checking the summary file. 350 */ 351 xchk_ino_xref_set_corrupt(sc, mp->m_rbmip->i_ino); 352 error = 0; 353 goto out_rbm; 354 } 355 if (error) 356 goto out_rbm; 357 358 /* Does the computed summary file match the actual rtsummary file? */ 359 error = xchk_rtsum_compare(sc); 360 361 out_rbm: 362 /* 363 * Unlock the rtbitmap since we're done with it. All other writers of 364 * the rt free space metadata grab the bitmap and summary ILOCKs in 365 * that order, so we're still protected against allocation activities 366 * even if we continue on to the repair function. 367 */ 368 xfs_iunlock(mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP); 369 return error; 370 } 371