Skip to content

Commit

Permalink
xfs: return start block of first bad log record during recovery
Browse files Browse the repository at this point in the history
Each log recovery pass walks from the tail block to the head block and
processes records appropriately based on the associated log pass type.
There are various failure conditions that can occur through this
sequence, such as I/O errors, CRC errors, etc. Log torn write detection
will perform CRC verification near the head of the log to detect torn
writes and trim torn records from the log appropriately.

As it is, xlog_do_recovery_pass() only returns an error code in the
event of CRC failure, which isn't enough information to trim the head of
the log. Update xlog_do_recovery_pass() to optionally return the start
block of the associated record when an error occurs. This patch contains
no functional changes.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
  • Loading branch information
Brian Foster authored and Dave Chinner committed Jan 4, 2016
1 parent b94fb2d commit d7f3769
Showing 1 changed file with 16 additions and 4 deletions.
20 changes: 16 additions & 4 deletions fs/xfs/xfs_log_recover.c
Original file line number Diff line number Diff line change
Expand Up @@ -4239,10 +4239,12 @@ xlog_do_recovery_pass(
struct xlog *log,
xfs_daddr_t head_blk,
xfs_daddr_t tail_blk,
int pass)
int pass,
xfs_daddr_t *first_bad) /* out: first bad log rec */
{
xlog_rec_header_t *rhead;
xfs_daddr_t blk_no;
xfs_daddr_t rhead_blk;
char *offset;
xfs_buf_t *hbp, *dbp;
int error = 0, h_size, h_len;
Expand All @@ -4251,6 +4253,7 @@ xlog_do_recovery_pass(
struct hlist_head rhash[XLOG_RHASH_SIZE];

ASSERT(head_blk != tail_blk);
rhead_blk = 0;

/*
* Read the header of the tail block and get the iclog buffer size from
Expand Down Expand Up @@ -4325,7 +4328,7 @@ xlog_do_recovery_pass(
}

memset(rhash, 0, sizeof(rhash));
blk_no = tail_blk;
blk_no = rhead_blk = tail_blk;
if (tail_blk > head_blk) {
/*
* Perform recovery around the end of the physical log.
Expand Down Expand Up @@ -4436,11 +4439,14 @@ xlog_do_recovery_pass(
pass);
if (error)
goto bread_err2;

blk_no += bblks;
rhead_blk = blk_no;
}

ASSERT(blk_no >= log->l_logBBsize);
blk_no -= log->l_logBBsize;
rhead_blk = blk_no;
}

/* read first part of physical log */
Expand All @@ -4464,13 +4470,19 @@ xlog_do_recovery_pass(
error = xlog_recover_process(log, rhash, rhead, offset, pass);
if (error)
goto bread_err2;

blk_no += bblks + hblks;
rhead_blk = blk_no;
}

bread_err2:
xlog_put_bp(dbp);
bread_err1:
xlog_put_bp(hbp);

if (error && first_bad)
*first_bad = rhead_blk;

return error;
}

Expand Down Expand Up @@ -4508,7 +4520,7 @@ xlog_do_log_recovery(
INIT_LIST_HEAD(&log->l_buf_cancel_table[i]);

error = xlog_do_recovery_pass(log, head_blk, tail_blk,
XLOG_RECOVER_PASS1);
XLOG_RECOVER_PASS1, NULL);
if (error != 0) {
kmem_free(log->l_buf_cancel_table);
log->l_buf_cancel_table = NULL;
Expand All @@ -4519,7 +4531,7 @@ xlog_do_log_recovery(
* When it is complete free the table of buf cancel items.
*/
error = xlog_do_recovery_pass(log, head_blk, tail_blk,
XLOG_RECOVER_PASS2);
XLOG_RECOVER_PASS2, NULL);
#ifdef DEBUG
if (!error) {
int i;
Expand Down

0 comments on commit d7f3769

Please sign in to comment.