Message ID | 162742546552.32498.14429836898036234922.stgit@noble.brown (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | expose btrfs subvols in mount table correctly | expand |
On Wed, Jul 28, 2021 at 08:37:45AM +1000, NeilBrown wrote: > This patch introduces the concept of an "internal" mount which is a > mount where a filesystem has create the mount itself. > > Both the mounted-on-dentry and the mount's root dentry must refer to the > same superblock (they may be the same dentry), and the mounted-on dentry > must be an automount. And what happens if you mount --move it?
On Wed, 28 Jul 2021, Al Viro wrote: > On Wed, Jul 28, 2021 at 08:37:45AM +1000, NeilBrown wrote: > > This patch introduces the concept of an "internal" mount which is a > > mount where a filesystem has create the mount itself. > > > > Both the mounted-on-dentry and the mount's root dentry must refer to the > > same superblock (they may be the same dentry), and the mounted-on dentry > > must be an automount. > > And what happens if you mount --move it? > > If you move the mount, then the mounted-on dentry would not longer be an automount (.... I assume???...) so it would not longer be mount_is_internal(). I think that is reasonable. Whoever moved the mount has now taken over responsibility for it - it no longer is controlled by the filesystem. The moving will have removed the mount from the list of auto-expire mounts, and the mount-trap will now be exposed and can be mounted-on again. It would be just like unmounting the automount, and bind-mounting the same dentry elsewhere. NeilBrown
On Wed, Jul 28, 2021 at 01:32:45PM +1000, NeilBrown wrote: > On Wed, 28 Jul 2021, Al Viro wrote: > > On Wed, Jul 28, 2021 at 08:37:45AM +1000, NeilBrown wrote: > > > This patch introduces the concept of an "internal" mount which is a > > > mount where a filesystem has create the mount itself. > > > > > > Both the mounted-on-dentry and the mount's root dentry must refer to the > > > same superblock (they may be the same dentry), and the mounted-on dentry > > > must be an automount. > > > > And what happens if you mount --move it? > > > > > If you move the mount, then the mounted-on dentry would not longer be an > automount (.... I assume???...) so it would not longer be > mount_is_internal(). > > I think that is reasonable. Whoever moved the mount has now taken over > responsibility for it - it no longer is controlled by the filesystem. > The moving will have removed the mount from the list of auto-expire > mounts, and the mount-trap will now be exposed and can be mounted-on > again. > > It would be just like unmounting the automount, and bind-mounting the > same dentry elsewhere. Once more, with feeling: what happens to your function if it gets called during mount --move? What locking environment is going to be provided for it? And what is going to provide said environment?
diff --git a/fs/namespace.c b/fs/namespace.c index 73bbdb921e24..a14efbccfb03 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1273,6 +1273,35 @@ bool path_is_mountpoint(const struct path *path) } EXPORT_SYMBOL(path_is_mountpoint); +/** + * mount_is_internal() - Check if path is a mount internal to a single filesystem + * @mnt: vfsmount to check + * + * Some filesystems present multiple file-sets using a single + * superblock, such as btrfs with multiple subvolumes. Names within a + * parent filesystem which lead to a subordinate filesystem are + * implemented as automounts so that the structure is visible in the + * mount table. nfsd needs visibility into this arrangement so that it + * can determine if a mountpoint requires a new export, or is completely + * covered by an existing mount. + * + * An "internal" mount is one where the parent and child have the same + * superblock, and the mounted-on dentry is "managed" as an automount. A + * filehandle found for an inode in the child can be looked-up using either + * vfsmount. + */ +bool mount_is_internal(struct vfsmount *mnt) +{ + struct mount *m = real_mount(mnt); + + if (!mnt_has_parent(m)) + return false; + if (m->mnt_parent->mnt.mnt_sb != m->mnt.mnt_sb) + return false; + return m->mnt_mountpoint->d_flags & DCACHE_NEED_AUTOMOUNT; +} +EXPORT_SYMBOL(mount_is_internal); + struct vfsmount *mnt_clone_internal(const struct path *path) { struct mount *p; diff --git a/include/linux/mount.h b/include/linux/mount.h index 1d3daed88f83..ab58087728ba 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -118,6 +118,8 @@ extern unsigned int sysctl_mount_max; extern bool path_is_mountpoint(const struct path *path); +extern bool mount_is_internal(struct vfsmount *mnt); + extern struct vfsmount *lookup_mnt(const struct path *); extern void kern_unmount_array(struct vfsmount *mnt[], unsigned int num);
This patch introduces the concept of an "internal" mount which is a mount where a filesystem has create the mount itself. Both the mounted-on-dentry and the mount's root dentry must refer to the same superblock (they may be the same dentry), and the mounted-on dentry must be an automount. Signed-off-by: NeilBrown <neilb@suse.de> --- fs/namespace.c | 29 +++++++++++++++++++++++++++++ include/linux/mount.h | 2 ++ 2 files changed, 31 insertions(+)