diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-14 18:56:02 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-14 18:56:02 +0300 |
commit | 781fca5b104693bc9242199cc47c690dcaf6a4cb (patch) | |
tree | d216d4299ae5715331a535c84bab390a907bebd6 /fs/xfs/scrub/refcount.c | |
parent | 10f3e23f07cb0c20f9bcb77a5b5a7eb2a1b2a2fe (diff) | |
parent | 01239d77b9dd978863d1a75f0d095ab942a1fe66 (diff) | |
download | linux-781fca5b104693bc9242199cc47c690dcaf6a4cb.tar.xz |
Merge tag 'xfs-4.19-merge-6' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs updates from Darrick Wong:
"This is the second part of the XFS changes for 4.19.
The biggest changes are the removal of buffer heads frm XFS, a massive
reworking of the deferred transaction operations handling code, the
removal of the long defunct barrier/nobarrier mount options, and the
addition of a few more online repair functions.
Summary:
- Use extent maps to track pagecache page status instead of
bufferhead state.
- Refactor pagecache read and write paths to use the new iomap
library functions, which enable us to drop the old bufferhead code
for pagesize == blocksize filesystems.
- Set up parallel per-block-per-page metadata to track subpage
information that was tracked by buffer heads, which enables us to
drop the old bufferhead code for pagesize > blocksize filesystems.
- Tie a deferred ops control structure to a transaction so that we
can take advantage of an upper-level dfops without having to plumb
pointer passing through the code.
- Refactor the deferred ops code to track deferred ops as part of the
transaction structure (instead of as a separate data structure) so
that we can simplify the scoping rules around defer_ops.
- Refactor twisty delwri buffer submission code to avoid deadlocks.
- Shorten and fix indenting problems in the scrub code.
- Detect obviously bad summary counts at mount and fix them.
- Directly associate deferred ops control structure with a
transaction so that callers no longer have to manage it themselves.
- Remove a couple of IRIX-era inode macros.
- Remove the long-deprecated 'barrier' and 'nobarrier' mount options.
- Clean up the inode fork structure a bit.
- Check for bad fs summary counter values in the superblock.
- Reduce COW fork lookups during writeback.
- Refactor the deferred ops control structures into the transaction
structure, thereby eliminating the need for transaction users to
handle the deferred ops as a separate data structure.
- Add the ability to repair AG headers online.
- Fix a crash due to insufficient return value checking.
- Various fixes and cleanups"
* tag 'xfs-4.19-merge-6' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: (155 commits)
xfs: fix a null pointer dereference in xfs_bmap_extents_to_btree
xfs: remove b_last_holder & associated macros
iomap: Switch to offset_in_page for clarity
xfs: Close race between direct IO and xfs_break_layouts()
xfs: repair the AGI
xfs: repair the AGFL
xfs: repair the AGF
xfs: remove dead error handling code in xfs_dquot_disk_alloc()
xfs: use WRITE_ONCE to update if_seq
xfs: fix a comment in xfs_log_reserve
xfs: only validate summary counts on primary superblock
xfs: substitute spaces with tabs
xfs: fold dfops into the transaction
xfs: always defer agfl block frees
xfs: pass transaction to xfs_defer_add()
xfs: replace xfs_defer_ops ->dop_pending with on-stack list
xfs: cancel dfops on xfs_defer_finish() error
xfs: clean out superfluous dfops dop params/vars
xfs: drop dop param from xfs_defer_op_type ->finish_item() callback
xfs: automatic dfops inode relogging
...
Diffstat (limited to 'fs/xfs/scrub/refcount.c')
-rw-r--r-- | fs/xfs/scrub/refcount.c | 194 |
1 files changed, 97 insertions, 97 deletions
diff --git a/fs/xfs/scrub/refcount.c b/fs/xfs/scrub/refcount.c index 607a9faa8ecc..e8c82b026083 100644 --- a/fs/xfs/scrub/refcount.c +++ b/fs/xfs/scrub/refcount.c @@ -28,11 +28,11 @@ * Set us up to scrub reference count btrees. */ int -xfs_scrub_setup_ag_refcountbt( - struct xfs_scrub_context *sc, - struct xfs_inode *ip) +xchk_setup_ag_refcountbt( + struct xfs_scrub *sc, + struct xfs_inode *ip) { - return xfs_scrub_setup_ag_btree(sc, ip, false); + return xchk_setup_ag_btree(sc, ip, false); } /* Reference count btree scrubber. */ @@ -73,22 +73,22 @@ xfs_scrub_setup_ag_refcountbt( * If the refcount is correct, all the check conditions in the algorithm * should always hold true. If not, the refcount is incorrect. */ -struct xfs_scrub_refcnt_frag { - struct list_head list; - struct xfs_rmap_irec rm; +struct xchk_refcnt_frag { + struct list_head list; + struct xfs_rmap_irec rm; }; -struct xfs_scrub_refcnt_check { - struct xfs_scrub_context *sc; - struct list_head fragments; +struct xchk_refcnt_check { + struct xfs_scrub *sc; + struct list_head fragments; /* refcount extent we're examining */ - xfs_agblock_t bno; - xfs_extlen_t len; - xfs_nlink_t refcount; + xfs_agblock_t bno; + xfs_extlen_t len; + xfs_nlink_t refcount; /* number of owners seen */ - xfs_nlink_t seen; + xfs_nlink_t seen; }; /* @@ -99,18 +99,18 @@ struct xfs_scrub_refcnt_check { * fragments as the refcountbt says we should have. */ STATIC int -xfs_scrub_refcountbt_rmap_check( +xchk_refcountbt_rmap_check( struct xfs_btree_cur *cur, struct xfs_rmap_irec *rec, void *priv) { - struct xfs_scrub_refcnt_check *refchk = priv; - struct xfs_scrub_refcnt_frag *frag; + struct xchk_refcnt_check *refchk = priv; + struct xchk_refcnt_frag *frag; xfs_agblock_t rm_last; xfs_agblock_t rc_last; int error = 0; - if (xfs_scrub_should_terminate(refchk->sc, &error)) + if (xchk_should_terminate(refchk->sc, &error)) return error; rm_last = rec->rm_startblock + rec->rm_blockcount - 1; @@ -118,7 +118,7 @@ xfs_scrub_refcountbt_rmap_check( /* Confirm that a single-owner refc extent is a CoW stage. */ if (refchk->refcount == 1 && rec->rm_owner != XFS_RMAP_OWN_COW) { - xfs_scrub_btree_xref_set_corrupt(refchk->sc, cur, 0); + xchk_btree_xref_set_corrupt(refchk->sc, cur, 0); return 0; } @@ -135,7 +135,7 @@ xfs_scrub_refcountbt_rmap_check( * is healthy each rmap_irec we see will be in agbno order * so we don't need insertion sort here. */ - frag = kmem_alloc(sizeof(struct xfs_scrub_refcnt_frag), + frag = kmem_alloc(sizeof(struct xchk_refcnt_frag), KM_MAYFAIL); if (!frag) return -ENOMEM; @@ -154,12 +154,12 @@ xfs_scrub_refcountbt_rmap_check( * we have a refcountbt error. */ STATIC void -xfs_scrub_refcountbt_process_rmap_fragments( - struct xfs_scrub_refcnt_check *refchk) +xchk_refcountbt_process_rmap_fragments( + struct xchk_refcnt_check *refchk) { struct list_head worklist; - struct xfs_scrub_refcnt_frag *frag; - struct xfs_scrub_refcnt_frag *n; + struct xchk_refcnt_frag *frag; + struct xchk_refcnt_frag *n; xfs_agblock_t bno; xfs_agblock_t rbno; xfs_agblock_t next_rbno; @@ -277,13 +277,13 @@ done: /* Use the rmap entries covering this extent to verify the refcount. */ STATIC void -xfs_scrub_refcountbt_xref_rmap( - struct xfs_scrub_context *sc, +xchk_refcountbt_xref_rmap( + struct xfs_scrub *sc, xfs_agblock_t bno, xfs_extlen_t len, xfs_nlink_t refcount) { - struct xfs_scrub_refcnt_check refchk = { + struct xchk_refcnt_check refchk = { .sc = sc, .bno = bno, .len = len, @@ -292,11 +292,11 @@ xfs_scrub_refcountbt_xref_rmap( }; struct xfs_rmap_irec low; struct xfs_rmap_irec high; - struct xfs_scrub_refcnt_frag *frag; - struct xfs_scrub_refcnt_frag *n; + struct xchk_refcnt_frag *frag; + struct xchk_refcnt_frag *n; int error; - if (!sc->sa.rmap_cur || xfs_scrub_skip_xref(sc->sm)) + if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm)) return; /* Cross-reference with the rmapbt to confirm the refcount. */ @@ -307,13 +307,13 @@ xfs_scrub_refcountbt_xref_rmap( INIT_LIST_HEAD(&refchk.fragments); error = xfs_rmap_query_range(sc->sa.rmap_cur, &low, &high, - &xfs_scrub_refcountbt_rmap_check, &refchk); - if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.rmap_cur)) + &xchk_refcountbt_rmap_check, &refchk); + if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur)) goto out_free; - xfs_scrub_refcountbt_process_rmap_fragments(&refchk); + xchk_refcountbt_process_rmap_fragments(&refchk); if (refcount != refchk.seen) - xfs_scrub_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0); + xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0); out_free: list_for_each_entry_safe(frag, n, &refchk.fragments, list) { @@ -324,34 +324,34 @@ out_free: /* Cross-reference with the other btrees. */ STATIC void -xfs_scrub_refcountbt_xref( - struct xfs_scrub_context *sc, - xfs_agblock_t agbno, - xfs_extlen_t len, - xfs_nlink_t refcount) +xchk_refcountbt_xref( + struct xfs_scrub *sc, + xfs_agblock_t agbno, + xfs_extlen_t len, + xfs_nlink_t refcount) { if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) return; - xfs_scrub_xref_is_used_space(sc, agbno, len); - xfs_scrub_xref_is_not_inode_chunk(sc, agbno, len); - xfs_scrub_refcountbt_xref_rmap(sc, agbno, len, refcount); + xchk_xref_is_used_space(sc, agbno, len); + xchk_xref_is_not_inode_chunk(sc, agbno, len); + xchk_refcountbt_xref_rmap(sc, agbno, len, refcount); } /* Scrub a refcountbt record. */ STATIC int -xfs_scrub_refcountbt_rec( - struct xfs_scrub_btree *bs, - union xfs_btree_rec *rec) +xchk_refcountbt_rec( + struct xchk_btree *bs, + union xfs_btree_rec *rec) { - struct xfs_mount *mp = bs->cur->bc_mp; - xfs_agblock_t *cow_blocks = bs->private; - xfs_agnumber_t agno = bs->cur->bc_private.a.agno; - xfs_agblock_t bno; - xfs_extlen_t len; - xfs_nlink_t refcount; - bool has_cowflag; - int error = 0; + struct xfs_mount *mp = bs->cur->bc_mp; + xfs_agblock_t *cow_blocks = bs->private; + xfs_agnumber_t agno = bs->cur->bc_private.a.agno; + xfs_agblock_t bno; + xfs_extlen_t len; + xfs_nlink_t refcount; + bool has_cowflag; + int error = 0; bno = be32_to_cpu(rec->refc.rc_startblock); len = be32_to_cpu(rec->refc.rc_blockcount); @@ -360,7 +360,7 @@ xfs_scrub_refcountbt_rec( /* Only CoW records can have refcount == 1. */ has_cowflag = (bno & XFS_REFC_COW_START); if ((refcount == 1 && !has_cowflag) || (refcount != 1 && has_cowflag)) - xfs_scrub_btree_set_corrupt(bs->sc, bs->cur, 0); + xchk_btree_set_corrupt(bs->sc, bs->cur, 0); if (has_cowflag) (*cow_blocks) += len; @@ -369,75 +369,75 @@ xfs_scrub_refcountbt_rec( if (bno + len <= bno || !xfs_verify_agbno(mp, agno, bno) || !xfs_verify_agbno(mp, agno, bno + len - 1)) - xfs_scrub_btree_set_corrupt(bs->sc, bs->cur, 0); + xchk_btree_set_corrupt(bs->sc, bs->cur, 0); if (refcount == 0) - xfs_scrub_btree_set_corrupt(bs->sc, bs->cur, 0); + xchk_btree_set_corrupt(bs->sc, bs->cur, 0); - xfs_scrub_refcountbt_xref(bs->sc, bno, len, refcount); + xchk_refcountbt_xref(bs->sc, bno, len, refcount); return error; } /* Make sure we have as many refc blocks as the rmap says. */ STATIC void -xfs_scrub_refcount_xref_rmap( - struct xfs_scrub_context *sc, - struct xfs_owner_info *oinfo, - xfs_filblks_t cow_blocks) +xchk_refcount_xref_rmap( + struct xfs_scrub *sc, + struct xfs_owner_info *oinfo, + xfs_filblks_t cow_blocks) { - xfs_extlen_t refcbt_blocks = 0; - xfs_filblks_t blocks; - int error; + xfs_extlen_t refcbt_blocks = 0; + xfs_filblks_t blocks; + int error; - if (!sc->sa.rmap_cur || xfs_scrub_skip_xref(sc->sm)) + if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm)) return; /* Check that we saw as many refcbt blocks as the rmap knows about. */ error = xfs_btree_count_blocks(sc->sa.refc_cur, &refcbt_blocks); - if (!xfs_scrub_btree_process_error(sc, sc->sa.refc_cur, 0, &error)) + if (!xchk_btree_process_error(sc, sc->sa.refc_cur, 0, &error)) return; - error = xfs_scrub_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur, oinfo, + error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur, oinfo, &blocks); - if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.rmap_cur)) + if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur)) return; if (blocks != refcbt_blocks) - xfs_scrub_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0); + xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0); /* Check that we saw as many cow blocks as the rmap knows about. */ xfs_rmap_ag_owner(oinfo, XFS_RMAP_OWN_COW); - error = xfs_scrub_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur, oinfo, + error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur, oinfo, &blocks); - if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.rmap_cur)) + if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur)) return; if (blocks != cow_blocks) - xfs_scrub_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0); + xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0); } /* Scrub the refcount btree for some AG. */ int -xfs_scrub_refcountbt( - struct xfs_scrub_context *sc) +xchk_refcountbt( + struct xfs_scrub *sc) { - struct xfs_owner_info oinfo; - xfs_agblock_t cow_blocks = 0; - int error; + struct xfs_owner_info oinfo; + xfs_agblock_t cow_blocks = 0; + int error; xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_REFC); - error = xfs_scrub_btree(sc, sc->sa.refc_cur, xfs_scrub_refcountbt_rec, + error = xchk_btree(sc, sc->sa.refc_cur, xchk_refcountbt_rec, &oinfo, &cow_blocks); if (error) return error; - xfs_scrub_refcount_xref_rmap(sc, &oinfo, cow_blocks); + xchk_refcount_xref_rmap(sc, &oinfo, cow_blocks); return 0; } /* xref check that a cow staging extent is marked in the refcountbt. */ void -xfs_scrub_xref_is_cow_staging( - struct xfs_scrub_context *sc, +xchk_xref_is_cow_staging( + struct xfs_scrub *sc, xfs_agblock_t agbno, xfs_extlen_t len) { @@ -446,35 +446,35 @@ xfs_scrub_xref_is_cow_staging( int has_refcount; int error; - if (!sc->sa.refc_cur || xfs_scrub_skip_xref(sc->sm)) + if (!sc->sa.refc_cur || xchk_skip_xref(sc->sm)) return; /* Find the CoW staging extent. */ error = xfs_refcount_lookup_le(sc->sa.refc_cur, agbno + XFS_REFC_COW_START, &has_refcount); - if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.refc_cur)) + if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur)) return; if (!has_refcount) { - xfs_scrub_btree_xref_set_corrupt(sc, sc->sa.refc_cur, 0); + xchk_btree_xref_set_corrupt(sc, sc->sa.refc_cur, 0); return; } error = xfs_refcount_get_rec(sc->sa.refc_cur, &rc, &has_refcount); - if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.refc_cur)) + if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur)) return; if (!has_refcount) { - xfs_scrub_btree_xref_set_corrupt(sc, sc->sa.refc_cur, 0); + xchk_btree_xref_set_corrupt(sc, sc->sa.refc_cur, 0); return; } /* CoW flag must be set, refcount must be 1. */ has_cowflag = (rc.rc_startblock & XFS_REFC_COW_START); if (!has_cowflag || rc.rc_refcount != 1) - xfs_scrub_btree_xref_set_corrupt(sc, sc->sa.refc_cur, 0); + xchk_btree_xref_set_corrupt(sc, sc->sa.refc_cur, 0); /* Must be at least as long as what was passed in */ if (rc.rc_blockcount < len) - xfs_scrub_btree_xref_set_corrupt(sc, sc->sa.refc_cur, 0); + xchk_btree_xref_set_corrupt(sc, sc->sa.refc_cur, 0); } /* @@ -482,20 +482,20 @@ xfs_scrub_xref_is_cow_staging( * can have multiple owners. */ void -xfs_scrub_xref_is_not_shared( - struct xfs_scrub_context *sc, - xfs_agblock_t agbno, - xfs_extlen_t len) +xchk_xref_is_not_shared( + struct xfs_scrub *sc, + xfs_agblock_t agbno, + xfs_extlen_t len) { - bool shared; - int error; + bool shared; + int error; - if (!sc->sa.refc_cur || xfs_scrub_skip_xref(sc->sm)) + if (!sc->sa.refc_cur || xchk_skip_xref(sc->sm)) return; error = xfs_refcount_has_record(sc->sa.refc_cur, agbno, len, &shared); - if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.refc_cur)) + if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur)) return; if (shared) - xfs_scrub_btree_xref_set_corrupt(sc, sc->sa.refc_cur, 0); + xchk_btree_xref_set_corrupt(sc, sc->sa.refc_cur, 0); } |