.. | .. |
---|
9 | 9 | #include "xfs_format.h" |
---|
10 | 10 | #include "xfs_trans_resv.h" |
---|
11 | 11 | #include "xfs_mount.h" |
---|
12 | | -#include "xfs_defer.h" |
---|
13 | | -#include "xfs_btree.h" |
---|
14 | | -#include "xfs_bit.h" |
---|
15 | 12 | #include "xfs_log_format.h" |
---|
16 | 13 | #include "xfs_trans.h" |
---|
17 | | -#include "xfs_sb.h" |
---|
18 | 14 | #include "xfs_inode.h" |
---|
19 | 15 | #include "xfs_icache.h" |
---|
20 | | -#include "xfs_itable.h" |
---|
21 | | -#include "xfs_da_format.h" |
---|
22 | | -#include "xfs_da_btree.h" |
---|
23 | 16 | #include "xfs_dir2.h" |
---|
24 | 17 | #include "xfs_dir2_priv.h" |
---|
25 | | -#include "xfs_ialloc.h" |
---|
26 | | -#include "scrub/xfs_scrub.h" |
---|
27 | 18 | #include "scrub/scrub.h" |
---|
28 | 19 | #include "scrub/common.h" |
---|
29 | | -#include "scrub/trace.h" |
---|
30 | 20 | #include "scrub/dabtree.h" |
---|
31 | 21 | |
---|
32 | 22 | /* Set us up to scrub directories. */ |
---|
.. | .. |
---|
123 | 113 | offset = xfs_dir2_db_to_da(mp->m_dir_geo, |
---|
124 | 114 | xfs_dir2_dataptr_to_db(mp->m_dir_geo, pos)); |
---|
125 | 115 | |
---|
| 116 | + if (xchk_should_terminate(sdc->sc, &error)) |
---|
| 117 | + return error; |
---|
| 118 | + |
---|
126 | 119 | /* Does this inode number make sense? */ |
---|
127 | 120 | if (!xfs_verify_dir_ino(mp, ino)) { |
---|
| 121 | + xchk_fblock_set_corrupt(sdc->sc, XFS_DATA_FORK, offset); |
---|
| 122 | + goto out; |
---|
| 123 | + } |
---|
| 124 | + |
---|
| 125 | + /* Does this name make sense? */ |
---|
| 126 | + if (!xfs_dir2_namecheck(name, namelen)) { |
---|
128 | 127 | xchk_fblock_set_corrupt(sdc->sc, XFS_DATA_FORK, offset); |
---|
129 | 128 | goto out; |
---|
130 | 129 | } |
---|
.. | .. |
---|
186 | 185 | STATIC int |
---|
187 | 186 | xchk_dir_rec( |
---|
188 | 187 | struct xchk_da_btree *ds, |
---|
189 | | - int level, |
---|
190 | | - void *rec) |
---|
| 188 | + int level) |
---|
191 | 189 | { |
---|
| 190 | + struct xfs_da_state_blk *blk = &ds->state->path.blk[level]; |
---|
192 | 191 | struct xfs_mount *mp = ds->state->mp; |
---|
193 | | - struct xfs_dir2_leaf_entry *ent = rec; |
---|
194 | 192 | struct xfs_inode *dp = ds->dargs.dp; |
---|
| 193 | + struct xfs_da_geometry *geo = mp->m_dir_geo; |
---|
195 | 194 | struct xfs_dir2_data_entry *dent; |
---|
196 | 195 | struct xfs_buf *bp; |
---|
197 | | - char *p, *endp; |
---|
| 196 | + struct xfs_dir2_leaf_entry *ent; |
---|
| 197 | + unsigned int end; |
---|
| 198 | + unsigned int iter_off; |
---|
198 | 199 | xfs_ino_t ino; |
---|
199 | 200 | xfs_dablk_t rec_bno; |
---|
200 | 201 | xfs_dir2_db_t db; |
---|
.. | .. |
---|
202 | 203 | xfs_dir2_dataptr_t ptr; |
---|
203 | 204 | xfs_dahash_t calc_hash; |
---|
204 | 205 | xfs_dahash_t hash; |
---|
| 206 | + struct xfs_dir3_icleaf_hdr hdr; |
---|
205 | 207 | unsigned int tag; |
---|
206 | 208 | int error; |
---|
| 209 | + |
---|
| 210 | + ASSERT(blk->magic == XFS_DIR2_LEAF1_MAGIC || |
---|
| 211 | + blk->magic == XFS_DIR2_LEAFN_MAGIC); |
---|
| 212 | + |
---|
| 213 | + xfs_dir2_leaf_hdr_from_disk(mp, &hdr, blk->bp->b_addr); |
---|
| 214 | + ent = hdr.ents + blk->index; |
---|
207 | 215 | |
---|
208 | 216 | /* Check the hash of the entry. */ |
---|
209 | 217 | error = xchk_da_btree_hash(ds, level, &ent->hashval); |
---|
.. | .. |
---|
216 | 224 | return 0; |
---|
217 | 225 | |
---|
218 | 226 | /* Find the directory entry's location. */ |
---|
219 | | - db = xfs_dir2_dataptr_to_db(mp->m_dir_geo, ptr); |
---|
220 | | - off = xfs_dir2_dataptr_to_off(mp->m_dir_geo, ptr); |
---|
221 | | - rec_bno = xfs_dir2_db_to_da(mp->m_dir_geo, db); |
---|
| 227 | + db = xfs_dir2_dataptr_to_db(geo, ptr); |
---|
| 228 | + off = xfs_dir2_dataptr_to_off(geo, ptr); |
---|
| 229 | + rec_bno = xfs_dir2_db_to_da(geo, db); |
---|
222 | 230 | |
---|
223 | | - if (rec_bno >= mp->m_dir_geo->leafblk) { |
---|
| 231 | + if (rec_bno >= geo->leafblk) { |
---|
224 | 232 | xchk_da_set_corrupt(ds, level); |
---|
225 | 233 | goto out; |
---|
226 | 234 | } |
---|
227 | | - error = xfs_dir3_data_read(ds->dargs.trans, dp, rec_bno, -2, &bp); |
---|
| 235 | + error = xfs_dir3_data_read(ds->dargs.trans, dp, rec_bno, |
---|
| 236 | + XFS_DABUF_MAP_HOLE_OK, &bp); |
---|
228 | 237 | if (!xchk_fblock_process_error(ds->sc, XFS_DATA_FORK, rec_bno, |
---|
229 | 238 | &error)) |
---|
230 | 239 | goto out; |
---|
.. | .. |
---|
237 | 246 | if (ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) |
---|
238 | 247 | goto out_relse; |
---|
239 | 248 | |
---|
240 | | - dent = (struct xfs_dir2_data_entry *)(((char *)bp->b_addr) + off); |
---|
| 249 | + dent = bp->b_addr + off; |
---|
241 | 250 | |
---|
242 | 251 | /* Make sure we got a real directory entry. */ |
---|
243 | | - p = (char *)mp->m_dir_inode_ops->data_entry_p(bp->b_addr); |
---|
244 | | - endp = xfs_dir3_data_endp(mp->m_dir_geo, bp->b_addr); |
---|
245 | | - if (!endp) { |
---|
| 252 | + iter_off = geo->data_entry_offset; |
---|
| 253 | + end = xfs_dir3_data_end_offset(geo, bp->b_addr); |
---|
| 254 | + if (!end) { |
---|
246 | 255 | xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); |
---|
247 | 256 | goto out_relse; |
---|
248 | 257 | } |
---|
249 | | - while (p < endp) { |
---|
250 | | - struct xfs_dir2_data_entry *dep; |
---|
251 | | - struct xfs_dir2_data_unused *dup; |
---|
| 258 | + for (;;) { |
---|
| 259 | + struct xfs_dir2_data_entry *dep = bp->b_addr + iter_off; |
---|
| 260 | + struct xfs_dir2_data_unused *dup = bp->b_addr + iter_off; |
---|
252 | 261 | |
---|
253 | | - dup = (struct xfs_dir2_data_unused *)p; |
---|
| 262 | + if (iter_off >= end) { |
---|
| 263 | + xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); |
---|
| 264 | + goto out_relse; |
---|
| 265 | + } |
---|
| 266 | + |
---|
254 | 267 | if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { |
---|
255 | | - p += be16_to_cpu(dup->length); |
---|
| 268 | + iter_off += be16_to_cpu(dup->length); |
---|
256 | 269 | continue; |
---|
257 | 270 | } |
---|
258 | | - dep = (struct xfs_dir2_data_entry *)p; |
---|
259 | 271 | if (dep == dent) |
---|
260 | 272 | break; |
---|
261 | | - p += mp->m_dir_inode_ops->data_entsize(dep->namelen); |
---|
262 | | - } |
---|
263 | | - if (p >= endp) { |
---|
264 | | - xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); |
---|
265 | | - goto out_relse; |
---|
| 273 | + iter_off += xfs_dir2_data_entsize(mp, dep->namelen); |
---|
266 | 274 | } |
---|
267 | 275 | |
---|
268 | 276 | /* Retrieve the entry, sanity check it, and compare hashes. */ |
---|
269 | 277 | ino = be64_to_cpu(dent->inumber); |
---|
270 | 278 | hash = be32_to_cpu(ent->hashval); |
---|
271 | | - tag = be16_to_cpup(dp->d_ops->data_entry_tag_p(dent)); |
---|
| 279 | + tag = be16_to_cpup(xfs_dir2_data_entry_tag_p(mp, dent)); |
---|
272 | 280 | if (!xfs_verify_dir_ino(mp, ino) || tag != off) |
---|
273 | 281 | xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); |
---|
274 | 282 | if (dent->namelen == 0) { |
---|
.. | .. |
---|
326 | 334 | struct xfs_buf *bp; |
---|
327 | 335 | struct xfs_dir2_data_free *bf; |
---|
328 | 336 | struct xfs_mount *mp = sc->mp; |
---|
329 | | - const struct xfs_dir_ops *d_ops; |
---|
330 | | - char *ptr; |
---|
331 | | - char *endptr; |
---|
332 | 337 | u16 tag; |
---|
333 | 338 | unsigned int nr_bestfrees = 0; |
---|
334 | 339 | unsigned int nr_frees = 0; |
---|
335 | 340 | unsigned int smallest_bestfree; |
---|
336 | 341 | int newlen; |
---|
337 | | - int offset; |
---|
| 342 | + unsigned int offset; |
---|
| 343 | + unsigned int end; |
---|
338 | 344 | int error; |
---|
339 | | - |
---|
340 | | - d_ops = sc->ip->d_ops; |
---|
341 | 345 | |
---|
342 | 346 | if (is_block) { |
---|
343 | 347 | /* dir block format */ |
---|
.. | .. |
---|
346 | 350 | error = xfs_dir3_block_read(sc->tp, sc->ip, &bp); |
---|
347 | 351 | } else { |
---|
348 | 352 | /* dir data format */ |
---|
349 | | - error = xfs_dir3_data_read(sc->tp, sc->ip, lblk, -1, &bp); |
---|
| 353 | + error = xfs_dir3_data_read(sc->tp, sc->ip, lblk, 0, &bp); |
---|
350 | 354 | } |
---|
351 | 355 | if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error)) |
---|
352 | 356 | goto out; |
---|
.. | .. |
---|
358 | 362 | goto out_buf; |
---|
359 | 363 | |
---|
360 | 364 | /* Do the bestfrees correspond to actual free space? */ |
---|
361 | | - bf = d_ops->data_bestfree_p(bp->b_addr); |
---|
| 365 | + bf = xfs_dir2_data_bestfree_p(mp, bp->b_addr); |
---|
362 | 366 | smallest_bestfree = UINT_MAX; |
---|
363 | 367 | for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) { |
---|
364 | 368 | offset = be16_to_cpu(dfp->offset); |
---|
.. | .. |
---|
368 | 372 | xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); |
---|
369 | 373 | goto out_buf; |
---|
370 | 374 | } |
---|
371 | | - dup = (struct xfs_dir2_data_unused *)(bp->b_addr + offset); |
---|
| 375 | + dup = bp->b_addr + offset; |
---|
372 | 376 | tag = be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)); |
---|
373 | 377 | |
---|
374 | 378 | /* bestfree doesn't match the entry it points at? */ |
---|
375 | 379 | if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG) || |
---|
376 | 380 | be16_to_cpu(dup->length) != be16_to_cpu(dfp->length) || |
---|
377 | | - tag != ((char *)dup - (char *)bp->b_addr)) { |
---|
| 381 | + tag != offset) { |
---|
378 | 382 | xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); |
---|
379 | 383 | goto out_buf; |
---|
380 | 384 | } |
---|
.. | .. |
---|
390 | 394 | } |
---|
391 | 395 | |
---|
392 | 396 | /* Make sure the bestfrees are actually the best free spaces. */ |
---|
393 | | - ptr = (char *)d_ops->data_entry_p(bp->b_addr); |
---|
394 | | - endptr = xfs_dir3_data_endp(mp->m_dir_geo, bp->b_addr); |
---|
| 397 | + offset = mp->m_dir_geo->data_entry_offset; |
---|
| 398 | + end = xfs_dir3_data_end_offset(mp->m_dir_geo, bp->b_addr); |
---|
395 | 399 | |
---|
396 | 400 | /* Iterate the entries, stopping when we hit or go past the end. */ |
---|
397 | | - while (ptr < endptr) { |
---|
398 | | - dup = (struct xfs_dir2_data_unused *)ptr; |
---|
| 401 | + while (offset < end) { |
---|
| 402 | + dup = bp->b_addr + offset; |
---|
| 403 | + |
---|
399 | 404 | /* Skip real entries */ |
---|
400 | 405 | if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG)) { |
---|
401 | | - struct xfs_dir2_data_entry *dep; |
---|
| 406 | + struct xfs_dir2_data_entry *dep = bp->b_addr + offset; |
---|
402 | 407 | |
---|
403 | | - dep = (struct xfs_dir2_data_entry *)ptr; |
---|
404 | | - newlen = d_ops->data_entsize(dep->namelen); |
---|
| 408 | + newlen = xfs_dir2_data_entsize(mp, dep->namelen); |
---|
405 | 409 | if (newlen <= 0) { |
---|
406 | 410 | xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, |
---|
407 | 411 | lblk); |
---|
408 | 412 | goto out_buf; |
---|
409 | 413 | } |
---|
410 | | - ptr += newlen; |
---|
| 414 | + offset += newlen; |
---|
411 | 415 | continue; |
---|
412 | 416 | } |
---|
413 | 417 | |
---|
414 | 418 | /* Spot check this free entry */ |
---|
415 | 419 | tag = be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)); |
---|
416 | | - if (tag != ((char *)dup - (char *)bp->b_addr)) { |
---|
| 420 | + if (tag != offset) { |
---|
417 | 421 | xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); |
---|
418 | 422 | goto out_buf; |
---|
419 | 423 | } |
---|
.. | .. |
---|
432 | 436 | xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); |
---|
433 | 437 | goto out_buf; |
---|
434 | 438 | } |
---|
435 | | - ptr += newlen; |
---|
436 | | - if (ptr <= endptr) |
---|
| 439 | + offset += newlen; |
---|
| 440 | + if (offset <= end) |
---|
437 | 441 | nr_frees++; |
---|
438 | 442 | } |
---|
439 | 443 | |
---|
440 | 444 | /* We're required to fill all the space. */ |
---|
441 | | - if (ptr != endptr) |
---|
| 445 | + if (offset != end) |
---|
442 | 446 | xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); |
---|
443 | 447 | |
---|
444 | 448 | /* Did we see at least as many free slots as there are bestfrees? */ |
---|
.. | .. |
---|
465 | 469 | { |
---|
466 | 470 | struct xfs_dir2_data_free *dfp; |
---|
467 | 471 | |
---|
468 | | - dfp = sc->ip->d_ops->data_bestfree_p(dbp->b_addr); |
---|
| 472 | + dfp = xfs_dir2_data_bestfree_p(sc->mp, dbp->b_addr); |
---|
469 | 473 | |
---|
470 | 474 | if (len != be16_to_cpu(dfp->length)) |
---|
471 | 475 | xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); |
---|
.. | .. |
---|
482 | 486 | xfs_dablk_t lblk) |
---|
483 | 487 | { |
---|
484 | 488 | struct xfs_dir3_icleaf_hdr leafhdr; |
---|
485 | | - struct xfs_dir2_leaf_entry *ents; |
---|
486 | 489 | struct xfs_dir2_leaf_tail *ltp; |
---|
487 | 490 | struct xfs_dir2_leaf *leaf; |
---|
488 | 491 | struct xfs_buf *dbp; |
---|
489 | 492 | struct xfs_buf *bp; |
---|
490 | | - const struct xfs_dir_ops *d_ops = sc->ip->d_ops; |
---|
491 | 493 | struct xfs_da_geometry *geo = sc->mp->m_dir_geo; |
---|
492 | 494 | __be16 *bestp; |
---|
493 | 495 | __u16 best; |
---|
.. | .. |
---|
499 | 501 | int error; |
---|
500 | 502 | |
---|
501 | 503 | /* Read the free space block. */ |
---|
502 | | - error = xfs_dir3_leaf_read(sc->tp, sc->ip, lblk, -1, &bp); |
---|
| 504 | + error = xfs_dir3_leaf_read(sc->tp, sc->ip, lblk, &bp); |
---|
503 | 505 | if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error)) |
---|
504 | | - goto out; |
---|
| 506 | + return error; |
---|
505 | 507 | xchk_buffer_recheck(sc, bp); |
---|
506 | 508 | |
---|
507 | 509 | leaf = bp->b_addr; |
---|
508 | | - d_ops->leaf_hdr_from_disk(&leafhdr, leaf); |
---|
509 | | - ents = d_ops->leaf_ents_p(leaf); |
---|
| 510 | + xfs_dir2_leaf_hdr_from_disk(sc->ip->i_mount, &leafhdr, leaf); |
---|
510 | 511 | ltp = xfs_dir2_leaf_tail_p(geo, leaf); |
---|
511 | 512 | bestcount = be32_to_cpu(ltp->bestcount); |
---|
512 | 513 | bestp = xfs_dir2_leaf_bests_p(ltp); |
---|
.. | .. |
---|
528 | 529 | } |
---|
529 | 530 | |
---|
530 | 531 | /* Is the leaf count even remotely sane? */ |
---|
531 | | - if (leafhdr.count > d_ops->leaf_max_ents(geo)) { |
---|
| 532 | + if (leafhdr.count > geo->leaf_max_ents) { |
---|
532 | 533 | xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); |
---|
533 | 534 | goto out; |
---|
534 | 535 | } |
---|
535 | 536 | |
---|
536 | 537 | /* Leaves and bests don't overlap in leaf format. */ |
---|
537 | | - if ((char *)&ents[leafhdr.count] > (char *)bestp) { |
---|
| 538 | + if ((char *)&leafhdr.ents[leafhdr.count] > (char *)bestp) { |
---|
538 | 539 | xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); |
---|
539 | 540 | goto out; |
---|
540 | 541 | } |
---|
541 | 542 | |
---|
542 | 543 | /* Check hash value order, count stale entries. */ |
---|
543 | 544 | for (i = 0; i < leafhdr.count; i++) { |
---|
544 | | - hash = be32_to_cpu(ents[i].hashval); |
---|
| 545 | + hash = be32_to_cpu(leafhdr.ents[i].hashval); |
---|
545 | 546 | if (i > 0 && lasthash > hash) |
---|
546 | 547 | xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); |
---|
547 | 548 | lasthash = hash; |
---|
548 | | - if (ents[i].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) |
---|
| 549 | + if (leafhdr.ents[i].address == |
---|
| 550 | + cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) |
---|
549 | 551 | stale++; |
---|
550 | 552 | } |
---|
551 | 553 | if (leafhdr.stale != stale) |
---|
.. | .. |
---|
556 | 558 | /* Check all the bestfree entries. */ |
---|
557 | 559 | for (i = 0; i < bestcount; i++, bestp++) { |
---|
558 | 560 | best = be16_to_cpu(*bestp); |
---|
559 | | - if (best == NULLDATAOFF) |
---|
560 | | - continue; |
---|
561 | 561 | error = xfs_dir3_data_read(sc->tp, sc->ip, |
---|
562 | | - i * args->geo->fsbcount, -1, &dbp); |
---|
| 562 | + xfs_dir2_db_to_da(args->geo, i), |
---|
| 563 | + XFS_DABUF_MAP_HOLE_OK, |
---|
| 564 | + &dbp); |
---|
563 | 565 | if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, |
---|
564 | 566 | &error)) |
---|
565 | 567 | break; |
---|
566 | | - xchk_directory_check_freesp(sc, lblk, dbp, best); |
---|
| 568 | + |
---|
| 569 | + if (!dbp) { |
---|
| 570 | + if (best != NULLDATAOFF) { |
---|
| 571 | + xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, |
---|
| 572 | + lblk); |
---|
| 573 | + break; |
---|
| 574 | + } |
---|
| 575 | + continue; |
---|
| 576 | + } |
---|
| 577 | + |
---|
| 578 | + if (best == NULLDATAOFF) |
---|
| 579 | + xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); |
---|
| 580 | + else |
---|
| 581 | + xchk_directory_check_freesp(sc, lblk, dbp, best); |
---|
567 | 582 | xfs_trans_brelse(sc->tp, dbp); |
---|
568 | 583 | if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) |
---|
569 | | - goto out; |
---|
| 584 | + break; |
---|
570 | 585 | } |
---|
571 | 586 | out: |
---|
| 587 | + xfs_trans_brelse(sc->tp, bp); |
---|
572 | 588 | return error; |
---|
573 | 589 | } |
---|
574 | 590 | |
---|
.. | .. |
---|
582 | 598 | struct xfs_dir3_icfree_hdr freehdr; |
---|
583 | 599 | struct xfs_buf *dbp; |
---|
584 | 600 | struct xfs_buf *bp; |
---|
585 | | - __be16 *bestp; |
---|
586 | 601 | __u16 best; |
---|
587 | 602 | unsigned int stale = 0; |
---|
588 | 603 | int i; |
---|
.. | .. |
---|
591 | 606 | /* Read the free space block */ |
---|
592 | 607 | error = xfs_dir2_free_read(sc->tp, sc->ip, lblk, &bp); |
---|
593 | 608 | if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error)) |
---|
594 | | - goto out; |
---|
| 609 | + return error; |
---|
595 | 610 | xchk_buffer_recheck(sc, bp); |
---|
596 | 611 | |
---|
597 | 612 | if (xfs_sb_version_hascrc(&sc->mp->m_sb)) { |
---|
.. | .. |
---|
602 | 617 | } |
---|
603 | 618 | |
---|
604 | 619 | /* Check all the entries. */ |
---|
605 | | - sc->ip->d_ops->free_hdr_from_disk(&freehdr, bp->b_addr); |
---|
606 | | - bestp = sc->ip->d_ops->free_bests_p(bp->b_addr); |
---|
607 | | - for (i = 0; i < freehdr.nvalid; i++, bestp++) { |
---|
608 | | - best = be16_to_cpu(*bestp); |
---|
| 620 | + xfs_dir2_free_hdr_from_disk(sc->ip->i_mount, &freehdr, bp->b_addr); |
---|
| 621 | + for (i = 0; i < freehdr.nvalid; i++) { |
---|
| 622 | + best = be16_to_cpu(freehdr.bests[i]); |
---|
609 | 623 | if (best == NULLDATAOFF) { |
---|
610 | 624 | stale++; |
---|
611 | 625 | continue; |
---|
612 | 626 | } |
---|
613 | 627 | error = xfs_dir3_data_read(sc->tp, sc->ip, |
---|
614 | 628 | (freehdr.firstdb + i) * args->geo->fsbcount, |
---|
615 | | - -1, &dbp); |
---|
| 629 | + 0, &dbp); |
---|
616 | 630 | if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, |
---|
617 | 631 | &error)) |
---|
618 | | - break; |
---|
| 632 | + goto out; |
---|
619 | 633 | xchk_directory_check_freesp(sc, lblk, dbp, best); |
---|
620 | 634 | xfs_trans_brelse(sc->tp, dbp); |
---|
621 | 635 | } |
---|
.. | .. |
---|
623 | 637 | if (freehdr.nused + stale != freehdr.nvalid) |
---|
624 | 638 | xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); |
---|
625 | 639 | out: |
---|
| 640 | + xfs_trans_brelse(sc->tp, bp); |
---|
626 | 641 | return error; |
---|
627 | 642 | } |
---|
628 | 643 | |
---|
.. | .. |
---|
633 | 648 | { |
---|
634 | 649 | struct xfs_bmbt_irec got; |
---|
635 | 650 | struct xfs_da_args args; |
---|
636 | | - struct xfs_ifork *ifp; |
---|
| 651 | + struct xfs_ifork *ifp = XFS_IFORK_PTR(sc->ip, XFS_DATA_FORK); |
---|
637 | 652 | struct xfs_mount *mp = sc->mp; |
---|
638 | 653 | xfs_fileoff_t leaf_lblk; |
---|
639 | 654 | xfs_fileoff_t free_lblk; |
---|
.. | .. |
---|
645 | 660 | int error; |
---|
646 | 661 | |
---|
647 | 662 | /* Ignore local format directories. */ |
---|
648 | | - if (sc->ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS && |
---|
649 | | - sc->ip->i_d.di_format != XFS_DINODE_FMT_BTREE) |
---|
| 663 | + if (ifp->if_format != XFS_DINODE_FMT_EXTENTS && |
---|
| 664 | + ifp->if_format != XFS_DINODE_FMT_BTREE) |
---|
650 | 665 | return 0; |
---|
651 | 666 | |
---|
652 | | - ifp = XFS_IFORK_PTR(sc->ip, XFS_DATA_FORK); |
---|
653 | 667 | lblk = XFS_B_TO_FSB(mp, XFS_DIR2_DATA_OFFSET); |
---|
654 | 668 | leaf_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_LEAF_OFFSET); |
---|
655 | 669 | free_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_FREE_OFFSET); |
---|