diff options
Diffstat (limited to 'fs/xfs/xfs_btree.c')
-rw-r--r-- | fs/xfs/xfs_btree.c | 196 |
1 files changed, 101 insertions, 95 deletions
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index 4d793e4ccdcc..966d58d50fad 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c | |||
@@ -81,24 +81,6 @@ xfs_btree_maxrecs( | |||
81 | 81 | ||
82 | #ifdef DEBUG | 82 | #ifdef DEBUG |
83 | /* | 83 | /* |
84 | * Debug routine: check that block header is ok. | ||
85 | */ | ||
86 | void | ||
87 | xfs_btree_check_block( | ||
88 | xfs_btree_cur_t *cur, /* btree cursor */ | ||
89 | xfs_btree_block_t *block, /* generic btree block pointer */ | ||
90 | int level, /* level of the btree block */ | ||
91 | xfs_buf_t *bp) /* buffer containing block, if any */ | ||
92 | { | ||
93 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) | ||
94 | xfs_btree_check_lblock(cur, (xfs_btree_lblock_t *)block, level, | ||
95 | bp); | ||
96 | else | ||
97 | xfs_btree_check_sblock(cur, (xfs_btree_sblock_t *)block, level, | ||
98 | bp); | ||
99 | } | ||
100 | |||
101 | /* | ||
102 | * Debug routine: check that keys are in the right order. | 84 | * Debug routine: check that keys are in the right order. |
103 | */ | 85 | */ |
104 | void | 86 | void |
@@ -150,66 +132,8 @@ xfs_btree_check_key( | |||
150 | ASSERT(0); | 132 | ASSERT(0); |
151 | } | 133 | } |
152 | } | 134 | } |
153 | #endif /* DEBUG */ | ||
154 | |||
155 | /* | ||
156 | * Checking routine: check that long form block header is ok. | ||
157 | */ | ||
158 | /* ARGSUSED */ | ||
159 | int /* error (0 or EFSCORRUPTED) */ | ||
160 | xfs_btree_check_lblock( | ||
161 | xfs_btree_cur_t *cur, /* btree cursor */ | ||
162 | xfs_btree_lblock_t *block, /* btree long form block pointer */ | ||
163 | int level, /* level of the btree block */ | ||
164 | xfs_buf_t *bp) /* buffer for block, if any */ | ||
165 | { | ||
166 | int lblock_ok; /* block passes checks */ | ||
167 | xfs_mount_t *mp; /* file system mount point */ | ||
168 | |||
169 | mp = cur->bc_mp; | ||
170 | lblock_ok = | ||
171 | be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] && | ||
172 | be16_to_cpu(block->bb_level) == level && | ||
173 | be16_to_cpu(block->bb_numrecs) <= | ||
174 | xfs_btree_maxrecs(cur, (xfs_btree_block_t *)block) && | ||
175 | block->bb_leftsib && | ||
176 | (be64_to_cpu(block->bb_leftsib) == NULLDFSBNO || | ||
177 | XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_leftsib))) && | ||
178 | block->bb_rightsib && | ||
179 | (be64_to_cpu(block->bb_rightsib) == NULLDFSBNO || | ||
180 | XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_rightsib))); | ||
181 | if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp, XFS_ERRTAG_BTREE_CHECK_LBLOCK, | ||
182 | XFS_RANDOM_BTREE_CHECK_LBLOCK))) { | ||
183 | if (bp) | ||
184 | xfs_buftrace("LBTREE ERROR", bp); | ||
185 | XFS_ERROR_REPORT("xfs_btree_check_lblock", XFS_ERRLEVEL_LOW, | ||
186 | mp); | ||
187 | return XFS_ERROR(EFSCORRUPTED); | ||
188 | } | ||
189 | return 0; | ||
190 | } | ||
191 | 135 | ||
192 | /* | 136 | /* |
193 | * Checking routine: check that (long) pointer is ok. | ||
194 | */ | ||
195 | int /* error (0 or EFSCORRUPTED) */ | ||
196 | xfs_btree_check_lptr( | ||
197 | xfs_btree_cur_t *cur, /* btree cursor */ | ||
198 | xfs_dfsbno_t ptr, /* btree block disk address */ | ||
199 | int level) /* btree block level */ | ||
200 | { | ||
201 | xfs_mount_t *mp; /* file system mount point */ | ||
202 | |||
203 | mp = cur->bc_mp; | ||
204 | XFS_WANT_CORRUPTED_RETURN( | ||
205 | level > 0 && | ||
206 | ptr != NULLDFSBNO && | ||
207 | XFS_FSB_SANITY_CHECK(mp, ptr)); | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | #ifdef DEBUG | ||
212 | /* | ||
213 | * Debug routine: check that records are in the right order. | 137 | * Debug routine: check that records are in the right order. |
214 | */ | 138 | */ |
215 | void | 139 | void |
@@ -268,19 +192,49 @@ xfs_btree_check_rec( | |||
268 | } | 192 | } |
269 | #endif /* DEBUG */ | 193 | #endif /* DEBUG */ |
270 | 194 | ||
271 | /* | 195 | int /* error (0 or EFSCORRUPTED) */ |
272 | * Checking routine: check that block header is ok. | 196 | xfs_btree_check_lblock( |
273 | */ | 197 | struct xfs_btree_cur *cur, /* btree cursor */ |
274 | /* ARGSUSED */ | 198 | struct xfs_btree_lblock *block, /* btree long form block pointer */ |
199 | int level, /* level of the btree block */ | ||
200 | struct xfs_buf *bp) /* buffer for block, if any */ | ||
201 | { | ||
202 | int lblock_ok; /* block passes checks */ | ||
203 | struct xfs_mount *mp; /* file system mount point */ | ||
204 | |||
205 | mp = cur->bc_mp; | ||
206 | lblock_ok = | ||
207 | be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] && | ||
208 | be16_to_cpu(block->bb_level) == level && | ||
209 | be16_to_cpu(block->bb_numrecs) <= | ||
210 | xfs_btree_maxrecs(cur, (xfs_btree_block_t *)block) && | ||
211 | block->bb_leftsib && | ||
212 | (be64_to_cpu(block->bb_leftsib) == NULLDFSBNO || | ||
213 | XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_leftsib))) && | ||
214 | block->bb_rightsib && | ||
215 | (be64_to_cpu(block->bb_rightsib) == NULLDFSBNO || | ||
216 | XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_rightsib))); | ||
217 | if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp, | ||
218 | XFS_ERRTAG_BTREE_CHECK_LBLOCK, | ||
219 | XFS_RANDOM_BTREE_CHECK_LBLOCK))) { | ||
220 | if (bp) | ||
221 | xfs_buftrace("LBTREE ERROR", bp); | ||
222 | XFS_ERROR_REPORT("xfs_btree_check_lblock", XFS_ERRLEVEL_LOW, | ||
223 | mp); | ||
224 | return XFS_ERROR(EFSCORRUPTED); | ||
225 | } | ||
226 | return 0; | ||
227 | } | ||
228 | |||
275 | int /* error (0 or EFSCORRUPTED) */ | 229 | int /* error (0 or EFSCORRUPTED) */ |
276 | xfs_btree_check_sblock( | 230 | xfs_btree_check_sblock( |
277 | xfs_btree_cur_t *cur, /* btree cursor */ | 231 | struct xfs_btree_cur *cur, /* btree cursor */ |
278 | xfs_btree_sblock_t *block, /* btree short form block pointer */ | 232 | struct xfs_btree_sblock *block, /* btree short form block pointer */ |
279 | int level, /* level of the btree block */ | 233 | int level, /* level of the btree block */ |
280 | xfs_buf_t *bp) /* buffer containing block */ | 234 | struct xfs_buf *bp) /* buffer containing block */ |
281 | { | 235 | { |
282 | xfs_buf_t *agbp; /* buffer for ag. freespace struct */ | 236 | struct xfs_buf *agbp; /* buffer for ag. freespace struct */ |
283 | xfs_agf_t *agf; /* ag. freespace structure */ | 237 | struct xfs_agf *agf; /* ag. freespace structure */ |
284 | xfs_agblock_t agflen; /* native ag. freespace length */ | 238 | xfs_agblock_t agflen; /* native ag. freespace length */ |
285 | int sblock_ok; /* block passes checks */ | 239 | int sblock_ok; /* block passes checks */ |
286 | 240 | ||
@@ -311,27 +265,79 @@ xfs_btree_check_sblock( | |||
311 | } | 265 | } |
312 | 266 | ||
313 | /* | 267 | /* |
314 | * Checking routine: check that (short) pointer is ok. | 268 | * Debug routine: check that block header is ok. |
269 | */ | ||
270 | int | ||
271 | xfs_btree_check_block( | ||
272 | struct xfs_btree_cur *cur, /* btree cursor */ | ||
273 | struct xfs_btree_block *block, /* generic btree block pointer */ | ||
274 | int level, /* level of the btree block */ | ||
275 | struct xfs_buf *bp) /* buffer containing block, if any */ | ||
276 | { | ||
277 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { | ||
278 | return xfs_btree_check_lblock(cur, | ||
279 | (struct xfs_btree_lblock *)block, level, bp); | ||
280 | } else { | ||
281 | return xfs_btree_check_sblock(cur, | ||
282 | (struct xfs_btree_sblock *)block, level, bp); | ||
283 | } | ||
284 | } | ||
285 | |||
286 | /* | ||
287 | * Check that (long) pointer is ok. | ||
288 | */ | ||
289 | int /* error (0 or EFSCORRUPTED) */ | ||
290 | xfs_btree_check_lptr( | ||
291 | struct xfs_btree_cur *cur, /* btree cursor */ | ||
292 | xfs_dfsbno_t bno, /* btree block disk address */ | ||
293 | int level) /* btree block level */ | ||
294 | { | ||
295 | XFS_WANT_CORRUPTED_RETURN( | ||
296 | level > 0 && | ||
297 | bno != NULLDFSBNO && | ||
298 | XFS_FSB_SANITY_CHECK(cur->bc_mp, bno)); | ||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * Check that (short) pointer is ok. | ||
315 | */ | 304 | */ |
316 | int /* error (0 or EFSCORRUPTED) */ | 305 | int /* error (0 or EFSCORRUPTED) */ |
317 | xfs_btree_check_sptr( | 306 | xfs_btree_check_sptr( |
318 | xfs_btree_cur_t *cur, /* btree cursor */ | 307 | struct xfs_btree_cur *cur, /* btree cursor */ |
319 | xfs_agblock_t ptr, /* btree block disk address */ | 308 | xfs_agblock_t bno, /* btree block disk address */ |
320 | int level) /* btree block level */ | 309 | int level) /* btree block level */ |
321 | { | 310 | { |
322 | xfs_buf_t *agbp; /* buffer for ag. freespace struct */ | 311 | xfs_agblock_t agblocks = cur->bc_mp->m_sb.sb_agblocks; |
323 | xfs_agf_t *agf; /* ag. freespace structure */ | ||
324 | 312 | ||
325 | agbp = cur->bc_private.a.agbp; | ||
326 | agf = XFS_BUF_TO_AGF(agbp); | ||
327 | XFS_WANT_CORRUPTED_RETURN( | 313 | XFS_WANT_CORRUPTED_RETURN( |
328 | level > 0 && | 314 | level > 0 && |
329 | ptr != NULLAGBLOCK && ptr != 0 && | 315 | bno != NULLAGBLOCK && |
330 | ptr < be32_to_cpu(agf->agf_length)); | 316 | bno != 0 && |
317 | bno < agblocks); | ||
331 | return 0; | 318 | return 0; |
332 | } | 319 | } |
333 | 320 | ||
334 | /* | 321 | /* |
322 | * Check that block ptr is ok. | ||
323 | */ | ||
324 | int /* error (0 or EFSCORRUPTED) */ | ||
325 | xfs_btree_check_ptr( | ||
326 | struct xfs_btree_cur *cur, /* btree cursor */ | ||
327 | union xfs_btree_ptr *ptr, /* btree block disk address */ | ||
328 | int index, /* offset from ptr to check */ | ||
329 | int level) /* btree block level */ | ||
330 | { | ||
331 | if (cur->bc_flags & XFS_BTREE_LONG_PTRS) { | ||
332 | return xfs_btree_check_lptr(cur, | ||
333 | be64_to_cpu((&ptr->l)[index]), level); | ||
334 | } else { | ||
335 | return xfs_btree_check_sptr(cur, | ||
336 | be32_to_cpu((&ptr->s)[index]), level); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | /* | ||
335 | * Delete the btree cursor. | 341 | * Delete the btree cursor. |
336 | */ | 342 | */ |
337 | void | 343 | void |