2015-10-19 01:08:49

by NeilBrown

[permalink] [raw]
Subject: mount does not accurately identify existing NFS mounts, and shouldn't try.


When I run "mount -a" (and possibly in other circumstances) mount
attempts to determine if the requested filesystem is already mounted.
It seems to have some handling for various special cases, but doesn't
handle all cases properly.

For example, if I have
server:/export /import nfs ....
192.168.1.1:/private private nfs ....

in /etc/fstab and the IP address of 'server' is 192.168.1.1,
then both entries will appear in /proc/mounts with the same host name
(depending on which order there were mounted).

When I run "mount -a" a second time it will detect that one of these is
already correctly mounted, and will ignore it.
The other will not be detected as already being mounted (as the hostname
appears different) and "mount -a" will try to mount it again.

This will fail with "EBUSY" and mount will report an error
.... is busy or already mounted.

So while both filesystems are already mounted, we only get an error for
one of them.

The irony here is that while it is hard for user-space to determine
if the mounted filesystem matches the requested filesystem it is trivial
for the kernel.
For NFS we could try canonicalizing the server name, but undoubtedly
other issues would arrive. I believe there are similar issues with
btrfs and submount, though I have looked closely.

For the kernel, it is as simple as

/* Refuse the same filesystem on the same mount point */
err = -EBUSY;
if (path->mnt->mnt_sb == newmnt->mnt.mnt_sb &&
path->mnt->mnt_root == path->dentry)
goto unlock;

This is the *only* time that the kernel returns EBUSY for a "mount a new
filesystem" request (remount can return EBUSY for other reasons I
think).

So in the case where "mount" thinks it should check if the filesystem is
already mounted and ignore the request if it is, the best thing it can
do is to just try the mount and ignore any "EBUSY" error status - treat
that the same as success.

So all that code for "is this the same mountpoint" can probably be
discarded.

Did I miss any important consideration there?

Unfortunately this change could be awkward to implement as /sbin/mount
decides whether to try the mount and (for NFS), /sbin/mount.nfs gives an
error message if EBUSY is returned. Would we need to pass a "noebusy"
flag, but only if mount.nfs were willing to accept it....

Any suggestions?

NeilBrown


Attachments:
signature.asc (818.00 B)

2015-10-30 10:55:11

by Karel Zak

[permalink] [raw]
Subject: Re: mount does not accurately identify existing NFS mounts, and shouldn't try.

On Mon, Oct 19, 2015 at 12:08:41PM +1100, Neil Brown wrote:
> /* Refuse the same filesystem on the same mount point */
> err = -EBUSY;
> if (path->mnt->mnt_sb == newmnt->mnt.mnt_sb &&
> path->mnt->mnt_root == path->dentry)
> goto unlock;
>
> This is the *only* time that the kernel returns EBUSY for a "mount a new
> filesystem" request (remount can return EBUSY for other reasons I
> think).
>
> So in the case where "mount" thinks it should check if the filesystem is
> already mounted and ignore the request if it is, the best thing it can
> do is to just try the mount and ignore any "EBUSY" error status - treat
> that the same as success.
>
> So all that code for "is this the same mountpoint" can probably be
> discarded.

Well, we have many situations (another than mount -a) when you want to
know if the FS is mounted, but you have not permissions for mount(2)
or you don't want to try it (because mount(2) may trigger many another
things in userspace).

> Did I miss any important consideration there?

The problem is that the way between fstab entry and mount(2) is
sometimes pretty complex (mount.<type> helpers, loop devices,
UUID/LABEL translation, etc).

So, compare fstab with /proc/mounts is usually good compromise...

Your suggestion seems usable for mount -a, but it's one small use-case
(and for example systemd don't use "mount -a" during boot).

> Unfortunately this change could be awkward to implement as /sbin/mount
> decides whether to try the mount and (for NFS), /sbin/mount.nfs gives an
> error message if EBUSY is returned. Would we need to pass a "noebusy"
> flag, but only if mount.nfs were willing to accept it....
>
> Any suggestions?

We have kill(PID, 0) to detect if the PID is valid, you don't have to
parse all /proc. It would be nice to have the same for filesystems,
something like

mount("/dev/sda1, "/mnt", "ext4", MS_NOMOUNT, NULL)

Karel

--
Karel Zak <[email protected]>
http://karelzak.blogspot.com

2015-10-30 22:46:18

by NeilBrown

[permalink] [raw]
Subject: Re: mount does not accurately identify existing NFS mounts, and shouldn't try.

On Fri, Oct 30 2015, Karel Zak wrote:

> On Mon, Oct 19, 2015 at 12:08:41PM +1100, Neil Brown wrote:
>> /* Refuse the same filesystem on the same mount point */
>> err = -EBUSY;
>> if (path->mnt->mnt_sb == newmnt->mnt.mnt_sb &&
>> path->mnt->mnt_root == path->dentry)
>> goto unlock;
>>
>> This is the *only* time that the kernel returns EBUSY for a "mount a new
>> filesystem" request (remount can return EBUSY for other reasons I
>> think).
>>
>> So in the case where "mount" thinks it should check if the filesystem is
>> already mounted and ignore the request if it is, the best thing it can
>> do is to just try the mount and ignore any "EBUSY" error status - treat
>> that the same as success.
>>
>> So all that code for "is this the same mountpoint" can probably be
>> discarded.
>
> Well, we have many situations (another than mount -a) when you want to
> know if the FS is mounted, but you have not permissions for mount(2)
> or you don't want to try it (because mount(2) may trigger many another
> things in userspace).
>
>> Did I miss any important consideration there?
>
> The problem is that the way between fstab entry and mount(2) is
> sometimes pretty complex (mount.<type> helpers, loop devices,
> UUID/LABEL translation, etc).
>
> So, compare fstab with /proc/mounts is usually good compromise...
>
> Your suggestion seems usable for mount -a, but it's one small use-case
> (and for example systemd don't use "mount -a" during boot).
>
>> Unfortunately this change could be awkward to implement as /sbin/mount
>> decides whether to try the mount and (for NFS), /sbin/mount.nfs gives an
>> error message if EBUSY is returned. Would we need to pass a "noebusy"
>> flag, but only if mount.nfs were willing to accept it....
>>
>> Any suggestions?
>
> We have kill(PID, 0) to detect if the PID is valid, you don't have to
> parse all /proc. It would be nice to have the same for filesystems,
> something like
>
> mount("/dev/sda1, "/mnt", "ext4", MS_NOMOUNT, NULL)

I like that! I really do. It returns the same error as mount would if
run by a privileged uses, or returns success without actually changing
anything.
MS_NOMOUNT is incompatible with MS_REMOUNT, MS_MOVE and several others.

I won't be providing a kernel patch straight away, but I would like to
see this happen.

Thanks,
NeilBrown


Attachments:
signature.asc (818.00 B)