Re: [PATCH v4 06/11] KVM: guest_memfd: Move internal definitions to internal header
From: Ackerley Tng
Date: Thu Jul 30 2026 - 14:39:39 EST
Tarun Sahu <tarunsahu@xxxxxxxxxx> writes:
> Extract 'struct gmem_file', 'struct gmem_inode', and GMEM_I() from
> virt/kvm/guest_memfd.c into a new internal header virt/kvm/guest_memfd.h.
> Also split __kvm_gmem_create() to expose a non-static
> __kvm_gmem_create_file() helper that returns a 'struct file *' instead of
> an fd.
>
This is done basically to support a new virt/kvm/guest_memfd_luo.c
file.
Would like to know what Sean thinks of this! I'd like to know for future
guest_memfd work too.
> These internal definitions and helpers allow upcoming guest_memfd Live
> Update Orchestrator (LUO) preservation code to access guest_memfd
> internals and reconstruct guest_memfd file instances from preserved state
> without installing them into a file descriptor table up front.
>
> Signed-off-by: Tarun Sahu <tarunsahu@xxxxxxxxxx>
> ---
> virt/kvm/guest_memfd.c | 68 +++++++++++++++++-------------------------
> virt/kvm/guest_memfd.h | 39 ++++++++++++++++++++++++
> 2 files changed, 67 insertions(+), 40 deletions(-)
> create mode 100644 virt/kvm/guest_memfd.h
>
> diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
> index db57c5766ab6..dd84bba8974b 100644
> --- a/virt/kvm/guest_memfd.c
> +++ b/virt/kvm/guest_memfd.c
> @@ -7,38 +7,12 @@
> #include <linux/mempolicy.h>
> #include <linux/pseudo_fs.h>
> #include <linux/pagemap.h>
> +#include "guest_memfd.h"
>
> #include "kvm_mm.h"
>
> static struct vfsmount *kvm_gmem_mnt;
>
> -/*
> - * A guest_memfd instance can be associated multiple VMs, each with its own
> - * "view" of the underlying physical memory.
> - *
> - * The gmem's inode is effectively the raw underlying physical storage, and is
> - * used to track properties of the physical memory, while each gmem file is
> - * effectively a single VM's view of that storage, and is used to track assets
> - * specific to its associated VM, e.g. memslots=>gmem bindings.
> - */
> -struct gmem_file {
> - struct kvm *kvm;
> - struct xarray bindings;
> - struct list_head entry;
> -};
> -
> -struct gmem_inode {
> - struct shared_policy policy;
> - struct inode vfs_inode;
> - struct list_head gmem_file_list;
> -
> - u64 flags;
> -};
> -
> -static __always_inline struct gmem_inode *GMEM_I(struct inode *inode)
> -{
> - return container_of(inode, struct gmem_inode, vfs_inode);
> -}
>
> #define kvm_gmem_for_each_file(f, inode) \
> list_for_each_entry(f, &GMEM_I(inode)->gmem_file_list, entry)
> @@ -557,23 +531,17 @@ bool __weak kvm_arch_supports_gmem_init_shared(struct kvm *kvm)
> return true;
> }
>
> -static int __kvm_gmem_create(struct kvm *kvm, loff_t size, u64 flags)
> +struct file *__kvm_gmem_create_file(struct kvm *kvm, loff_t size, u64 flags)
> {
> static const char *name = "[kvm-gmem]";
> struct gmem_file *f;
> struct inode *inode;
> struct file *file;
> - int fd, err;
> -
> - fd = get_unused_fd_flags(0);
> - if (fd < 0)
> - return fd;
> + int err;
>
> f = kzalloc_obj(*f);
> - if (!f) {
> - err = -ENOMEM;
> - goto err_fd;
> - }
> + if (!f)
> + return ERR_PTR(-ENOMEM);
>
> /* __fput() will take care of fops_put(). */
> if (!fops_get(&kvm_gmem_fops)) {
> @@ -612,8 +580,7 @@ static int __kvm_gmem_create(struct kvm *kvm, loff_t size, u64 flags)
> xa_init(&f->bindings);
> list_add(&f->entry, &GMEM_I(inode)->gmem_file_list);
>
> - fd_install(fd, file);
> - return fd;
> + return file;
>
> err_inode:
> iput(inode);
> @@ -621,7 +588,28 @@ static int __kvm_gmem_create(struct kvm *kvm, loff_t size, u64 flags)
> fops_put(&kvm_gmem_fops);
> err_gmem:
> kfree(f);
> -err_fd:
> + return ERR_PTR(err);
> +}
> +
> +static int __kvm_gmem_create(struct kvm *kvm, loff_t size, u64 flags)
> +{
> + struct file *file;
> + int fd, err;
> +
> + fd = get_unused_fd_flags(0);
> + if (fd < 0)
> + return fd;
> +
> + file = __kvm_gmem_create_file(kvm, size, flags);
> + if (IS_ERR(file)) {
> + err = PTR_ERR(file);
> + goto err_put_fd;
> + }
> +
> + fd_install(fd, file);
> + return fd;
> +
> +err_put_fd:
> put_unused_fd(fd);
> return err;
> }
> diff --git a/virt/kvm/guest_memfd.h b/virt/kvm/guest_memfd.h
> new file mode 100644
> index 000000000000..c528b046dd69
> --- /dev/null
> +++ b/virt/kvm/guest_memfd.h
> @@ -0,0 +1,39 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +#ifndef __KVM_GUEST_MEMFD_H__
> +#define __KVM_GUEST_MEMFD_H__ 1
> +
> +#include <linux/kvm_host.h>
> +#include <linux/fs.h>
> +#include <linux/mempolicy.h>
> +
> +/*
> + * A guest_memfd instance can be associated multiple VMs, each with its own
> + * "view" of the underlying physical memory.
> + *
> + * The gmem's inode is effectively the raw underlying physical storage, and is
> + * used to track properties of the physical memory, while each gmem file is
> + * effectively a single VM's view of that storage, and is used to track assets
> + * specific to its associated VM, e.g. memslots=>gmem bindings.
> + */
> +struct gmem_file {
> + struct kvm *kvm;
> + struct xarray bindings;
> + struct list_head entry;
> +};
> +
> +struct gmem_inode {
> + struct shared_policy policy;
> + struct inode vfs_inode;
> + struct list_head gmem_file_list;
> +
> + u64 flags;
> +};
> +
> +static inline struct gmem_inode *GMEM_I(struct inode *inode)
> +{
> + return container_of(inode, struct gmem_inode, vfs_inode);
> +}
> +
> +struct file *__kvm_gmem_create_file(struct kvm *kvm, loff_t size, u64 flags);
> +
> +#endif /* __KVM_GUEST_MEMFD_H__ */
> --
> 2.55.0.229.g6434b31f56-goog