Commit | Line | Data |
---|---|---|
0b61f8a4 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
29b0767b DW |
2 | /* |
3 | * Copyright (C) 2017 Oracle. All Rights Reserved. | |
29b0767b | 4 | * Author: Darrick J. Wong <darrick.wong@oracle.com> |
29b0767b DW |
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_defer.h" | |
13 | #include "xfs_btree.h" | |
14 | #include "xfs_bit.h" | |
15 | #include "xfs_log_format.h" | |
16 | #include "xfs_trans.h" | |
17 | #include "xfs_sb.h" | |
18 | #include "xfs_alloc.h" | |
19 | #include "xfs_rtalloc.h" | |
20 | #include "xfs_inode.h" | |
21 | #include "scrub/xfs_scrub.h" | |
22 | #include "scrub/scrub.h" | |
23 | #include "scrub/common.h" | |
24 | #include "scrub/trace.h" | |
25 | ||
26 | /* Set us up with the realtime metadata locked. */ | |
27 | int | |
c517b3aa | 28 | xchk_setup_rt( |
1d8a748a | 29 | struct xfs_scrub *sc, |
032d91f9 | 30 | struct xfs_inode *ip) |
29b0767b | 31 | { |
032d91f9 | 32 | int error; |
29b0767b | 33 | |
c517b3aa | 34 | error = xchk_setup_fs(sc, ip); |
29b0767b DW |
35 | if (error) |
36 | return error; | |
37 | ||
38 | sc->ilock_flags = XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP; | |
8e630837 | 39 | sc->ip = sc->mp->m_rbmip; |
29b0767b DW |
40 | xfs_ilock(sc->ip, sc->ilock_flags); |
41 | ||
42 | return 0; | |
43 | } | |
44 | ||
45 | /* Realtime bitmap. */ | |
46 | ||
47 | /* Scrub a free extent record from the realtime bitmap. */ | |
48 | STATIC int | |
c517b3aa | 49 | xchk_rtbitmap_rec( |
032d91f9 DW |
50 | struct xfs_trans *tp, |
51 | struct xfs_rtalloc_rec *rec, | |
52 | void *priv) | |
29b0767b | 53 | { |
1d8a748a | 54 | struct xfs_scrub *sc = priv; |
032d91f9 DW |
55 | xfs_rtblock_t startblock; |
56 | xfs_rtblock_t blockcount; | |
29b0767b | 57 | |
a0e5c435 DW |
58 | startblock = rec->ar_startext * tp->t_mountp->m_sb.sb_rextsize; |
59 | blockcount = rec->ar_extcount * tp->t_mountp->m_sb.sb_rextsize; | |
60 | ||
61 | if (startblock + blockcount <= startblock || | |
62 | !xfs_verify_rtbno(sc->mp, startblock) || | |
63 | !xfs_verify_rtbno(sc->mp, startblock + blockcount - 1)) | |
c517b3aa | 64 | xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0); |
29b0767b DW |
65 | return 0; |
66 | } | |
67 | ||
68 | /* Scrub the realtime bitmap. */ | |
69 | int | |
c517b3aa | 70 | xchk_rtbitmap( |
1d8a748a | 71 | struct xfs_scrub *sc) |
29b0767b | 72 | { |
032d91f9 | 73 | int error; |
29b0767b | 74 | |
517b32b7 | 75 | /* Invoke the fork scrubber. */ |
c517b3aa | 76 | error = xchk_metadata_inode_forks(sc); |
517b32b7 DW |
77 | if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) |
78 | return error; | |
79 | ||
c517b3aa DW |
80 | error = xfs_rtalloc_query_all(sc->tp, xchk_rtbitmap_rec, sc); |
81 | if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error)) | |
29b0767b DW |
82 | goto out; |
83 | ||
84 | out: | |
85 | return error; | |
86 | } | |
87 | ||
88 | /* Scrub the realtime summary. */ | |
89 | int | |
c517b3aa | 90 | xchk_rtsummary( |
1d8a748a | 91 | struct xfs_scrub *sc) |
29b0767b | 92 | { |
032d91f9 DW |
93 | struct xfs_inode *rsumip = sc->mp->m_rsumip; |
94 | struct xfs_inode *old_ip = sc->ip; | |
95 | uint old_ilock_flags = sc->ilock_flags; | |
96 | int error = 0; | |
517b32b7 DW |
97 | |
98 | /* | |
99 | * We ILOCK'd the rt bitmap ip in the setup routine, now lock the | |
100 | * rt summary ip in compliance with the rt inode locking rules. | |
101 | * | |
102 | * Since we switch sc->ip to rsumip we have to save the old ilock | |
103 | * flags so that we don't mix up the inode state that @sc tracks. | |
104 | */ | |
105 | sc->ip = rsumip; | |
106 | sc->ilock_flags = XFS_ILOCK_EXCL | XFS_ILOCK_RTSUM; | |
107 | xfs_ilock(sc->ip, sc->ilock_flags); | |
108 | ||
109 | /* Invoke the fork scrubber. */ | |
c517b3aa | 110 | error = xchk_metadata_inode_forks(sc); |
517b32b7 DW |
111 | if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) |
112 | goto out; | |
113 | ||
29b0767b | 114 | /* XXX: implement this some day */ |
c517b3aa | 115 | xchk_set_incomplete(sc); |
517b32b7 DW |
116 | out: |
117 | /* Switch back to the rtbitmap inode and lock flags. */ | |
118 | xfs_iunlock(sc->ip, sc->ilock_flags); | |
119 | sc->ilock_flags = old_ilock_flags; | |
120 | sc->ip = old_ip; | |
121 | return error; | |
29b0767b | 122 | } |
46d9bfb5 DW |
123 | |
124 | ||
125 | /* xref check that the extent is not free in the rtbitmap */ | |
126 | void | |
c517b3aa | 127 | xchk_xref_is_used_rt_space( |
1d8a748a | 128 | struct xfs_scrub *sc, |
032d91f9 DW |
129 | xfs_rtblock_t fsbno, |
130 | xfs_extlen_t len) | |
46d9bfb5 | 131 | { |
032d91f9 DW |
132 | xfs_rtblock_t startext; |
133 | xfs_rtblock_t endext; | |
134 | xfs_rtblock_t extcount; | |
135 | bool is_free; | |
136 | int error; | |
46d9bfb5 | 137 | |
c517b3aa | 138 | if (xchk_skip_xref(sc->sm)) |
8389f3ff DW |
139 | return; |
140 | ||
a0e5c435 DW |
141 | startext = fsbno; |
142 | endext = fsbno + len - 1; | |
143 | do_div(startext, sc->mp->m_sb.sb_rextsize); | |
144 | if (do_div(endext, sc->mp->m_sb.sb_rextsize)) | |
145 | endext++; | |
146 | extcount = endext - startext; | |
46d9bfb5 | 147 | xfs_ilock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP); |
a0e5c435 | 148 | error = xfs_rtalloc_extent_is_free(sc->mp, sc->tp, startext, extcount, |
46d9bfb5 | 149 | &is_free); |
c517b3aa | 150 | if (!xchk_should_check_xref(sc, &error, NULL)) |
46d9bfb5 DW |
151 | goto out_unlock; |
152 | if (is_free) | |
c517b3aa | 153 | xchk_ino_xref_set_corrupt(sc, sc->mp->m_rbmip->i_ino); |
46d9bfb5 DW |
154 | out_unlock: |
155 | xfs_iunlock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP); | |
156 | } |