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 "xfs.h" |
8 | #include "xfs_fs.h" |
9 | #include "xfs_format.h" |
10 | #include "xfs_shared.h" |
11 | #include "xfs_trans_resv.h" |
12 | #include "xfs_bit.h" |
13 | #include "xfs_mount.h" |
14 | #include "xfs_ag.h" |
15 | |
16 | |
17 | /* |
18 | * Verify that an AG block number pointer neither points outside the AG |
19 | * nor points at static metadata. |
20 | */ |
21 | static inline bool |
22 | xfs_verify_agno_agbno( |
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 | */ |
41 | inline bool |
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; |
50 | return xfs_verify_agno_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno)); |
51 | } |
52 | |
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 | |
76 | /* |
77 | * Verify that an AG inode number pointer neither points outside the AG |
78 | * nor points at static metadata. |
79 | */ |
80 | static inline bool |
81 | xfs_verify_agno_agino( |
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 | */ |
97 | inline bool |
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; |
109 | return xfs_verify_agno_agino(mp, agno, agino); |
110 | } |
111 | |
112 | /* Is this an internal inode number? */ |
113 | inline bool |
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 || |
119 | (xfs_has_quota(mp) && |
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 | */ |
141 | inline bool |
142 | xfs_verify_rtbno( |
143 | struct xfs_mount *mp, |
144 | xfs_rtblock_t rtbno) |
145 | { |
146 | return rtbno < mp->m_sb.sb_rblocks; |
147 | } |
148 | |
149 | /* Verify that a realtime device extent is fully contained inside the volume. */ |
150 | bool |
151 | xfs_verify_rtbext( |
152 | struct xfs_mount *mp, |
153 | xfs_rtblock_t rtbno, |
154 | xfs_filblks_t len) |
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 | |
165 | /* Calculate the range of valid icount values. */ |
166 | inline void |
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; |
173 | struct xfs_perag *pag; |
174 | xfs_agnumber_t agno; |
175 | |
176 | /* root, rtbitmap, rtsum all live in the first chunk */ |
177 | *min = XFS_INODES_PER_CHUNK; |
178 | |
179 | for_each_perag(mp, agno, pag) |
180 | nr_inos += pag->agino_max - pag->agino_min + 1; |
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: &min, max: &max); |
193 | return icount >= min && icount <= max; |
194 | } |
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 | } |
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 | } |
231 | |