diff mbox series

[RFC,2/2] NFSv4: set sb_flags to second superblock

Message ID 20240604112636.236517-3-lilingfeng@huaweicloud.com (mailing list archive)
State New, archived
Headers show
Series NFSv4: set sb_flags to second superblock | expand

Commit Message

Li Lingfeng June 4, 2024, 11:26 a.m. UTC
From: Li Lingfeng <lilingfeng3@huawei.com>

During the process of mounting an NFSv4 client, two superblocks will be
created in sequence. The first superblock corresponds to the root
directory exported by the server, and the second superblock corresponds to
the directory that will be actually mounted. The first superblock will
eventually be destroyed.
The flag passed from user mode will only be passed to the first
superblock, resulting in the actual used superblock not carrying the flag
passed from user mode(fs_context_for_submount() will set sb_flags as 0).

If the 'ro' parameter is used in two consecutive mount commands, only the
first execution will create a new vfsmount, and the kernel will return
EBUSY on the second execution. However, if a remount command with the 'ro'
parameter is executed between the two mount commands, both mount commands
will create new vfsmounts.

The superblock generated after the first mount command does not have the
'ro' flag, and the read-only status of the file system is implemented by
checking the read-only flag of the vfsmount. After executing the remount
command, the 'ro' flag will be added to the superblock. When the second
mount command is executed, the comparison result between the superblock
with the 'ro' flag and the fs_context without the flag in the
nfs_compare_mount_options() function will be different, resulting in the
creation of a new vfsmount.

This problem can be reproduced by performing the following operations:
mount -t nfs -o ro,vers=4.0 192.168.240.250:/sdb /mnt/sdb
mount -t nfs -o remount,ro,vers=4.0 192.168.240.250:/sdb /mnt/sdb
mount -t nfs -o ro,vers=4.0 192.168.240.250:/sdb /mnt/sdb
Two vfsmounts are generated:
[root@localhost ~]# mount | grep nfs
192.168.240.250:/sdb on /mnt/sdb type nfs4 (ro,relatime,vers=4.0,
rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,
sec=sys,clientaddr=192.168.240.251,local_lock=none,addr=192.168.240.250)
192.168.240.250:/sdb on /mnt/sdb type nfs4 (ro,relatime,vers=4.0,
rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,
sec=sys,clientaddr=192.168.240.251,local_lock=none,addr=192.168.240.250)

Fix this by setting sb_flags to second superblock.

Signed-off-by: Li Lingfeng <lilingfeng3@huawei.com>
---
 fs/nfs/namespace.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Li Lingfeng June 14, 2024, 3:14 a.m. UTC | #1
I think this may be a problem, but I'm unable to come up with a suitable 
solution. Would you mind providing some suggestions?

在 2024/6/4 19:26, Li Lingfeng 写道:
> From: Li Lingfeng <lilingfeng3@huawei.com>
>
> During the process of mounting an NFSv4 client, two superblocks will be
> created in sequence. The first superblock corresponds to the root
> directory exported by the server, and the second superblock corresponds to
> the directory that will be actually mounted. The first superblock will
> eventually be destroyed.
> The flag passed from user mode will only be passed to the first
> superblock, resulting in the actual used superblock not carrying the flag
> passed from user mode(fs_context_for_submount() will set sb_flags as 0).
>
> If the 'ro' parameter is used in two consecutive mount commands, only the
> first execution will create a new vfsmount, and the kernel will return
> EBUSY on the second execution. However, if a remount command with the 'ro'
> parameter is executed between the two mount commands, both mount commands
> will create new vfsmounts.
>
> The superblock generated after the first mount command does not have the
> 'ro' flag, and the read-only status of the file system is implemented by
> checking the read-only flag of the vfsmount. After executing the remount
> command, the 'ro' flag will be added to the superblock. When the second
> mount command is executed, the comparison result between the superblock
> with the 'ro' flag and the fs_context without the flag in the
> nfs_compare_mount_options() function will be different, resulting in the
> creation of a new vfsmount.
>
> This problem can be reproduced by performing the following operations:
> mount -t nfs -o ro,vers=4.0 192.168.240.250:/sdb /mnt/sdb
> mount -t nfs -o remount,ro,vers=4.0 192.168.240.250:/sdb /mnt/sdb
> mount -t nfs -o ro,vers=4.0 192.168.240.250:/sdb /mnt/sdb
> Two vfsmounts are generated:
> [root@localhost ~]# mount | grep nfs
> 192.168.240.250:/sdb on /mnt/sdb type nfs4 (ro,relatime,vers=4.0,
> rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,
> sec=sys,clientaddr=192.168.240.251,local_lock=none,addr=192.168.240.250)
> 192.168.240.250:/sdb on /mnt/sdb type nfs4 (ro,relatime,vers=4.0,
> rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,
> sec=sys,clientaddr=192.168.240.251,local_lock=none,addr=192.168.240.250)
>
> Fix this by setting sb_flags to second superblock.
>
> Signed-off-by: Li Lingfeng <lilingfeng3@huawei.com>
> ---
>   fs/nfs/namespace.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
> index 887aeacedebd..8b3d75af60d4 100644
> --- a/fs/nfs/namespace.c
> +++ b/fs/nfs/namespace.c
> @@ -158,7 +158,7 @@ struct vfsmount *nfs_d_automount(struct path *path, unsigned int sb_flags)
>   	/* Open a new filesystem context, transferring parameters from the
>   	 * parent superblock, including the network namespace.
>   	 */
> -	fc = fs_context_for_submount(path->mnt->mnt_sb->s_type, path->dentry, 0);
> +	fc = fs_context_for_submount(path->mnt->mnt_sb->s_type, path->dentry, sb_flags);
>   	if (IS_ERR(fc))
>   		return ERR_CAST(fc);
>
Li Lingfeng July 13, 2024, 9:33 a.m. UTC | #2
Friendly ping ...

