aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoger Willcocks <roger@filmlight.ltd.uk>2016-10-20 00:48:38 -0400
committerDave Chinner <david@fromorbit.com>2016-10-20 00:48:38 -0400
commit8cdcc8102c0cfad20513ed1bfb96e0e9963928a8 (patch)
tree25f6467ff79b46d176c68b391d315226f9bf2383
parent58d789678546d46d7bbd809dd7dab417c0f23655 (diff)
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: Leslie Rhorer <lrhorer@mygrande.net> Signed-off-by: Roger Willcocks <roger@filmlight.ltd.uk> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
-rw-r--r--fs/xfs/libxfs/xfs_format.h1
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.c13
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.h2
3 files changed, 14 insertions, 2 deletions
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index f6547fc5e016..6b7579e7b60a 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -865,7 +865,6 @@ typedef struct xfs_timestamp {
865 * padding field for v3 inodes. 865 * padding field for v3 inodes.
866 */ 866 */
867#define XFS_DINODE_MAGIC 0x494e /* 'IN' */ 867#define XFS_DINODE_MAGIC 0x494e /* 'IN' */
868#define XFS_DINODE_GOOD_VERSION(v) ((v) >= 1 && (v) <= 3)
869typedef struct xfs_dinode { 868typedef struct xfs_dinode {
870 __be16 di_magic; /* inode magic # = XFS_DINODE_MAGIC */ 869 __be16 di_magic; /* inode magic # = XFS_DINODE_MAGIC */
871 __be16 di_mode; /* mode and type of file */ 870 __be16 di_mode; /* mode and type of file */
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index 8de9a3a29589..134424fac434 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -57,6 +57,17 @@ xfs_inobp_check(
57} 57}
58#endif 58#endif
59 59
60bool
61xfs_dinode_good_version(
62 struct xfs_mount *mp,
63 __u8 version)
64{
65 if (xfs_sb_version_hascrc(&mp->m_sb))
66 return version == 3;
67
68 return version == 1 || version == 2;
69}
70
60/* 71/*
61 * If we are doing readahead on an inode buffer, we might be in log recovery 72 * If we are doing readahead on an inode buffer, we might be in log recovery
62 * reading an inode allocation buffer that hasn't yet been replayed, and hence 73 * reading an inode allocation buffer that hasn't yet been replayed, and hence
@@ -91,7 +102,7 @@ xfs_inode_buf_verify(
91 102
92 dip = xfs_buf_offset(bp, (i << mp->m_sb.sb_inodelog)); 103 dip = xfs_buf_offset(bp, (i << mp->m_sb.sb_inodelog));
93 di_ok = dip->di_magic == cpu_to_be16(XFS_DINODE_MAGIC) && 104 di_ok = dip->di_magic == cpu_to_be16(XFS_DINODE_MAGIC) &&
94 XFS_DINODE_GOOD_VERSION(dip->di_version); 105 xfs_dinode_good_version(mp, dip->di_version);
95 if (unlikely(XFS_TEST_ERROR(!di_ok, mp, 106 if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
96 XFS_ERRTAG_ITOBP_INOTOBP, 107 XFS_ERRTAG_ITOBP_INOTOBP,
97 XFS_RANDOM_ITOBP_INOTOBP))) { 108 XFS_RANDOM_ITOBP_INOTOBP))) {
diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h
index 62d9d4681c8c..3cfe12a4f58a 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.h
+++ b/fs/xfs/libxfs/xfs_inode_buf.h
@@ -74,6 +74,8 @@ void xfs_inode_from_disk(struct xfs_inode *ip, struct xfs_dinode *from);
74void xfs_log_dinode_to_disk(struct xfs_log_dinode *from, 74void xfs_log_dinode_to_disk(struct xfs_log_dinode *from,
75 struct xfs_dinode *to); 75 struct xfs_dinode *to);
76 76
77bool xfs_dinode_good_version(struct xfs_mount *mp, __u8 version);
78
77#if defined(DEBUG) 79#if defined(DEBUG)
78void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *); 80void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
79#else 81#else