aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_btree.c196
-rw-r--r--fs/xfs/xfs_btree.h97
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 */
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
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 */
222void 221int /* error (0 or EFSCORRUPTED) */
223xfs_btree_check_block( 222xfs_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 */
232void 231int /* error (0 or EFSCORRUPTED) */
233xfs_btree_check_key( 232xfs_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 */
241void
242xfs_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 */
255int /* error (0 or EFSCORRUPTED) */ 241int
256xfs_btree_check_lblock( 242xfs_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 */
265int /* error (0 or EFSCORRUPTED) */ 251int /* error (0 or EFSCORRUPTED) */
266xfs_btree_check_lptr( 252xfs_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 */
277int /* error (0 or EFSCORRUPTED) */ 264int /* error (0 or EFSCORRUPTED) */
278xfs_btree_check_sblock( 265xfs_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 */
287int /* error (0 or EFSCORRUPTED) */ 273int /* error (0 or EFSCORRUPTED) */
288xfs_btree_check_sptr( 274xfs_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 */
285void
286xfs_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 */
294void
295xfs_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 */