Thanks

在 2024/6/14 11:14, Li Lingfeng 写道:
> I think this may be a problem, but I'm unable to come up with a 
> suitable solution. Would you mind providing some suggestions?
>
> 在 2024/6/4 19:26, Li Lingfeng 写道:
>> From: Li Lingfeng <lilingfeng3@huawei.com>
>>
>> During the process of mounting an NFSv4 client, two superblocks will be
>> created in sequence. The first superblock corresponds to the root
>> directory exported by the server, and the second superblock 
>> corresponds to
>> the directory that will be actually mounted. The first superblock will
>> eventually be destroyed.
>> The flag passed from user mode will only be passed to the first
>> superblock, resulting in the actual used superblock not carrying the 
>> flag
>> passed from user mode(fs_context_for_submount() will set sb_flags as 0).
>>
>> If the 'ro' parameter is used in two consecutive mount commands, only 
>> the
>> first execution will create a new vfsmount, and the kernel will return
>> EBUSY on the second execution. However, if a remount command with the 
>> 'ro'
>> parameter is executed between the two mount commands, both mount 
>> commands
>> will create new vfsmounts.
>>
>> The superblock generated after the first mount command does not have the
>> 'ro' flag, and the read-only status of the file system is implemented by
>> checking the read-only flag of the vfsmount. After executing the remount
>> command, the 'ro' flag will be added to the superblock. When the second
>> mount command is executed, the comparison result between the superblock
>> with the 'ro' flag and the fs_context without the flag in the
>> nfs_compare_mount_options() function will be different, resulting in the
>> creation of a new vfsmount.
>>
>> This problem can be reproduced by performing the following operations:
>> mount -t nfs -o ro,vers=4.0 192.168.240.250:/sdb /mnt/sdb
>> mount -t nfs -o remount,ro,vers=4.0 192.168.240.250:/sdb /mnt/sdb
>> mount -t nfs -o ro,vers=4.0 192.168.240.250:/sdb /mnt/sdb
>> Two vfsmounts are generated:
>> [root@localhost ~]# mount | grep nfs
>> 192.168.240.250:/sdb on /mnt/sdb type nfs4 (ro,relatime,vers=4.0,
>> rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2, 
>>
>> sec=sys,clientaddr=192.168.240.251,local_lock=none,addr=192.168.240.250)
>> 192.168.240.250:/sdb on /mnt/sdb type nfs4 (ro,relatime,vers=4.0,
>> rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2, 
>>
>> sec=sys,clientaddr=192.168.240.251,local_lock=none,addr=192.168.240.250)
>>
>> Fix this by setting sb_flags to second superblock.
>>
>> Signed-off-by: Li Lingfeng <lilingfeng3@huawei.com>
>> ---
>>   fs/nfs/namespace.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
>> index 887aeacedebd..8b3d75af60d4 100644
>> --- a/fs/nfs/namespace.c
>> +++ b/fs/nfs/namespace.c
>> @@ -158,7 +158,7 @@ struct vfsmount *nfs_d_automount(struct path 
>> *path, unsigned int sb_flags)
>>       /* Open a new filesystem context, transferring parameters from the
>>        * parent superblock, including the network namespace.
>>        */
>> -    fc = fs_context_for_submount(path->mnt->mnt_sb->s_type, 
>> path->dentry, 0);
>> +    fc = fs_context_for_submount(path->mnt->mnt_sb->s_type, 
>> path->dentry, sb_flags);
>>       if (IS_ERR(fc))
>>           return ERR_CAST(fc);
diff mbox series

Patch

diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 887aeacedebd..8b3d75af60d4 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -158,7 +158,7 @@  struct vfsmount *nfs_d_automount(struct path *path, unsigned int sb_flags)
 	/* Open a new filesystem context, transferring parameters from the
 	 * parent superblock, including the network namespace.
 	 */
-	fc = fs_context_for_submount(path->mnt->mnt_sb->s_type, path->dentry, 0);
+	fc = fs_context_for_submount(path->mnt->mnt_sb->s_type, path->dentry, sb_flags);
 	if (IS_ERR(fc))
 		return ERR_CAST(fc);