]>
Commit | Line | Data |
---|---|---|
1727fd17 DC |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. | |
4 | * Copyright (C) 2017 Oracle. | |
5 | * All Rights Reserved. | |
6 | */ | |
7 | #include "libxfs_priv.h" | |
8 | #include "xfs_fs.h" | |
9 | #include "xfs_format.h" | |
1727fd17 DC |
10 | #include "xfs_shared.h" |
11 | #include "xfs_trans_resv.h" | |
12 | #include "xfs_bit.h" | |
1727fd17 | 13 | #include "xfs_mount.h" |
29d36774 | 14 | #include "xfs_ag.h" |
1727fd17 | 15 | |
1727fd17 DC |
16 | |
17 | /* | |
18 | * Verify that an AG block number pointer neither points outside the AG | |
19 | * nor points at static metadata. | |
20 | */ | |
83af0d13 DC |
21 | static inline bool |
22 | xfs_verify_agno_agbno( | |
1727fd17 DC |
23 | struct xfs_mount *mp, |
24 | xfs_agnumber_t agno, | |
25 | xfs_agblock_t agbno) | |
26 | { | |
27 | xfs_agblock_t eoag; | |
28 | ||
29 | eoag = xfs_ag_block_count(mp, agno); | |
30 | if (agbno >= eoag) | |
31 | return false; | |
32 | if (agbno <= XFS_AGFL_BLOCK(mp)) | |
33 | return false; | |
34 | return true; | |
35 | } | |
36 | ||
37 | /* | |
38 | * Verify that an FS block number pointer neither points outside the | |
39 | * filesystem nor points at static AG metadata. | |
40 | */ | |
dc91402a | 41 | inline bool |
1727fd17 DC |
42 | xfs_verify_fsbno( |
43 | struct xfs_mount *mp, | |
44 | xfs_fsblock_t fsbno) | |
45 | { | |
46 | xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, fsbno); | |
47 | ||
48 | if (agno >= mp->m_sb.sb_agcount) | |
49 | return false; | |
83af0d13 | 50 | return xfs_verify_agno_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno)); |
1727fd17 DC |
51 | } |
52 | ||
f28f7e4a DW |
53 | /* |
54 | * Verify that a data device extent is fully contained inside the filesystem, | |
55 | * does not cross an AG boundary, and does not point at static metadata. | |
56 | */ | |
57 | bool | |
58 | xfs_verify_fsbext( | |
59 | struct xfs_mount *mp, | |
60 | xfs_fsblock_t fsbno, | |
61 | xfs_fsblock_t len) | |
62 | { | |
63 | if (fsbno + len <= fsbno) | |
64 | return false; | |
65 | ||
66 | if (!xfs_verify_fsbno(mp, fsbno)) | |
67 | return false; | |
68 | ||
69 | if (!xfs_verify_fsbno(mp, fsbno + len - 1)) | |
70 | return false; | |
71 | ||
72 | return XFS_FSB_TO_AGNO(mp, fsbno) == | |
73 | XFS_FSB_TO_AGNO(mp, fsbno + len - 1); | |
74 | } | |
75 | ||
1727fd17 DC |
76 | /* |
77 | * Verify that an AG inode number pointer neither points outside the AG | |
78 | * nor points at static metadata. | |
79 | */ | |
8aa34dc9 DC |
80 | static inline bool |
81 | xfs_verify_agno_agino( | |
1727fd17 DC |
82 | struct xfs_mount *mp, |
83 | xfs_agnumber_t agno, | |
84 | xfs_agino_t agino) | |
85 | { | |
86 | xfs_agino_t first; | |
87 | xfs_agino_t last; | |
88 | ||
89 | xfs_agino_range(mp, agno, &first, &last); | |
90 | return agino >= first && agino <= last; | |
91 | } | |
92 | ||
93 | /* | |
94 | * Verify that an FS inode number pointer neither points outside the | |
95 | * filesystem nor points at static AG metadata. | |
96 | */ | |
dc91402a | 97 | inline bool |
1727fd17 DC |
98 | xfs_verify_ino( |
99 | struct xfs_mount *mp, | |
100 | xfs_ino_t ino) | |
101 | { | |
102 | xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, ino); | |
103 | xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ino); | |
104 | ||
105 | if (agno >= mp->m_sb.sb_agcount) | |
106 | return false; | |
107 | if (XFS_AGINO_TO_INO(mp, agno, agino) != ino) | |
108 | return false; | |
8aa34dc9 | 109 | return xfs_verify_agno_agino(mp, agno, agino); |
1727fd17 DC |
110 | } |
111 | ||
112 | /* Is this an internal inode number? */ | |
dc91402a | 113 | inline bool |
1727fd17 DC |
114 | xfs_internal_inum( |
115 | struct xfs_mount *mp, | |
116 | xfs_ino_t ino) | |
117 | { | |
118 | return ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino || | |
b16a427a | 119 | (xfs_has_quota(mp) && |
1727fd17 DC |
120 | xfs_is_quota_inode(&mp->m_sb, ino)); |
121 | } | |
122 | ||
123 | /* | |
124 | * Verify that a directory entry's inode number doesn't point at an internal | |
125 | * inode, empty space, or static AG metadata. | |
126 | */ | |
127 | bool | |
128 | xfs_verify_dir_ino( | |
129 | struct xfs_mount *mp, | |
130 | xfs_ino_t ino) | |
131 | { | |
132 | if (xfs_internal_inum(mp, ino)) | |
133 | return false; | |
134 | return xfs_verify_ino(mp, ino); | |
135 | } | |
136 | ||
137 | /* | |
138 | * Verify that an realtime block number pointer doesn't point off the | |
139 | * end of the realtime device. | |
140 | */ | |
dc91402a | 141 | inline bool |
1727fd17 DC |
142 | xfs_verify_rtbno( |
143 | struct xfs_mount *mp, | |
144 | xfs_rtblock_t rtbno) | |
145 | { | |
146 | return rtbno < mp->m_sb.sb_rblocks; | |
147 | } | |
751d83bc | 148 | |
23e306ae DW |
149 | /* Verify that a realtime device extent is fully contained inside the volume. */ |
150 | bool | |
95bc0a4d | 151 | xfs_verify_rtbext( |
23e306ae DW |
152 | struct xfs_mount *mp, |
153 | xfs_rtblock_t rtbno, | |
95bc0a4d | 154 | xfs_filblks_t len) |
23e306ae DW |
155 | { |
156 | if (rtbno + len <= rtbno) | |
157 | return false; | |
158 | ||
159 | if (!xfs_verify_rtbno(mp, rtbno)) | |
160 | return false; | |
161 | ||
162 | return xfs_verify_rtbno(mp, rtbno + len - 1); | |
163 | } | |
164 | ||
751d83bc | 165 | /* Calculate the range of valid icount values. */ |
dc91402a | 166 | inline void |
751d83bc DW |
167 | xfs_icount_range( |
168 | struct xfs_mount *mp, | |
169 | unsigned long long *min, | |
170 | unsigned long long *max) | |
171 | { | |
172 | unsigned long long nr_inos = 0; | |
29d36774 | 173 | struct xfs_perag *pag; |
751d83bc DW |
174 | xfs_agnumber_t agno; |
175 | ||
176 | /* root, rtbitmap, rtsum all live in the first chunk */ | |
177 | *min = XFS_INODES_PER_CHUNK; | |
178 | ||
8aa34dc9 DC |
179 | for_each_perag(mp, agno, pag) |
180 | nr_inos += pag->agino_max - pag->agino_min + 1; | |
751d83bc DW |
181 | *max = nr_inos; |
182 | } | |
183 | ||
184 | /* Sanity-checking of inode counts. */ | |
185 | bool | |
186 | xfs_verify_icount( | |
187 | struct xfs_mount *mp, | |
188 | unsigned long long icount) | |
189 | { | |
190 | unsigned long long min, max; | |
191 | ||
192 | xfs_icount_range(mp, &min, &max); | |
193 | return icount >= min && icount <= max; | |
194 | } | |
95a8c918 DW |
195 | |
196 | /* Sanity-checking of dir/attr block offsets. */ | |
197 | bool | |
198 | xfs_verify_dablk( | |
199 | struct xfs_mount *mp, | |
200 | xfs_fileoff_t dabno) | |
201 | { | |
202 | xfs_dablk_t max_dablk = -1U; | |
203 | ||
204 | return dabno <= max_dablk; | |
205 | } | |
7626c690 DW |
206 | |
207 | /* Check that a file block offset does not exceed the maximum. */ | |
208 | bool | |
209 | xfs_verify_fileoff( | |
210 | struct xfs_mount *mp, | |
211 | xfs_fileoff_t off) | |
212 | { | |
213 | return off <= XFS_MAX_FILEOFF; | |
214 | } | |
215 | ||
216 | /* Check that a range of file block offsets do not exceed the maximum. */ | |
217 | bool | |
218 | xfs_verify_fileext( | |
219 | struct xfs_mount *mp, | |
220 | xfs_fileoff_t off, | |
221 | xfs_fileoff_t len) | |
222 | { | |
223 | if (off + len <= off) | |
224 | return false; | |
225 | ||
226 | if (!xfs_verify_fileoff(mp, off)) | |
227 | return false; | |
228 | ||
229 | return xfs_verify_fileoff(mp, off + len - 1); | |
230 | } |