brintos

brintos / linux-shallow public Read only

0
0
Text · 5.6 KiB · 4658351 Raw
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