diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/xfs_inode_buf.c | 36 | ||||
-rw-r--r-- | fs/xfs/xfs_inode_buf.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 2 |
3 files changed, 35 insertions, 4 deletions
diff --git a/fs/xfs/xfs_inode_buf.c b/fs/xfs/xfs_inode_buf.c index 38fe509827dd..e011d597f12f 100644 --- a/fs/xfs/xfs_inode_buf.c +++ b/fs/xfs/xfs_inode_buf.c | |||
@@ -61,9 +61,22 @@ xfs_inobp_check( | |||
61 | } | 61 | } |
62 | #endif | 62 | #endif |
63 | 63 | ||
64 | /* | ||
65 | * If we are doing readahead on an inode buffer, we might be in log recovery | ||
66 | * reading an inode allocation buffer that hasn't yet been replayed, and hence | ||
67 | * has not had the inode cores stamped into it. Hence for readahead, the buffer | ||
68 | * may be potentially invalid. | ||
69 | * | ||
70 | * If the readahead buffer is invalid, we don't want to mark it with an error, | ||
71 | * but we do want to clear the DONE status of the buffer so that a followup read | ||
72 | * will re-read it from disk. This will ensure that we don't get an unnecessary | ||
73 | * warnings during log recovery and we don't get unnecssary panics on debug | ||
74 | * kernels. | ||
75 | */ | ||
64 | static void | 76 | static void |
65 | xfs_inode_buf_verify( | 77 | xfs_inode_buf_verify( |
66 | struct xfs_buf *bp) | 78 | struct xfs_buf *bp, |
79 | bool readahead) | ||
67 | { | 80 | { |
68 | struct xfs_mount *mp = bp->b_target->bt_mount; | 81 | struct xfs_mount *mp = bp->b_target->bt_mount; |
69 | int i; | 82 | int i; |
@@ -84,6 +97,11 @@ xfs_inode_buf_verify( | |||
84 | if (unlikely(XFS_TEST_ERROR(!di_ok, mp, | 97 | if (unlikely(XFS_TEST_ERROR(!di_ok, mp, |
85 | XFS_ERRTAG_ITOBP_INOTOBP, | 98 | XFS_ERRTAG_ITOBP_INOTOBP, |
86 | XFS_RANDOM_ITOBP_INOTOBP))) { | 99 | XFS_RANDOM_ITOBP_INOTOBP))) { |
100 | if (readahead) { | ||
101 | bp->b_flags &= ~XBF_DONE; | ||
102 | return; | ||
103 | } | ||
104 | |||
87 | xfs_buf_ioerror(bp, EFSCORRUPTED); | 105 | xfs_buf_ioerror(bp, EFSCORRUPTED); |
88 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH, | 106 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_HIGH, |
89 | mp, dip); | 107 | mp, dip); |
@@ -104,14 +122,21 @@ static void | |||
104 | xfs_inode_buf_read_verify( | 122 | xfs_inode_buf_read_verify( |
105 | struct xfs_buf *bp) | 123 | struct xfs_buf *bp) |
106 | { | 124 | { |
107 | xfs_inode_buf_verify(bp); | 125 | xfs_inode_buf_verify(bp, false); |
126 | } | ||
127 | |||
128 | static void | ||
129 | xfs_inode_buf_readahead_verify( | ||
130 | struct xfs_buf *bp) | ||
131 | { | ||
132 | xfs_inode_buf_verify(bp, true); | ||
108 | } | 133 | } |
109 | 134 | ||
110 | static void | 135 | static void |
111 | xfs_inode_buf_write_verify( | 136 | xfs_inode_buf_write_verify( |
112 | struct xfs_buf *bp) | 137 | struct xfs_buf *bp) |
113 | { | 138 | { |
114 | xfs_inode_buf_verify(bp); | 139 | xfs_inode_buf_verify(bp, false); |
115 | } | 140 | } |
116 | 141 | ||
117 | const struct xfs_buf_ops xfs_inode_buf_ops = { | 142 | const struct xfs_buf_ops xfs_inode_buf_ops = { |
@@ -119,6 +144,11 @@ const struct xfs_buf_ops xfs_inode_buf_ops = { | |||
119 | .verify_write = xfs_inode_buf_write_verify, | 144 | .verify_write = xfs_inode_buf_write_verify, |
120 | }; | 145 | }; |
121 | 146 | ||
147 | const struct xfs_buf_ops xfs_inode_buf_ra_ops = { | ||
148 | .verify_read = xfs_inode_buf_readahead_verify, | ||
149 | .verify_write = xfs_inode_buf_write_verify, | ||
150 | }; | ||
151 | |||
122 | 152 | ||
123 | /* | 153 | /* |
124 | * This routine is called to map an inode to the buffer containing the on-disk | 154 | * This routine is called to map an inode to the buffer containing the on-disk |
diff --git a/fs/xfs/xfs_inode_buf.h b/fs/xfs/xfs_inode_buf.h index aae9fc465fe0..599e6c0ca2a9 100644 --- a/fs/xfs/xfs_inode_buf.h +++ b/fs/xfs/xfs_inode_buf.h | |||
@@ -48,5 +48,6 @@ void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *); | |||
48 | #endif /* DEBUG */ | 48 | #endif /* DEBUG */ |
49 | 49 | ||
50 | extern const struct xfs_buf_ops xfs_inode_buf_ops; | 50 | extern const struct xfs_buf_ops xfs_inode_buf_ops; |
51 | extern const struct xfs_buf_ops xfs_inode_buf_ra_ops; | ||
51 | 52 | ||
52 | #endif /* __XFS_INODE_BUF_H__ */ | 53 | #endif /* __XFS_INODE_BUF_H__ */ |
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index dc100fed1973..7c0c1fdc728b 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -3309,7 +3309,7 @@ xlog_recover_inode_ra_pass2( | |||
3309 | return; | 3309 | return; |
3310 | 3310 | ||
3311 | xfs_buf_readahead(mp->m_ddev_targp, ilfp->ilf_blkno, | 3311 | xfs_buf_readahead(mp->m_ddev_targp, ilfp->ilf_blkno, |
3312 | ilfp->ilf_len, &xfs_inode_buf_ops); | 3312 | ilfp->ilf_len, &xfs_inode_buf_ra_ops); |
3313 | } | 3313 | } |
3314 | 3314 | ||
3315 | STATIC void | 3315 | STATIC void |