From: "Darrick J. Wong" <djwong@xxxxxxxxxx> Make sure the flag isn't set incorrectly. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> Signed-off-by: John Garry <john.g.garry@xxxxxxxxxx> --- repair/dinode.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/repair/dinode.c b/repair/dinode.c index e534a01b5009..a9de2ee73ef4 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -2262,6 +2262,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_has_forcealign(mp)) { + 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 @@ -2833,6 +2896,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.34.1