diff mbox series

[05/11] VFS: new function: mount_is_internal()

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

Commit Message

NeilBrown July 27, 2021, 10:37 p.m. UTC
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(+)

Comments

Al Viro July 28, 2021, 2:16 a.m. UTC | #1
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?
NeilBrown July 28, 2021, 3:32 a.m. UTC | #2
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
Al Viro July 30, 2021, 12:34 a.m. UTC | #3
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 mbox series

Patch

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);