[PATCH 15/25] xfs: scrub inodes

"Darrick J. Wong" <[email protected]>
Newsgroups gmane.comp.file-systems.xfs.general
Message-ID <[email protected]>
Scrub the fields within an inode.

Signed-off-by: Darrick J. Wong <[email protected]>
---
 fs/xfs/libxfs/xfs_fs.h |    3 +-
 fs/xfs/xfs_itable.c    |    2 +
 fs/xfs/xfs_itable.h    |    5 +++
 fs/xfs/xfs_scrub.c     |   69 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 77 insertions(+), 2 deletions(-)


diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index 60dfe03..30903d1 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -545,7 +545,8 @@ struct xfs_scrub_metadata {
 #define XFS_SCRUB_TYPE_FINOBT	7	/* free inode btree */
 #define XFS_SCRUB_TYPE_RMAPBT	8	/* reverse mapping btree */
 #define XFS_SCRUB_TYPE_REFCNTBT	9	/* reference count btree */
-#define XFS_SCRUB_TYPE_MAX	9
+#define XFS_SCRUB_TYPE_INODE	10	/* inode record */
+#define XFS_SCRUB_TYPE_MAX	10
 
 #define XFS_SCRUB_FLAGS_ALL	0x0	/* no flags yet */
 
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 66e8817..4fd5fe1 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -31,7 +31,7 @@
 #include "xfs_trace.h"
 #include "xfs_icache.h"
 
-STATIC int
+int
 xfs_internal_inum(
 	xfs_mount_t	*mp,
 	xfs_ino_t	ino)
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index 6ea8b39..dd2427b 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -96,4 +96,9 @@ xfs_inumbers(
 	void			__user *buffer, /* buffer with inode info */
 	inumbers_fmt_pf		formatter);
 
+int
+xfs_internal_inum(
+	xfs_mount_t	*mp,
+	xfs_ino_t	ino);
+
 #endif	/* __XFS_ITABLE_H__ */
diff --git a/fs/xfs/xfs_scrub.c b/fs/xfs/xfs_scrub.c
index 4894221..383a00e 100644
--- a/fs/xfs/xfs_scrub.c
+++ b/fs/xfs/xfs_scrub.c
@@ -43,6 +43,8 @@
 #include "xfs_rmap.h"
 #include "xfs_rmap_btree.h"
 #include "xfs_rtalloc.h"
+#include "xfs_icache.h"
+#include "xfs_itable.h"
 
 /* Report a scrub corruption in dmesg. */
 STATIC void
@@ -1313,6 +1315,72 @@ xfs_scrub_refcountbt(
 	return error;
 }
 
+/* Scrub an inode. */
+STATIC int
+xfs_scrub_inode(
+	struct xfs_inode		*ip,
+	struct xfs_scrub_metadata	*sm)
+{
+	struct xfs_mount		*mp = ip->i_mount;
+	struct xfs_inode		*ips;
+	int				error;
+
+	if (sm->flags)
+		return -EINVAL;
+
+	if (sm->control && sm->control != ip->i_ino) {
+		if (xfs_internal_inum(mp, sm->control)) {
+			error = -ENOENT;
+			goto out;
+		}
+		error = xfs_iget(ip->i_mount, NULL, sm->control,
+				XFS_IGET_UNTRUSTED | XFS_IGET_DONTCACHE,
+				XFS_ILOCK_EXCL, &ips);
+		if (error)
+			goto out;
+	} else {
+		ips = ip;
+		xfs_ilock(ips, XFS_ILOCK_EXCL);
+	}
+
+	/* The verifiers should refuse any inode with bad fields. */
+	XFS_INO_SCRUB_GOTO(ips, NULL, "inode", ips != NULL, out_unlock);
+
+	XFS_INO_SCRUB_CHECK(ips, NULL, "inode",
+			ips->i_d.di_projid_hi == 0 ||
+			xfs_sb_version_hasprojid32bit(&mp->m_sb));
+
+	if (ips->i_d.di_flags & XFS_DIFLAG_EXTSIZE) {
+		XFS_INO_SCRUB_CHECK(ips, NULL, "inode",
+				ips->i_d.di_extsize > 0);
+		XFS_INO_SCRUB_CHECK(ips, NULL, "inode",
+				ips->i_d.di_extsize <= MAXEXTLEN);
+		XFS_INO_SCRUB_CHECK(ips, NULL, "inode",
+				XFS_IS_REALTIME_INODE(ip) ||
+				ips->i_d.di_extsize <= mp->m_sb.sb_agblocks / 2);
+	}
+	XFS_INO_SCRUB_CHECK(ips, NULL, "inode",
+			!(ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE) ||
+			!(ip->i_d.di_flags & XFS_DIFLAG_APPEND));
+
+	if (ips->i_d.di_version == 3 &&
+	    ips->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE) {
+		XFS_INO_SCRUB_CHECK(ips, NULL, "inode",
+				ips->i_d.di_cowextsize > 0);
+		XFS_INO_SCRUB_CHECK(ips, NULL, "inode",
+				ips->i_d.di_cowextsize <= MAXEXTLEN);
+		XFS_INO_SCRUB_CHECK(ips, NULL, "inode",
+				ips->i_d.di_cowextsize <= mp->m_sb.sb_agblocks / 2);
+	}
+
+out_unlock:
+	xfs_iunlock(ips, XFS_ILOCK_EXCL);
+	if (ips != ip)
+		IRELE(ips);
+out:
+	return error;
+}
+
 /* Scrubbing dispatch. */
 
 struct xfs_scrub_meta_fns {
@@ -1331,6 +1399,7 @@ static const struct xfs_scrub_meta_fns meta_scrub_fns[] = {
 	{xfs_scrub_finobt,	xfs_sb_version_hasfinobt},
 	{xfs_scrub_rmapbt,	xfs_sb_version_hasrmapbt},
 	{xfs_scrub_refcountbt,	xfs_sb_version_hasreflink},
+	{xfs_scrub_inode,	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.