Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (C) 2017 Oracle.  All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Author: Darrick J. Wong <darrick.wong@oracle.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include "xfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include "xfs_fs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include "xfs_shared.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include "xfs_format.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include "xfs_trans_resv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include "xfs_mount.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include "xfs_log_format.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include "xfs_trans.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include "xfs_inode.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include "xfs_quota.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include "xfs_qm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include "xfs_errortag.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include "xfs_error.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "xfs_scrub.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include "scrub/scrub.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include "scrub/common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include "scrub/trace.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include "scrub/repair.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include "scrub/health.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * Online Scrub and Repair
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  * Traditionally, XFS (the kernel driver) did not know how to check or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  * repair on-disk data structures.  That task was left to the xfs_check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * and xfs_repair tools, both of which require taking the filesystem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  * offline for a thorough but time consuming examination.  Online
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  * scrub & repair, on the other hand, enables us to check the metadata
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  * for obvious errors while carefully stepping around the filesystem's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  * ongoing operations, locking rules, etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)  * Given that most XFS metadata consist of records stored in a btree,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  * most of the checking functions iterate the btree blocks themselves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  * looking for irregularities.  When a record block is encountered, each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  * record can be checked for obviously bad values.  Record values can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  * also be cross-referenced against other btrees to look for potential
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  * misunderstandings between pieces of metadata.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  * It is expected that the checkers responsible for per-AG metadata
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  * structures will lock the AG headers (AGI, AGF, AGFL), iterate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  * metadata structure, and perform any relevant cross-referencing before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  * unlocking the AG and returning the results to userspace.  These
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  * scrubbers must not keep an AG locked for too long to avoid tying up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  * the block and inode allocators.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  * Block maps and b-trees rooted in an inode present a special challenge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  * because they can involve extents from any AG.  The general scrubber
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  * structure of lock -> check -> xref -> unlock still holds, but AG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * locking order rules /must/ be obeyed to avoid deadlocks.  The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * ordering rule, of course, is that we must lock in increasing AG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * order.  Helper functions are provided to track which AG headers we've
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  * already locked.  If we detect an imminent locking order violation, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  * can signal a potential deadlock, in which case the scrubber can jump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  * out to the top level, lock all the AGs in order, and retry the scrub.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * For file data (directories, extended attributes, symlinks) scrub, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * can simply lock the inode and walk the data.  For btree data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  * (directories and attributes) we follow the same btree-scrubbing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  * strategy outlined previously to check the records.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  * We use a bit of trickery with transactions to avoid buffer deadlocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * if there is a cycle in the metadata.  The basic problem is that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  * travelling down a btree involves locking the current buffer at each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  * tree level.  If a pointer should somehow point back to a buffer that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  * we've already examined, we will deadlock due to the second buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  * locking attempt.  Note however that grabbing a buffer in transaction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  * context links the locked buffer to the transaction.  If we try to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  * re-grab the buffer in the context of the same transaction, we avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  * the second lock attempt and continue.  Between the verifier and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  * scrubber, something will notice that something is amiss and report
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  * the corruption.  Therefore, each scrubber will allocate an empty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  * transaction, attach buffers to it, and cancel the transaction at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)  * end of the scrub run.  Cancelling a non-dirty transaction simply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)  * unlocks the buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  * There are four pieces of data that scrub can communicate to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  * userspace.  The first is the error code (errno), which can be used to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  * communicate operational errors in performing the scrub.  There are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  * also three flags that can be set in the scrub context.  If the data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  * structure itself is corrupt, the CORRUPT flag will be set.  If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * the metadata is correct but otherwise suboptimal, the PREEN flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  * will be set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)  * We perform secondary validation of filesystem metadata by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90)  * cross-referencing every record with all other available metadata.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91)  * For example, for block mapping extents, we verify that there are no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)  * records in the free space and inode btrees corresponding to that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)  * space extent and that there is a corresponding entry in the reverse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)  * mapping btree.  Inconsistent metadata is noted by setting the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95)  * XCORRUPT flag; btree query function errors are noted by setting the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96)  * XFAIL flag and deleting the cursor to prevent further attempts to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97)  * cross-reference with a defective btree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99)  * If a piece of metadata proves corrupt or suboptimal, the userspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)  * program can ask the kernel to apply some tender loving care (TLC) to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)  * the metadata object by setting the REPAIR flag and re-calling the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)  * scrub ioctl.  "Corruption" is defined by metadata violating the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)  * on-disk specification; operations cannot continue if the violation is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)  * left untreated.  It is possible for XFS to continue if an object is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)  * "suboptimal", however performance may be degraded.  Repairs are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)  * usually performed by rebuilding the metadata entirely out of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)  * redundant metadata.  Optimizing, on the other hand, can sometimes be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)  * done without rebuilding entire structures.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)  * Generally speaking, the repair code has the following code structure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)  * Lock -> scrub -> repair -> commit -> re-lock -> re-scrub -> unlock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)  * The first check helps us figure out if we need to rebuild or simply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  * optimize the structure so that the rebuild knows what to do.  The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)  * second check evaluates the completeness of the repair; that is what
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)  * is reported to userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)  * A quick note on symbol prefixes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)  * - "xfs_" are general XFS symbols.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)  * - "xchk_" are symbols related to metadata checking.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)  * - "xrep_" are symbols related to metadata repair.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)  * - "xfs_scrub_" are symbols that tie online fsck to the rest of XFS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)  * Scrub probe -- userspace uses this to probe if we're willing to scrub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)  * or repair a given mountpoint.  This will be used by xfs_scrub to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)  * probe the kernel's abilities to scrub (and repair) the metadata.  We
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)  * do this by validating the ioctl inputs from userspace, preparing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)  * filesystem for a scrub (or a repair) operation, and immediately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)  * returning to userspace.  Userspace can use the returned errno and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)  * structure state to decide (in broad terms) if scrub/repair are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)  * supported by the running kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) xchk_probe(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	struct xfs_scrub	*sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	int			error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	if (xchk_should_terminate(sc, &error))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* Scrub setup and teardown */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* Free all the resources and finish the transactions. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) xchk_teardown(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	struct xfs_scrub	*sc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	struct xfs_inode	*ip_in,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	int			error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	xchk_ag_free(sc, &sc->sa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	if (sc->tp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		if (error == 0 && (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			error = xfs_trans_commit(sc->tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			xfs_trans_cancel(sc->tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		sc->tp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	if (sc->ip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		if (sc->ilock_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 			xfs_iunlock(sc->ip, sc->ilock_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		if (sc->ip != ip_in &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		    !xfs_internal_inum(sc->mp, sc->ip->i_ino))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 			xfs_irele(sc->ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		sc->ip = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	sb_end_write(sc->mp->m_super);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	if (sc->flags & XCHK_REAPING_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		xchk_start_reaping(sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	if (sc->flags & XCHK_HAS_QUOTAOFFLOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		mutex_unlock(&sc->mp->m_quotainfo->qi_quotaofflock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		sc->flags &= ~XCHK_HAS_QUOTAOFFLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	if (sc->buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		kmem_free(sc->buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		sc->buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /* Scrubbing dispatch. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static const struct xchk_meta_ops meta_scrub_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	[XFS_SCRUB_TYPE_PROBE] = {	/* ioctl presence test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		.type	= ST_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		.setup	= xchk_setup_fs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		.scrub	= xchk_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		.repair = xrep_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	[XFS_SCRUB_TYPE_SB] = {		/* superblock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		.type	= ST_PERAG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		.setup	= xchk_setup_fs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		.scrub	= xchk_superblock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		.repair	= xrep_superblock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	[XFS_SCRUB_TYPE_AGF] = {	/* agf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		.type	= ST_PERAG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		.setup	= xchk_setup_fs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		.scrub	= xchk_agf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		.repair	= xrep_agf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	[XFS_SCRUB_TYPE_AGFL]= {	/* agfl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		.type	= ST_PERAG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		.setup	= xchk_setup_fs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		.scrub	= xchk_agfl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		.repair	= xrep_agfl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	[XFS_SCRUB_TYPE_AGI] = {	/* agi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		.type	= ST_PERAG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		.setup	= xchk_setup_fs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		.scrub	= xchk_agi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		.repair	= xrep_agi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	[XFS_SCRUB_TYPE_BNOBT] = {	/* bnobt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		.type	= ST_PERAG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		.setup	= xchk_setup_ag_allocbt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		.scrub	= xchk_bnobt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	[XFS_SCRUB_TYPE_CNTBT] = {	/* cntbt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		.type	= ST_PERAG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		.setup	= xchk_setup_ag_allocbt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		.scrub	= xchk_cntbt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	[XFS_SCRUB_TYPE_INOBT] = {	/* inobt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		.type	= ST_PERAG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		.setup	= xchk_setup_ag_iallocbt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		.scrub	= xchk_inobt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	[XFS_SCRUB_TYPE_FINOBT] = {	/* finobt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		.type	= ST_PERAG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		.setup	= xchk_setup_ag_iallocbt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		.scrub	= xchk_finobt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		.has	= xfs_sb_version_hasfinobt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	[XFS_SCRUB_TYPE_RMAPBT] = {	/* rmapbt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		.type	= ST_PERAG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		.setup	= xchk_setup_ag_rmapbt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		.scrub	= xchk_rmapbt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		.has	= xfs_sb_version_hasrmapbt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	[XFS_SCRUB_TYPE_REFCNTBT] = {	/* refcountbt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		.type	= ST_PERAG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		.setup	= xchk_setup_ag_refcountbt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		.scrub	= xchk_refcountbt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		.has	= xfs_sb_version_hasreflink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	[XFS_SCRUB_TYPE_INODE] = {	/* inode record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		.type	= ST_INODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		.setup	= xchk_setup_inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		.scrub	= xchk_inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	[XFS_SCRUB_TYPE_BMBTD] = {	/* inode data fork */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		.type	= ST_INODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		.setup	= xchk_setup_inode_bmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		.scrub	= xchk_bmap_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	[XFS_SCRUB_TYPE_BMBTA] = {	/* inode attr fork */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		.type	= ST_INODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		.setup	= xchk_setup_inode_bmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		.scrub	= xchk_bmap_attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	[XFS_SCRUB_TYPE_BMBTC] = {	/* inode CoW fork */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		.type	= ST_INODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		.setup	= xchk_setup_inode_bmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		.scrub	= xchk_bmap_cow,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	[XFS_SCRUB_TYPE_DIR] = {	/* directory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		.type	= ST_INODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		.setup	= xchk_setup_directory,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		.scrub	= xchk_directory,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	[XFS_SCRUB_TYPE_XATTR] = {	/* extended attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		.type	= ST_INODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		.setup	= xchk_setup_xattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		.scrub	= xchk_xattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	[XFS_SCRUB_TYPE_SYMLINK] = {	/* symbolic link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		.type	= ST_INODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		.setup	= xchk_setup_symlink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		.scrub	= xchk_symlink,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	[XFS_SCRUB_TYPE_PARENT] = {	/* parent pointers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		.type	= ST_INODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		.setup	= xchk_setup_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		.scrub	= xchk_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	[XFS_SCRUB_TYPE_RTBITMAP] = {	/* realtime bitmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		.type	= ST_FS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		.setup	= xchk_setup_rt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		.scrub	= xchk_rtbitmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		.has	= xfs_sb_version_hasrealtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	[XFS_SCRUB_TYPE_RTSUM] = {	/* realtime summary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		.type	= ST_FS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		.setup	= xchk_setup_rt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		.scrub	= xchk_rtsummary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		.has	= xfs_sb_version_hasrealtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	[XFS_SCRUB_TYPE_UQUOTA] = {	/* user quota */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		.type	= ST_FS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		.setup	= xchk_setup_quota,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		.scrub	= xchk_quota,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	[XFS_SCRUB_TYPE_GQUOTA] = {	/* group quota */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		.type	= ST_FS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 		.setup	= xchk_setup_quota,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		.scrub	= xchk_quota,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	[XFS_SCRUB_TYPE_PQUOTA] = {	/* project quota */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		.type	= ST_FS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		.setup	= xchk_setup_quota,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		.scrub	= xchk_quota,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	[XFS_SCRUB_TYPE_FSCOUNTERS] = {	/* fs summary counters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		.type	= ST_FS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		.setup	= xchk_setup_fscounters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		.scrub	= xchk_fscounters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		.repair	= xrep_notsupported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /* This isn't a stable feature, warn once per day. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) xchk_experimental_warning(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	struct xfs_mount	*mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	static struct ratelimit_state scrub_warning = RATELIMIT_STATE_INIT(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 			"xchk_warning", 86400 * HZ, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	ratelimit_set_flags(&scrub_warning, RATELIMIT_MSG_ON_RELEASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	if (__ratelimit(&scrub_warning))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		xfs_alert(mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) "EXPERIMENTAL online scrub feature in use. Use at your own risk!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) xchk_validate_inputs(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	struct xfs_mount		*mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	struct xfs_scrub_metadata	*sm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	int				error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	const struct xchk_meta_ops	*ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	/* Check our inputs. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	sm->sm_flags &= ~XFS_SCRUB_FLAGS_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	if (sm->sm_flags & ~XFS_SCRUB_FLAGS_IN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	/* sm_reserved[] must be zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	if (memchr_inv(sm->sm_reserved, 0, sizeof(sm->sm_reserved)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	error = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	/* Do we know about this type of metadata? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	if (sm->sm_type >= XFS_SCRUB_TYPE_NR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	ops = &meta_scrub_ops[sm->sm_type];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	if (ops->setup == NULL || ops->scrub == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	/* Does this fs even support this type of metadata? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	if (ops->has && !ops->has(&mp->m_sb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	error = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	/* restricting fields must be appropriate for type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	switch (ops->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	case ST_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	case ST_FS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 		if (sm->sm_ino || sm->sm_gen || sm->sm_agno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	case ST_PERAG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 		if (sm->sm_ino || sm->sm_gen ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 		    sm->sm_agno >= mp->m_sb.sb_agcount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	case ST_INODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 		if (sm->sm_agno || (sm->sm_gen && !sm->sm_ino))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	 * We only want to repair read-write v5+ filesystems.  Defer the check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	 * for ops->repair until after our scrub confirms that we need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	 * perform repairs so that we avoid failing due to not supporting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	 * repairing an object that doesn't need repairs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	if (sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		error = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		if (!xfs_sb_version_hascrc(&mp->m_sb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		error = -EROFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		if (mp->m_flags & XFS_MOUNT_RDONLY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) #ifdef CONFIG_XFS_ONLINE_REPAIR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static inline void xchk_postmortem(struct xfs_scrub *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	 * Userspace asked us to repair something, we repaired it, rescanned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	 * it, and the rescan says it's still broken.  Scream about this in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	 * the system logs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	if ((sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	    (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 				 XFS_SCRUB_OFLAG_XCORRUPT)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 		xrep_failure(sc->mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static inline void xchk_postmortem(struct xfs_scrub *sc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	 * Userspace asked us to scrub something, it's broken, and we have no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	 * way of fixing it.  Scream in the logs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	if (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 				XFS_SCRUB_OFLAG_XCORRUPT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 		xfs_alert_ratelimited(sc->mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 				"Corruption detected during scrub.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) #endif /* CONFIG_XFS_ONLINE_REPAIR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /* Dispatch metadata scrubbing. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) xfs_scrub_metadata(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	struct xfs_inode		*ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	struct xfs_scrub_metadata	*sm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	struct xfs_scrub		sc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		.mp			= ip->i_mount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 		.sm			= sm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 		.sa			= {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 			.agno		= NULLAGNUMBER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	struct xfs_mount		*mp = ip->i_mount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	int				error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	BUILD_BUG_ON(sizeof(meta_scrub_ops) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		(sizeof(struct xchk_meta_ops) * XFS_SCRUB_TYPE_NR));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	trace_xchk_start(ip, sm, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	/* Forbidden if we are shut down or mounted norecovery. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	error = -ESHUTDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	if (XFS_FORCED_SHUTDOWN(mp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	error = -ENOTRECOVERABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	if (mp->m_flags & XFS_MOUNT_NORECOVERY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	error = xchk_validate_inputs(mp, sm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	xchk_experimental_warning(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	sc.ops = &meta_scrub_ops[sm->sm_type];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	sc.sick_mask = xchk_health_mask_for_scrub_type(sm->sm_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) retry_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	 * If freeze runs concurrently with a scrub, the freeze can be delayed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	 * indefinitely as we walk the filesystem and iterate over metadata
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	 * buffers.  Freeze quiesces the log (which waits for the buffer LRU to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	 * be emptied) and that won't happen while checking is running.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	sb_start_write(mp->m_super);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	/* Set up for the operation. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	error = sc.ops->setup(&sc, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 		goto out_teardown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	/* Scrub for errors. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	error = sc.ops->scrub(&sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	if (!(sc.flags & XCHK_TRY_HARDER) && error == -EDEADLOCK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		 * Scrubbers return -EDEADLOCK to mean 'try harder'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 		 * Tear down everything we hold, then set up again with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 		 * preparation for worst-case scenarios.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 		error = xchk_teardown(&sc, ip, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		sc.flags |= XCHK_TRY_HARDER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 		goto retry_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	} else if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 		goto out_teardown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	xchk_update_health(&sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	if ((sc.sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	    !(sc.flags & XREP_ALREADY_FIXED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 		bool needs_fix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 		/* Let debug users force us into the repair routines. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 		if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_FORCE_SCRUB_REPAIR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 			sc.sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 		needs_fix = (sc.sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 						XFS_SCRUB_OFLAG_XCORRUPT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 						XFS_SCRUB_OFLAG_PREEN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 		 * If userspace asked for a repair but it wasn't necessary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 		 * report that back to userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 		if (!needs_fix) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 			sc.sm->sm_flags |= XFS_SCRUB_OFLAG_NO_REPAIR_NEEDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 			goto out_nofix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 		 * If it's broken, userspace wants us to fix it, and we haven't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 		 * already tried to fix it, then attempt a repair.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 		error = xrep_attempt(ip, &sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 		if (error == -EAGAIN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 			 * Either the repair function succeeded or it couldn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 			 * get all the resources it needs; either way, we go
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 			 * back to the beginning and call the scrub function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 			error = xchk_teardown(&sc, ip, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 			if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 				xrep_failure(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 			goto retry_op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) out_nofix:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	xchk_postmortem(&sc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) out_teardown:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	error = xchk_teardown(&sc, ip, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	trace_xchk_done(ip, sm, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	if (error == -EFSCORRUPTED || error == -EFSBADCRC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 		sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 		error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }