aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_btree.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2008-10-30 01:54:53 -0400
committerLachlan McIlroy <lachlan@sgi.com>2008-10-30 01:54:53 -0400
commita23f6ef8ce966abc0f6e24a81ceb6a74ed30693b (patch)
treefa0d60a742dd47a966c177298268ca956c8bae4b /fs/xfs/xfs_btree.c
parentb524bfeee2152fa64b6210f28ced80489b9d2439 (diff)
[XFS] refactor btree validation helpers
Move the various btree validation helpers around in xfs_btree.c so that they are close to each other and in common #ifdef DEBUG sections. Also add a new xfs_btree_check_ptr helper to check a btree ptr that can be either long or short form. Split out from a bigger patch from Dave Chinner with various small changes applied by me. SGI-PV: 985583 SGI-Modid: xfs-linux-melb:xfs-kern:32183a Signed-off-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com> Signed-off-by: Bill O'Donnell <billodo@sgi.com> Signed-off-by: David Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/xfs_btree.c')
-rw-r--r--fs/xfs/xfs_btree.c196
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 */
86void
87xfs_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 */
104void 86void
@@ -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 */
159int /* error (0 or EFSCORRUPTED) */
160xfs_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 */
195int /* error (0 or EFSCORRUPTED) */
196xfs_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 */
215void 139void
@@ -268,19 +192,49 @@ xfs_btree_check_rec(
268} 192}
269#endif /* DEBUG */ 193#endif /* DEBUG */
270 194
271/* 195int /* error (0 or EFSCORRUPTED) */
272 * Checking routine: check that block header is ok. 196xfs_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
275int /* error (0 or EFSCORRUPTED) */ 229int /* error (0 or EFSCORRUPTED) */
276xfs_btree_check_sblock( 230xfs_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 */
270int
271xfs_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 */
289int /* error (0 or EFSCORRUPTED) */
290xfs_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 */
316int /* error (0 or EFSCORRUPTED) */ 305int /* error (0 or EFSCORRUPTED) */
317xfs_btree_check_sptr( 306xfs_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 */
324int /* error (0 or EFSCORRUPTED) */
325xfs_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 */
337void 343void