[PATCH 10/25] xfs: scrub the AGI

"Darrick J. Wong" <[email protected]>
Newsgroups gmane.comp.file-systems.xfs.general
Message-ID <[email protected]>
Add a forgotten check to the AGI verifier, then wire up the scrub
infrastructure to check the AGI contents.

Signed-off-by: Darrick J. Wong <[email protected]>
---
 fs/xfs/libxfs/xfs_fs.h     |    3 ++-
 fs/xfs/libxfs/xfs_ialloc.c |    5 ++++
 fs/xfs/xfs_scrub.c         |   51 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+), 1 deletion(-)


diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index 8249ae0..2d320a7 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -538,7 +538,8 @@ struct xfs_scrub_metadata {
 #define XFS_SCRUB_TYPE_SB	0	/* superblock */
 #define XFS_SCRUB_TYPE_AGF	1	/* AG free header */
 #define XFS_SCRUB_TYPE_AGFL	2	/* AG free list */
-#define XFS_SCRUB_TYPE_MAX	2
+#define XFS_SCRUB_TYPE_AGI	3	/* AG inode header */
+#define XFS_SCRUB_TYPE_MAX	3
 
 #define XFS_SCRUB_FLAGS_ALL	0x0	/* no flags yet */
 
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 60e1a67..1240064 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -2514,6 +2514,11 @@ xfs_agi_verify(
 
 	if (be32_to_cpu(agi->agi_level) > XFS_BTREE_MAXLEVELS)
 		return false;
+
+	if (xfs_sb_version_hasfinobt(&mp->m_sb) &&
+	    be32_to_cpu(agi->agi_free_level) > XFS_BTREE_MAXLEVELS)
+		return false;
+
 	/*
 	 * during growfs operations, the perag is not fully initialised,
 	 * so we can't use it for any useful checking. growfs ensures we can't
diff --git a/fs/xfs/xfs_scrub.c b/fs/xfs/xfs_scrub.c
index c04a097..2b1d669 100644
--- a/fs/xfs/xfs_scrub.c
+++ b/fs/xfs/xfs_scrub.c
@@ -909,6 +909,56 @@ err_no_agfl:
 	return error;
 }
 
+/* Scrub the AGI. */
+STATIC int
+xfs_scrub_agi(
+	struct xfs_inode		*ip,
+	struct xfs_scrub_metadata	*sm)
+{
+	struct xfs_mount		*mp = ip->i_mount;
+	struct xfs_agi			*agi;
+	struct xfs_agf			*agf;
+	struct xfs_buf			*agi_bp = NULL;
+	struct xfs_buf			*agf_bp = NULL;
+	xfs_agnumber_t			agno;
+	xfs_agblock_t			agbno;
+	xfs_agblock_t			eoag;
+	xfs_daddr_t			daddr;
+	xfs_daddr_t			eofs;
+	int				error;
+
+	if (sm->control >= mp->m_sb.sb_agcount || sm->flags)
+		return -EINVAL;
+	agno = sm->control;
+
+	error = xfs_scrub_get_ag_headers(mp, agno, &agi_bp, &agf_bp);
+	if (error)
+		return error;
+
+	agi = XFS_BUF_TO_AGI(agi_bp);
+	agf = XFS_BUF_TO_AGF(agf_bp);
+	eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
+	eoag = be32_to_cpu(agf->agf_length);
+
+	agbno = be32_to_cpu(agi->agi_root);
+	daddr = XFS_AGB_TO_DADDR(mp, agno, agbno);
+	XFS_SCRUB_CHECK(mp, agi_bp, "AGI", agbno < mp->m_sb.sb_agblocks);
+	XFS_SCRUB_CHECK(mp, agi_bp, "AGI", agbno < eoag);
+	XFS_SCRUB_CHECK(mp, agi_bp, "AGI", daddr < eofs);
+
+	if (xfs_sb_version_hasfinobt(&mp->m_sb)) {
+		agbno = be32_to_cpu(agi->agi_free_root);
+		daddr = XFS_AGB_TO_DADDR(mp, agno, agbno);
+		XFS_SCRUB_CHECK(mp, agi_bp, "AGI",
+				agbno < mp->m_sb.sb_agblocks);
+		XFS_SCRUB_CHECK(mp, agi_bp, "AGI", agbno < eoag);
+		XFS_SCRUB_CHECK(mp, agi_bp, "AGI", daddr < eofs);
+	}
+
+	xfs_scrub_put_ag_headers(&agi_bp, &agf_bp);
+	return error;
+}
+
 /* Scrubbing dispatch. */
 
 struct xfs_scrub_meta_fns {
@@ -920,6 +970,7 @@ static const struct xfs_scrub_meta_fns meta_scrub_fns[] = {
 	{xfs_scrub_sb,		NULL},
 	{xfs_scrub_agf,		NULL},
 	{xfs_scrub_agfl,	NULL},
+	{xfs_scrub_agi,		NULL},
 };
 
 /* Dispatch metadata scrubbing. */

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.