Skip to content

Commit

Permalink
xfs: refactor and open code log record crc check
Browse files Browse the repository at this point in the history
Log record CRC verification currently occurs during active log recovery,
immediately before a log record is unpacked. Therefore, the CRC
calculation code is buried within the data unpack function. CRC
verification pass support only needs to go so far as check the CRC, but
this is not easily allowed as the code is currently organized.

Since we now have a new log record processing helper, pull the record
CRC verification code out from the unpack helper and open-code it at the
top of the new process helper. This facilitates the ability to modify
how records are processed based on the type of the current pass. 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 9d94901 commit b94fb2d
Showing 1 changed file with 26 additions and 46 deletions.
72 changes: 26 additions & 46 deletions fs/xfs/xfs_log_recover.c
Original file line number Diff line number Diff line change
Expand Up @@ -4118,58 +4118,13 @@ xlog_recover_process_iunlinks(
mp->m_dmevmask = mp_dmevmask;
}

/*
* Upack the log buffer data and crc check it. If the check fails, issue a
* warning if and only if the CRC in the header is non-zero. This makes the
* check an advisory warning, and the zero CRC check will prevent failure
* warnings from being emitted when upgrading the kernel from one that does not
* add CRCs by default.
*
* When filesystems are CRC enabled, this CRC mismatch becomes a fatal log
* corruption failure
*/
STATIC int
xlog_unpack_data_crc(
struct xlog_rec_header *rhead,
char *dp,
struct xlog *log)
{
__le32 crc;

crc = xlog_cksum(log, rhead, dp, be32_to_cpu(rhead->h_len));
if (crc != rhead->h_crc) {
if (rhead->h_crc || xfs_sb_version_hascrc(&log->l_mp->m_sb)) {
xfs_alert(log->l_mp,
"log record CRC mismatch: found 0x%x, expected 0x%x.",
le32_to_cpu(rhead->h_crc),
le32_to_cpu(crc));
xfs_hex_dump(dp, 32);
}

/*
* If we've detected a log record corruption, then we can't
* recover past this point. Abort recovery if we are enforcing
* CRC protection by punting an error back up the stack.
*/
if (xfs_sb_version_hascrc(&log->l_mp->m_sb))
return -EFSCORRUPTED;
}

return 0;
}

STATIC int
xlog_unpack_data(
struct xlog_rec_header *rhead,
char *dp,
struct xlog *log)
{
int i, j, k;
int error;

error = xlog_unpack_data_crc(rhead, dp, log);
if (error)
return error;

for (i = 0; i < BTOBB(be32_to_cpu(rhead->h_len)) &&
i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) {
Expand All @@ -4191,7 +4146,7 @@ xlog_unpack_data(
}

/*
* Unpack and process a log record.
* CRC check, unpack and process a log record.
*/
STATIC int
xlog_recover_process(
Expand All @@ -4202,6 +4157,31 @@ xlog_recover_process(
int pass)
{
int error;
__le32 crc;

/*
* Check the CRC and issue a warning if and only if the CRC in the
* header is non-zero. This is an advisory warning and the zero CRC
* check prevents warnings from being emitted when upgrading the kernel
* from one that does not add CRCs by default.
*/
crc = xlog_cksum(log, rhead, dp, be32_to_cpu(rhead->h_len));
if (crc != le32_to_cpu(rhead->h_crc)) {
if (rhead->h_crc || xfs_sb_version_hascrc(&log->l_mp->m_sb)) {
xfs_alert(log->l_mp,
"log record CRC mismatch: found 0x%x, expected 0x%x.",
le32_to_cpu(rhead->h_crc),
le32_to_cpu(crc));
xfs_hex_dump(dp, 32);
}

/*
* If the filesystem is CRC enabled, this mismatch becomes a
* fatal log corruption failure.
*/
if (xfs_sb_version_hascrc(&log->l_mp->m_sb))
return -EFSCORRUPTED;
}

error = xlog_unpack_data(rhead, dp, log);
if (error)
Expand Down

0 comments on commit b94fb2d

Please sign in to comment.