From 2a14aafc618a9878d45240c4f0c1f0c7dc8f3d6b Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 29 Sep 2023 09:53:40 +0000 Subject: [PATCH 05/11] xfs_repair: check the force-align flag Make sure the flag isn't set incorrectly. Signed-off-by: "Darrick J. Wong" Signed-off-by: John Garry --- repair/dinode.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/repair/dinode.c b/repair/dinode.c index f39ab2d..7747070 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -2229,6 +2229,69 @@ _("Bad extent size hint %u on inode %" PRIu64 ", "), } } +static void +validate_forcealign( + struct xfs_mount *mp, + struct xfs_dinode *dino, + xfs_ino_t lino, + int *dirty) +{ + uint16_t mode; + uint16_t flags; + uint64_t flags2; + + mode = be16_to_cpu(dino->di_mode); + flags = be16_to_cpu(dino->di_flags); + flags2 = be64_to_cpu(dino->di_flags2); + + if (!(flags2 & XFS_DIFLAG2_FORCEALIGN)) + return; + + if (!xfs_sb_version_hasforcealign(&mp->m_sb)) { + do_warn( + _("Filesystem does not support forcealign flag set on inode %" PRIu64 ", "), + lino); + goto zap; + } + + if (!S_ISDIR(mode) && !S_ISREG(mode)) { + do_warn( + _("Cannot have forcealign inode flag set on non-dir non-regular file inode %" PRIu64 "\n"), + lino); + goto zap; + } + + if (flags & XFS_DIFLAG_REALTIME) { + do_warn( + _("Cannot have forcealign inode flag set on realtime inode %" PRIu64 "\n"), + lino); + goto zap; + } + + if (dino->di_extsize == 0) { + do_warn( + _("Cannot have forcealign inode flag set without an extent size hint on inode %" PRIu64 "\n"), + lino); + goto zap; + } + + if (dino->di_cowextsize != 0) { + do_warn( + _("Cannot have forcealign inode flag set with nonzero CoW extent size hint on inode %" PRIu64 "\n"), + lino); + goto zap; + } + + return; +zap: + if (!no_modify) { + do_warn(_("clearing flag\n")); + dino->di_flags2 &= ~cpu_to_be64(XFS_DIFLAG2_FORCEALIGN); + *dirty = 1; + } else + do_warn(_("would clear flag\n")); +} + /* * returns 0 if the inode is ok, 1 if the inode is corrupt * check_dups can be set to 1 *only* when called by the @@ -2764,6 +2827,9 @@ _("Bad CoW extent size %u on inode %" PRIu64 ", "), do_warn(_("would reset to zero\n")); } + if (dino->di_version >= 3) + validate_forcealign(mp, dino, lino, dirty); + /* nsec fields cannot be larger than 1 billion */ check_nsec("atime", lino, dino, &dino->di_atime, dirty); check_nsec("mtime", lino, dino, &dino->di_mtime, dirty); -- 2.33.0