diff options
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 72 |
1 files changed, 26 insertions, 46 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 236ebaf678f2..9ec4bbd28d55 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -4118,46 +4118,6 @@ xlog_recover_process_iunlinks( | |||
4118 | mp->m_dmevmask = mp_dmevmask; | 4118 | mp->m_dmevmask = mp_dmevmask; |
4119 | } | 4119 | } |
4120 | 4120 | ||
4121 | /* | ||
4122 | * Upack the log buffer data and crc check it. If the check fails, issue a | ||
4123 | * warning if and only if the CRC in the header is non-zero. This makes the | ||
4124 | * check an advisory warning, and the zero CRC check will prevent failure | ||
4125 | * warnings from being emitted when upgrading the kernel from one that does not | ||
4126 | * add CRCs by default. | ||
4127 | * | ||
4128 | * When filesystems are CRC enabled, this CRC mismatch becomes a fatal log | ||
4129 | * corruption failure | ||
4130 | */ | ||
4131 | STATIC int | ||
4132 | xlog_unpack_data_crc( | ||
4133 | struct xlog_rec_header *rhead, | ||
4134 | char *dp, | ||
4135 | struct xlog *log) | ||
4136 | { | ||
4137 | __le32 crc; | ||
4138 | |||
4139 | crc = xlog_cksum(log, rhead, dp, be32_to_cpu(rhead->h_len)); | ||
4140 | if (crc != rhead->h_crc) { | ||
4141 | if (rhead->h_crc || xfs_sb_version_hascrc(&log->l_mp->m_sb)) { | ||
4142 | xfs_alert(log->l_mp, | ||
4143 | "log record CRC mismatch: found 0x%x, expected 0x%x.", | ||
4144 | le32_to_cpu(rhead->h_crc), | ||
4145 | le32_to_cpu(crc)); | ||
4146 | xfs_hex_dump(dp, 32); | ||
4147 | } | ||
4148 | |||
4149 | /* | ||
4150 | * If we've detected a log record corruption, then we can't | ||
4151 | * recover past this point. Abort recovery if we are enforcing | ||
4152 | * CRC protection by punting an error back up the stack. | ||
4153 | */ | ||
4154 | if (xfs_sb_version_hascrc(&log->l_mp->m_sb)) | ||
4155 | return -EFSCORRUPTED; | ||
4156 | } | ||
4157 | |||
4158 | return 0; | ||
4159 | } | ||
4160 | |||
4161 | STATIC int | 4121 | STATIC int |
4162 | xlog_unpack_data( | 4122 | xlog_unpack_data( |
4163 | struct xlog_rec_header *rhead, | 4123 | struct xlog_rec_header *rhead, |
@@ -4165,11 +4125,6 @@ xlog_unpack_data( | |||
4165 | struct xlog *log) | 4125 | struct xlog *log) |
4166 | { | 4126 | { |
4167 | int i, j, k; | 4127 | int i, j, k; |
4168 | int error; | ||
4169 | |||
4170 | error = xlog_unpack_data_crc(rhead, dp, log); | ||
4171 | if (error) | ||
4172 | return error; | ||
4173 | 4128 | ||
4174 | for (i = 0; i < BTOBB(be32_to_cpu(rhead->h_len)) && | 4129 | for (i = 0; i < BTOBB(be32_to_cpu(rhead->h_len)) && |
4175 | i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) { | 4130 | i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) { |
@@ -4191,7 +4146,7 @@ xlog_unpack_data( | |||
4191 | } | 4146 | } |
4192 | 4147 | ||
4193 | /* | 4148 | /* |
4194 | * Unpack and process a log record. | 4149 | * CRC check, unpack and process a log record. |
4195 | */ | 4150 | */ |
4196 | STATIC int | 4151 | STATIC int |
4197 | xlog_recover_process( | 4152 | xlog_recover_process( |
@@ -4202,6 +4157,31 @@ xlog_recover_process( | |||
4202 | int pass) | 4157 | int pass) |
4203 | { | 4158 | { |
4204 | int error; | 4159 | int error; |
4160 | __le32 crc; | ||
4161 | |||
4162 | /* | ||
4163 | * Check the CRC and issue a warning if and only if the CRC in the | ||
4164 | * header is non-zero. This is an advisory warning and the zero CRC | ||
4165 | * check prevents warnings from being emitted when upgrading the kernel | ||
4166 | * from one that does not add CRCs by default. | ||
4167 | */ | ||
4168 | crc = xlog_cksum(log, rhead, dp, be32_to_cpu(rhead->h_len)); | ||
4169 | if (crc != le32_to_cpu(rhead->h_crc)) { | ||
4170 | if (rhead->h_crc || xfs_sb_version_hascrc(&log->l_mp->m_sb)) { | ||
4171 | xfs_alert(log->l_mp, | ||
4172 | "log record CRC mismatch: found 0x%x, expected 0x%x.", | ||
4173 | le32_to_cpu(rhead->h_crc), | ||
4174 | le32_to_cpu(crc)); | ||
4175 | xfs_hex_dump(dp, 32); | ||
4176 | } | ||
4177 | |||
4178 | /* | ||
4179 | * If the filesystem is CRC enabled, this mismatch becomes a | ||
4180 | * fatal log corruption failure. | ||
4181 | */ | ||
4182 | if (xfs_sb_version_hascrc(&log->l_mp->m_sb)) | ||
4183 | return -EFSCORRUPTED; | ||
4184 | } | ||
4205 | 4185 | ||
4206 | error = xlog_unpack_data(rhead, dp, log); | 4186 | error = xlog_unpack_data(rhead, dp, log); |
4207 | if (error) | 4187 | if (error) |