Merge branch 'xfs-logging-fixes' into for-next
This commit is contained in:
Коммит
316433beda
|
@ -482,7 +482,9 @@ xfs_agfl_verify(
|
|||
be32_to_cpu(agfl->agfl_bno[i]) >= mp->m_sb.sb_agblocks)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
return xfs_log_check_lsn(mp,
|
||||
be64_to_cpu(XFS_BUF_TO_AGFL(bp)->agfl_lsn));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2259,9 +2261,13 @@ xfs_agf_verify(
|
|||
{
|
||||
struct xfs_agf *agf = XFS_BUF_TO_AGF(bp);
|
||||
|
||||
if (xfs_sb_version_hascrc(&mp->m_sb) &&
|
||||
!uuid_equal(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid))
|
||||
if (xfs_sb_version_hascrc(&mp->m_sb)) {
|
||||
if (!uuid_equal(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid))
|
||||
return false;
|
||||
if (!xfs_log_check_lsn(mp,
|
||||
be64_to_cpu(XFS_BUF_TO_AGF(bp)->agf_lsn)))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(agf->agf_magicnum == cpu_to_be32(XFS_AGF_MAGIC) &&
|
||||
XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum)) &&
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "xfs_buf_item.h"
|
||||
#include "xfs_cksum.h"
|
||||
#include "xfs_dir2.h"
|
||||
#include "xfs_log.h"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -266,6 +267,8 @@ xfs_attr3_leaf_verify(
|
|||
return false;
|
||||
if (be64_to_cpu(hdr3->info.blkno) != bp->b_bn)
|
||||
return false;
|
||||
if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->info.lsn)))
|
||||
return false;
|
||||
} else {
|
||||
if (ichdr.magic != XFS_ATTR_LEAF_MAGIC)
|
||||
return false;
|
||||
|
|
|
@ -948,14 +948,16 @@ xfs_bmap_local_to_extents(
|
|||
bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);
|
||||
|
||||
/*
|
||||
* Initialise the block and copy the data
|
||||
* Initialize the block, copy the data and log the remote buffer.
|
||||
*
|
||||
* Note: init_fn must set the buffer log item type correctly!
|
||||
* The callout is responsible for logging because the remote format
|
||||
* might differ from the local format and thus we don't know how much to
|
||||
* log here. Note that init_fn must also set the buffer log item type
|
||||
* correctly.
|
||||
*/
|
||||
init_fn(tp, bp, ip, ifp);
|
||||
|
||||
/* account for the change in fork size and log everything */
|
||||
xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
|
||||
/* account for the change in fork size */
|
||||
xfs_idata_realloc(ip, -ifp->if_bytes, whichfork);
|
||||
xfs_bmap_local_to_extents_empty(ip, whichfork);
|
||||
flags |= XFS_ILOG_CORE;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "xfs_trace.h"
|
||||
#include "xfs_cksum.h"
|
||||
#include "xfs_alloc.h"
|
||||
#include "xfs_log.h"
|
||||
|
||||
/*
|
||||
* Cursor allocation zone.
|
||||
|
@ -243,8 +244,14 @@ bool
|
|||
xfs_btree_lblock_verify_crc(
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
if (xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb))
|
||||
struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
|
||||
struct xfs_mount *mp = bp->b_target->bt_mount;
|
||||
|
||||
if (xfs_sb_version_hascrc(&mp->m_sb)) {
|
||||
if (!xfs_log_check_lsn(mp, be64_to_cpu(block->bb_u.l.bb_lsn)))
|
||||
return false;
|
||||
return xfs_buf_verify_cksum(bp, XFS_BTREE_LBLOCK_CRC_OFF);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -275,8 +282,14 @@ bool
|
|||
xfs_btree_sblock_verify_crc(
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
if (xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb))
|
||||
struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
|
||||
struct xfs_mount *mp = bp->b_target->bt_mount;
|
||||
|
||||
if (xfs_sb_version_hascrc(&mp->m_sb)) {
|
||||
if (!xfs_log_check_lsn(mp, be64_to_cpu(block->bb_u.s.bb_lsn)))
|
||||
return false;
|
||||
return xfs_buf_verify_cksum(bp, XFS_BTREE_SBLOCK_CRC_OFF);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "xfs_trace.h"
|
||||
#include "xfs_cksum.h"
|
||||
#include "xfs_buf_item.h"
|
||||
#include "xfs_log.h"
|
||||
|
||||
/*
|
||||
* xfs_da_btree.c
|
||||
|
@ -150,6 +151,8 @@ xfs_da3_node_verify(
|
|||
return false;
|
||||
if (be64_to_cpu(hdr3->info.blkno) != bp->b_bn)
|
||||
return false;
|
||||
if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->info.lsn)))
|
||||
return false;
|
||||
} else {
|
||||
if (ichdr.magic != XFS_DA_NODE_MAGIC)
|
||||
return false;
|
||||
|
@ -322,6 +325,7 @@ xfs_da3_node_create(
|
|||
if (xfs_sb_version_hascrc(&mp->m_sb)) {
|
||||
struct xfs_da3_node_hdr *hdr3 = bp->b_addr;
|
||||
|
||||
memset(hdr3, 0, sizeof(struct xfs_da3_node_hdr));
|
||||
ichdr.magic = XFS_DA3_NODE_MAGIC;
|
||||
hdr3->info.blkno = cpu_to_be64(bp->b_bn);
|
||||
hdr3->info.owner = cpu_to_be64(args->dp->i_ino);
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "xfs_error.h"
|
||||
#include "xfs_trace.h"
|
||||
#include "xfs_cksum.h"
|
||||
#include "xfs_log.h"
|
||||
|
||||
/*
|
||||
* Local function prototypes.
|
||||
|
@ -71,6 +72,8 @@ xfs_dir3_block_verify(
|
|||
return false;
|
||||
if (be64_to_cpu(hdr3->blkno) != bp->b_bn)
|
||||
return false;
|
||||
if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))
|
||||
return false;
|
||||
} else {
|
||||
if (hdr3->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC))
|
||||
return false;
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "xfs_trans.h"
|
||||
#include "xfs_buf_item.h"
|
||||
#include "xfs_cksum.h"
|
||||
#include "xfs_log.h"
|
||||
|
||||
/*
|
||||
* Check the consistency of the data block.
|
||||
|
@ -224,6 +225,8 @@ xfs_dir3_data_verify(
|
|||
return false;
|
||||
if (be64_to_cpu(hdr3->blkno) != bp->b_bn)
|
||||
return false;
|
||||
if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))
|
||||
return false;
|
||||
} else {
|
||||
if (hdr3->magic != cpu_to_be32(XFS_DIR2_DATA_MAGIC))
|
||||
return false;
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "xfs_trans.h"
|
||||
#include "xfs_buf_item.h"
|
||||
#include "xfs_cksum.h"
|
||||
#include "xfs_log.h"
|
||||
|
||||
/*
|
||||
* Local function declarations.
|
||||
|
@ -164,6 +165,8 @@ xfs_dir3_leaf_verify(
|
|||
return false;
|
||||
if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn)
|
||||
return false;
|
||||
if (!xfs_log_check_lsn(mp, be64_to_cpu(leaf3->info.lsn)))
|
||||
return false;
|
||||
} else {
|
||||
if (leaf->hdr.info.magic != cpu_to_be16(magic))
|
||||
return false;
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "xfs_trans.h"
|
||||
#include "xfs_buf_item.h"
|
||||
#include "xfs_cksum.h"
|
||||
#include "xfs_log.h"
|
||||
|
||||
/*
|
||||
* Function declarations.
|
||||
|
@ -97,6 +98,8 @@ xfs_dir3_free_verify(
|
|||
return false;
|
||||
if (be64_to_cpu(hdr3->blkno) != bp->b_bn)
|
||||
return false;
|
||||
if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))
|
||||
return false;
|
||||
} else {
|
||||
if (hdr->magic != cpu_to_be32(XFS_DIR2_FREE_MAGIC))
|
||||
return false;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "xfs_icreate_item.h"
|
||||
#include "xfs_icache.h"
|
||||
#include "xfs_trace.h"
|
||||
#include "xfs_log.h"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -2500,9 +2501,14 @@ xfs_agi_verify(
|
|||
struct xfs_mount *mp = bp->b_target->bt_mount;
|
||||
struct xfs_agi *agi = XFS_BUF_TO_AGI(bp);
|
||||
|
||||
if (xfs_sb_version_hascrc(&mp->m_sb) &&
|
||||
!uuid_equal(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid))
|
||||
if (xfs_sb_version_hascrc(&mp->m_sb)) {
|
||||
if (!uuid_equal(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid))
|
||||
return false;
|
||||
if (!xfs_log_check_lsn(mp,
|
||||
be64_to_cpu(XFS_BUF_TO_AGI(bp)->agi_lsn)))
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate the magic number of the agi block.
|
||||
*/
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "xfs_bmap_btree.h"
|
||||
#include "xfs_alloc_btree.h"
|
||||
#include "xfs_ialloc_btree.h"
|
||||
#include "xfs_log.h"
|
||||
|
||||
/*
|
||||
* Physical superblock buffer manipulations. Shared with libxfs in userspace.
|
||||
|
@ -163,6 +164,15 @@ xfs_mount_validate_sb(
|
|||
"Filesystem can not be safely mounted by this kernel.");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (xfs_sb_version_hascrc(sbp)) {
|
||||
/*
|
||||
* We can't read verify the sb LSN because the read verifier is
|
||||
* called before the log is allocated and processed. We know the
|
||||
* log is set up before write verifier (!check_version) calls,
|
||||
* so just check it here.
|
||||
*/
|
||||
if (!xfs_log_check_lsn(mp, sbp->sb_lsn))
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
if (xfs_sb_version_has_pquotino(sbp)) {
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "xfs_cksum.h"
|
||||
#include "xfs_trans.h"
|
||||
#include "xfs_buf_item.h"
|
||||
#include "xfs_log.h"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -60,6 +61,7 @@ xfs_symlink_hdr_set(
|
|||
if (!xfs_sb_version_hascrc(&mp->m_sb))
|
||||
return 0;
|
||||
|
||||
memset(dsl, 0, sizeof(struct xfs_dsymlink_hdr));
|
||||
dsl->sl_magic = cpu_to_be32(XFS_SYMLINK_MAGIC);
|
||||
dsl->sl_offset = cpu_to_be32(offset);
|
||||
dsl->sl_bytes = cpu_to_be32(size);
|
||||
|
@ -116,6 +118,8 @@ xfs_symlink_verify(
|
|||
return false;
|
||||
if (dsl->sl_owner == 0)
|
||||
return false;
|
||||
if (!xfs_log_check_lsn(mp, be64_to_cpu(dsl->sl_lsn)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -183,6 +187,7 @@ xfs_symlink_local_to_remote(
|
|||
if (!xfs_sb_version_hascrc(&mp->m_sb)) {
|
||||
bp->b_ops = NULL;
|
||||
memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
|
||||
xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -198,4 +203,6 @@ xfs_symlink_local_to_remote(
|
|||
buf = bp->b_addr;
|
||||
buf += xfs_symlink_hdr_set(mp, ip->i_ino, 0, ifp->if_bytes, bp);
|
||||
memcpy(buf, ifp->if_u1.if_data, ifp->if_bytes);
|
||||
xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsymlink_hdr) +
|
||||
ifp->if_bytes - 1);
|
||||
}
|
||||
|
|
|
@ -1027,7 +1027,7 @@ xfs_alloc_file_space(
|
|||
xfs_bmap_init(&free_list, &firstfsb);
|
||||
error = xfs_bmapi_write(tp, ip, startoffset_fsb,
|
||||
allocatesize_fsb, alloc_type, &firstfsb,
|
||||
0, imapp, &nimaps, &free_list);
|
||||
resblks, imapp, &nimaps, &free_list);
|
||||
if (error) {
|
||||
goto error0;
|
||||
}
|
||||
|
|
|
@ -202,8 +202,8 @@ xfs_iomap_write_direct(
|
|||
xfs_bmap_init(&free_list, &firstfsb);
|
||||
nimaps = 1;
|
||||
error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb,
|
||||
XFS_BMAPI_PREALLOC, &firstfsb, 0,
|
||||
imap, &nimaps, &free_list);
|
||||
XFS_BMAPI_PREALLOC, &firstfsb, resblks, imap,
|
||||
&nimaps, &free_list);
|
||||
if (error)
|
||||
goto out_bmap_cancel;
|
||||
|
||||
|
@ -750,9 +750,9 @@ xfs_iomap_write_allocate(
|
|||
* pointer that the caller gave to us.
|
||||
*/
|
||||
error = xfs_bmapi_write(tp, ip, map_start_fsb,
|
||||
count_fsb, 0,
|
||||
&first_block, 1,
|
||||
imap, &nimaps, &free_list);
|
||||
count_fsb, 0, &first_block,
|
||||
nres, imap, &nimaps,
|
||||
&free_list);
|
||||
if (error)
|
||||
goto trans_cancel;
|
||||
|
||||
|
@ -866,8 +866,8 @@ xfs_iomap_write_unwritten(
|
|||
xfs_bmap_init(&free_list, &firstfsb);
|
||||
nimaps = 1;
|
||||
error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb,
|
||||
XFS_BMAPI_CONVERT, &firstfsb,
|
||||
1, &imap, &nimaps, &free_list);
|
||||
XFS_BMAPI_CONVERT, &firstfsb, resblks,
|
||||
&imap, &nimaps, &free_list);
|
||||
if (error)
|
||||
goto error_on_bmapi_transaction;
|
||||
|
||||
|
|
|
@ -2422,11 +2422,20 @@ xlog_write(
|
|||
&partial_copy_len);
|
||||
xlog_verify_dest_ptr(log, ptr);
|
||||
|
||||
/* copy region */
|
||||
/*
|
||||
* Copy region.
|
||||
*
|
||||
* Unmount records just log an opheader, so can have
|
||||
* empty payloads with no data region to copy. Hence we
|
||||
* only copy the payload if the vector says it has data
|
||||
* to copy.
|
||||
*/
|
||||
ASSERT(copy_len >= 0);
|
||||
memcpy(ptr, reg->i_addr + copy_off, copy_len);
|
||||
xlog_write_adv_cnt(&ptr, &len, &log_offset, copy_len);
|
||||
|
||||
if (copy_len > 0) {
|
||||
memcpy(ptr, reg->i_addr + copy_off, copy_len);
|
||||
xlog_write_adv_cnt(&ptr, &len, &log_offset,
|
||||
copy_len);
|
||||
}
|
||||
copy_len += start_rec_copy + sizeof(xlog_op_header_t);
|
||||
record_cnt++;
|
||||
data_cnt += contwr ? copy_len : 0;
|
||||
|
@ -3165,11 +3174,19 @@ xlog_state_switch_iclogs(
|
|||
}
|
||||
|
||||
if (log->l_curr_block >= log->l_logBBsize) {
|
||||
/*
|
||||
* Rewind the current block before the cycle is bumped to make
|
||||
* sure that the combined LSN never transiently moves forward
|
||||
* when the log wraps to the next cycle. This is to support the
|
||||
* unlocked sample of these fields from xlog_valid_lsn(). Most
|
||||
* other cases should acquire l_icloglock.
|
||||
*/
|
||||
log->l_curr_block -= log->l_logBBsize;
|
||||
ASSERT(log->l_curr_block >= 0);
|
||||
smp_wmb();
|
||||
log->l_curr_cycle++;
|
||||
if (log->l_curr_cycle == XLOG_HEADER_MAGIC_NUM)
|
||||
log->l_curr_cycle++;
|
||||
log->l_curr_block -= log->l_logBBsize;
|
||||
ASSERT(log->l_curr_block >= 0);
|
||||
}
|
||||
ASSERT(iclog == log->l_iclog);
|
||||
log->l_iclog = iclog->ic_next;
|
||||
|
@ -4023,3 +4040,45 @@ xlog_iclogs_empty(
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that an LSN stamped into a piece of metadata is valid. This is
|
||||
* intended for use in read verifiers on v5 superblocks.
|
||||
*/
|
||||
bool
|
||||
xfs_log_check_lsn(
|
||||
struct xfs_mount *mp,
|
||||
xfs_lsn_t lsn)
|
||||
{
|
||||
struct xlog *log = mp->m_log;
|
||||
bool valid;
|
||||
|
||||
/*
|
||||
* norecovery mode skips mount-time log processing and unconditionally
|
||||
* resets the in-core LSN. We can't validate in this mode, but
|
||||
* modifications are not allowed anyways so just return true.
|
||||
*/
|
||||
if (mp->m_flags & XFS_MOUNT_NORECOVERY)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Some metadata LSNs are initialized to NULL (e.g., the agfl). This is
|
||||
* handled by recovery and thus safe to ignore here.
|
||||
*/
|
||||
if (lsn == NULLCOMMITLSN)
|
||||
return true;
|
||||
|
||||
valid = xlog_valid_lsn(mp->m_log, lsn);
|
||||
|
||||
/* warn the user about what's gone wrong before verifier failure */
|
||||
if (!valid) {
|
||||
spin_lock(&log->l_icloglock);
|
||||
xfs_warn(mp,
|
||||
"Corruption warning: Metadata has LSN (%d:%d) ahead of current LSN (%d:%d). "
|
||||
"Please unmount and run xfs_repair (>= v4.3) to resolve.",
|
||||
CYCLE_LSN(lsn), BLOCK_LSN(lsn),
|
||||
log->l_curr_cycle, log->l_curr_block);
|
||||
spin_unlock(&log->l_icloglock);
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
|
|
@ -181,5 +181,6 @@ bool xfs_log_item_in_current_chkpt(struct xfs_log_item *lip);
|
|||
void xfs_log_work_queue(struct xfs_mount *mp);
|
||||
void xfs_log_worker(struct work_struct *work);
|
||||
void xfs_log_quiesce(struct xfs_mount *mp);
|
||||
bool xfs_log_check_lsn(struct xfs_mount *, xfs_lsn_t);
|
||||
|
||||
#endif /* __XFS_LOG_H__ */
|
||||
|
|
|
@ -560,4 +560,55 @@ static inline void xlog_wait(wait_queue_head_t *wq, spinlock_t *lock)
|
|||
remove_wait_queue(wq, &wait);
|
||||
}
|
||||
|
||||
/*
|
||||
* The LSN is valid so long as it is behind the current LSN. If it isn't, this
|
||||
* means that the next log record that includes this metadata could have a
|
||||
* smaller LSN. In turn, this means that the modification in the log would not
|
||||
* replay.
|
||||
*/
|
||||
static inline bool
|
||||
xlog_valid_lsn(
|
||||
struct xlog *log,
|
||||
xfs_lsn_t lsn)
|
||||
{
|
||||
int cur_cycle;
|
||||
int cur_block;
|
||||
bool valid = true;
|
||||
|
||||
/*
|
||||
* First, sample the current lsn without locking to avoid added
|
||||
* contention from metadata I/O. The current cycle and block are updated
|
||||
* (in xlog_state_switch_iclogs()) and read here in a particular order
|
||||
* to avoid false negatives (e.g., thinking the metadata LSN is valid
|
||||
* when it is not).
|
||||
*
|
||||
* The current block is always rewound before the cycle is bumped in
|
||||
* xlog_state_switch_iclogs() to ensure the current LSN is never seen in
|
||||
* a transiently forward state. Instead, we can see the LSN in a
|
||||
* transiently behind state if we happen to race with a cycle wrap.
|
||||
*/
|
||||
cur_cycle = ACCESS_ONCE(log->l_curr_cycle);
|
||||
smp_rmb();
|
||||
cur_block = ACCESS_ONCE(log->l_curr_block);
|
||||
|
||||
if ((CYCLE_LSN(lsn) > cur_cycle) ||
|
||||
(CYCLE_LSN(lsn) == cur_cycle && BLOCK_LSN(lsn) > cur_block)) {
|
||||
/*
|
||||
* If the metadata LSN appears invalid, it's possible the check
|
||||
* above raced with a wrap to the next log cycle. Grab the lock
|
||||
* to check for sure.
|
||||
*/
|
||||
spin_lock(&log->l_icloglock);
|
||||
cur_cycle = log->l_curr_cycle;
|
||||
cur_block = log->l_curr_block;
|
||||
spin_unlock(&log->l_icloglock);
|
||||
|
||||
if ((CYCLE_LSN(lsn) > cur_cycle) ||
|
||||
(CYCLE_LSN(lsn) == cur_cycle && BLOCK_LSN(lsn) > cur_block))
|
||||
valid = false;
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
#endif /* __XFS_LOG_PRIV_H__ */
|
||||
|
|
|
@ -4609,9 +4609,19 @@ xlog_recover(
|
|||
int error;
|
||||
|
||||
/* find the tail of the log */
|
||||
if ((error = xlog_find_tail(log, &head_blk, &tail_blk)))
|
||||
error = xlog_find_tail(log, &head_blk, &tail_blk);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* The superblock was read before the log was available and thus the LSN
|
||||
* could not be verified. Check the superblock LSN against the current
|
||||
* LSN now that it's known.
|
||||
*/
|
||||
if (xfs_sb_version_hascrc(&log->l_mp->m_sb) &&
|
||||
!xfs_log_check_lsn(log->l_mp, log->l_mp->m_sb.sb_lsn))
|
||||
return -EINVAL;
|
||||
|
||||
if (tail_blk != head_blk) {
|
||||
/* There used to be a comment here:
|
||||
*
|
||||
|
|
Загрузка…
Ссылка в новой задаче