diff options
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 132 |
1 files changed, 63 insertions, 69 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 931e8e23f19..9c3651c9e75 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include "xfs_trans_priv.h" | 41 | #include "xfs_trans_priv.h" |
42 | #include "xfs_quota.h" | 42 | #include "xfs_quota.h" |
43 | #include "xfs_utils.h" | 43 | #include "xfs_utils.h" |
44 | #include "xfs_cksum.h" | ||
44 | #include "xfs_trace.h" | 45 | #include "xfs_trace.h" |
45 | #include "xfs_icache.h" | 46 | #include "xfs_icache.h" |
46 | 47 | ||
@@ -3216,80 +3217,58 @@ xlog_recover_process_iunlinks( | |||
3216 | mp->m_dmevmask = mp_dmevmask; | 3217 | mp->m_dmevmask = mp_dmevmask; |
3217 | } | 3218 | } |
3218 | 3219 | ||
3219 | |||
3220 | #ifdef DEBUG | ||
3221 | STATIC void | ||
3222 | xlog_pack_data_checksum( | ||
3223 | struct xlog *log, | ||
3224 | struct xlog_in_core *iclog, | ||
3225 | int size) | ||
3226 | { | ||
3227 | int i; | ||
3228 | __be32 *up; | ||
3229 | uint chksum = 0; | ||
3230 | |||
3231 | up = (__be32 *)iclog->ic_datap; | ||
3232 | /* divide length by 4 to get # words */ | ||
3233 | for (i = 0; i < (size >> 2); i++) { | ||
3234 | chksum ^= be32_to_cpu(*up); | ||
3235 | up++; | ||
3236 | } | ||
3237 | iclog->ic_header.h_chksum = cpu_to_be32(chksum); | ||
3238 | } | ||
3239 | #else | ||
3240 | #define xlog_pack_data_checksum(log, iclog, size) | ||
3241 | #endif | ||
3242 | |||
3243 | /* | 3220 | /* |
3244 | * Stamp cycle number in every block | 3221 | * Upack the log buffer data and crc check it. If the check fails, issue a |
3222 | * warning if and only if the CRC in the header is non-zero. This makes the | ||
3223 | * check an advisory warning, and the zero CRC check will prevent failure | ||
3224 | * warnings from being emitted when upgrading the kernel from one that does not | ||
3225 | * add CRCs by default. | ||
3226 | * | ||
3227 | * When filesystems are CRC enabled, this CRC mismatch becomes a fatal log | ||
3228 | * corruption failure | ||
3245 | */ | 3229 | */ |
3246 | void | 3230 | STATIC int |
3247 | xlog_pack_data( | 3231 | xlog_unpack_data_crc( |
3248 | struct xlog *log, | 3232 | struct xlog_rec_header *rhead, |
3249 | struct xlog_in_core *iclog, | 3233 | xfs_caddr_t dp, |
3250 | int roundoff) | 3234 | struct xlog *log) |
3251 | { | 3235 | { |
3252 | int i, j, k; | 3236 | __be32 crc; |
3253 | int size = iclog->ic_offset + roundoff; | 3237 | |
3254 | __be32 cycle_lsn; | 3238 | crc = xlog_cksum(log, rhead, dp, be32_to_cpu(rhead->h_len)); |
3255 | xfs_caddr_t dp; | 3239 | if (crc != rhead->h_crc) { |
3256 | 3240 | if (rhead->h_crc || xfs_sb_version_hascrc(&log->l_mp->m_sb)) { | |
3257 | xlog_pack_data_checksum(log, iclog, size); | 3241 | xfs_alert(log->l_mp, |
3258 | 3242 | "log record CRC mismatch: found 0x%x, expected 0x%x.\n", | |
3259 | cycle_lsn = CYCLE_LSN_DISK(iclog->ic_header.h_lsn); | 3243 | be32_to_cpu(rhead->h_crc), |
3260 | 3244 | be32_to_cpu(crc)); | |
3261 | dp = iclog->ic_datap; | 3245 | xfs_hex_dump(dp, 32); |
3262 | for (i = 0; i < BTOBB(size) && | ||
3263 | i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) { | ||
3264 | iclog->ic_header.h_cycle_data[i] = *(__be32 *)dp; | ||
3265 | *(__be32 *)dp = cycle_lsn; | ||
3266 | dp += BBSIZE; | ||
3267 | } | ||
3268 | |||
3269 | if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) { | ||
3270 | xlog_in_core_2_t *xhdr = iclog->ic_data; | ||
3271 | |||
3272 | for ( ; i < BTOBB(size); i++) { | ||
3273 | j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE); | ||
3274 | k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE); | ||
3275 | xhdr[j].hic_xheader.xh_cycle_data[k] = *(__be32 *)dp; | ||
3276 | *(__be32 *)dp = cycle_lsn; | ||
3277 | dp += BBSIZE; | ||
3278 | } | 3246 | } |
3279 | 3247 | ||
3280 | for (i = 1; i < log->l_iclog_heads; i++) { | 3248 | /* |
3281 | xhdr[i].hic_xheader.xh_cycle = cycle_lsn; | 3249 | * If we've detected a log record corruption, then we can't |
3282 | } | 3250 | * recover past this point. Abort recovery if we are enforcing |
3251 | * CRC protection by punting an error back up the stack. | ||
3252 | */ | ||
3253 | if (xfs_sb_version_hascrc(&log->l_mp->m_sb)) | ||
3254 | return EFSCORRUPTED; | ||
3283 | } | 3255 | } |
3256 | |||
3257 | return 0; | ||
3284 | } | 3258 | } |
3285 | 3259 | ||
3286 | STATIC void | 3260 | STATIC int |
3287 | xlog_unpack_data( | 3261 | xlog_unpack_data( |
3288 | struct xlog_rec_header *rhead, | 3262 | struct xlog_rec_header *rhead, |
3289 | xfs_caddr_t dp, | 3263 | xfs_caddr_t dp, |
3290 | struct xlog *log) | 3264 | struct xlog *log) |
3291 | { | 3265 | { |
3292 | int i, j, k; | 3266 | int i, j, k; |
3267 | int error; | ||
3268 | |||
3269 | error = xlog_unpack_data_crc(rhead, dp, log); | ||
3270 | if (error) | ||
3271 | return error; | ||
3293 | 3272 | ||
3294 | for (i = 0; i < BTOBB(be32_to_cpu(rhead->h_len)) && | 3273 | for (i = 0; i < BTOBB(be32_to_cpu(rhead->h_len)) && |
3295 | i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) { | 3274 | i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) { |
@@ -3306,6 +3285,8 @@ xlog_unpack_data( | |||
3306 | dp += BBSIZE; | 3285 | dp += BBSIZE; |
3307 | } | 3286 | } |
3308 | } | 3287 | } |
3288 | |||
3289 | return 0; | ||
3309 | } | 3290 | } |
3310 | 3291 | ||
3311 | STATIC int | 3292 | STATIC int |
@@ -3437,9 +3418,13 @@ xlog_do_recovery_pass( | |||
3437 | if (error) | 3418 | if (error) |
3438 | goto bread_err2; | 3419 | goto bread_err2; |
3439 | 3420 | ||
3440 | xlog_unpack_data(rhead, offset, log); | 3421 | error = xlog_unpack_data(rhead, offset, log); |
3441 | if ((error = xlog_recover_process_data(log, | 3422 | if (error) |
3442 | rhash, rhead, offset, pass))) | 3423 | goto bread_err2; |
3424 | |||
3425 | error = xlog_recover_process_data(log, | ||
3426 | rhash, rhead, offset, pass); | ||
3427 | if (error) | ||
3443 | goto bread_err2; | 3428 | goto bread_err2; |
3444 | blk_no += bblks + hblks; | 3429 | blk_no += bblks + hblks; |
3445 | } | 3430 | } |
@@ -3549,9 +3534,14 @@ xlog_do_recovery_pass( | |||
3549 | if (error) | 3534 | if (error) |
3550 | goto bread_err2; | 3535 | goto bread_err2; |
3551 | } | 3536 | } |
3552 | xlog_unpack_data(rhead, offset, log); | 3537 | |
3553 | if ((error = xlog_recover_process_data(log, rhash, | 3538 | error = xlog_unpack_data(rhead, offset, log); |
3554 | rhead, offset, pass))) | 3539 | if (error) |
3540 | goto bread_err2; | ||
3541 | |||
3542 | error = xlog_recover_process_data(log, rhash, | ||
3543 | rhead, offset, pass); | ||
3544 | if (error) | ||
3555 | goto bread_err2; | 3545 | goto bread_err2; |
3556 | blk_no += bblks; | 3546 | blk_no += bblks; |
3557 | } | 3547 | } |
@@ -3576,9 +3566,13 @@ xlog_do_recovery_pass( | |||
3576 | if (error) | 3566 | if (error) |
3577 | goto bread_err2; | 3567 | goto bread_err2; |
3578 | 3568 | ||
3579 | xlog_unpack_data(rhead, offset, log); | 3569 | error = xlog_unpack_data(rhead, offset, log); |
3580 | if ((error = xlog_recover_process_data(log, rhash, | 3570 | if (error) |
3581 | rhead, offset, pass))) | 3571 | goto bread_err2; |
3572 | |||
3573 | error = xlog_recover_process_data(log, rhash, | ||
3574 | rhead, offset, pass); | ||
3575 | if (error) | ||
3582 | goto bread_err2; | 3576 | goto bread_err2; |
3583 | blk_no += bblks + hblks; | 3577 | blk_no += bblks + hblks; |
3584 | } | 3578 | } |