diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/xfs_btree.c | 196 | ||||
-rw-r--r-- | fs/xfs/xfs_btree.h | 97 |
2 files changed, 155 insertions, 138 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 |
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h index 8be838f0154a..a57918276d9f 100644 --- a/fs/xfs/xfs_btree.h +++ b/fs/xfs/xfs_btree.h | |||
@@ -215,81 +215,92 @@ typedef struct xfs_btree_cur | |||
215 | 215 | ||
216 | #ifdef __KERNEL__ | 216 | #ifdef __KERNEL__ |
217 | 217 | ||
218 | #ifdef DEBUG | ||
219 | /* | 218 | /* |
220 | * Debug routine: check that block header is ok. | 219 | * Check that long form block header is ok. |
221 | */ | 220 | */ |
222 | void | 221 | int /* error (0 or EFSCORRUPTED) */ |
223 | xfs_btree_check_block( | 222 | xfs_btree_check_lblock( |
224 | xfs_btree_cur_t *cur, /* btree cursor */ | 223 | struct xfs_btree_cur *cur, /* btree cursor */ |
225 | xfs_btree_block_t *block, /* generic btree block pointer */ | 224 | struct xfs_btree_lblock *block, /* btree long form block pointer */ |
226 | int level, /* level of the btree block */ | 225 | int level, /* level of the btree block */ |
227 | struct xfs_buf *bp); /* buffer containing block, if any */ | 226 | struct xfs_buf *bp); /* buffer containing block, if any */ |
228 | 227 | ||
229 | /* | 228 | /* |
230 | * Debug routine: check that keys are in the right order. | 229 | * Check that short form block header is ok. |
231 | */ | 230 | */ |
232 | void | 231 | int /* error (0 or EFSCORRUPTED) */ |
233 | xfs_btree_check_key( | 232 | xfs_btree_check_sblock( |
234 | xfs_btnum_t btnum, /* btree identifier */ | 233 | struct xfs_btree_cur *cur, /* btree cursor */ |
235 | void *ak1, /* pointer to left (lower) key */ | 234 | struct xfs_btree_sblock *block, /* btree short form block pointer */ |
236 | void *ak2); /* pointer to right (higher) key */ | 235 | int level, /* level of the btree block */ |
237 | 236 | struct xfs_buf *bp); /* buffer containing block */ | |
238 | /* | ||
239 | * Debug routine: check that records are in the right order. | ||
240 | */ | ||
241 | void | ||
242 | xfs_btree_check_rec( | ||
243 | xfs_btnum_t btnum, /* btree identifier */ | ||
244 | void *ar1, /* pointer to left (lower) record */ | ||
245 | void *ar2); /* pointer to right (higher) record */ | ||
246 | #else | ||
247 | #define xfs_btree_check_block(a,b,c,d) | ||
248 | #define xfs_btree_check_key(a,b,c) | ||
249 | #define xfs_btree_check_rec(a,b,c) | ||
250 | #endif /* DEBUG */ | ||
251 | 237 | ||
252 | /* | 238 | /* |
253 | * Checking routine: check that long form block header is ok. | 239 | * Check that block header is ok. |
254 | */ | 240 | */ |
255 | int /* error (0 or EFSCORRUPTED) */ | 241 | int |
256 | xfs_btree_check_lblock( | 242 | xfs_btree_check_block( |
257 | xfs_btree_cur_t *cur, /* btree cursor */ | 243 | struct xfs_btree_cur *cur, /* btree cursor */ |
258 | xfs_btree_lblock_t *block, /* btree long form block pointer */ | 244 | struct xfs_btree_block *block, /* generic btree block pointer */ |
259 | int level, /* level of the btree block */ | 245 | int level, /* level of the btree block */ |
260 | struct xfs_buf *bp); /* buffer containing block, if any */ | 246 | struct xfs_buf *bp); /* buffer containing block, if any */ |
261 | 247 | ||
262 | /* | 248 | /* |
263 | * Checking routine: check that (long) pointer is ok. | 249 | * Check that (long) pointer is ok. |
264 | */ | 250 | */ |
265 | int /* error (0 or EFSCORRUPTED) */ | 251 | int /* error (0 or EFSCORRUPTED) */ |
266 | xfs_btree_check_lptr( | 252 | xfs_btree_check_lptr( |
267 | xfs_btree_cur_t *cur, /* btree cursor */ | 253 | struct xfs_btree_cur *cur, /* btree cursor */ |
268 | xfs_dfsbno_t ptr, /* btree block disk address */ | 254 | xfs_dfsbno_t ptr, /* btree block disk address */ |
269 | int level); /* btree block level */ | 255 | int level); /* btree block level */ |
270 | 256 | ||
271 | #define xfs_btree_check_lptr_disk(cur, ptr, level) \ | 257 | #define xfs_btree_check_lptr_disk(cur, ptr, level) \ |
272 | xfs_btree_check_lptr(cur, be64_to_cpu(ptr), level) | 258 | xfs_btree_check_lptr(cur, be64_to_cpu(ptr), level) |
273 | 259 | ||
260 | |||
274 | /* | 261 | /* |
275 | * Checking routine: check that short form block header is ok. | 262 | * Check that (short) pointer is ok. |
276 | */ | 263 | */ |
277 | int /* error (0 or EFSCORRUPTED) */ | 264 | int /* error (0 or EFSCORRUPTED) */ |
278 | xfs_btree_check_sblock( | 265 | xfs_btree_check_sptr( |
279 | xfs_btree_cur_t *cur, /* btree cursor */ | 266 | struct xfs_btree_cur *cur, /* btree cursor */ |
280 | xfs_btree_sblock_t *block, /* btree short form block pointer */ | 267 | xfs_agblock_t ptr, /* btree block disk address */ |
281 | int level, /* level of the btree block */ | 268 | int level); /* btree block level */ |
282 | struct xfs_buf *bp); /* buffer containing block */ | ||
283 | 269 | ||
284 | /* | 270 | /* |
285 | * Checking routine: check that (short) pointer is ok. | 271 | * Check that (short) pointer is ok. |
286 | */ | 272 | */ |
287 | int /* error (0 or EFSCORRUPTED) */ | 273 | int /* error (0 or EFSCORRUPTED) */ |
288 | xfs_btree_check_sptr( | 274 | xfs_btree_check_ptr( |
289 | xfs_btree_cur_t *cur, /* btree cursor */ | 275 | struct xfs_btree_cur *cur, /* btree cursor */ |
290 | xfs_agblock_t ptr, /* btree block disk address */ | 276 | union xfs_btree_ptr *ptr, /* btree block disk address */ |
277 | int index, /* offset from ptr to check */ | ||
291 | int level); /* btree block level */ | 278 | int level); /* btree block level */ |
292 | 279 | ||
280 | #ifdef DEBUG | ||
281 | |||
282 | /* | ||
283 | * Debug routine: check that keys are in the right order. | ||
284 | */ | ||
285 | void | ||
286 | xfs_btree_check_key( | ||
287 | xfs_btnum_t btnum, /* btree identifier */ | ||
288 | void *ak1, /* pointer to left (lower) key */ | ||
289 | void *ak2); /* pointer to right (higher) key */ | ||
290 | |||
291 | /* | ||
292 | * Debug routine: check that records are in the right order. | ||
293 | */ | ||
294 | void | ||
295 | xfs_btree_check_rec( | ||
296 | xfs_btnum_t btnum, /* btree identifier */ | ||
297 | void *ar1, /* pointer to left (lower) record */ | ||
298 | void *ar2); /* pointer to right (higher) record */ | ||
299 | #else | ||
300 | #define xfs_btree_check_key(a, b, c) | ||
301 | #define xfs_btree_check_rec(a, b, c) | ||
302 | #endif /* DEBUG */ | ||
303 | |||
293 | /* | 304 | /* |
294 | * Delete the btree cursor. | 305 | * Delete the btree cursor. |
295 | */ | 306 | */ |