| .. | .. |
|---|
| 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 | 12 | #include "xfs_btree.h" |
|---|
| 14 | | -#include "xfs_bit.h" |
|---|
| 15 | 13 | #include "xfs_log_format.h" |
|---|
| 16 | 14 | #include "xfs_trans.h" |
|---|
| 17 | 15 | #include "xfs_sb.h" |
|---|
| 18 | 16 | #include "xfs_inode.h" |
|---|
| 19 | 17 | #include "xfs_icache.h" |
|---|
| 20 | | -#include "xfs_itable.h" |
|---|
| 21 | 18 | #include "xfs_alloc.h" |
|---|
| 22 | 19 | #include "xfs_alloc_btree.h" |
|---|
| 23 | | -#include "xfs_bmap.h" |
|---|
| 24 | | -#include "xfs_bmap_btree.h" |
|---|
| 25 | 20 | #include "xfs_ialloc.h" |
|---|
| 26 | 21 | #include "xfs_ialloc_btree.h" |
|---|
| 27 | | -#include "xfs_refcount.h" |
|---|
| 28 | 22 | #include "xfs_refcount_btree.h" |
|---|
| 29 | 23 | #include "xfs_rmap.h" |
|---|
| 30 | 24 | #include "xfs_rmap_btree.h" |
|---|
| .. | .. |
|---|
| 32 | 26 | #include "xfs_trans_priv.h" |
|---|
| 33 | 27 | #include "xfs_attr.h" |
|---|
| 34 | 28 | #include "xfs_reflink.h" |
|---|
| 35 | | -#include "scrub/xfs_scrub.h" |
|---|
| 36 | 29 | #include "scrub/scrub.h" |
|---|
| 37 | 30 | #include "scrub/common.h" |
|---|
| 38 | 31 | #include "scrub/trace.h" |
|---|
| 39 | | -#include "scrub/btree.h" |
|---|
| 40 | 32 | #include "scrub/repair.h" |
|---|
| 33 | +#include "scrub/health.h" |
|---|
| 41 | 34 | |
|---|
| 42 | 35 | /* Common code for the metadata scrubbers. */ |
|---|
| 43 | 36 | |
|---|
| .. | .. |
|---|
| 208 | 201 | trace_xchk_ino_preen(sc, ino, __return_address); |
|---|
| 209 | 202 | } |
|---|
| 210 | 203 | |
|---|
| 204 | +/* Record something being wrong with the filesystem primary superblock. */ |
|---|
| 205 | +void |
|---|
| 206 | +xchk_set_corrupt( |
|---|
| 207 | + struct xfs_scrub *sc) |
|---|
| 208 | +{ |
|---|
| 209 | + sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT; |
|---|
| 210 | + trace_xchk_fs_error(sc, 0, __return_address); |
|---|
| 211 | +} |
|---|
| 212 | + |
|---|
| 211 | 213 | /* Record a corrupt block. */ |
|---|
| 212 | 214 | void |
|---|
| 213 | 215 | xchk_block_set_corrupt( |
|---|
| .. | .. |
|---|
| 313 | 315 | */ |
|---|
| 314 | 316 | |
|---|
| 315 | 317 | struct xchk_rmap_ownedby_info { |
|---|
| 316 | | - struct xfs_owner_info *oinfo; |
|---|
| 317 | | - xfs_filblks_t *blocks; |
|---|
| 318 | + const struct xfs_owner_info *oinfo; |
|---|
| 319 | + xfs_filblks_t *blocks; |
|---|
| 318 | 320 | }; |
|---|
| 319 | 321 | |
|---|
| 320 | 322 | STATIC int |
|---|
| .. | .. |
|---|
| 347 | 349 | xchk_count_rmap_ownedby_ag( |
|---|
| 348 | 350 | struct xfs_scrub *sc, |
|---|
| 349 | 351 | struct xfs_btree_cur *cur, |
|---|
| 350 | | - struct xfs_owner_info *oinfo, |
|---|
| 352 | + const struct xfs_owner_info *oinfo, |
|---|
| 351 | 353 | xfs_filblks_t *blocks) |
|---|
| 352 | 354 | { |
|---|
| 353 | | - struct xchk_rmap_ownedby_info sroi; |
|---|
| 355 | + struct xchk_rmap_ownedby_info sroi = { |
|---|
| 356 | + .oinfo = oinfo, |
|---|
| 357 | + .blocks = blocks, |
|---|
| 358 | + }; |
|---|
| 354 | 359 | |
|---|
| 355 | | - sroi.oinfo = oinfo; |
|---|
| 356 | 360 | *blocks = 0; |
|---|
| 357 | | - sroi.blocks = blocks; |
|---|
| 358 | | - |
|---|
| 359 | 361 | return xfs_rmap_query_all(cur, xchk_count_rmap_ownedby_irec, |
|---|
| 360 | 362 | &sroi); |
|---|
| 361 | 363 | } |
|---|
| .. | .. |
|---|
| 458 | 460 | struct xfs_mount *mp = sc->mp; |
|---|
| 459 | 461 | xfs_agnumber_t agno = sa->agno; |
|---|
| 460 | 462 | |
|---|
| 461 | | - if (sa->agf_bp) { |
|---|
| 463 | + xchk_perag_get(sc->mp, sa); |
|---|
| 464 | + if (sa->agf_bp && |
|---|
| 465 | + xchk_ag_btree_healthy_enough(sc, sa->pag, XFS_BTNUM_BNO)) { |
|---|
| 462 | 466 | /* Set up a bnobt cursor for cross-referencing. */ |
|---|
| 463 | 467 | sa->bno_cur = xfs_allocbt_init_cursor(mp, sc->tp, sa->agf_bp, |
|---|
| 464 | 468 | agno, XFS_BTNUM_BNO); |
|---|
| 465 | 469 | if (!sa->bno_cur) |
|---|
| 466 | 470 | goto err; |
|---|
| 471 | + } |
|---|
| 467 | 472 | |
|---|
| 473 | + if (sa->agf_bp && |
|---|
| 474 | + xchk_ag_btree_healthy_enough(sc, sa->pag, XFS_BTNUM_CNT)) { |
|---|
| 468 | 475 | /* Set up a cntbt cursor for cross-referencing. */ |
|---|
| 469 | 476 | sa->cnt_cur = xfs_allocbt_init_cursor(mp, sc->tp, sa->agf_bp, |
|---|
| 470 | 477 | agno, XFS_BTNUM_CNT); |
|---|
| .. | .. |
|---|
| 473 | 480 | } |
|---|
| 474 | 481 | |
|---|
| 475 | 482 | /* Set up a inobt cursor for cross-referencing. */ |
|---|
| 476 | | - if (sa->agi_bp) { |
|---|
| 483 | + if (sa->agi_bp && |
|---|
| 484 | + xchk_ag_btree_healthy_enough(sc, sa->pag, XFS_BTNUM_INO)) { |
|---|
| 477 | 485 | sa->ino_cur = xfs_inobt_init_cursor(mp, sc->tp, sa->agi_bp, |
|---|
| 478 | 486 | agno, XFS_BTNUM_INO); |
|---|
| 479 | 487 | if (!sa->ino_cur) |
|---|
| .. | .. |
|---|
| 481 | 489 | } |
|---|
| 482 | 490 | |
|---|
| 483 | 491 | /* Set up a finobt cursor for cross-referencing. */ |
|---|
| 484 | | - if (sa->agi_bp && xfs_sb_version_hasfinobt(&mp->m_sb)) { |
|---|
| 492 | + if (sa->agi_bp && xfs_sb_version_hasfinobt(&mp->m_sb) && |
|---|
| 493 | + xchk_ag_btree_healthy_enough(sc, sa->pag, XFS_BTNUM_FINO)) { |
|---|
| 485 | 494 | sa->fino_cur = xfs_inobt_init_cursor(mp, sc->tp, sa->agi_bp, |
|---|
| 486 | 495 | agno, XFS_BTNUM_FINO); |
|---|
| 487 | 496 | if (!sa->fino_cur) |
|---|
| .. | .. |
|---|
| 489 | 498 | } |
|---|
| 490 | 499 | |
|---|
| 491 | 500 | /* Set up a rmapbt cursor for cross-referencing. */ |
|---|
| 492 | | - if (sa->agf_bp && xfs_sb_version_hasrmapbt(&mp->m_sb)) { |
|---|
| 501 | + if (sa->agf_bp && xfs_sb_version_hasrmapbt(&mp->m_sb) && |
|---|
| 502 | + xchk_ag_btree_healthy_enough(sc, sa->pag, XFS_BTNUM_RMAP)) { |
|---|
| 493 | 503 | sa->rmap_cur = xfs_rmapbt_init_cursor(mp, sc->tp, sa->agf_bp, |
|---|
| 494 | 504 | agno); |
|---|
| 495 | 505 | if (!sa->rmap_cur) |
|---|
| .. | .. |
|---|
| 497 | 507 | } |
|---|
| 498 | 508 | |
|---|
| 499 | 509 | /* Set up a refcountbt cursor for cross-referencing. */ |
|---|
| 500 | | - if (sa->agf_bp && xfs_sb_version_hasreflink(&mp->m_sb)) { |
|---|
| 510 | + if (sa->agf_bp && xfs_sb_version_hasreflink(&mp->m_sb) && |
|---|
| 511 | + xchk_ag_btree_healthy_enough(sc, sa->pag, XFS_BTNUM_REFC)) { |
|---|
| 501 | 512 | sa->refc_cur = xfs_refcountbt_init_cursor(mp, sc->tp, |
|---|
| 502 | 513 | sa->agf_bp, agno); |
|---|
| 503 | 514 | if (!sa->refc_cur) |
|---|
| .. | .. |
|---|
| 884 | 895 | } |
|---|
| 885 | 896 | return -EDEADLOCK; |
|---|
| 886 | 897 | } |
|---|
| 898 | + |
|---|
| 899 | +/* Pause background reaping of resources. */ |
|---|
| 900 | +void |
|---|
| 901 | +xchk_stop_reaping( |
|---|
| 902 | + struct xfs_scrub *sc) |
|---|
| 903 | +{ |
|---|
| 904 | + sc->flags |= XCHK_REAPING_DISABLED; |
|---|
| 905 | + xfs_stop_block_reaping(sc->mp); |
|---|
| 906 | +} |
|---|
| 907 | + |
|---|
| 908 | +/* Restart background reaping of resources. */ |
|---|
| 909 | +void |
|---|
| 910 | +xchk_start_reaping( |
|---|
| 911 | + struct xfs_scrub *sc) |
|---|
| 912 | +{ |
|---|
| 913 | + xfs_start_block_reaping(sc->mp); |
|---|
| 914 | + sc->flags &= ~XCHK_REAPING_DISABLED; |
|---|
| 915 | +} |
|---|