xref: /kernel/linux/linux-6.6/fs/xfs/scrub/rtbitmap.c (revision 62306a36)
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_log_format.h"
13#include "xfs_trans.h"
14#include "xfs_rtalloc.h"
15#include "xfs_inode.h"
16#include "xfs_bmap.h"
17#include "scrub/scrub.h"
18#include "scrub/common.h"
19
20/* Set us up with the realtime metadata locked. */
21int
22xchk_setup_rtbitmap(
23	struct xfs_scrub	*sc)
24{
25	int			error;
26
27	error = xchk_trans_alloc(sc, 0);
28	if (error)
29		return error;
30
31	error = xchk_install_live_inode(sc, sc->mp->m_rbmip);
32	if (error)
33		return error;
34
35	xchk_ilock(sc, XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP);
36	return 0;
37}
38
39/* Realtime bitmap. */
40
41/* Scrub a free extent record from the realtime bitmap. */
42STATIC int
43xchk_rtbitmap_rec(
44	struct xfs_mount	*mp,
45	struct xfs_trans	*tp,
46	const struct xfs_rtalloc_rec *rec,
47	void			*priv)
48{
49	struct xfs_scrub	*sc = priv;
50	xfs_rtblock_t		startblock;
51	xfs_rtblock_t		blockcount;
52
53	startblock = rec->ar_startext * mp->m_sb.sb_rextsize;
54	blockcount = rec->ar_extcount * mp->m_sb.sb_rextsize;
55
56	if (!xfs_verify_rtext(mp, startblock, blockcount))
57		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
58	return 0;
59}
60
61/* Make sure the entire rtbitmap file is mapped with written extents. */
62STATIC int
63xchk_rtbitmap_check_extents(
64	struct xfs_scrub	*sc)
65{
66	struct xfs_mount	*mp = sc->mp;
67	struct xfs_bmbt_irec	map;
68	xfs_rtblock_t		off;
69	int			nmap;
70	int			error = 0;
71
72	for (off = 0; off < mp->m_sb.sb_rbmblocks;) {
73		if (xchk_should_terminate(sc, &error) ||
74		    (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
75			break;
76
77		/* Make sure we have a written extent. */
78		nmap = 1;
79		error = xfs_bmapi_read(mp->m_rbmip, off,
80				mp->m_sb.sb_rbmblocks - off, &map, &nmap,
81				XFS_DATA_FORK);
82		if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, off, &error))
83			break;
84
85		if (nmap != 1 || !xfs_bmap_is_written_extent(&map)) {
86			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, off);
87			break;
88		}
89
90		off += map.br_blockcount;
91	}
92
93	return error;
94}
95
96/* Scrub the realtime bitmap. */
97int
98xchk_rtbitmap(
99	struct xfs_scrub	*sc)
100{
101	int			error;
102
103	/* Is the size of the rtbitmap correct? */
104	if (sc->mp->m_rbmip->i_disk_size !=
105	    XFS_FSB_TO_B(sc->mp, sc->mp->m_sb.sb_rbmblocks)) {
106		xchk_ino_set_corrupt(sc, sc->mp->m_rbmip->i_ino);
107		return 0;
108	}
109
110	/* Invoke the fork scrubber. */
111	error = xchk_metadata_inode_forks(sc);
112	if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
113		return error;
114
115	error = xchk_rtbitmap_check_extents(sc);
116	if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
117		return error;
118
119	error = xfs_rtalloc_query_all(sc->mp, sc->tp, xchk_rtbitmap_rec, sc);
120	if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
121		goto out;
122
123out:
124	return error;
125}
126
127/* xref check that the extent is not free in the rtbitmap */
128void
129xchk_xref_is_used_rt_space(
130	struct xfs_scrub	*sc,
131	xfs_rtblock_t		fsbno,
132	xfs_extlen_t		len)
133{
134	xfs_rtblock_t		startext;
135	xfs_rtblock_t		endext;
136	xfs_rtblock_t		extcount;
137	bool			is_free;
138	int			error;
139
140	if (xchk_skip_xref(sc->sm))
141		return;
142
143	startext = fsbno;
144	endext = fsbno + len - 1;
145	do_div(startext, sc->mp->m_sb.sb_rextsize);
146	do_div(endext, sc->mp->m_sb.sb_rextsize);
147	extcount = endext - startext + 1;
148	xfs_ilock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
149	error = xfs_rtalloc_extent_is_free(sc->mp, sc->tp, startext, extcount,
150			&is_free);
151	if (!xchk_should_check_xref(sc, &error, NULL))
152		goto out_unlock;
153	if (is_free)
154		xchk_ino_xref_set_corrupt(sc, sc->mp->m_rbmip->i_ino);
155out_unlock:
156	xfs_iunlock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
157}
158