1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2017 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
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"
17 #include "scrub/scrub.h"
18 #include "scrub/common.h"
20 /* Set us up with the realtime metadata locked. */
28 error
= xchk_setup_fs(sc
, ip
);
32 sc
->ilock_flags
= XFS_ILOCK_EXCL
| XFS_ILOCK_RTBITMAP
;
33 sc
->ip
= sc
->mp
->m_rbmip
;
34 xfs_ilock(sc
->ip
, sc
->ilock_flags
);
39 /* Realtime bitmap. */
41 /* Scrub a free extent record from the realtime bitmap. */
45 struct xfs_rtalloc_rec
*rec
,
48 struct xfs_scrub
*sc
= priv
;
49 xfs_rtblock_t startblock
;
50 xfs_rtblock_t blockcount
;
52 startblock
= rec
->ar_startext
* tp
->t_mountp
->m_sb
.sb_rextsize
;
53 blockcount
= rec
->ar_extcount
* tp
->t_mountp
->m_sb
.sb_rextsize
;
55 if (!xfs_verify_rtext(sc
->mp
, startblock
, blockcount
))
56 xchk_fblock_set_corrupt(sc
, XFS_DATA_FORK
, 0);
60 /* Make sure the entire rtbitmap file is mapped with written extents. */
62 xchk_rtbitmap_check_extents(
65 struct xfs_mount
*mp
= sc
->mp
;
66 struct xfs_bmbt_irec map
;
71 for (off
= 0; off
< mp
->m_sb
.sb_rbmblocks
;) {
72 if (xchk_should_terminate(sc
, &error
) ||
73 (sc
->sm
->sm_flags
& XFS_SCRUB_OFLAG_CORRUPT
))
76 /* Make sure we have a written extent. */
78 error
= xfs_bmapi_read(mp
->m_rbmip
, off
,
79 mp
->m_sb
.sb_rbmblocks
- off
, &map
, &nmap
,
81 if (!xchk_fblock_process_error(sc
, XFS_DATA_FORK
, off
, &error
))
84 if (nmap
!= 1 || !xfs_bmap_is_written_extent(&map
)) {
85 xchk_fblock_set_corrupt(sc
, XFS_DATA_FORK
, off
);
89 off
+= map
.br_blockcount
;
95 /* Scrub the realtime bitmap. */
102 /* Is the size of the rtbitmap correct? */
103 if (sc
->mp
->m_rbmip
->i_d
.di_size
!=
104 XFS_FSB_TO_B(sc
->mp
, sc
->mp
->m_sb
.sb_rbmblocks
)) {
105 xchk_ino_set_corrupt(sc
, sc
->mp
->m_rbmip
->i_ino
);
109 /* Invoke the fork scrubber. */
110 error
= xchk_metadata_inode_forks(sc
);
111 if (error
|| (sc
->sm
->sm_flags
& XFS_SCRUB_OFLAG_CORRUPT
))
114 error
= xchk_rtbitmap_check_extents(sc
);
115 if (error
|| (sc
->sm
->sm_flags
& XFS_SCRUB_OFLAG_CORRUPT
))
118 error
= xfs_rtalloc_query_all(sc
->tp
, xchk_rtbitmap_rec
, sc
);
119 if (!xchk_fblock_process_error(sc
, XFS_DATA_FORK
, 0, &error
))
126 /* Scrub the realtime summary. */
129 struct xfs_scrub
*sc
)
131 struct xfs_inode
*rsumip
= sc
->mp
->m_rsumip
;
132 struct xfs_inode
*old_ip
= sc
->ip
;
133 uint old_ilock_flags
= sc
->ilock_flags
;
137 * We ILOCK'd the rt bitmap ip in the setup routine, now lock the
138 * rt summary ip in compliance with the rt inode locking rules.
140 * Since we switch sc->ip to rsumip we have to save the old ilock
141 * flags so that we don't mix up the inode state that @sc tracks.
144 sc
->ilock_flags
= XFS_ILOCK_EXCL
| XFS_ILOCK_RTSUM
;
145 xfs_ilock(sc
->ip
, sc
->ilock_flags
);
147 /* Invoke the fork scrubber. */
148 error
= xchk_metadata_inode_forks(sc
);
149 if (error
|| (sc
->sm
->sm_flags
& XFS_SCRUB_OFLAG_CORRUPT
))
152 /* XXX: implement this some day */
153 xchk_set_incomplete(sc
);
155 /* Switch back to the rtbitmap inode and lock flags. */
156 xfs_iunlock(sc
->ip
, sc
->ilock_flags
);
157 sc
->ilock_flags
= old_ilock_flags
;
163 /* xref check that the extent is not free in the rtbitmap */
165 xchk_xref_is_used_rt_space(
166 struct xfs_scrub
*sc
,
170 xfs_rtblock_t startext
;
171 xfs_rtblock_t endext
;
172 xfs_rtblock_t extcount
;
176 if (xchk_skip_xref(sc
->sm
))
180 endext
= fsbno
+ len
- 1;
181 do_div(startext
, sc
->mp
->m_sb
.sb_rextsize
);
182 do_div(endext
, sc
->mp
->m_sb
.sb_rextsize
);
183 extcount
= endext
- startext
+ 1;
184 xfs_ilock(sc
->mp
->m_rbmip
, XFS_ILOCK_SHARED
| XFS_ILOCK_RTBITMAP
);
185 error
= xfs_rtalloc_extent_is_free(sc
->mp
, sc
->tp
, startext
, extcount
,
187 if (!xchk_should_check_xref(sc
, &error
, NULL
))
190 xchk_ino_xref_set_corrupt(sc
, sc
->mp
->m_rbmip
->i_ino
);
192 xfs_iunlock(sc
->mp
->m_rbmip
, XFS_ILOCK_SHARED
| XFS_ILOCK_RTBITMAP
);