From: Ackerley Tng via B4 Relay <devnull+ackerleytng.google.com@kernel.org>
To: Hugh Dickins <hughd@google.com>,
Baolin Wang <baolin.wang@linux.alibaba.com>,
Andrew Morton <akpm@linux-foundation.org>,
Sean Christopherson <seanjc@google.com>,
Paolo Bonzini <pbonzini@redhat.com>,
David Hildenbrand <david@kernel.org>,
Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
Randy Dunlap <rdunlap@infradead.org>,
Shuah Khan <shuah@kernel.org>,
vannapurve@google.com, erdemaktas@google.com, jxgao@google.com,
rientjes@google.com, fvdl@google.com, jthoughton@google.com,
tarunsahu@google.com, pratyush@kernel.org, fuad.tabba@linux.dev,
Gregory Price <gourry@gourry.net>,
David Woodhouse <dwmw2@infradead.org>,
yan.y.zhao@intel.com, michael.roth@amd.com,
suzuki.poulose@arm.com, Christian Brauner <brauner@kernel.org>,
Jason Gunthorpe <jgg@ziepe.ca>,
Nicolin Chen <nicolinc@nvidia.com>,
Xu Yilun <yilun.xu@linux.intel.com>,
aik@amd.com, aneesh.kumar@kernel.org,
Vlastimil Babka <vbabka@kernel.org>
Cc: kernel-team@android.com, kernel-team@meta.com,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
kvm@vger.kernel.org, linux-doc@vger.kernel.org,
linux-kselftest@vger.kernel.org,
Ackerley Tng <ackerleytng@google.com>
Subject: [PATCH RFC 01/17] mm: shmem: Implement guest_memfd provider operations for tmpfs
Date: Fri, 25 Sep 2026 17:50:48 -0700 [thread overview]
Message-ID: <20260925-gmem-tmpfs-backend-v1-1-d36159822d18@google.com> (raw)
In-Reply-To: <20260925-gmem-tmpfs-backend-v1-0-d36159822d18@google.com>
From: Ackerley Tng <ackerleytng@google.com>
Implement guest_memfd provider operations to declare that tmpfs supports
providing memory to guest_memfd.
I'm implementing it directly in tmpfs as an illustration, one alternative I
can think of is that guest_memfd (KVM the module) could provide a registry,
supporting filesystems in the kernel, and loaded filesystems could register
themselves as providers.
Would it introduce ordering issues? Like if KVM were loaded after the
provider? Should the registry be built-in to the kernel?
Perhaps another way to key the provider functions could be TMPFS_MAGIC?
I put guest_memfd_provider_operations as a pointer in
super_operations. There might be a better place, to support different kinds
of providers. What do other providers need? Perhaps it's also okay to have
guest_memfd look up in a few different places, beginning with the resource
fd it was provided.
Signed-off-by: Ackerley Tng <ackerleytng@google.com>
---
include/linux/fs/super_types.h | 4 ++
include/linux/guest_memfd.h | 29 +++++++++++
mm/shmem.c | 112 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 145 insertions(+)
diff --git a/include/linux/fs/super_types.h b/include/linux/fs/super_types.h
index ecd96aeb1cee7..29e502439648a 100644
--- a/include/linux/fs/super_types.h
+++ b/include/linux/fs/super_types.h
@@ -37,6 +37,7 @@ struct workqueue_struct;
struct writeback_control;
struct xattr_handler;
struct fserror_event;
+struct guest_memfd_provider_operations;
extern struct super_block *blockdev_superblock;
@@ -130,6 +131,9 @@ struct super_operations {
/* Report a filesystem error */
void (*report_error)(const struct fserror_event *event);
+#ifdef CONFIG_KVM_GUEST_MEMFD
+ const struct guest_memfd_provider_operations *gmem_provider_ops;
+#endif
};
struct super_block {
diff --git a/include/linux/guest_memfd.h b/include/linux/guest_memfd.h
new file mode 100644
index 0000000000000..60eb4f008c246
--- /dev/null
+++ b/include/linux/guest_memfd.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _LINUX_GUEST_MEMFD_H
+#define _LINUX_GUEST_MEMFD_H
+
+#include <linux/types.h>
+
+struct file;
+struct folio;
+struct mempolicy;
+
+/**
+ * struct guest_memfd_provider_operations - Operations for external memory providers
+ * @attach: Attach to a resource file, perform filesystem-specific validation,
+ * and return an opaque provider context.
+ * @release: Release provider context and unpin any resources.
+ * @alloc_folio: Allocate an uninserted folio for a given index and NUMA policy.
+ * @invalidate_folio: Notify provider that a folio has been invalidated.
+ *
+ * Used by filesystems and device drivers that provide memory for guest_memfd.
+ */
+struct guest_memfd_provider_operations {
+ void *(*attach)(struct file *resource_file);
+ void (*release)(void *provider);
+ struct folio *(*alloc_folio)(void *provider, pgoff_t index,
+ struct mempolicy *mpol);
+ void (*invalidate_folio)(void *provider, struct folio *folio);
+};
+
+#endif /* _LINUX_GUEST_MEMFD_H */
diff --git a/mm/shmem.c b/mm/shmem.c
index 897fa2b61346f..279f29a9861c1 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -38,6 +38,7 @@
#include <linux/uio.h>
#include <linux/hugetlb.h>
#include <linux/fs_parser.h>
+#include <linux/guest_memfd.h>
#include <linux/swapfile.h>
#include <linux/iversion.h>
#include <linux/unicode.h>
@@ -5234,6 +5235,114 @@ static const struct inode_operations shmem_special_inode_operations = {
#endif
};
+#ifdef CONFIG_KVM_GUEST_MEMFD
+static void *shmem_gmem_attach(struct file *resource_file)
+{
+ struct inode *inode = file_inode(resource_file);
+ struct shmem_sb_info *sbinfo;
+
+ if (!S_ISDIR(inode->i_mode))
+ return ERR_PTR(-ENOTDIR);
+
+ /*
+ * Would like comments: Requiring the root directory of the mount
+ * provides a less confusing interface, although this is not strictly
+ * necessary.
+ */
+ if (resource_file->f_path.dentry != resource_file->f_path.mnt->mnt_root)
+ return ERR_PTR(-EINVAL);
+
+ if (__mnt_is_readonly(resource_file->f_path.mnt))
+ return ERR_PTR(-EROFS);
+
+ if (inode_permission(file_mnt_idmap(resource_file), inode,
+ MAY_WRITE | MAY_EXEC))
+ return ERR_PTR(-EACCES);
+
+ /* Enforce noswap because guest_memfd does not support swapping. */
+ sbinfo = SHMEM_SB(inode->i_sb);
+ if (!sbinfo->noswap)
+ return ERR_PTR(-EINVAL);
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ /*
+ * guest_memfd does not support huge pages yet; this restriction can be
+ * relaxed in the future.
+ *
+ * TODO: Block rebinding with huge page support.
+ */
+ if (sbinfo->huge != SHMEM_HUGE_NEVER)
+ return ERR_PTR(-EINVAL);
+#endif
+
+ return (void *)mntget(resource_file->f_path.mnt);
+}
+
+static void shmem_gmem_release(void *provider)
+{
+ struct vfsmount *mnt = provider;
+
+ mntput(mnt);
+}
+
+/*
+ * TODO: Consider refactoring shmem allocation helpers to share code between
+ * internal tmpfs folio allocation and guest_memfd provider allocation.
+ */
+static struct folio *shmem_gmem_alloc_folio(void *provider, pgoff_t index,
+ struct mempolicy *mpol)
+{
+ struct mempolicy *sb_mpol = NULL;
+ struct vfsmount *mnt = provider;
+ struct shmem_sb_info *sbinfo;
+ struct folio *folio;
+
+ sbinfo = SHMEM_SB(mnt->mnt_sb);
+ if (sbinfo->max_blocks &&
+ !percpu_counter_limited_add(&sbinfo->used_blocks,
+ sbinfo->max_blocks, 1))
+ return ERR_PTR(-ENOSPC);
+
+ if (!mpol) {
+ sb_mpol = shmem_get_sbmpol(sbinfo);
+ mpol = sb_mpol;
+ }
+
+ if (mpol)
+ folio = folio_alloc_mpol(GFP_HIGHUSER_MOVABLE, 0, mpol, index,
+ numa_node_id());
+ else
+ folio = folio_alloc(GFP_HIGHUSER_MOVABLE, 0);
+
+ mpol_cond_put(sb_mpol);
+
+ if (!folio) {
+ if (sbinfo->max_blocks)
+ percpu_counter_sub(&sbinfo->used_blocks, 1);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ return folio;
+}
+
+static void shmem_gmem_invalidate_folio(void *provider, struct folio *folio)
+{
+ struct vfsmount *mnt = provider;
+ struct shmem_sb_info *sbinfo;
+
+ sbinfo = SHMEM_SB(mnt->mnt_sb);
+ if (sbinfo->max_blocks)
+ percpu_counter_sub(&sbinfo->used_blocks, folio_nr_pages(folio));
+}
+
+static const struct guest_memfd_provider_operations shmem_gmem_provider_ops = {
+ .attach = shmem_gmem_attach,
+ .release = shmem_gmem_release,
+ .alloc_folio = shmem_gmem_alloc_folio,
+ .invalidate_folio = shmem_gmem_invalidate_folio,
+};
+#endif /* CONFIG_KVM_GUEST_MEMFD */
+
static const struct super_operations shmem_ops = {
.alloc_inode = shmem_alloc_inode,
.free_inode = shmem_free_in_core_inode,
@@ -5252,6 +5361,9 @@ static const struct super_operations shmem_ops = {
.nr_cached_objects = shmem_unused_huge_count,
.free_cached_objects = shmem_unused_huge_scan,
#endif
+#ifdef CONFIG_KVM_GUEST_MEMFD
+ .gmem_provider_ops = &shmem_gmem_provider_ops,
+#endif
};
static const struct vm_operations_struct shmem_vm_ops = {
--
2.56.0.rc1.315.gc6ed9934b7-goog
next prev parent reply other threads:[~2026-09-26 0:50 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-26 0:50 [PATCH RFC 00/17] Allow guest_memfd to be created using a resource (pool) fd Ackerley Tng via B4 Relay
2026-09-26 0:50 ` Ackerley Tng via B4 Relay [this message]
2026-09-26 0:50 ` [PATCH RFC 02/17] KVM: guest_memfd: Support provider folio allocation Ackerley Tng via B4 Relay
2026-09-26 0:50 ` [PATCH RFC 03/17] KVM: guest_memfd: Support provider folio invalidation Ackerley Tng via B4 Relay
2026-09-26 0:50 ` [PATCH RFC 04/17] KVM: guest_memfd: Add helper to attach resource provider file Ackerley Tng via B4 Relay
2026-09-26 0:50 ` [PATCH RFC 05/17] KVM: selftests: Add helper to create guest_memfd with a resource file Ackerley Tng via B4 Relay
2026-09-26 0:50 ` [PATCH RFC 06/17] KVM: selftests: Test negative validation of resource_fd argument Ackerley Tng via B4 Relay
2026-09-26 0:50 ` [PATCH RFC 07/17] KVM: selftests: Test rejection of unsupported filesystem for resource_fd Ackerley Tng via B4 Relay
2026-09-26 0:50 ` [PATCH RFC 08/17] KVM: selftests: Test rejection of tmpfs file " Ackerley Tng via B4 Relay
2026-09-26 0:50 ` [PATCH RFC 09/17] KVM: selftests: Test rejection of swap tmpfs mounts Ackerley Tng via B4 Relay
2026-09-26 0:50 ` [PATCH RFC 10/17] KVM: selftests: Test rejection of hugepage " Ackerley Tng via B4 Relay
2026-09-26 0:50 ` [PATCH RFC 11/17] KVM: selftests: Test guest_memfd with anonymous fsmount() tmpfs pool Ackerley Tng via B4 Relay
2026-09-26 0:50 ` [PATCH RFC 12/17] KVM: selftests: Test guest_memfd with mounted tmpfs root directory Ackerley Tng via B4 Relay
2026-09-26 0:51 ` [PATCH RFC 13/17] KVM: selftests: Test guest_memfd resource pool sharing across instances Ackerley Tng via B4 Relay
2026-09-26 0:51 ` [PATCH RFC 14/17] KVM: selftests: Test memory allocation against shared tmpfs resource pool Ackerley Tng via B4 Relay
2026-09-26 0:51 ` [PATCH RFC 15/17] KVM: selftests: Test that shared tmpfs resource pool size limit is respected Ackerley Tng via B4 Relay
2026-09-26 0:51 ` [PATCH RFC 16/17] KVM: selftests: Test guest execution with tmpfs-backed guest_memfd Ackerley Tng via B4 Relay
2026-09-26 0:51 ` [PATCH RFC 17/17] KVM: selftests: Document testing TODOs Ackerley Tng via B4 Relay
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=20260925-gmem-tmpfs-backend-v1-1-d36159822d18@google.com \
--to=devnull+ackerleytng.google.com@kernel.org \
--cc=ackerleytng@google.com \
--cc=aik@amd.com \
--cc=akpm@linux-foundation.org \
--cc=aneesh.kumar@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=brauner@kernel.org \
--cc=corbet@lwn.net \
--cc=david@kernel.org \
--cc=dwmw2@infradead.org \
--cc=erdemaktas@google.com \
--cc=fuad.tabba@linux.dev \
--cc=fvdl@google.com \
--cc=gourry@gourry.net \
--cc=hughd@google.com \
--cc=jgg@ziepe.ca \
--cc=jthoughton@google.com \
--cc=jxgao@google.com \
--cc=kernel-team@android.com \
--cc=kernel-team@meta.com \
--cc=kvm@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=michael.roth@amd.com \
--cc=nicolinc@nvidia.com \
--cc=pbonzini@redhat.com \
--cc=pratyush@kernel.org \
--cc=rdunlap@infradead.org \
--cc=rientjes@google.com \
--cc=seanjc@google.com \
--cc=shuah@kernel.org \
--cc=skhan@linuxfoundation.org \
--cc=suzuki.poulose@arm.com \
--cc=tarunsahu@google.com \
--cc=vannapurve@google.com \
--cc=vbabka@kernel.org \
--cc=yan.y.zhao@intel.com \
--cc=yilun.xu@linux.intel.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®