summaryrefslogtreecommitdiff
path: root/fs/xfs/scrub/refcount.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-08-14 18:56:02 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2018-08-14 18:56:02 +0300
commit781fca5b104693bc9242199cc47c690dcaf6a4cb (patch)
treed216d4299ae5715331a535c84bab390a907bebd6 /fs/xfs/scrub/refcount.c
parent10f3e23f07cb0c20f9bcb77a5b5a7eb2a1b2a2fe (diff)
parent01239d77b9dd978863d1a75f0d095ab942a1fe66 (diff)
downloadlinux-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.c194
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);
}