mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Pratyush Yadav <pratyush@kernel.org>
To: Pasha Tatashin <pasha.tatashin@soleen.com>,
	Mike Rapoport <rppt@kernel.org>,
	Pratyush Yadav <pratyush@kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	David Hildenbrand <david@kernel.org>,
	Lorenzo Stoakes <ljs@kernel.org>,
	Alexander Graf <graf@amazon.com>, Hugh Dickins <hughd@google.com>,
	Baolin Wang <baolin.wang@linux.alibaba.com>,
	David Matlack <dmatlack@google.com>,
	Samiullah Khawaja <skhawaja@google.com>
Cc: kexec@lists.infradead.org, linux-kernel@vger.kernel.org,
	linux-mm@kvack.org
Subject: [RFC PATCH 3/6] fs/namespace: Add vfs_open_detached_mount()
Date: Thu, 24 Sep 2026 00:44:02 +0200	[thread overview]
Message-ID: <20260923224408.3745689-4-pratyush@kernel.org> (raw)
In-Reply-To: <20260923224408.3745689-1-pratyush@kernel.org>

From: "Pratyush Yadav (Google)" <pratyush@kernel.org>

A mount created in the kernel by fc_mount() and friends has mnt_ns ==
NULL, and userspace cannot attach such a mount anywhere.

The missing step is the tail of fsmount(2): allocate an anonymous mount
namespace, insert the mount as its root, open an O_PATH file on it and
mark the file FMODE_NEED_UNMOUNT so the mount is torn down on the final
fput() if it is never attached. The anonymous namespace is what gives
the detached mount an owning user namespace for permission checks, a
place for child mounts, and a lifetime tied to the file.

None of the pieces are reachable from outside fs/namespace.c:
alloc_mnt_ns() and mnt_add_to_ns() are static, and the sequence is
already open-coded twice, in fsmount(2) and in open_detached_copy().

Factor it out so an in-kernel creator of a mount can hand it to
userspace. The Live Update Orchestrator needs this to return a tmpfs it
re-created from state preserved across a kexec; userspace attaches the
resulting fd with move_mount(), exactly as it would an fsmount(2) fd.

Only add the helper. Converting fsmount() and open_detached_copy() to it
is an obvious follow-up but is left out to keep this small. It is not
exported, as the only caller is built in.

Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>

---

This patch is entirely LLM generated. It works, but I am not competent
enough with VFS APIs to even guess if it is sensible. So please don't
take it too seriously. It makes the RFC testable, but for a proper
series I will do a lot more homework to make sure this doesn't
completely abuse VFS APIs.
---
 fs/namespace.c        | 59 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/mount.h |  1 +
 2 files changed, 60 insertions(+)

diff --git a/fs/namespace.c b/fs/namespace.c
index 1ecd96c918b3..5e7ba2b61dd9 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -4435,6 +4435,65 @@ static unsigned int attr_flags_to_mnt_flags(u64 attr_flags)
 	return mnt_flags;
 }
 
