aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_log_recover.c42
1 files changed, 31 insertions, 11 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 9ac8aa8dc38c..e7aa82faa3d5 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1376,17 +1376,6 @@ xlog_find_tail(
1376 *tail_blk = BLOCK_LSN(be64_to_cpu(rhead->h_tail_lsn)); 1376 *tail_blk = BLOCK_LSN(be64_to_cpu(rhead->h_tail_lsn));
1377 1377
1378 /* 1378 /*
1379 * Trim the head block back to skip over torn records. We can have
1380 * multiple log I/Os in flight at any time, so we assume CRC failures
1381 * back through the previous several records are torn writes and skip
1382 * them.
1383 */
1384 error = xlog_verify_head(log, head_blk, tail_blk, bp, &rhead_blk,
1385 &rhead, &wrapped);
1386 if (error)
1387 goto done;
1388
1389 /*
1390 * Set the log state based on the current head record. 1379 * Set the log state based on the current head record.
1391 */ 1380 */
1392 xlog_set_state(log, *head_blk, rhead, rhead_blk, wrapped); 1381 xlog_set_state(log, *head_blk, rhead, rhead_blk, wrapped);
@@ -1402,6 +1391,37 @@ xlog_find_tail(
1402 goto done; 1391 goto done;
1403 1392
1404 /* 1393 /*
1394 * Verify the log head if the log is not clean (e.g., we have anything
1395 * but an unmount record at the head). This uses CRC verification to
1396 * detect and trim torn writes. If discovered, CRC failures are
1397 * considered torn writes and the log head is trimmed accordingly.
1398 *
1399 * Note that we can only run CRC verification when the log is dirty
1400 * because there's no guarantee that the log data behind an unmount
1401 * record is compatible with the current architecture.
1402 */
1403 if (!clean) {
1404 xfs_daddr_t orig_head = *head_blk;
1405
1406 error = xlog_verify_head(log, head_blk, tail_blk, bp,
1407 &rhead_blk, &rhead, &wrapped);
1408 if (error)
1409 goto done;
1410
1411 /* update in-core state again if the head changed */
1412 if (*head_blk != orig_head) {
1413 xlog_set_state(log, *head_blk, rhead, rhead_blk,
1414 wrapped);
1415 tail_lsn = atomic64_read(&log->l_tail_lsn);
1416 error = xlog_check_unmount_rec(log, head_blk, tail_blk,
1417 rhead, rhead_blk, bp,
1418 &clean);
1419 if (error)
1420 goto done;
1421 }
1422 }
1423
1424 /*
1405 * Note that the unmount was clean. If the unmount was not clean, we 1425 * Note that the unmount was clean. If the unmount was not clean, we
1406 * need to know this to rebuild the superblock counters from the perag 1426 * need to know this to rebuild the superblock counters from the perag
1407 * headers if we have a filesystem using non-persistent counters. 1427 * headers if we have a filesystem using non-persistent counters.