Re: [PATCH] Fix read-only superblock in case of subvol RO remount

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10/02/2022 16:51, Goldwyn Rodrigues wrote:
> If a read-write root mount is remounted as read-only, the subvolume
> is also set to read-only.

Errrr... Isn't that exactly what I want?

If I have a btrfs filesystem with hundreds of subvols, some of which may
be mounted into various places in my filesystem, I would expect that if
I remount the main mountpoint as RO, that all the subvols become RO as
well. I actually don't mind if the behaviour went further and remounting
ANY of the mount points as RO would make them all RO.

My mental model is that mounting a subvol somewhere is rather like a
bind mount. And a bind mount goes RO if the underlying fs goes RO -
doesn't it?

Or am I just confused about what this patch is discussing?

Graham

> 
> Use a rw_mounts counter to check the number of read-write mounts, and change
> superblock to read-only only in case there are no read-write subvol mounts.
> 
> Since sb->s_flags can change while calling legacy_reconfigure(), use
> sb->s_flags instead of fc->sb_flags to re-evaluate sb->s_flags in
> reconfigure_super().
> 
> Test case:
> dd if=/dev/zero of=btrfsfs seek=240 count=0 bs=1M
> mkfs.btrfs btrfsfs
> mount btrfsfs /mnt
> btrfs subvol create /mnt/sv
> mount -o remount,ro /mnt
> mount -osubvol=/sv btrfsfs /mnt/sv
> findmnt # /mnt is RO, /mnt/sv RW
> mount -o remount,ro /mnt
> findmnt # /mnt is RO, /mnt/sv RO as well
> umount /mnt{/sv,}
> rm btrfsfs
> 
> Reported-by: Fabian Vogt <fvogt@xxxxxxxx>
> Signed-off-by: Goldwyn Rodrigues <rgoldwyn@xxxxxxxx>
> 
> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> index a2991971c6b5..2bb6869f15af 100644
> --- a/fs/btrfs/ctree.h
> +++ b/fs/btrfs/ctree.h
> @@ -1060,6 +1060,9 @@ struct btrfs_fs_info {
>  	spinlock_t zone_active_bgs_lock;
>  	struct list_head zone_active_bgs;
>  
> +	/* Count of subvol mounts read-write */
> +	int rw_mounts;
> +
>  #ifdef CONFIG_BTRFS_FS_REF_VERIFY
>  	spinlock_t ref_verify_lock;
>  	struct rb_root block_tree;
> diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
> index 33cfc9e27451..32941e11e551 100644
> --- a/fs/btrfs/super.c
> +++ b/fs/btrfs/super.c
> @@ -1835,6 +1835,11 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
>  	/* mount_subvol() will free subvol_name and mnt_root */
>  	root = mount_subvol(subvol_name, subvol_objectid, mnt_root);
>  
> +	if (!IS_ERR(root) && !(flags & SB_RDONLY)) {
> +		struct btrfs_fs_info *fs_info = btrfs_sb(mnt_root->mnt_sb);
> +		fs_info->rw_mounts++;
> +	}
> +
>  out:
>  	return root;
>  }
> @@ -1958,6 +1963,9 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
>  		goto out;
>  
>  	if (*flags & SB_RDONLY) {
> +
> +		if (--fs_info->rw_mounts > 0)
> +			goto out;
>  		/*
>  		 * this also happens on 'umount -rf' or on shutdown, when
>  		 * the filesystem is busy.
> @@ -2057,6 +2065,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
>  		if (ret)
>  			goto restore;
>  
> +		fs_info->rw_mounts++;
> +
>  		btrfs_clear_sb_rdonly(sb);
>  
>  		set_bit(BTRFS_FS_OPEN, &fs_info->flags);
> diff --git a/fs/super.c b/fs/super.c
> index f1d4a193602d..fd528f76f14b 100644
> --- a/fs/super.c
> +++ b/fs/super.c
> @@ -913,7 +913,8 @@ int reconfigure_super(struct fs_context *fc)
>  	}
>  
>  	WRITE_ONCE(sb->s_flags, ((sb->s_flags & ~fc->sb_flags_mask) |
> -				 (fc->sb_flags & fc->sb_flags_mask)));
> +				 (sb->s_flags & fc->sb_flags_mask)));
> +
>  	/* Needs to be ordered wrt mnt_is_readonly() */
>  	smp_wmb();
>  	sb->s_readonly_remount = 0;
> 




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux