From patchwork Sun Dec 31 20:12:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507352 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ED300BA22 for ; Sun, 31 Dec 2023 20:12:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BoFPVq5u" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 53FE2C433C8; Sun, 31 Dec 2023 20:12:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704053567; bh=MHVtLvqFpt5urDbIyKV4i+0hJGtKlJD+DTjvmrkg41A=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=BoFPVq5uuTjV/vdXB0ozP1r/1ipkDyqtSOM3aeCPaXKuv8XwZb91RguYScQoZWSHU aPIJBPLDrd3uA6Zghz4p9Cmrta12ZBdgsr4FwfC4Lvt/ptp7fldctmv7F8u3UxcxEV YJrkEJKrliNoD75X3mFvTmJkioRqx1kbsQvTD7I9sUB8RCkTCWseDbyQTSNcdt3bHB aJuY9qCKtSct79ZJiauemQGlr1qCHVX4tRbyKn8sI8JB92SOcF8P9lw3FPRPAgn0PQ t7Zy+Er4Su9mvOpxNkXFH5YGsn5EnrusHYlBUVdWd1Ma4j1AflmsxjTipmg/s68cWc WPxiFg8CGDDjg== Date: Sun, 31 Dec 2023 12:12:46 -0800 Subject: [PATCH 1/3] xfs: add secondary and indirect classes to the health tracking system From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404828829.1748648.4029931620882730072.stgit@frogsfrogsfrogs> In-Reply-To: <170404828806.1748648.14558047021297001140.stgit@frogsfrogsfrogs> References: <170404828806.1748648.14558047021297001140.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Establish two more classes of health tracking bits: * Indirect problems, which suggest problems in other health domains that we weren't able to preserve. * Secondary problems, which track state that's related to primary evidence of health problems; and The first class we'll use in an upcoming patch to record in the AG health status the fact that we ran out of memory and had to inactivate an inode with defective metadata. The second class we use to indicate that repair knows that an inode is bad and we need to fix it later. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_health.h | 43 +++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_health.c | 26 +++++++++++++++++--------- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/fs/xfs/libxfs/xfs_health.h b/fs/xfs/libxfs/xfs_health.h index a5b346b377cbb..26a2661571b1d 100644 --- a/fs/xfs/libxfs/xfs_health.h +++ b/fs/xfs/libxfs/xfs_health.h @@ -31,6 +31,19 @@ * - !checked && sick => errors have been observed during normal operation, * but the metadata has not been checked thoroughly * - !checked && !sick => has not been examined since mount + * + * Evidence of health problems can be sorted into three basic categories: + * + * a) Primary evidence, which signals that something is defective within the + * general grouping of metadata. + * + * b) Secondary evidence, which are side effects of primary problem but are + * not themselves problems. These can be forgotten when the primary + * health problems are addressed. + * + * c) Indirect evidence, which points to something being wrong in another + * group, but we had to release resources and this is all that's left of + * that state. */ struct xfs_mount; @@ -115,6 +128,36 @@ struct xfs_da_args; XFS_SICK_INO_DIR_ZAPPED | \ XFS_SICK_INO_SYMLINK_ZAPPED) +/* Secondary state related to (but not primary evidence of) health problems. */ +#define XFS_SICK_FS_SECONDARY (0) +#define XFS_SICK_RT_SECONDARY (0) +#define XFS_SICK_AG_SECONDARY (0) +#define XFS_SICK_INO_SECONDARY (0) + +/* Evidence of health problems elsewhere. */ +#define XFS_SICK_FS_INDIRECT (0) +#define XFS_SICK_RT_INDIRECT (0) +#define XFS_SICK_AG_INDIRECT (0) +#define XFS_SICK_INO_INDIRECT (0) + +/* All health masks. */ +#define XFS_SICK_FS_ALL (XFS_SICK_FS_PRIMARY | \ + XFS_SICK_FS_SECONDARY | \ + XFS_SICK_FS_INDIRECT) + +#define XFS_SICK_RT_ALL (XFS_SICK_RT_PRIMARY | \ + XFS_SICK_RT_SECONDARY | \ + XFS_SICK_RT_INDIRECT) + +#define XFS_SICK_AG_ALL (XFS_SICK_AG_PRIMARY | \ + XFS_SICK_AG_SECONDARY | \ + XFS_SICK_AG_INDIRECT) + +#define XFS_SICK_INO_ALL (XFS_SICK_INO_PRIMARY | \ + XFS_SICK_INO_SECONDARY | \ + XFS_SICK_INO_INDIRECT | \ + XFS_SICK_INO_ZAPPED) + /* * These functions must be provided by the xfs implementation. Function * behavior with respect to the first argument should be as follows: diff --git a/fs/xfs/xfs_health.c b/fs/xfs/xfs_health.c index 64dffc69a219d..6ea85cd6b66f8 100644 --- a/fs/xfs/xfs_health.c +++ b/fs/xfs/xfs_health.c @@ -97,7 +97,7 @@ xfs_fs_mark_sick( struct xfs_mount *mp, unsigned int mask) { - ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY)); + ASSERT(!(mask & ~XFS_SICK_FS_ALL)); trace_xfs_fs_mark_sick(mp, mask); spin_lock(&mp->m_sb_lock); @@ -124,11 +124,13 @@ xfs_fs_mark_healthy( struct xfs_mount *mp, unsigned int mask) { - ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY)); + ASSERT(!(mask & ~XFS_SICK_FS_ALL)); trace_xfs_fs_mark_healthy(mp, mask); spin_lock(&mp->m_sb_lock); mp->m_fs_sick &= ~mask; + if (!(mp->m_fs_sick & XFS_SICK_FS_PRIMARY)) + mp->m_fs_sick &= ~XFS_SICK_FS_SECONDARY; mp->m_fs_checked |= mask; spin_unlock(&mp->m_sb_lock); } @@ -152,7 +154,7 @@ xfs_rt_mark_sick( struct xfs_mount *mp, unsigned int mask) { - ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY)); + ASSERT(!(mask & ~XFS_SICK_RT_ALL)); trace_xfs_rt_mark_sick(mp, mask); spin_lock(&mp->m_sb_lock); @@ -180,11 +182,13 @@ xfs_rt_mark_healthy( struct xfs_mount *mp, unsigned int mask) { - ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY)); + ASSERT(!(mask & ~XFS_SICK_RT_ALL)); trace_xfs_rt_mark_healthy(mp, mask); spin_lock(&mp->m_sb_lock); mp->m_rt_sick &= ~mask; + if (!(mp->m_rt_sick & XFS_SICK_RT_PRIMARY)) + mp->m_rt_sick &= ~XFS_SICK_RT_SECONDARY; mp->m_rt_checked |= mask; spin_unlock(&mp->m_sb_lock); } @@ -225,7 +229,7 @@ xfs_ag_mark_sick( struct xfs_perag *pag, unsigned int mask) { - ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY)); + ASSERT(!(mask & ~XFS_SICK_AG_ALL)); trace_xfs_ag_mark_sick(pag->pag_mount, pag->pag_agno, mask); spin_lock(&pag->pag_state_lock); @@ -252,11 +256,13 @@ xfs_ag_mark_healthy( struct xfs_perag *pag, unsigned int mask) { - ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY)); + ASSERT(!(mask & ~XFS_SICK_AG_ALL)); trace_xfs_ag_mark_healthy(pag->pag_mount, pag->pag_agno, mask); spin_lock(&pag->pag_state_lock); pag->pag_sick &= ~mask; + if (!(pag->pag_sick & XFS_SICK_AG_PRIMARY)) + pag->pag_sick &= ~XFS_SICK_AG_SECONDARY; pag->pag_checked |= mask; spin_unlock(&pag->pag_state_lock); } @@ -280,7 +286,7 @@ xfs_inode_mark_sick( struct xfs_inode *ip, unsigned int mask) { - ASSERT(!(mask & ~(XFS_SICK_INO_PRIMARY | XFS_SICK_INO_ZAPPED))); + ASSERT(!(mask & ~XFS_SICK_INO_ALL)); trace_xfs_inode_mark_sick(ip, mask); spin_lock(&ip->i_flags_lock); @@ -303,7 +309,7 @@ xfs_inode_mark_checked( struct xfs_inode *ip, unsigned int mask) { - ASSERT(!(mask & ~(XFS_SICK_INO_PRIMARY | XFS_SICK_INO_ZAPPED))); + ASSERT(!(mask & ~XFS_SICK_INO_ALL)); spin_lock(&ip->i_flags_lock); ip->i_checked |= mask; @@ -316,11 +322,13 @@ xfs_inode_mark_healthy( struct xfs_inode *ip, unsigned int mask) { - ASSERT(!(mask & ~(XFS_SICK_INO_PRIMARY | XFS_SICK_INO_ZAPPED))); + ASSERT(!(mask & ~XFS_SICK_INO_ALL)); trace_xfs_inode_mark_healthy(ip, mask); spin_lock(&ip->i_flags_lock); ip->i_sick &= ~mask; + if (!(ip->i_sick & XFS_SICK_INO_PRIMARY)) + ip->i_sick &= ~XFS_SICK_INO_SECONDARY; ip->i_checked |= mask; spin_unlock(&ip->i_flags_lock); } From patchwork Sun Dec 31 20:13:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507353 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6D6CBBA2E for ; Sun, 31 Dec 2023 20:13:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="H1WQooLE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EE25AC433C7; Sun, 31 Dec 2023 20:13:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704053583; bh=fsyoIFua6TNP+7wn+jwlHfY0nsbjeyOMNlNX2pMugXk=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=H1WQooLEHX52wJ5eoMfRUayxYyZnszfzSsxmskvTC03vGJ8p6Zk8n27OrAtLCy9FS FY+u2o+QifNHNMyu6KTur38P3evHcHGrXTbEfkUM4awCwVH/SNh0vnxhBgViQ59EGt f9N/S5TW4Bm9i2MLPsuhlJNiCfK0ujkRWQi34Vgte9wVDkXI7U1dEK7zccBfMIt3vn ZL5ixduxcHOneXBq4qwtu9K4n5O37j53jhgQMD8QM8AXly1BDnfhaWY24f8DDVIJn8 NdhJd5rb/w9fwxdKsQJC3SUDhofh7fE0yBvgdaEJ9mp/vADGBLwcWx4s5u8NH6ofE3 A3Lppvt3LBdDw== Date: Sun, 31 Dec 2023 12:13:02 -0800 Subject: [PATCH 2/3] xfs: remember sick inodes that get inactivated From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404828845.1748648.14811776992278882263.stgit@frogsfrogsfrogs> In-Reply-To: <170404828806.1748648.14558047021297001140.stgit@frogsfrogsfrogs> References: <170404828806.1748648.14558047021297001140.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong If an unhealthy inode gets inactivated, remember this fact in the per-fs health summary. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_fs.h | 1 + fs/xfs/libxfs/xfs_health.h | 8 ++++++-- fs/xfs/libxfs/xfs_inode_buf.c | 2 +- fs/xfs/scrub/health.c | 12 +++++++++++- fs/xfs/xfs_health.c | 1 + fs/xfs/xfs_inode.c | 35 +++++++++++++++++++++++++++++++++++ fs/xfs/xfs_trace.h | 1 + 7 files changed, 56 insertions(+), 4 deletions(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 515cd27d3b3a8..b5c8da7e6aa99 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -294,6 +294,7 @@ struct xfs_ag_geometry { #define XFS_AG_GEOM_SICK_FINOBT (1 << 7) /* free inode index */ #define XFS_AG_GEOM_SICK_RMAPBT (1 << 8) /* reverse mappings */ #define XFS_AG_GEOM_SICK_REFCNTBT (1 << 9) /* reference counts */ +#define XFS_AG_GEOM_SICK_INODES (1 << 10) /* bad inodes were seen */ /* * Structures for XFS_IOC_FSGROWFSDATA, XFS_IOC_FSGROWFSLOG & XFS_IOC_FSGROWFSRT diff --git a/fs/xfs/libxfs/xfs_health.h b/fs/xfs/libxfs/xfs_health.h index 26a2661571b1d..df07c5877ba44 100644 --- a/fs/xfs/libxfs/xfs_health.h +++ b/fs/xfs/libxfs/xfs_health.h @@ -76,6 +76,7 @@ struct xfs_da_args; #define XFS_SICK_AG_FINOBT (1 << 7) /* free inode index */ #define XFS_SICK_AG_RMAPBT (1 << 8) /* reverse mappings */ #define XFS_SICK_AG_REFCNTBT (1 << 9) /* reference counts */ +#define XFS_SICK_AG_INODES (1 << 10) /* inactivated bad inodes */ /* Observable health issues for inode metadata. */ #define XFS_SICK_INO_CORE (1 << 0) /* inode core */ @@ -92,6 +93,9 @@ struct xfs_da_args; #define XFS_SICK_INO_DIR_ZAPPED (1 << 10) /* directory erased */ #define XFS_SICK_INO_SYMLINK_ZAPPED (1 << 11) /* symlink erased */ +/* Don't propagate sick status to ag health summary during inactivation */ +#define XFS_SICK_INO_FORGET (1 << 12) + /* Primary evidence of health problems in a given group. */ #define XFS_SICK_FS_PRIMARY (XFS_SICK_FS_COUNTERS | \ XFS_SICK_FS_UQUOTA | \ @@ -132,12 +136,12 @@ struct xfs_da_args; #define XFS_SICK_FS_SECONDARY (0) #define XFS_SICK_RT_SECONDARY (0) #define XFS_SICK_AG_SECONDARY (0) -#define XFS_SICK_INO_SECONDARY (0) +#define XFS_SICK_INO_SECONDARY (XFS_SICK_INO_FORGET) /* Evidence of health problems elsewhere. */ #define XFS_SICK_FS_INDIRECT (0) #define XFS_SICK_RT_INDIRECT (0) -#define XFS_SICK_AG_INDIRECT (0) +#define XFS_SICK_AG_INDIRECT (XFS_SICK_AG_INODES) #define XFS_SICK_INO_INDIRECT (0) /* All health masks. */ diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index 1280d6acd1c1b..d0dcce462bf42 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c @@ -139,7 +139,7 @@ xfs_imap_to_bp( imap->im_len, XBF_UNMAPPED, bpp, &xfs_inode_buf_ops); if (xfs_metadata_is_sick(error)) xfs_agno_mark_sick(mp, xfs_daddr_to_agno(mp, imap->im_blkno), - XFS_SICK_AG_INOBT); + XFS_SICK_AG_INODES); return error; } diff --git a/fs/xfs/scrub/health.c b/fs/xfs/scrub/health.c index 0f235501ed8a5..e26d71716c922 100644 --- a/fs/xfs/scrub/health.c +++ b/fs/xfs/scrub/health.c @@ -187,7 +187,17 @@ xchk_update_health( if (!sc->ip) return; if (bad) { - xfs_inode_mark_sick(sc->ip, sc->sick_mask); + unsigned int mask = sc->sick_mask; + + /* + * If we're coming in for repairs then we don't want + * sickness flags to propagate to the incore health + * status if the inode gets inactivated before we can + * fix it. + */ + if (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR) + mask |= XFS_SICK_INO_FORGET; + xfs_inode_mark_sick(sc->ip, mask); xfs_inode_mark_checked(sc->ip, sc->sick_mask); } else xfs_inode_mark_healthy(sc->ip, sc->sick_mask); diff --git a/fs/xfs/xfs_health.c b/fs/xfs/xfs_health.c index 6ea85cd6b66f8..2be1ac83f4c41 100644 --- a/fs/xfs/xfs_health.c +++ b/fs/xfs/xfs_health.c @@ -415,6 +415,7 @@ static const struct ioctl_sick_map ag_map[] = { { XFS_SICK_AG_FINOBT, XFS_AG_GEOM_SICK_FINOBT }, { XFS_SICK_AG_RMAPBT, XFS_AG_GEOM_SICK_RMAPBT }, { XFS_SICK_AG_REFCNTBT, XFS_AG_GEOM_SICK_REFCNTBT }, + { XFS_SICK_AG_INODES, XFS_AG_GEOM_SICK_INODES }, { 0, 0 }, }; diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 6db00c5097ec0..04fa933061c7d 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1751,6 +1751,39 @@ xfs_inode_needs_inactive( return xfs_can_free_eofblocks(ip, true); } +/* + * Save health status somewhere, if we're dumping an inode with uncorrected + * errors and online repair isn't running. + */ +static inline void +xfs_inactive_health( + struct xfs_inode *ip) +{ + struct xfs_mount *mp = ip->i_mount; + struct xfs_perag *pag; + unsigned int sick; + unsigned int checked; + + xfs_inode_measure_sickness(ip, &sick, &checked); + if (!sick) + return; + + trace_xfs_inode_unfixed_corruption(ip, sick); + + if (sick & XFS_SICK_INO_FORGET) + return; + + pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); + if (!pag) { + /* There had better still be a perag structure! */ + ASSERT(0); + return; + } + + xfs_ag_mark_sick(pag, XFS_SICK_AG_INODES); + xfs_perag_put(pag); +} + /* * xfs_inactive * @@ -1779,6 +1812,8 @@ xfs_inactive( mp = ip->i_mount; ASSERT(!xfs_iflags_test(ip, XFS_IRECOVERY)); + xfs_inactive_health(ip); + /* * If this is a read-only mount, don't do this (would generate I/O) * unless we're in log recovery and cleaning the iunlinked list. diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 0efcdb79d10e5..7d075e426c5d0 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -3978,6 +3978,7 @@ DEFINE_EVENT(xfs_inode_corrupt_class, name, \ TP_ARGS(ip, flags)) DEFINE_INODE_CORRUPT_EVENT(xfs_inode_mark_sick); DEFINE_INODE_CORRUPT_EVENT(xfs_inode_mark_healthy); +DEFINE_INODE_CORRUPT_EVENT(xfs_inode_unfixed_corruption); TRACE_EVENT(xfs_iwalk_ag, TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, From patchwork Sun Dec 31 20:13:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507354 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2E398BA30 for ; Sun, 31 Dec 2023 20:13:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="oc5wGAtB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A2263C433C8; Sun, 31 Dec 2023 20:13:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704053598; bh=irjApS69uq+zao5zflw2ywJPjCG1RTdkrLgq4fNkyQA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=oc5wGAtBj4AYX/4tAyhW83YHtmngdOftAv+yRpBDSuImI7lIrZ2GosaZqtdU2OcrZ hP7bf4Vh+L9O3I+NQITnldFI/9SES+31TFqjIMbMJRHEZA5/1KKCUX1wGTKHvCY0O2 LlWDSZt9jy6qorZiD2/X2XMSREgDoeikrPEubF/t48Tosrop5YR4cVwcbe1hhRcb2P p2a7YdvzvlYu+1+9jw5c2LnhH6aGHwT7kf50MbyRKd/ezyZsb5wCOgPQmg5NBq8mLg 5uY/TxhjnKhOpwAnbFoEnGEApIaD9PEHWqqHiuhmazW1v/UICvHBymN03XNMDtCMIj ZZ8ntZXO7MgaQ== Date: Sun, 31 Dec 2023 12:13:18 -0800 Subject: [PATCH 3/3] xfs: update health status if we get a clean bill of health From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404828862.1748648.8875885962116664930.stgit@frogsfrogsfrogs> In-Reply-To: <170404828806.1748648.14558047021297001140.stgit@frogsfrogsfrogs> References: <170404828806.1748648.14558047021297001140.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong If scrub finds that everything is ok with the filesystem, we need a way to tell the health tracking that it can let go of indirect health flags, since indirect flags only mean that at some point in the past we lost some context. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_fs.h | 3 ++ fs/xfs/scrub/health.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/scrub/health.h | 1 + fs/xfs/scrub/repair.c | 1 + fs/xfs/scrub/scrub.c | 6 +++++ fs/xfs/scrub/trace.h | 4 ++- 6 files changed, 77 insertions(+), 2 deletions(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index b5c8da7e6aa99..ca1b17d014377 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -714,9 +714,10 @@ struct xfs_scrub_metadata { #define XFS_SCRUB_TYPE_FSCOUNTERS 24 /* fs summary counters */ #define XFS_SCRUB_TYPE_QUOTACHECK 25 /* quota counters */ #define XFS_SCRUB_TYPE_NLINKS 26 /* inode link counts */ +#define XFS_SCRUB_TYPE_HEALTHY 27 /* everything checked out ok */ /* Number of scrub subcommands. */ -#define XFS_SCRUB_TYPE_NR 27 +#define XFS_SCRUB_TYPE_NR 28 /* i: Repair this metadata. */ #define XFS_SCRUB_IFLAG_REPAIR (1u << 0) diff --git a/fs/xfs/scrub/health.c b/fs/xfs/scrub/health.c index e26d71716c922..664d57247ddf5 100644 --- a/fs/xfs/scrub/health.c +++ b/fs/xfs/scrub/health.c @@ -16,6 +16,7 @@ #include "xfs_health.h" #include "scrub/scrub.h" #include "scrub/health.h" +#include "scrub/common.h" /* * Scrub and In-Core Filesystem Health Assessments @@ -151,6 +152,24 @@ xchk_file_looks_zapped( return xfs_inode_has_sickness(sc->ip, mask); } +/* + * Scrub gave the filesystem a clean bill of health, so clear all the indirect + * markers of past problems (at least for the fs and ags) so that we can be + * healthy again. + */ +STATIC void +xchk_mark_all_healthy( + struct xfs_mount *mp) +{ + struct xfs_perag *pag; + xfs_agnumber_t agno; + + xfs_fs_mark_healthy(mp, XFS_SICK_FS_INDIRECT); + xfs_rt_mark_healthy(mp, XFS_SICK_RT_INDIRECT); + for_each_perag(mp, agno, pag) + xfs_ag_mark_healthy(pag, XFS_SICK_AG_INDIRECT); +} + /* * Update filesystem health assessments based on what we found and did. * @@ -168,6 +187,18 @@ xchk_update_health( struct xfs_perag *pag; bool bad; + /* + * The HEALTHY scrub type is a request from userspace to clear all the + * indirect flags after a clean scan of the entire filesystem. As such + * there's no sick flag defined for it, so we branch here ahead of the + * mask check. + */ + if (sc->sm->sm_type == XFS_SCRUB_TYPE_HEALTHY && + !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) { + xchk_mark_all_healthy(sc->mp); + return; + } + if (!sc->sick_mask) return; @@ -291,3 +322,36 @@ xchk_ag_btree_healthy_enough( return true; } + +/* + * Quick scan to double-check that there isn't any evidence of lingering + * primary health problems. If we're still clear, then the health update will + * take care of clearing the indirect evidence. + */ +int +xchk_health_record( + struct xfs_scrub *sc) +{ + struct xfs_mount *mp = sc->mp; + struct xfs_perag *pag; + xfs_agnumber_t agno; + + unsigned int sick; + unsigned int checked; + + xfs_fs_measure_sickness(mp, &sick, &checked); + if (sick & XFS_SICK_FS_PRIMARY) + xchk_set_corrupt(sc); + + xfs_rt_measure_sickness(mp, &sick, &checked); + if (sick & XFS_SICK_RT_PRIMARY) + xchk_set_corrupt(sc); + + for_each_perag(mp, agno, pag) { + xfs_ag_measure_sickness(pag, &sick, &checked); + if (sick & XFS_SICK_AG_PRIMARY) + xchk_set_corrupt(sc); + } + + return 0; +} diff --git a/fs/xfs/scrub/health.h b/fs/xfs/scrub/health.h index a731b2467399f..06d17941776cc 100644 --- a/fs/xfs/scrub/health.h +++ b/fs/xfs/scrub/health.h @@ -12,5 +12,6 @@ bool xchk_ag_btree_healthy_enough(struct xfs_scrub *sc, struct xfs_perag *pag, xfs_btnum_t btnum); void xchk_mark_healthy_if_clean(struct xfs_scrub *sc, unsigned int mask); bool xchk_file_looks_zapped(struct xfs_scrub *sc, unsigned int mask); +int xchk_health_record(struct xfs_scrub *sc); #endif /* __XFS_SCRUB_HEALTH_H__ */ diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c index 7141b17789028..ab510cea96d86 100644 --- a/fs/xfs/scrub/repair.c +++ b/fs/xfs/scrub/repair.c @@ -30,6 +30,7 @@ #include "xfs_errortag.h" #include "xfs_error.h" #include "xfs_reflink.h" +#include "xfs_health.h" #include "scrub/scrub.h" #include "scrub/common.h" #include "scrub/trace.h" diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c index c0b99184bb3ef..0f23b7f36d4a5 100644 --- a/fs/xfs/scrub/scrub.c +++ b/fs/xfs/scrub/scrub.c @@ -378,6 +378,12 @@ static const struct xchk_meta_ops meta_scrub_ops[] = { .scrub = xchk_nlinks, .repair = xrep_nlinks, }, + [XFS_SCRUB_TYPE_HEALTHY] = { /* fs healthy; clean all reminders */ + .type = ST_FS, + .setup = xchk_setup_fs, + .scrub = xchk_health_record, + .repair = xrep_notsupported, + }, }; static int diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h index fbadec84f45a2..86af0efa15d7c 100644 --- a/fs/xfs/scrub/trace.h +++ b/fs/xfs/scrub/trace.h @@ -69,6 +69,7 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_PQUOTA); TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_FSCOUNTERS); TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_QUOTACHECK); TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_NLINKS); +TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_HEALTHY); #define XFS_SCRUB_TYPE_STRINGS \ { XFS_SCRUB_TYPE_PROBE, "probe" }, \ @@ -97,7 +98,8 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_NLINKS); { XFS_SCRUB_TYPE_PQUOTA, "prjquota" }, \ { XFS_SCRUB_TYPE_FSCOUNTERS, "fscounters" }, \ { XFS_SCRUB_TYPE_QUOTACHECK, "quotacheck" }, \ - { XFS_SCRUB_TYPE_NLINKS, "nlinks" } + { XFS_SCRUB_TYPE_NLINKS, "nlinks" }, \ + { XFS_SCRUB_TYPE_HEALTHY, "healthy" } #define XFS_SCRUB_FLAG_STRINGS \ { XFS_SCRUB_IFLAG_REPAIR, "repair" }, \