// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2022-2023 Oracle. All Rights Reserved. * Author: Darrick J. Wong <[email protected]> */ #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" #include "xfs_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" #include "xfs_btree.h" #include "xfs_log_format.h" #include "xfs_trans.h" #include "xfs_sb.h" #include "xfs_inode.h" #include "xfs_alloc.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc.h" #include "xfs_ialloc_btree.h" #include "xfs_rmap.h" #include "xfs_rmap_btree.h" #include "xfs_refcount.h" #include "xfs_refcount_btree.h" #include "xfs_extent_busy.h" #include "xfs_ag.h" #include "xfs_ag_resv.h" #include "xfs_quota.h" #include "xfs_qm.h" #include "xfs_bmap.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_attr.h" #include "xfs_attr_remote.h" #include "xfs_defer.h" #include "scrub/scrub.h" #include "scrub/common.h" #include "scrub/trace.h" #include "scrub/repair.h" #include "scrub/bitmap.h" #include "scrub/agb_bitmap.h" #include "scrub/fsb_bitmap.h" #include "scrub/reap.h" /* * Disposal of Blocks from Old Metadata * * Now that we've constructed a new btree to replace the damaged one, we want * to dispose of the blocks that (we think) the old btree was using. * Previously, we used the rmapbt to collect the extents (bitmap) with the * rmap owner corresponding to the tree we rebuilt, collected extents for any * blocks with the same rmap owner that are owned by another data structure * (sublist), and subtracted sublist from bitmap. In theory the extents * remaining in bitmap are the old btree's blocks. * * Unfortunately, it's possible that the btree was crosslinked with other * blocks on disk. The rmap data can tell us if there are multiple owners, so * if the rmapbt says there is an owner of this block other than @oinfo, then * the block is crosslinked. Remove the reverse mapping and continue. * * If there is one rmap record, we can free the block, which removes the * reverse mapping but doesn't add the block to the free space. Our repair * strategy is to hope the other metadata objects crosslinked on this block * will be rebuilt (atop different blocks), thereby removing all the cross * links. * * If there are no rmap records at all, we also free the block. If the btree * being rebuilt lives in the free space (bnobt/cntbt/rmapbt) then there isn't * supposed to be a rmap record and everything is ok. For other btrees there * had to have been an rmap entry for the block to have ended up on @bitmap, * so if it's gone now there's something wrong and the fs will shut down. * * Note: If there are multiple rmap records with only the same rmap owner as * the btree we're trying to rebuild and the block is indeed owned by another * data structure with the same rmap owner, then the block will be in sublist * and therefore doesn't need disposal. If there are multiple rmap records * with only the same rmap owner but the block is not owned by something with * the same rmap owner, the block will be freed. * * The caller is responsible for locking the AG headers/inode for the entire * rebuild operation so that nothing else can sneak in and change the incore * state while we're not looking. We must also invalidate any buffers * associated with @bitmap. */ /* Information about reaping extents after a repair. */ struct xreap_state { … }; /* Put a block back on the AGFL. */ STATIC int xreap_put_freelist( struct xfs_scrub *sc, xfs_agblock_t agbno) { … } /* Are there any uncommitted reap operations? */ static inline bool xreap_dirty(const struct xreap_state *rs) { … } #define XREAP_MAX_BINVAL … /* * Decide if we want to roll the transaction after reaping an extent. We don't * want to overrun the transaction reservation, so we prohibit more than * 128 EFIs per transaction. For the same reason, we limit the number * of buffer invalidations to 2048. */ static inline bool xreap_want_roll(const struct xreap_state *rs) { … } static inline void xreap_reset(struct xreap_state *rs) { … } #define XREAP_MAX_DEFER_CHAIN … /* * Decide if we want to finish the deferred ops that are attached to the scrub * transaction. We don't want to queue huge chains of deferred ops because * that can consume a lot of log space and kernel memory. Hence we trigger a * xfs_defer_finish if there are more than 2048 deferred reap operations or the * caller did some real work. */ static inline bool xreap_want_defer_finish(const struct xreap_state *rs) { … } static inline void xreap_defer_finish_reset(struct xreap_state *rs) { … } /* * Compute the maximum length of a buffer cache scan (in units of sectors), * given a quantity of fs blocks. */ xfs_daddr_t xrep_bufscan_max_sectors( struct xfs_mount *mp, xfs_extlen_t fsblocks) { … } /* * Return an incore buffer from a sector scan, or NULL if there are no buffers * left to return. */ struct xfs_buf * xrep_bufscan_advance( struct xfs_mount *mp, struct xrep_bufscan *scan) { … } /* Try to invalidate the incore buffers for an extent that we're freeing. */ STATIC void xreap_agextent_binval( struct xreap_state *rs, xfs_agblock_t agbno, xfs_extlen_t *aglenp) { … } /* * Figure out the longest run of blocks that we can dispose of with a single * call. Cross-linked blocks should have their reverse mappings removed, but * single-owner extents can be freed. AGFL blocks can only be put back one at * a time. */ STATIC int xreap_agextent_select( struct xreap_state *rs, xfs_agblock_t agbno, xfs_agblock_t agbno_next, bool *crosslinked, xfs_extlen_t *aglenp) { … } /* * Dispose of as much of the beginning of this AG extent as possible. The * number of blocks disposed of will be returned in @aglenp. */ STATIC int xreap_agextent_iter( struct xreap_state *rs, xfs_agblock_t agbno, xfs_extlen_t *aglenp, bool crosslinked) { … } /* * Break an AG metadata extent into sub-extents by fate (crosslinked, not * crosslinked), and dispose of each sub-extent separately. */ STATIC int xreap_agmeta_extent( uint32_t agbno, uint32_t len, void *priv) { … } /* Dispose of every block of every AG metadata extent in the bitmap. */ int xrep_reap_agblocks( struct xfs_scrub *sc, struct xagb_bitmap *bitmap, const struct xfs_owner_info *oinfo, enum xfs_ag_resv_type type) { … } /* * Break a file metadata extent into sub-extents by fate (crosslinked, not * crosslinked), and dispose of each sub-extent separately. The extent must * not cross an AG boundary. */ STATIC int xreap_fsmeta_extent( uint64_t fsbno, uint64_t len, void *priv) { … } /* * Dispose of every block of every fs metadata extent in the bitmap. * Do not use this to dispose of the mappings in an ondisk inode fork. */ int xrep_reap_fsblocks( struct xfs_scrub *sc, struct xfsb_bitmap *bitmap, const struct xfs_owner_info *oinfo) { … } /* * Metadata files are not supposed to share blocks with anything else. * If blocks are shared, we remove the reverse mapping (thus reducing the * crosslink factor); if blocks are not shared, we also need to free them. * * This first step determines the longest subset of the passed-in imap * (starting at its beginning) that is either crosslinked or not crosslinked. * The blockcount will be adjust down as needed. */ STATIC int xreap_bmapi_select( struct xfs_scrub *sc, struct xfs_inode *ip, int whichfork, struct xfs_bmbt_irec *imap, bool *crosslinked) { … } /* * Decide if this buffer can be joined to a transaction. This is true for most * buffers, but there are two cases that we want to catch: large remote xattr * value buffers are not logged and can overflow the buffer log item dirty * bitmap size; and oversized cached buffers if things have really gone * haywire. */ static inline bool xreap_buf_loggable( const struct xfs_buf *bp) { … } /* * Invalidate any buffers for this file mapping. The @imap blockcount may be * adjusted downward if we need to roll the transaction. */ STATIC int xreap_bmapi_binval( struct xfs_scrub *sc, struct xfs_inode *ip, int whichfork, struct xfs_bmbt_irec *imap) { … } /* * Dispose of as much of the beginning of this file fork mapping as possible. * The number of blocks disposed of is returned in @imap->br_blockcount. */ STATIC int xrep_reap_bmapi_iter( struct xfs_scrub *sc, struct xfs_inode *ip, int whichfork, struct xfs_bmbt_irec *imap, bool crosslinked) { … } /* * Dispose of as much of this file extent as we can. Upon successful return, * the imap will reflect the mapping that was removed from the fork. */ STATIC int xreap_ifork_extent( struct xfs_scrub *sc, struct xfs_inode *ip, int whichfork, struct xfs_bmbt_irec *imap) { … } /* * Dispose of each block mapped to the given fork of the given file. Callers * must hold ILOCK_EXCL, and ip can only be sc->ip or sc->tempip. The fork * must not have any delalloc reservations. */ int xrep_reap_ifork( struct xfs_scrub *sc, struct xfs_inode *ip, int whichfork) { … }