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 24060 : xchk_setup_rtbitmap(
24 : struct xfs_scrub *sc)
25 : {
26 24060 : unsigned int resblks = 0;
27 24060 : int error;
28 :
29 48120 : if (xchk_could_repair(sc)) {
30 949 : error = xrep_setup_rtbitmap(sc, &resblks);
31 949 : if (error)
32 : return error;
33 : }
34 :
35 24060 : error = xchk_trans_alloc(sc, resblks);
36 24060 : if (error)
37 : return error;
38 :
39 24060 : error = xchk_install_live_inode(sc, sc->mp->m_rbmip);
40 24060 : if (error)
41 : return error;
42 :
43 24060 : error = xchk_ino_dqattach(sc);
44 24060 : if (error)
45 : return error;
46 :
47 24060 : xchk_ilock(sc, XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP);
48 24060 : return 0;
49 : }
50 :
51 : /* Realtime bitmap. */
52 :
53 : /* Scrub a free extent record from the realtime bitmap. */
54 : STATIC int
55 10146368 : 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 10146368 : struct xfs_scrub *sc = priv;
62 10146368 : xfs_rtblock_t startblock;
63 10146368 : xfs_rtblock_t blockcount;
64 :
65 10146368 : startblock = rec->ar_startext * mp->m_sb.sb_rextsize;
66 10146368 : blockcount = rec->ar_extcount * mp->m_sb.sb_rextsize;
67 :
68 10146368 : if (!xfs_verify_rtext(mp, startblock, blockcount))
69 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
70 10146368 : return 0;
71 : }
72 :
73 : /* Make sure the entire rtbitmap file is mapped with written extents. */
74 : STATIC int
75 24060 : xchk_rtbitmap_check_extents(
76 : struct xfs_scrub *sc)
77 : {
78 24060 : struct xfs_mount *mp = sc->mp;
79 24060 : struct xfs_bmbt_irec map;
80 24060 : xfs_rtblock_t off;
81 24060 : int nmap;
82 24060 : int error = 0;
83 :
84 48121 : for (off = 0; off < mp->m_sb.sb_rbmblocks;) {
85 24061 : if (xchk_should_terminate(sc, &error) ||
86 24061 : (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
87 : break;
88 :
89 : /* Make sure we have a written extent. */
90 24061 : nmap = 1;
91 48122 : error = xfs_bmapi_read(mp->m_rbmip, off,
92 24061 : mp->m_sb.sb_rbmblocks - off, &map, &nmap,
93 : XFS_DATA_FORK);
94 24061 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, off, &error))
95 : break;
96 :
97 24061 : 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 24061 : off += map.br_blockcount;
103 : }
104 :
105 24060 : return error;
106 : }
107 :
108 : /* Scrub the realtime bitmap. */
109 : int
110 24060 : xchk_rtbitmap(
111 : struct xfs_scrub *sc)
112 : {
113 24060 : int error;
114 :
115 : /* Is the size of the rtbitmap correct? */
116 24060 : if (sc->mp->m_rbmip->i_disk_size !=
117 24060 : 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 24060 : error = xchk_metadata_inode_forks(sc);
124 24060 : if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
125 : return error;
126 :
127 24060 : error = xchk_rtbitmap_check_extents(sc);
128 24060 : if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
129 : return error;
130 :
131 24060 : error = xfs_rtalloc_query_all(sc->mp, sc->tp, xchk_rtbitmap_rec, sc);
132 24060 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
133 : goto out;
134 :
135 : out:
136 24060 : return error;
137 : }
138 :
139 : /* xref check that the extent is not free in the rtbitmap */
140 : void
141 41372815 : xchk_xref_is_used_rt_space(
142 : struct xfs_scrub *sc,
143 : xfs_rtblock_t fsbno,
144 : xfs_extlen_t len)
145 : {
146 41372815 : xfs_rtblock_t startext;
147 41372815 : xfs_rtblock_t endext;
148 41372815 : xfs_rtblock_t extcount;
149 41372815 : bool is_free;
150 41372815 : int error;
151 :
152 41372815 : if (xchk_skip_xref(sc->sm))
153 0 : return;
154 :
155 41372815 : startext = fsbno;
156 41372815 : endext = fsbno + len - 1;
157 41372815 : do_div(startext, sc->mp->m_sb.sb_rextsize);
158 41372815 : do_div(endext, sc->mp->m_sb.sb_rextsize);
159 41372815 : extcount = endext - startext + 1;
160 41372815 : xfs_ilock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
161 41376578 : error = xfs_rtalloc_extent_is_free(sc->mp, sc->tp, startext, extcount,
162 : &is_free);
163 41377957 : if (!xchk_should_check_xref(sc, &error, NULL))
164 0 : goto out_unlock;
165 41378106 : if (is_free)
166 0 : xchk_ino_xref_set_corrupt(sc, sc->mp->m_rbmip->i_ino);
167 41378106 : out_unlock:
168 41378106 : xfs_iunlock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
169 : }
|