Skip to content

Commit f41d7d7

Browse files
author
Chandan Babu R
committed
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 <[email protected]> Signed-off-by: Chandan Babu R <[email protected]> * 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
2 parents 0a229c9 + 74ad469 commit f41d7d7

File tree

3 files changed

+12
-22
lines changed

3 files changed

+12
-22
lines changed

fs/xfs/libxfs/xfs_sb.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,8 @@ xfs_validate_sb_write(
266266
return -EFSCORRUPTED;
267267
}
268268

269-
if (xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
269+
if (!xfs_is_readonly(mp) &&
270+
xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
270271
xfs_alert(mp,
271272
"Corruption detected in superblock read-only compatible features (0x%x)!",
272273
(sbp->sb_features_ro_compat &

fs/xfs/xfs_inode.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1642,8 +1642,11 @@ xfs_inode_needs_inactive(
16421642
if (VFS_I(ip)->i_mode == 0)
16431643
return false;
16441644

1645-
/* If this is a read-only mount, don't do this (would generate I/O) */
1646-
if (xfs_is_readonly(mp))
1645+
/*
1646+
* If this is a read-only mount, don't do this (would generate I/O)
1647+
* unless we're in log recovery and cleaning the iunlinked list.
1648+
*/
1649+
if (xfs_is_readonly(mp) && !xlog_recovery_needed(mp->m_log))
16471650
return false;
16481651

16491652
/* If the log isn't running, push inodes straight to reclaim. */
@@ -1703,8 +1706,11 @@ xfs_inactive(
17031706
mp = ip->i_mount;
17041707
ASSERT(!xfs_iflags_test(ip, XFS_IRECOVERY));
17051708

1706-
/* If this is a read-only mount, don't do this (would generate I/O) */
1707-
if (xfs_is_readonly(mp))
1709+
/*
1710+
* If this is a read-only mount, don't do this (would generate I/O)
1711+
* unless we're in log recovery and cleaning the iunlinked list.
1712+
*/
1713+
if (xfs_is_readonly(mp) && !xlog_recovery_needed(mp->m_log))
17081714
goto out;
17091715

17101716
/* Metadata inodes require explicit resource cleanup. */

fs/xfs/xfs_log.c

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -715,15 +715,7 @@ xfs_log_mount(
715715
* just worked.
716716
*/
717717
if (!xfs_has_norecovery(mp)) {
718-
/*
719-
* log recovery ignores readonly state and so we need to clear
720-
* mount-based read only state so it can write to disk.
721-
*/
722-
bool readonly = test_and_clear_bit(XFS_OPSTATE_READONLY,
723-
&mp->m_opstate);
724718
error = xlog_recover(log);
725-
if (readonly)
726-
set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
727719
if (error) {
728720
xfs_warn(mp, "log mount/recovery failed: error %d",
729721
error);
@@ -772,20 +764,13 @@ xfs_log_mount_finish(
772764
struct xfs_mount *mp)
773765
{
774766
struct xlog *log = mp->m_log;
775-
bool readonly;
776767
int error = 0;
777768

778769
if (xfs_has_norecovery(mp)) {
779770
ASSERT(xfs_is_readonly(mp));
780771
return 0;
781772
}
782773

783-
/*
784-
* log recovery ignores readonly state and so we need to clear
785-
* mount-based read only state so it can write to disk.
786-
*/
787-
readonly = test_and_clear_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
788-
789774
/*
790775
* During the second phase of log recovery, we need iget and
791776
* iput to behave like they do for an active filesystem.
@@ -835,8 +820,6 @@ xfs_log_mount_finish(
835820
xfs_buftarg_drain(mp->m_ddev_targp);
836821

837822
clear_bit(XLOG_RECOVERY_NEEDED, &log->l_opstate);
838-
if (readonly)
839-
set_bit(XFS_OPSTATE_READONLY, &mp->m_opstate);
840823

841824
/* Make sure the log is dead if we're returning failure. */
842825
ASSERT(!error || xlog_is_shutdown(log));

0 commit comments

Comments
 (0)