Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8cdcc810 authored by Roger Willcocks's avatar Roger Willcocks Committed by Dave Chinner
Browse files

libxfs: v3 inodes are only valid on crc-enabled filesystems



xfs_repair was not detecting that version 3 inodes are invalid for
for non-CRC filesystems. The result is specific inode corruptions go
undetected and hence aren't repaired if only the version number is
out of range.

The core of the problem is that the XFS_DINODE_GOOD_VERSION() macro
doesn't know that valid inode versions are dependent on a superblock
version number. Fix this in libxfs, and propagate the new function
out into the rest of xfsprogs to fix the issue.

[Darrick: port to kernel from xfsprogs]

Reported-by: default avatarLeslie Rhorer <lrhorer@mygrande.net>
Signed-off-by: default avatarRoger Willcocks <roger@filmlight.ltd.uk>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent 58d78967
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -865,7 +865,6 @@ typedef struct xfs_timestamp {
 * padding field for v3 inodes.
 * padding field for v3 inodes.
 */
 */
#define	XFS_DINODE_MAGIC		0x494e	/* 'IN' */
#define	XFS_DINODE_MAGIC		0x494e	/* 'IN' */
#define XFS_DINODE_GOOD_VERSION(v)	((v) >= 1 && (v) <= 3)
typedef struct xfs_dinode {
typedef struct xfs_dinode {
	__be16		di_magic;	/* inode magic # = XFS_DINODE_MAGIC */
	__be16		di_magic;	/* inode magic # = XFS_DINODE_MAGIC */
	__be16		di_mode;	/* mode and type of file */
	__be16		di_mode;	/* mode and type of file */
+12 −1
Original line number Original line Diff line number Diff line
@@ -57,6 +57,17 @@ xfs_inobp_check(
}
}
#endif
#endif


bool
xfs_dinode_good_version(
	struct xfs_mount *mp,
	__u8		version)
{
	if (xfs_sb_version_hascrc(&mp->m_sb))
		return version == 3;

	return version == 1 || version == 2;
}

/*
/*
 * If we are doing readahead on an inode buffer, we might be in log recovery
 * If we are doing readahead on an inode buffer, we might be in log recovery
 * reading an inode allocation buffer that hasn't yet been replayed, and hence
 * reading an inode allocation buffer that hasn't yet been replayed, and hence
@@ -91,7 +102,7 @@ xfs_inode_buf_verify(


		dip = xfs_buf_offset(bp, (i << mp->m_sb.sb_inodelog));
		dip = xfs_buf_offset(bp, (i << mp->m_sb.sb_inodelog));
		di_ok = dip->di_magic == cpu_to_be16(XFS_DINODE_MAGIC) &&
		di_ok = dip->di_magic == cpu_to_be16(XFS_DINODE_MAGIC) &&
			    XFS_DINODE_GOOD_VERSION(dip->di_version);
			xfs_dinode_good_version(mp, dip->di_version);
		if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
		if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
						XFS_ERRTAG_ITOBP_INOTOBP,
						XFS_ERRTAG_ITOBP_INOTOBP,
						XFS_RANDOM_ITOBP_INOTOBP))) {
						XFS_RANDOM_ITOBP_INOTOBP))) {
+2 −0
Original line number Original line Diff line number Diff line
@@ -74,6 +74,8 @@ void xfs_inode_from_disk(struct xfs_inode *ip, struct xfs_dinode *from);
void	xfs_log_dinode_to_disk(struct xfs_log_dinode *from,
void	xfs_log_dinode_to_disk(struct xfs_log_dinode *from,
			       struct xfs_dinode *to);
			       struct xfs_dinode *to);


bool	xfs_dinode_good_version(struct xfs_mount *mp, __u8 version);

#if defined(DEBUG)
#if defined(DEBUG)
void	xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
void	xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
#else
#else