230 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*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_log_format.h"13#include "xfs_trans.h"14#include "xfs_rtbitmap.h"15#include "xfs_inode.h"16#include "xfs_bmap.h"17#include "xfs_bit.h"18#include "xfs_sb.h"19#include "scrub/scrub.h"20#include "scrub/common.h"21#include "scrub/repair.h"22#include "scrub/rtbitmap.h"23 24/* Set us up with the realtime metadata locked. */25int26xchk_setup_rtbitmap(27 struct xfs_scrub *sc)28{29 struct xfs_mount *mp = sc->mp;30 struct xchk_rtbitmap *rtb;31 int error;32 33 rtb = kzalloc(sizeof(struct xchk_rtbitmap), XCHK_GFP_FLAGS);34 if (!rtb)35 return -ENOMEM;36 sc->buf = rtb;37 38 if (xchk_could_repair(sc)) {39 error = xrep_setup_rtbitmap(sc, rtb);40 if (error)41 return error;42 }43 44 error = xchk_trans_alloc(sc, rtb->resblks);45 if (error)46 return error;47 48 error = xchk_install_live_inode(sc, sc->mp->m_rbmip);49 if (error)50 return error;51 52 error = xchk_ino_dqattach(sc);53 if (error)54 return error;55 56 xchk_ilock(sc, XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP);57 58 /*59 * Now that we've locked the rtbitmap, we can't race with growfsrt60 * trying to expand the bitmap or change the size of the rt volume.61 * Hence it is safe to compute and check the geometry values.62 */63 if (mp->m_sb.sb_rblocks) {64 rtb->rextents = xfs_rtb_to_rtx(mp, mp->m_sb.sb_rblocks);65 rtb->rextslog = xfs_compute_rextslog(rtb->rextents);66 rtb->rbmblocks = xfs_rtbitmap_blockcount(mp, rtb->rextents);67 }68 return 0;69}70 71/* Realtime bitmap. */72 73/* Scrub a free extent record from the realtime bitmap. */74STATIC int75xchk_rtbitmap_rec(76 struct xfs_mount *mp,77 struct xfs_trans *tp,78 const struct xfs_rtalloc_rec *rec,79 void *priv)80{81 struct xfs_scrub *sc = priv;82 xfs_rtblock_t startblock;83 xfs_filblks_t blockcount;84 85 startblock = xfs_rtx_to_rtb(mp, rec->ar_startext);86 blockcount = xfs_rtx_to_rtb(mp, rec->ar_extcount);87 88 if (!xfs_verify_rtbext(mp, startblock, blockcount))89 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);90 return 0;91}92 93/* Make sure the entire rtbitmap file is mapped with written extents. */94STATIC int95xchk_rtbitmap_check_extents(96 struct xfs_scrub *sc)97{98 struct xfs_bmbt_irec map;99 struct xfs_iext_cursor icur;100 struct xfs_mount *mp = sc->mp;101 struct xfs_inode *ip = sc->ip;102 xfs_fileoff_t off = 0;103 xfs_fileoff_t endoff;104 int error = 0;105 106 /* Mappings may not cross or lie beyond EOF. */107 endoff = XFS_B_TO_FSB(mp, ip->i_disk_size);108 if (xfs_iext_lookup_extent(ip, &ip->i_df, endoff, &icur, &map)) {109 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, endoff);110 return 0;111 }112 113 while (off < endoff) {114 int nmap = 1;115 116 if (xchk_should_terminate(sc, &error) ||117 (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))118 break;119 120 /* Make sure we have a written extent. */121 error = xfs_bmapi_read(ip, off, endoff - off, &map, &nmap,122 XFS_DATA_FORK);123 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, off, &error))124 break;125 126 if (nmap != 1 || !xfs_bmap_is_written_extent(&map)) {127 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, off);128 break;129 }130 131 off += map.br_blockcount;132 }133 134 return error;135}136 137/* Scrub the realtime bitmap. */138int139xchk_rtbitmap(140 struct xfs_scrub *sc)141{142 struct xfs_mount *mp = sc->mp;143 struct xchk_rtbitmap *rtb = sc->buf;144 int error;145 146 /* Is sb_rextents correct? */147 if (mp->m_sb.sb_rextents != rtb->rextents) {148 xchk_ino_set_corrupt(sc, mp->m_rbmip->i_ino);149 return 0;150 }151 152 /* Is sb_rextslog correct? */153 if (mp->m_sb.sb_rextslog != rtb->rextslog) {154 xchk_ino_set_corrupt(sc, mp->m_rbmip->i_ino);155 return 0;156 }157 158 /*159 * Is sb_rbmblocks large enough to handle the current rt volume? In no160 * case can we exceed 4bn bitmap blocks since the super field is a u32.161 */162 if (rtb->rbmblocks > U32_MAX) {163 xchk_ino_set_corrupt(sc, mp->m_rbmip->i_ino);164 return 0;165 }166 if (mp->m_sb.sb_rbmblocks != rtb->rbmblocks) {167 xchk_ino_set_corrupt(sc, mp->m_rbmip->i_ino);168 return 0;169 }170 171 /* The bitmap file length must be aligned to an fsblock. */172 if (mp->m_rbmip->i_disk_size & mp->m_blockmask) {173 xchk_ino_set_corrupt(sc, mp->m_rbmip->i_ino);174 return 0;175 }176 177 /*178 * Is the bitmap file itself large enough to handle the rt volume?179 * growfsrt expands the bitmap file before updating sb_rextents, so the180 * file can be larger than sb_rbmblocks.181 */182 if (mp->m_rbmip->i_disk_size < XFS_FSB_TO_B(mp, rtb->rbmblocks)) {183 xchk_ino_set_corrupt(sc, mp->m_rbmip->i_ino);184 return 0;185 }186 187 /* Invoke the fork scrubber. */188 error = xchk_metadata_inode_forks(sc);189 if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))190 return error;191 192 error = xchk_rtbitmap_check_extents(sc);193 if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))194 return error;195 196 error = xfs_rtalloc_query_all(mp, sc->tp, xchk_rtbitmap_rec, sc);197 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))198 return error;199 200 return 0;201}202 203/* xref check that the extent is not free in the rtbitmap */204void205xchk_xref_is_used_rt_space(206 struct xfs_scrub *sc,207 xfs_rtblock_t rtbno,208 xfs_extlen_t len)209{210 xfs_rtxnum_t startext;211 xfs_rtxnum_t endext;212 bool is_free;213 int error;214 215 if (xchk_skip_xref(sc->sm))216 return;217 218 startext = xfs_rtb_to_rtx(sc->mp, rtbno);219 endext = xfs_rtb_to_rtx(sc->mp, rtbno + len - 1);220 xfs_ilock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);221 error = xfs_rtalloc_extent_is_free(sc->mp, sc->tp, startext,222 endext - startext + 1, &is_free);223 if (!xchk_should_check_xref(sc, &error, NULL))224 goto out_unlock;225 if (is_free)226 xchk_ino_xref_set_corrupt(sc, sc->mp->m_rbmip->i_ino);227out_unlock:228 xfs_iunlock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);229}230