mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-09 15:29:16 +00:00
xfs: handle -EFSCORRUPTED during head/tail verification
Torn write and tail overwrite detection both trigger only on -EFSBADCRC errors. While this is the most likely failure scenario for each condition, -EFSCORRUPTED is still possible in certain cases depending on what ends up on disk when a torn write or partial tail overwrite occurs. For example, an invalid log record h_len can lead to an -EFSCORRUPTED error when running the log recovery CRC pass. Therefore, update log head and tail verification to trigger the associated head/tail fixups in the event of -EFSCORRUPTED errors along with -EFSBADCRC. Also, -EFSCORRUPTED can currently be returned from xlog_do_recovery_pass() before rhead_blk is initialized if the first record encountered happens to be corrupted. This leads to an incorrect 'first_bad' return value. Initialize rhead_blk earlier in the function to address that problem as well. Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
This commit is contained in:
parent
7f4d01f36a
commit
a4c9b34d6a
@ -1102,7 +1102,7 @@ xlog_verify_tail(
|
||||
first_bad = 0;
|
||||
error = xlog_do_recovery_pass(log, head_blk, *tail_blk,
|
||||
XLOG_RECOVER_CRCPASS, &first_bad);
|
||||
while (error == -EFSBADCRC && first_bad) {
|
||||
while ((error == -EFSBADCRC || error == -EFSCORRUPTED) && first_bad) {
|
||||
int tail_distance;
|
||||
|
||||
/*
|
||||
@ -1188,7 +1188,7 @@ xlog_verify_head(
|
||||
*/
|
||||
error = xlog_do_recovery_pass(log, *head_blk, tmp_rhead_blk,
|
||||
XLOG_RECOVER_CRCPASS, &first_bad);
|
||||
if (error == -EFSBADCRC) {
|
||||
if ((error == -EFSBADCRC || error == -EFSCORRUPTED) && first_bad) {
|
||||
/*
|
||||
* We've hit a potential torn write. Reset the error and warn
|
||||
* about it.
|
||||
@ -5257,7 +5257,7 @@ xlog_do_recovery_pass(
|
||||
LIST_HEAD (buffer_list);
|
||||
|
||||
ASSERT(head_blk != tail_blk);
|
||||
rhead_blk = 0;
|
||||
blk_no = rhead_blk = tail_blk;
|
||||
|
||||
for (i = 0; i < XLOG_RHASH_SIZE; i++)
|
||||
INIT_HLIST_HEAD(&rhash[i]);
|
||||
@ -5335,7 +5335,6 @@ xlog_do_recovery_pass(
|
||||
}
|
||||
|
||||
memset(rhash, 0, sizeof(rhash));
|
||||
blk_no = rhead_blk = tail_blk;
|
||||
if (tail_blk > head_blk) {
|
||||
/*
|
||||
* Perform recovery around the end of the physical log.
|
||||
|
Loading…
x
Reference in New Issue
Block a user