Commit | Line | Data |
---|---|---|
86210fbe 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 "xfs.h" | |
8 | #include "xfs_fs.h" | |
9 | #include "xfs_format.h" | |
86210fbe DC |
10 | #include "xfs_shared.h" |
11 | #include "xfs_trans_resv.h" | |
12 | #include "xfs_bit.h" | |
86210fbe | 13 | #include "xfs_mount.h" |
86210fbe DC |
14 | |
15 | /* Find the size of the AG, in blocks. */ | |
16 | xfs_agblock_t | |
17 | xfs_ag_block_count( | |
18 | struct xfs_mount *mp, | |
19 | xfs_agnumber_t agno) | |
20 | { | |
21 | ASSERT(agno < mp->m_sb.sb_agcount); | |
22 | ||
23 | if (agno < mp->m_sb.sb_agcount - 1) | |
24 | return mp->m_sb.sb_agblocks; | |
25 | return mp->m_sb.sb_dblocks - (agno * mp->m_sb.sb_agblocks); | |
26 | } | |
27 | ||
28 | /* | |
29 | * Verify that an AG block number pointer neither points outside the AG | |
30 | * nor points at static metadata. | |
31 | */ | |
32 | bool | |
33 | xfs_verify_agbno( | |
34 | struct xfs_mount *mp, | |
35 | xfs_agnumber_t agno, | |
36 | xfs_agblock_t agbno) | |
37 | { | |
38 | xfs_agblock_t eoag; | |
39 | ||
40 | eoag = xfs_ag_block_count(mp, agno); | |
41 | if (agbno >= eoag) | |
42 | return false; | |
43 | if (agbno <= XFS_AGFL_BLOCK(mp)) | |
44 | return false; | |
45 | return true; | |
46 | } | |
47 | ||
48 | /* | |
49 | * Verify that an FS block number pointer neither points outside the | |
50 | * filesystem nor points at static AG metadata. | |
51 | */ | |
52 | bool | |
53 | xfs_verify_fsbno( | |
54 | struct xfs_mount *mp, | |
55 | xfs_fsblock_t fsbno) | |
56 | { | |
57 | xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, fsbno); | |
58 | ||
59 | if (agno >= mp->m_sb.sb_agcount) | |
60 | return false; | |
61 | return xfs_verify_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno)); | |
62 | } | |
63 | ||
64 | /* Calculate the first and last possible inode number in an AG. */ | |
65 | void | |
66 | xfs_agino_range( | |
67 | struct xfs_mount *mp, | |
68 | xfs_agnumber_t agno, | |
69 | xfs_agino_t *first, | |
70 | xfs_agino_t *last) | |
71 | { | |
72 | xfs_agblock_t bno; | |
73 | xfs_agblock_t eoag; | |
74 | ||
75 | eoag = xfs_ag_block_count(mp, agno); | |
76 | ||
77 | /* | |
78 | * Calculate the first inode, which will be in the first | |
79 | * cluster-aligned block after the AGFL. | |
80 | */ | |
ef325959 | 81 | bno = round_up(XFS_AGFL_BLOCK(mp) + 1, M_IGEO(mp)->cluster_align); |
43004b2a | 82 | *first = XFS_AGB_TO_AGINO(mp, bno); |
86210fbe DC |
83 | |
84 | /* | |
85 | * Calculate the last inode, which will be at the end of the | |
86 | * last (aligned) cluster that can be allocated in the AG. | |
87 | */ | |
ef325959 | 88 | bno = round_down(eoag, M_IGEO(mp)->cluster_align); |
43004b2a | 89 | *last = XFS_AGB_TO_AGINO(mp, bno) - 1; |
86210fbe DC |
90 | } |
91 | ||
92 | /* | |
93 | * Verify that an AG inode number pointer neither points outside the AG | |
94 | * nor points at static metadata. | |
95 | */ | |
96 | bool | |
97 | xfs_verify_agino( | |
98 | struct xfs_mount *mp, | |
99 | xfs_agnumber_t agno, | |
100 | xfs_agino_t agino) | |
101 | { | |
102 | xfs_agino_t first; | |
103 | xfs_agino_t last; | |
104 | ||
105 | xfs_agino_range(mp, agno, &first, &last); | |
106 | return agino >= first && agino <= last; | |
107 | } | |
108 | ||
7d36c195 DW |
109 | /* |
110 | * Verify that an AG inode number pointer neither points outside the AG | |
111 | * nor points at static metadata, or is NULLAGINO. | |
112 | */ | |
113 | bool | |
114 | xfs_verify_agino_or_null( | |
115 | struct xfs_mount *mp, | |
116 | xfs_agnumber_t agno, | |
117 | xfs_agino_t agino) | |
118 | { | |
119 | return agino == NULLAGINO || xfs_verify_agino(mp, agno, agino); | |
120 | } | |
121 | ||
86210fbe DC |
122 | /* |
123 | * Verify that an FS inode number pointer neither points outside the | |
124 | * filesystem nor points at static AG metadata. | |
125 | */ | |
126 | bool | |
127 | xfs_verify_ino( | |
128 | struct xfs_mount *mp, | |
129 | xfs_ino_t ino) | |
130 | { | |
131 | xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, ino); | |
132 | xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ino); | |
133 | ||
134 | if (agno >= mp->m_sb.sb_agcount) | |
135 | return false; | |
136 | if (XFS_AGINO_TO_INO(mp, agno, agino) != ino) | |
137 | return false; | |
138 | return xfs_verify_agino(mp, agno, agino); | |
139 | } | |
140 | ||
141 | /* Is this an internal inode number? */ | |
142 | bool | |
143 | xfs_internal_inum( | |
144 | struct xfs_mount *mp, | |
145 | xfs_ino_t ino) | |
146 | { | |
147 | return ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino || | |
148 | (xfs_sb_version_hasquota(&mp->m_sb) && | |
149 | xfs_is_quota_inode(&mp->m_sb, ino)); | |
150 | } | |
151 | ||
152 | /* | |
153 | * Verify that a directory entry's inode number doesn't point at an internal | |
154 | * inode, empty space, or static AG metadata. | |
155 | */ | |
156 | bool | |
157 | xfs_verify_dir_ino( | |
158 | struct xfs_mount *mp, | |
159 | xfs_ino_t ino) | |
160 | { | |
161 | if (xfs_internal_inum(mp, ino)) | |
162 | return false; | |
163 | return xfs_verify_ino(mp, ino); | |
164 | } | |
165 | ||
166 | /* | |
167 | * Verify that an realtime block number pointer doesn't point off the | |
168 | * end of the realtime device. | |
169 | */ | |
170 | bool | |
171 | xfs_verify_rtbno( | |
172 | struct xfs_mount *mp, | |
173 | xfs_rtblock_t rtbno) | |
174 | { | |
175 | return rtbno < mp->m_sb.sb_rblocks; | |
176 | } | |
69775fd1 DW |
177 | |
178 | /* Calculate the range of valid icount values. */ | |
75efa57d | 179 | void |
69775fd1 DW |
180 | xfs_icount_range( |
181 | struct xfs_mount *mp, | |
182 | unsigned long long *min, | |
183 | unsigned long long *max) | |
184 | { | |
185 | unsigned long long nr_inos = 0; | |
186 | xfs_agnumber_t agno; | |
187 | ||
188 | /* root, rtbitmap, rtsum all live in the first chunk */ | |
189 | *min = XFS_INODES_PER_CHUNK; | |
190 | ||
191 | for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { | |
192 | xfs_agino_t first, last; | |
193 | ||
194 | xfs_agino_range(mp, agno, &first, &last); | |
195 | nr_inos += last - first + 1; | |
196 | } | |
197 | *max = nr_inos; | |
198 | } | |
199 | ||
200 | /* Sanity-checking of inode counts. */ | |
201 | bool | |
202 | xfs_verify_icount( | |
203 | struct xfs_mount *mp, | |
204 | unsigned long long icount) | |
205 | { | |
206 | unsigned long long min, max; | |
207 | ||
208 | xfs_icount_range(mp, &min, &max); | |
209 | return icount >= min && icount <= max; | |
210 | } | |
f8c1d702 DW |
211 | |
212 | /* Sanity-checking of dir/attr block offsets. */ | |
213 | bool | |
214 | xfs_verify_dablk( | |
215 | struct xfs_mount *mp, | |
216 | xfs_fileoff_t dabno) | |
217 | { | |
218 | xfs_dablk_t max_dablk = -1U; | |
219 | ||
220 | return dabno <= max_dablk; | |
221 | } |