+/**
+ * vfs_open_detached_mount - Publish a new mount as a detached mount file.
+ * @mnt: The mount to publish. Must not be attached to a mount namespace. The
+ *       caller's reference is consumed on success.
+ *
+ * Places @mnt into a new anonymous mount namespace and opens an O_PATH file on
+ * its root, marked FMODE_NEED_UNMOUNT. This is what fsmount(2) hands back, and
+ * the resulting file behaves the same way: it can be attached to the
+ * filesystem hierarchy with
+ *
+ *	move_mount(fd, "", dfd, path, MOVE_MOUNT_F_EMPTY_PATH)
+ *
+ * and the mount is torn down on the final fput() if it never was.
+ *
+ * A mount that is not the root of an anonymous mount namespace cannot be
+ * attached by userspace at all, so a mount freshly made by fc_mount() and
+ * friends has to go through here before it can be given away.
+ *
+ * Return: the new file, or an ERR_PTR. On failure the caller's reference to
+ *         @mnt is dropped, as the mount cannot be published.
+ */
+struct file *vfs_open_detached_mount(struct vfsmount *mnt)
+{
+	struct path path __free(path_put) = {};
+	struct mnt_namespace *ns;
+	struct file *file;
+
+	if (WARN_ON_ONCE(real_mount(mnt)->mnt_ns))
+		return ERR_PTR(-EINVAL);
+
+	ns = alloc_mnt_ns(current->nsproxy->mnt_ns->user_ns, true);
+	if (IS_ERR(ns)) {
+		mntput(mnt);
+		return ERR_CAST(ns);
+	}
+
+	/* The caller's reference becomes the namespace's reference. */
+	ns->root = real_mount(mnt);
+	ns->nr_mounts = 1;
+	mnt_add_to_ns(ns, real_mount(mnt));
+
+	path.mnt = mntget(mnt);
+	path.dentry = dget(mnt->mnt_root);
+
+	file = dentry_open(&path, O_PATH, current_cred());
+	if (IS_ERR(file)) {
+		dissolve_on_fput(mnt);
+		return file;
+	}
+
+	/*
+	 * An apparent O_PATH fd, with a note that the mount needs to be
+	 * unmounted on the final fput() rather than simply put.
+	 */
+	file->f_mode |= FMODE_NEED_UNMOUNT;
+
+	return file;
+}
+
 /*
  * Create a kernel mount representation for a new, prepared superblock
  * (specified by fs_fd) and attach to an open_tree-like file descriptor.
diff --git a/include/linux/mount.h b/include/linux/mount.h
index acfe7ef86a1b..44c1141bc574 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -89,6 +89,7 @@ extern struct vfsmount *vfs_create_mount(struct fs_context *fc);
 extern struct vfsmount *vfs_kern_mount(struct file_system_type *type,
 				      int flags, const char *name,
 				      void *data);
+struct file *vfs_open_detached_mount(struct vfsmount *mnt);
 
 extern void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list);
 extern void mark_mounts_for_expiry(struct list_head *mounts);
-- 
2.56.0.rc1.310.g51773c2048-goog


  parent reply	other threads:[~2026-09-23 22:44 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-23 22:43 [RFC PATCH 0/6] luo: tmpfs preservation Pratyush Yadav
2026-09-23 22:44 ` [RFC PATCH 1/6] liveupdate: luo_file: look up outgoing tokens by id Pratyush Yadav
2026-09-23 22:55   ` sashiko-bot
2026-09-24 13:26     ` Pratyush Yadav
2026-09-23 22:44 ` [RFC PATCH 2/6] shmem: add tmpfs_create_mount() to create tmpfs mounts internally Pratyush Yadav
2026-09-23 22:54   ` sashiko-bot
2026-09-23 22:44 ` Pratyush Yadav [this message]
2026-09-23 23:01   ` [RFC PATCH 3/6] fs/namespace: Add vfs_open_detached_mount() sashiko-bot
2026-09-23 22:44 ` [RFC PATCH 4/6] mm/memfd_luo: allow preserving a tmpfs mount Pratyush Yadav
2026-09-23 23:06   ` sashiko-bot
2026-09-23 22:44 ` [RFC PATCH 5/6] mm/memfd_luo: allow preserving a tmpfs file Pratyush Yadav
2026-09-23 23:24   ` sashiko-bot
2026-09-23 22:44 ` [RFC PATCH 6/6] selftests/liveupdate: add tmpfs kexec test Pratyush Yadav
2026-09-23 23:14   ` sashiko-bot
2026-09-24 21:10 ` [RFC PATCH 0/6] luo: tmpfs preservation David Matlack

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260923224408.3745689-4-pratyush@kernel.org \
    --to=pratyush@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=baolin.wang@linux.alibaba.com \
    --cc=david@kernel.org \
    --cc=dmatlack@google.com \
    --cc=graf@amazon.com \
    --cc=hughd@google.com \
    --cc=kexec@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=pasha.tatashin@soleen.com \
    --cc=rppt@kernel.org \
    --cc=skhawaja@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®