// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2018-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_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_defer.h" #include "xfs_errortag.h" #include "xfs_error.h" #include "xfs_reflink.h" #include "xfs_health.h" #include "xfs_buf_mem.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_attr.h" #include "xfs_dir2.h" #include "scrub/scrub.h" #include "scrub/common.h" #include "scrub/trace.h" #include "scrub/repair.h" #include "scrub/bitmap.h" #include "scrub/stats.h" #include "scrub/xfile.h" #include "scrub/attr_repair.h" /* * Attempt to repair some metadata, if the metadata is corrupt and userspace * told us to fix it. This function returns -EAGAIN to mean "re-run scrub", * and will set *fixed to true if it thinks it repaired anything. */ int xrep_attempt( struct xfs_scrub *sc, struct xchk_stats_run *run) { … } /* * Complain about unfixable problems in the filesystem. We don't log * corruptions when IFLAG_REPAIR wasn't set on the assumption that the driver * program is xfs_scrub, which will call back with IFLAG_REPAIR set if the * administrator isn't running xfs_scrub in no-repairs mode. * * Use this helper function because _ratelimited silently declares a static * structure to track rate limiting information. */ void xrep_failure( struct xfs_mount *mp) { … } /* * Repair probe -- userspace uses this to probe if we're willing to repair a * given mountpoint. */ int xrep_probe( struct xfs_scrub *sc) { … } /* * Roll a transaction, keeping the AG headers locked and reinitializing * the btree cursors. */ int xrep_roll_ag_trans( struct xfs_scrub *sc) { … } /* Roll the scrub transaction, holding the primary metadata locked. */ int xrep_roll_trans( struct xfs_scrub *sc) { … } /* Finish all deferred work attached to the repair transaction. */ int xrep_defer_finish( struct xfs_scrub *sc) { … } /* * Does the given AG have enough space to rebuild a btree? Neither AG * reservation can be critical, and we must have enough space (factoring * in AG reservations) to construct a whole btree. */ bool xrep_ag_has_space( struct xfs_perag *pag, xfs_extlen_t nr_blocks, enum xfs_ag_resv_type type) { … } /* * Figure out how many blocks to reserve for an AG repair. We calculate the * worst case estimate for the number of blocks we'd need to rebuild one of * any type of per-AG btree. */ xfs_extlen_t xrep_calc_ag_resblks( struct xfs_scrub *sc) { … } /* * Reconstructing per-AG Btrees * * When a space btree is corrupt, we don't bother trying to fix it. Instead, * we scan secondary space metadata to derive the records that should be in * the damaged btree, initialize a fresh btree root, and insert the records. * Note that for rebuilding the rmapbt we scan all the primary data to * generate the new records. * * However, that leaves the matter of removing all the metadata describing the * old broken structure. For primary metadata we use the rmap data to collect * every extent with a matching rmap owner (bitmap); we then iterate all other * metadata structures with the same rmap owner to collect the extents that * cannot be removed (sublist). We then subtract sublist from bitmap to * derive the blocks that were used by the old btree. These blocks can be * reaped. * * For rmapbt reconstructions we must use different tactics for extent * collection. First we iterate all primary metadata (this excludes the old * rmapbt, obviously) to generate new rmap records. The gaps in the rmap * records are collected as bitmap. The bnobt records are collected as * sublist. As with the other btrees we subtract sublist from bitmap, and the * result (since the rmapbt lives in the free space) are the blocks from the * old rmapbt. */ /* Ensure the freelist is the correct size. */ int xrep_fix_freelist( struct xfs_scrub *sc, int alloc_flags) { … } /* * Finding per-AG Btree Roots for AGF/AGI Reconstruction * * If the AGF or AGI become slightly corrupted, it may be necessary to rebuild * the AG headers by using the rmap data to rummage through the AG looking for * btree roots. This is not guaranteed to work if the AG is heavily damaged * or the rmap data are corrupt. * * Callers of xrep_find_ag_btree_roots must lock the AGF and AGFL * buffers if the AGF is being rebuilt; or the AGF and AGI buffers if the * AGI is being rebuilt. It must maintain these locks until it's safe for * other threads to change the btrees' shapes. The caller provides * information about the btrees to look for by passing in an array of * xrep_find_ag_btree with the (rmap owner, buf_ops, magic) fields set. * The (root, height) fields will be set on return if anything is found. The * last element of the array should have a NULL buf_ops to mark the end of the * array. * * For every rmapbt record matching any of the rmap owners in btree_info, * read each block referenced by the rmap record. If the block is a btree * block from this filesystem matching any of the magic numbers and has a * level higher than what we've already seen, remember the block and the * height of the tree required to have such a block. When the call completes, * we return the highest block we've found for each btree description; those * should be the roots. */ struct xrep_findroot { … }; /* See if our block is in the AGFL. */ STATIC int xrep_findroot_agfl_walk( struct xfs_mount *mp, xfs_agblock_t bno, void *priv) { … } /* Does this block match the btree information passed in? */ STATIC int xrep_findroot_block( struct xrep_findroot *ri, struct xrep_find_ag_btree *fab, uint64_t owner, xfs_agblock_t agbno, bool *done_with_block) { … } /* * Do any of the blocks in this rmap record match one of the btrees we're * looking for? */ STATIC int xrep_findroot_rmap( struct xfs_btree_cur *cur, const struct xfs_rmap_irec *rec, void *priv) { … } /* Find the roots of the per-AG btrees described in btree_info. */ int xrep_find_ag_btree_roots( struct xfs_scrub *sc, struct xfs_buf *agf_bp, struct xrep_find_ag_btree *btree_info, struct xfs_buf *agfl_bp) { … } #ifdef CONFIG_XFS_QUOTA /* Update some quota flags in the superblock. */ void xrep_update_qflags( struct xfs_scrub *sc, unsigned int clear_flags, unsigned int set_flags) { … } /* Force a quotacheck the next time we mount. */ void xrep_force_quotacheck( struct xfs_scrub *sc, xfs_dqtype_t type) { … } /* * Attach dquots to this inode, or schedule quotacheck to fix them. * * This function ensures that the appropriate dquots are attached to an inode. * We cannot allow the dquot code to allocate an on-disk dquot block here * because we're already in transaction context. The on-disk dquot should * already exist anyway. If the quota code signals corruption or missing quota * information, schedule quotacheck, which will repair corruptions in the quota * metadata. */ int xrep_ino_dqattach( struct xfs_scrub *sc) { … } #endif /* CONFIG_XFS_QUOTA */ /* * Ensure that the inode being repaired is ready to handle a certain number of * extents, or return EFSCORRUPTED. Caller must hold the ILOCK of the inode * being repaired and have joined it to the scrub transaction. */ int xrep_ino_ensure_extent_count( struct xfs_scrub *sc, int whichfork, xfs_extnum_t nextents) { … } /* * Initialize all the btree cursors for an AG repair except for the btree that * we're rebuilding. */ void xrep_ag_btcur_init( struct xfs_scrub *sc, struct xchk_ag *sa) { … } /* * Reinitialize the in-core AG state after a repair by rereading the AGF * buffer. We had better get the same AGF buffer as the one that's attached * to the scrub context. */ int xrep_reinit_pagf( struct xfs_scrub *sc) { … } /* * Reinitialize the in-core AG state after a repair by rereading the AGI * buffer. We had better get the same AGI buffer as the one that's attached * to the scrub context. */ int xrep_reinit_pagi( struct xfs_scrub *sc) { … } /* * Given an active reference to a perag structure, load AG headers and cursors. * This should only be called to scan an AG while repairing file-based metadata. */ int xrep_ag_init( struct xfs_scrub *sc, struct xfs_perag *pag, struct xchk_ag *sa) { … } /* Reinitialize the per-AG block reservation for the AG we just fixed. */ int xrep_reset_perag_resv( struct xfs_scrub *sc) { … } /* Decide if we are going to call the repair function for a scrub type. */ bool xrep_will_attempt( struct xfs_scrub *sc) { … } /* Try to fix some part of a metadata inode by calling another scrubber. */ STATIC int xrep_metadata_inode_subtype( struct xfs_scrub *sc, unsigned int scrub_type) { … } /* * Repair the ondisk forks of a metadata inode. The caller must ensure that * sc->ip points to the metadata inode and the ILOCK is held on that inode. * The inode must not be joined to the transaction before the call, and will * not be afterwards. */ int xrep_metadata_inode_forks( struct xfs_scrub *sc) { … } /* * Set up an in-memory buffer cache so that we can use the xfbtree. Allocating * a shmem file might take loks, so we cannot be in transaction context. Park * our resources in the scrub context and let the teardown function take care * of them at the right time. */ int xrep_setup_xfbtree( struct xfs_scrub *sc, const char *descr) { … } /* * Create a dummy transaction for use in a live update hook function. This * function MUST NOT be called from regular repair code because the current * process' transaction is saved via the cookie. */ int xrep_trans_alloc_hook_dummy( struct xfs_mount *mp, void **cookiep, struct xfs_trans **tpp) { … } /* Cancel a dummy transaction used by a live update hook function. */ void xrep_trans_cancel_hook_dummy( void **cookiep, struct xfs_trans *tp) { … } /* * See if this buffer can pass the given ->verify_struct() function. * * If the buffer already has ops attached and they're not the ones that were * passed in, we reject the buffer. Otherwise, we perform the structure test * (note that we do not check CRCs) and return the outcome of the test. The * buffer ops and error state are left unchanged. */ bool xrep_buf_verify_struct( struct xfs_buf *bp, const struct xfs_buf_ops *ops) { … }