On 7/29/26 02:35, Ackerley Tng via B4 Relay wrote:
> From: Sean Christopherson <[email protected]>
> 
> Start plumbing in guest_memfd support for in-place private<=>shared
> conversions by tracking attributes via a maple tree.  KVM currently tracks
> private vs. shared attributes on a per-VM basis, which made sense when a
> guest_memfd _only_ supported private memory, but tracking per-VM simply
> can't work for in-place conversions as the shared/private status of a given
> page needs to be per-gmem_inode, not per-VM.
> 
> Use the filemap invalidation lock to protect the maple tree, as taking the
> lock for read when faulting in memory (for userspace or the guest) isn't
> expected to result in meaningful contention, and using a separate lock
> would add significant complexity (avoiding deadlock is quite difficult).
> 
> Co-developed-by: Vishal Annapurve <[email protected]>
> Signed-off-by: Vishal Annapurve <[email protected]>
> Co-developed-by: Fuad Tabba <[email protected]>
> Signed-off-by: Fuad Tabba <[email protected]>
> Signed-off-by: Sean Christopherson <[email protected]>
> Tested-by: Shivank Garg <[email protected]>
> Co-developed-by: Ackerley Tng <[email protected]>
> Signed-off-by: Ackerley Tng <[email protected]>
> ---
>  virt/kvm/guest_memfd.c | 133 
> ++++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 116 insertions(+), 17 deletions(-)
> 
> diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
> index 0bca42a0b346b..3d6547c5ba9a6 100644
> --- a/virt/kvm/guest_memfd.c
> +++ b/virt/kvm/guest_memfd.c
> @@ -4,6 +4,7 @@
>  #include <linux/falloc.h>
>  #include <linux/fs.h>
>  #include <linux/kvm_host.h>
> +#include <linux/maple_tree.h>
>  #include <linux/mempolicy.h>
>  #include <linux/pseudo_fs.h>
>  #include <linux/pagemap.h>
> @@ -33,6 +34,13 @@ struct gmem_inode {
>       struct list_head gmem_file_list;
>  
>       u64 flags;
> +     /*
> +      * Every index in this inode, whether memory is populated or
> +      * not, is tracked in attributes. The entire range of indices,
> +      * corresponding to the size of this inode, is represented in
> +      * this maple tree.
> +      */
> +     struct maple_tree attributes;
>  };
>  
>  static __always_inline struct gmem_inode *GMEM_I(struct inode *inode)
> @@ -60,9 +68,25 @@ static pgoff_t kvm_gmem_get_index(struct kvm_memory_slot 
> *slot, gfn_t gfn)
>       return gfn - slot->base_gfn + slot->gmem.pgoff;
>  }
>  
> +static u64 kvm_gmem_interpret_entry(struct inode *inode, void *entry)
> +{
> +     if (WARN_ON_ONCE(!entry)) {
> +             bool initially_shared = GMEM_I(inode)->flags &
> +                                     GUEST_MEMFD_FLAG_INIT_SHARED;
> +
> +             return initially_shared ? 0 : KVM_MEMORY_ATTRIBUTE_PRIVATE;

We have the calculation of the default attribute here and ...

> +static int kvm_gmem_init_inode(struct inode *inode, loff_t size, u64 flags)
> +{
> +     struct gmem_inode *gi = GMEM_I(inode);
> +     MA_STATE(mas, &gi->attributes, 0, (size >> PAGE_SHIFT) - 1);
> +     u64 attrs;
> +     int r;
> +
> +     inode->i_op = &kvm_gmem_iops;
> +     inode->i_mapping->a_ops = &kvm_gmem_aops;
> +     inode->i_mode |= S_IFREG;
> +     inode->i_size = size;
> +     mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER);
> +
> +     /*
> +      * guest_memfd memory is neither migratable nor swappable: set
> +      * inaccessible to gate off both.
> +      */
> +     mapping_set_inaccessible(inode->i_mapping);
> +     WARN_ON_ONCE(!mapping_unevictable(inode->i_mapping));
> +
> +     gi->flags = flags;
> +
> +     mt_set_external_lock(&gi->attributes,
> +                          &inode->i_mapping->invalidate_lock);
> +
> +     /*
> +      * Store default attributes for the entire gmem instance. Ensuring every
> +      * index is represented in the maple tree at all times simplifies the
> +      * conversion and merging logic.
> +      */
> +     attrs = gi->flags & GUEST_MEMFD_FLAG_INIT_SHARED ? 0 : 
> KVM_MEMORY_ATTRIBUTE_PRIVATE;
... here.

Worth a helper?

kvm_gmem_default_attribute(struct inode *inode) ?

Nothing else jumped at me, and I agree with the kvm_gmem_get_attributes()
improvement :)

-- 
Cheers,

David

Reply via email to