Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
316433be
Commit
316433be
authored
Oct 12, 2015
by
Dave Chinner
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'xfs-logging-fixes' into for-next
parents
9e92054e
91f9f5fe
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
210 additions
and
26 deletions
+210
-26
fs/xfs/libxfs/xfs_alloc.c
fs/xfs/libxfs/xfs_alloc.c
+9
-3
fs/xfs/libxfs/xfs_attr_leaf.c
fs/xfs/libxfs/xfs_attr_leaf.c
+3
-0
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_bmap.c
+6
-4
fs/xfs/libxfs/xfs_btree.c
fs/xfs/libxfs/xfs_btree.c
+15
-2
fs/xfs/libxfs/xfs_da_btree.c
fs/xfs/libxfs/xfs_da_btree.c
+4
-0
fs/xfs/libxfs/xfs_dir2_block.c
fs/xfs/libxfs/xfs_dir2_block.c
+3
-0
fs/xfs/libxfs/xfs_dir2_data.c
fs/xfs/libxfs/xfs_dir2_data.c
+3
-0
fs/xfs/libxfs/xfs_dir2_leaf.c
fs/xfs/libxfs/xfs_dir2_leaf.c
+3
-0
fs/xfs/libxfs/xfs_dir2_node.c
fs/xfs/libxfs/xfs_dir2_node.c
+3
-0
fs/xfs/libxfs/xfs_ialloc.c
fs/xfs/libxfs/xfs_ialloc.c
+8
-2
fs/xfs/libxfs/xfs_sb.c
fs/xfs/libxfs/xfs_sb.c
+10
-0
fs/xfs/libxfs/xfs_symlink_remote.c
fs/xfs/libxfs/xfs_symlink_remote.c
+7
-0
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_bmap_util.c
+1
-1
fs/xfs/xfs_iomap.c
fs/xfs/xfs_iomap.c
+7
-7
fs/xfs/xfs_log.c
fs/xfs/xfs_log.c
+65
-6
fs/xfs/xfs_log.h
fs/xfs/xfs_log.h
+1
-0
fs/xfs/xfs_log_priv.h
fs/xfs/xfs_log_priv.h
+51
-0
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_log_recover.c
+11
-1
No files found.
fs/xfs/libxfs/xfs_alloc.c
View file @
316433be
...
...
@@ -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
))
&&
...
...
fs/xfs/libxfs/xfs_attr_leaf.c
View file @
316433be
...
...
@@ -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
;
...
...
fs/xfs/libxfs/xfs_bmap.c
View file @
316433be
...
...
@@ -948,14 +948,16 @@ xfs_bmap_local_to_extents(
bp
=
xfs_btree_get_bufl
(
args
.
mp
,
tp
,
args
.
fsbno
,
0
);
/*
* Initiali
se the block and copy the data
* Initiali
ze 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
;
...
...
fs/xfs/libxfs/xfs_btree.c
View file @
316433be
...
...
@@ -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
;
}
...
...
fs/xfs/libxfs/xfs_da_btree.c
View file @
316433be
...
...
@@ -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
);
...
...
fs/xfs/libxfs/xfs_dir2_block.c
View file @
316433be
...
...
@@ -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
;
...
...
fs/xfs/libxfs/xfs_dir2_data.c
View file @
316433be
...
...
@@ -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
;
...
...
fs/xfs/libxfs/xfs_dir2_leaf.c
View file @
316433be
...
...
@@ -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
;
...
...
fs/xfs/libxfs/xfs_dir2_node.c
View file @
316433be
...
...
@@ -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
;
...
...
fs/xfs/libxfs/xfs_ialloc.c
View file @
316433be
...
...
@@ -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.
*/
...
...
fs/xfs/libxfs/xfs_sb.c
View file @
316433be
...
...
@@ -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
))
{
...
...
fs/xfs/libxfs/xfs_symlink_remote.c
View file @
316433be
...
...
@@ -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
);
}
fs/xfs/xfs_bmap_util.c
View file @
316433be
...
...
@@ -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
;
}
...
...
fs/xfs/xfs_iomap.c
View file @
316433be
...
...
@@ -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
;
...
...
fs/xfs/xfs_log.c
View file @
316433be
...
...
@@ -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
;
}
fs/xfs/xfs_log.h
View file @
316433be
...
...
@@ -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__ */
fs/xfs/xfs_log_priv.h
View file @
316433be
...
...
@@ -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__ */
fs/xfs/xfs_log_recover.c
View file @
316433be
...
...
@@ -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:
*
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment