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