mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
xfs: fix ro mounting with unknown rocompat features [v2]
Dave pointed out some failures in xfs/270 when he upgraded Debian unstable and util-linux started using the new mount apis. Upon further inquiry I noticed that XFS is quite a hot mess when it encounters a filesystem with unrecognized rocompat bits set in the superblock. Whereas we used to allow readonly mounts under these conditions, a change to the sb write verifier several years ago resulted in the filesystem going down immediately because the post-mount log cleaning writes the superblock, which trips the sb write verifier on the unrecognized rocompat bit. I made the observation that the ROCOMPAT features RMAPBT and REFLINK both protect new log intent item types, which means that we actually cannot support recovering the log if we don't recognize all the rocompat bits. Therefore -- fix inode inactivation to work when we're recovering the log, disallow recovery when there's unrecognized rocompat bits, and don't clean the log if doing so would trip the rocompat checks. v2: change direction of series to allow log recovery on ro mounts This has been lightly tested with fstests. Enjoy! Signed-off-by: Darrick J. Wong <djwong@kernel.org> -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQ2qTKExjcn+O1o2YRKO3ySh0YRpgUCZQChOQAKCRBKO3ySh0YR pkFRAP0f7+do6A3cs5GuMSCRdH3DImjX1ts9nHJAgxKadTod8gEApeDb290wI+ek NTetY6RKfexMZLEgXI8YtAlhsR8nVwI= =LARv -----END PGP SIGNATURE----- Merge tag 'fix-ro-mounts-6.6_2023-09-12' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux into xfs-6.6-fixesA xfs: fix ro mounting with unknown rocompat features Dave pointed out some failures in xfs/270 when he upgraded Debian unstable and util-linux started using the new mount apis. Upon further inquiry I noticed that XFS is quite a hot mess when it encounters a filesystem with unrecognized rocompat bits set in the superblock. Whereas we used to allow readonly mounts under these conditions, a change to the sb write verifier several years ago resulted in the filesystem going down immediately because the post-mount log cleaning writes the superblock, which trips the sb write verifier on the unrecognized rocompat bit. I made the observation that the ROCOMPAT features RMAPBT and REFLINK both protect new log intent item types, which means that we actually cannot support recovering the log if we don't recognize all the rocompat bits. Therefore -- fix inode inactivation to work when we're recovering the log, disallow recovery when there's unrecognized rocompat bits, and don't clean the log if doing so would trip the rocompat checks. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Chandan Babu R <chandanbabu@kernel.org> * tag 'fix-ro-mounts-6.6_2023-09-12' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux: xfs: fix log recovery when unknown rocompat bits are set xfs: allow inode inactivation during a ro mount log recovery
This commit is contained in:
commit
f41d7d70b0
@ -266,7 +266,8 @@ xfs_validate_sb_write(
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
if (xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
|
||||
if (!xfs_is_readonly(mp) &&
|
||||
xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
|
||||
xfs_alert(mp,
|
||||
"Corruption detected in superblock read-only compatible features (0x%x)!",
|
||||
(sbp->sb_features_ro_compat &
|
||||
|
@ -1642,8 +1642,11 @@ xfs_inode_needs_inactive(
|
||||
if (VFS_I(ip)->i_mode == 0)
|
||||
return false;
|
||||
|
||||
/* If this is a read-only mount, don't do this (would generate I/O) */
|
||||
if (xfs_is_readonly(mp))
|
||||
/*
|
||||
* If this is a read-only mount, don't do this (would generate I/O)
|
||||
* unless we're in log recovery and cleaning the iunlinked list.
|
||||
*/
|
||||
if (xfs_is_readonly(mp) && !xlog_recovery_needed(mp->m_log))
|
||||
return false;
|
||||
|
||||
/* If the log isn't running, push inodes straight to reclaim. */
|
||||
@ -1703,8 +1706,11 @@ xfs_inactive(
|
||||
mp = ip->i_mount;
|
||||
ASSERT(!xfs_iflags_test(ip, XFS_IRECOVERY));
|
||||
|
||||
/* If this is a read-only mount, don't do this (would generate I/O) */
|
||||
if (xfs_is_readonly(mp))
|
||||
/*
|
||||
* If this is a read-only mount, don't do this (would generate I/O)
|
||||
* unless we're in log recovery and cleaning the iunlinked list.
|
||||
*/
|
||||
if (xfs_is_readonly(mp) && !xlog_recovery_needed(mp->m_log))
|
||||
goto out;
|
||||
|
||||
/* Metadata inodes require explicit resource cleanup. */
|
||||
|
@ -715,15 +715,7 @@ xfs_log_mount(
|
||||
* just worked.
|
||||
*/
|
||||
if (!xfs_has_norecovery(mp)) {
|
||||
/*
|
||||
* log recovery ignores readonly state and so we need to clear
|
||||
* mount-based read only state so it can write to disk.
|
||||
*/
|
||||
bool readonly = test_and_clear_bit(XFS_OPSTATE_READONLY,
|
||||
&mp->m_opstate);
|
||||
error = xlog_recover(log);
|
||||
if (readonly)
|
||||
set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
|
||||
if (error) {
|
||||
xfs_warn(mp, "log mount/recovery failed: error %d",
|
||||
error);
|
||||
@ -772,7 +764,6 @@ xfs_log_mount_finish(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
struct xlog *log = mp->m_log;
|
||||
bool readonly;
|
||||
int error = 0;
|
||||
|
||||
if (xfs_has_norecovery(mp)) {
|
||||
@ -780,12 +771,6 @@ xfs_log_mount_finish(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* log recovery ignores readonly state and so we need to clear
|
||||
* mount-based read only state so it can write to disk.
|
||||
*/
|
||||
readonly = test_and_clear_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
|
||||
|
||||
/*
|
||||
* During the second phase of log recovery, we need iget and
|
||||
* iput to behave like they do for an active filesystem.
|
||||
@ -835,8 +820,6 @@ xfs_log_mount_finish(
|
||||
xfs_buftarg_drain(mp->m_ddev_targp);
|
||||
|
||||
clear_bit(XLOG_RECOVERY_NEEDED, &log->l_opstate);
|
||||
if (readonly)
|
||||
set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
|
||||
|
||||
/* Make sure the log is dead if we're returning failure. */
|
||||
ASSERT(!error || xlog_is_shutdown(log));
|
||||
|
Loading…
Reference in New Issue
Block a user