Skip to content

Commit cda7163

Browse files
adam900710kdave
authored andcommitted
btrfs: fix per-subvolume RO/RW flags with new mount API
[BUG] With util-linux 2.40.2, the 'mount' utility is already utilizing the new mount API. e.g: # strace mount -o subvol=subv1,ro /dev/test/scratch1 /mnt/test/ ... fsconfig(3, FSCONFIG_SET_STRING, "source", "/dev/mapper/test-scratch1", 0) = 0 fsconfig(3, FSCONFIG_SET_STRING, "subvol", "subv1", 0) = 0 fsconfig(3, FSCONFIG_SET_FLAG, "ro", NULL, 0) = 0 fsconfig(3, FSCONFIG_CMD_CREATE, NULL, NULL, 0) = 0 fsmount(3, FSMOUNT_CLOEXEC, 0) = 4 mount_setattr(4, "", AT_EMPTY_PATH, {attr_set=MOUNT_ATTR_RDONLY, attr_clr=0, propagation=0 /* MS_??? */, userns_fd=0}, 32) = 0 move_mount(4, "", AT_FDCWD, "/mnt/test", MOVE_MOUNT_F_EMPTY_PATH) = 0 But this leads to a new problem, that per-subvolume RO/RW mount no longer works, if the initial mount is RO: # mount -o subvol=subv1,ro /dev/test/scratch1 /mnt/test # mount -o rw,subvol=subv2 /dev/test/scratch1 /mnt/scratch # mount | grep mnt /dev/mapper/test-scratch1 on /mnt/test type btrfs (ro,relatime,discard=async,space_cache=v2,subvolid=256,subvol=/subv1) /dev/mapper/test-scratch1 on /mnt/scratch type btrfs (ro,relatime,discard=async,space_cache=v2,subvolid=257,subvol=/subv2) # touch /mnt/scratch/foobar touch: cannot touch '/mnt/scratch/foobar': Read-only file system This is a common use cases on distros. [CAUSE] We have a workaround for remount to handle the RO->RW change, but if the mount is using the new mount API, we do not do that, and rely on the mount tool NOT to set the ro flag. But that's not how the mount tool is doing for the new API: fsconfig(3, FSCONFIG_SET_STRING, "source", "/dev/mapper/test-scratch1", 0) = 0 fsconfig(3, FSCONFIG_SET_STRING, "subvol", "subv1", 0) = 0 fsconfig(3, FSCONFIG_SET_FLAG, "ro", NULL, 0) = 0 <<<< Setting RO flag for super block fsconfig(3, FSCONFIG_CMD_CREATE, NULL, NULL, 0) = 0 fsmount(3, FSMOUNT_CLOEXEC, 0) = 4 mount_setattr(4, "", AT_EMPTY_PATH, {attr_set=MOUNT_ATTR_RDONLY, attr_clr=0, propagation=0 /* MS_??? */, userns_fd=0}, 32) = 0 move_mount(4, "", AT_FDCWD, "/mnt/test", MOVE_MOUNT_F_EMPTY_PATH) = 0 This means we will set the super block RO at the first mount. Later RW mount will not try to reconfigure the fs to RW because the mount tool is already using the new API. This totally breaks the per-subvolume RO/RW mount behavior. [FIX] Do not skip the reconfiguration even if using the new API. The old comments are just expecting any mount tool to properly skip the RO flag set even if we specify "ro", which is not the reality. Update the comments regarding the backward compatibility on the kernel level so it works with old and new mount utilities. CC: stable@vger.kernel.org # 6.8+ Fixes: f044b31 ("btrfs: handle the ro->rw transition for mounting different subvolumes") Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 77b0d11 commit cda7163

File tree

1 file changed

+5
-20
lines changed

1 file changed

+5
-20
lines changed

fs/btrfs/super.c

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1979,25 +1979,10 @@ static int btrfs_get_tree_super(struct fs_context *fc)
19791979
* fsconfig(FSCONFIG_SET_FLAG, "ro"). This option is seen by the filesystem
19801980
* in fc->sb_flags.
19811981
*
1982-
* This disambiguation has rather positive consequences. Mounting a subvolume
1983-
* ro will not also turn the superblock ro. Only the mount for the subvolume
1984-
* will become ro.
1985-
*
1986-
* So, if the superblock creation request comes from the new mount API the
1987-
* caller must have explicitly done:
1988-
*
1989-
* fsconfig(FSCONFIG_SET_FLAG, "ro")
1990-
* fsmount/mount_setattr(MOUNT_ATTR_RDONLY)
1991-
*
1992-
* IOW, at some point the caller must have explicitly turned the whole
1993-
* superblock ro and we shouldn't just undo it like we did for the old mount
1994-
* API. In any case, it lets us avoid the hack in the new mount API.
1995-
*
1996-
* Consequently, the remounting hack must only be used for requests originating
1997-
* from the old mount API and should be marked for full deprecation so it can be
1998-
* turned off in a couple of years.
1999-
*
2000-
* The new mount API has no reason to support this hack.
1982+
* But, currently the util-linux mount command already utilizes the new mount
1983+
* API and is still setting fsconfig(FSCONFIG_SET_FLAG, "ro") no matter if it's
1984+
* btrfs or not, setting the whole super block RO. To make per-subvolume mounting
1985+
* work with different options work we need to keep backward compatibility.
20011986
*/
20021987
static struct vfsmount *btrfs_reconfigure_for_mount(struct fs_context *fc)
20031988
{
@@ -2019,7 +2004,7 @@ static struct vfsmount *btrfs_reconfigure_for_mount(struct fs_context *fc)
20192004
if (IS_ERR(mnt))
20202005
return mnt;
20212006

2022-
if (!fc->oldapi || !ro2rw)
2007+
if (!ro2rw)
20232008
return mnt;
20242009

20252010
/* We need to convert to rw, call reconfigure. */

0 commit comments

Comments
 (0)