FAILED: patch "[PATCH] btrfs: fix compat_ro checks against remount" failed to apply to 5.15-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
Possible dependencies:
2ba48b20049b ("btrfs: fix compat_ro checks against remount")d7f67ac9a928 ("btrfs: relax block-group-tree feature dependency checks") a05d3c915314 ("btrfs: check superblock to ensure the fs was not modified at thaw time") 49f468c93807 ("btrfs: don't print 'has skinny extents' anymore on mount") 6b769dac219d ("btrfs: don't print 'flagging with big metadata' anymore on mount") e26b04c4c919 ("btrfs: properly flag filesystem with BTRFS_FEATURE_INCOMPAT_BIG_METADATA") dc4d31684974 ("btrfs: reject log replay if there is unsupported RO compat flag") 0591f0403621 ("btrfs: prevent remounting to v1 space cache for subpage mount") d5321a0fa8bc ("btrfs: add "0x" prefix for unsupported optional features") 8481dd80ab1e ("btrfs: subpage: introduce btrfs_subpage_bitmap_info")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 2ba48b20049b5a76f34a85f853c9496d1b10533a Mon Sep 17 00:00:00 2001
From: Qu Wenruo <[email protected]>
Date: Thu, 22 Dec 2022 07:59:17 +0800
Subject: [PATCH] btrfs: fix compat_ro checks against remount
[BUG]
Even with commit 81d5d61454c3 ("btrfs: enhance unsupported compat RO flags handling"), btrfs can still mount a fs with unsupported compat_ro flags read-only, then remount it RW:
# btrfs ins dump-super /dev/loop0 | grep compat_ro_flags -A 3 compat_ro_flags 0x403 ( FREE_SPACE_TREE | FREE_SPACE_TREE_VALID | unknown flag: 0x400 )
# mount /dev/loop0 /mnt/btrfs
mount: /mnt/btrfs: wrong fs type, bad option, bad superblock on /dev/loop0, missing codepage or helper program, or other error.
dmesg(1) may have more information after failed mount system call.
^^^ RW mount failed as expected ^^^# dmesg -t | tail -n5 loop0: detected capacity change from 0 to 1048576 BTRFS: device fsid cb5b82f5-0fdd-4d81-9b4b-78533c324afa devid 1 transid 7 /dev/loop0 scanned by mount (1146) BTRFS info (device loop0): using crc32c (crc32c-intel) checksum algorithm BTRFS info (device loop0): using free space tree BTRFS error (device loop0): cannot mount read-write because of unknown compat_ro features (0x403) BTRFS error (device loop0): open_ctree failed
# mount /dev/loop0 -o ro /mnt/btrfs # mount -o remount,rw /mnt/btrfs ^^^ RW remount succeeded unexpectedly ^^^
[CAUSE]
Currently we use btrfs_check_features() to check compat_ro flags against our current mount flags.
That function get reused between open_ctree() and btrfs_remount().
But for btrfs_remount(), the super block we passed in still has the old mount flags, thus btrfs_check_features() still believes we're mounting read-only.
[FIX]
Replace the existing @sb argument with @is_rw_mount.
As originally we only use @sb to determine if the mount is RW.
Now it's callers' responsibility to determine if the mount is RW, and since there are only two callers, the check is pretty simple:
- caller in open_ctree()
Just pass !sb_rdonly().
- caller in btrfs_remount()
Pass !(*flags & SB_RDONLY), as our check should be against the new flags.
Now we can correctly reject the RW remount:
# mount /dev/loop0 -o ro /mnt/btrfs
# mount -o remount,rw /mnt/btrfs
mount: /mnt/btrfs: mount point not mounted or bad option.
dmesg(1) may have more information after failed mount system call.
# dmesg -t | tail -n 1
BTRFS error (device loop0: state M): cannot mount read-write because of unknown compat_ro features (0x403)fs/btrfs/disk-io.c +5 -3
@@ -3384,6 +3384,8 @@ int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info)/* * Do various sanity and dependency checks of different features. * +* @is_rw_mount: If the mount is read-write. +* * This is the place for less strict checks (like for subpage or artificial * feature dependencies). *
@@ -3394,7 +3396,7 @@ int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info)* (space cache related) can modify on-disk format like free space tree and * screw up certain feature dependencies. */ -int btrfs_check_features (struct btrfs_fs_info *fs_info,struct super_block *sb) +int btrfs_check_features (struct btrfs_fs_info *fs_info,bool is_rw_mount) {struct btrfs_super_block *disk_super = fs_info->super_copy;u64 incompat =btrfs_super_incompat_flags (disk_super);
@@ -3433,7 +3435,7 @@ int btrfs_check_features(struct btrfs_fs_info *fs_info, struct super_block *sb)if (btrfs_super_nodesize (disk_super) >PAGE_SIZE ) incompat |=BTRFS_FEATURE_INCOMPAT_BIG_METADATA ; -if (compat_ro_unsupp && !sb_rdonly (sb)) { +if (compat_ro_unsupp && is_rw_mount) {btrfs_err (fs_info,"cannot mount read-write because of unknown compat_ro features (0x%llx)" , compat_ro);
@@ -3636,7 +3638,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device goto fail_alloc; } - ret =btrfs_check_features (fs_info, sb); + ret =btrfs_check_features (fs_info, !sb_rdonly (sb));if (ret <0 ) { err = ret; goto fail_alloc;
fs/btrfs/disk-io.h +1 -1
@@ -50,7 +50,7 @@ int __cold open_ctree(struct super_block *sb,void __cold close_ctree (struct btrfs_fs_info *fs_info);int btrfs_validate_super (struct btrfs_fs_info *fs_info,struct btrfs_super_block *sb,int mirror_num); -int btrfs_check_features (struct btrfs_fs_info *fs_info,struct super_block *sb); +int btrfs_check_features (struct btrfs_fs_info *fs_info,bool is_rw_mount);int write_all_supers (struct btrfs_fs_info *fs_info,int max_mirrors);struct btrfs_super_block *btrfs_read_dev_super (struct block_device *bdev); struct btrfs_super_block *btrfs_read_dev_one_super(struct block_device *bdev,
fs/btrfs/super.c +1 -1
@@ -1705,7 +1705,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)if (ret) goto restore; - ret =btrfs_check_features (fs_info, sb); + ret =btrfs_check_features (fs_info, !(*flags &SB_RDONLY ));if (ret <0 ) goto restore;