Re: [PATCH v10 09/41] KVM: guest_memfd: Filter both shared and private when invalidating
From: Fuad Tabba
Date: Wed Aug 12 2026 - 09:43:23 EST
On Fri, 7 Aug 2026 at 23:52, Ackerley Tng via B4 Relay
<devnull+ackerleytng.google.com@xxxxxxxxxx> wrote:
>
> From: Ackerley Tng <ackerleytng@xxxxxxxxxx>
>
> Before conversion, a guest_memfd could be either all shared, or all
> private, configured at creation time using the INIT_SHARED flag. Hence,
> when zapping pages from stage 2 page tables, guest_memfd can filter which
> to zap based on the initial shared/private state.
>
> With conversion, guest_memfd tracks shared/private state on a per-page
> level, so a range can contain both private and shared pages. Zap both
> private and shared pages for simplicity.
>
> An alternative would be to iterate guest_memfd attributes and only zap both
> if shared and private pages exist within the range. Setting both the shared
> and private filters lets the zapping logic do that iteration instead.
>
> Reviewed-by: Suzuki K Poulose <suzuki.poulose@xxxxxxx>
> Signed-off-by: Ackerley Tng <ackerleytng@xxxxxxxxxx>
Reviewed-by: Fuad Tabba <fuad.tabba@xxxxxxxxx>
Cheers,
/fuad
> ---
> virt/kvm/guest_memfd.c | 24 ++++++++----------------
> 1 file changed, 8 insertions(+), 16 deletions(-)
>
> diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
> index 75979c885e030..b1537226e5adf 100644
> --- a/virt/kvm/guest_memfd.c
> +++ b/virt/kvm/guest_memfd.c
> @@ -136,14 +136,6 @@ static struct folio *kvm_gmem_get_folio(struct inode *inode, pgoff_t index)
> return folio;
> }
>
> -static enum kvm_gfn_range_filter kvm_gmem_get_invalidate_filter(struct inode *inode)
> -{
> - if (GMEM_I(inode)->flags & GUEST_MEMFD_FLAG_INIT_SHARED)
> - return KVM_FILTER_SHARED;
> -
> - return KVM_FILTER_PRIVATE;
> -}
> -
> static void __kvm_gmem_invalidate_start(struct gmem_file *f, pgoff_t start,
> pgoff_t end,
> enum kvm_gfn_range_filter attr_filter)
> @@ -186,15 +178,13 @@ static void __kvm_gmem_invalidate_start(struct gmem_file *f, pgoff_t start,
> }
>
> static void kvm_gmem_invalidate_start(struct inode *inode, pgoff_t start,
> - pgoff_t end)
> + pgoff_t end,
> + enum kvm_gfn_range_filter filter)
> {
> - enum kvm_gfn_range_filter attr_filter;
> struct gmem_file *f;
>
> - attr_filter = kvm_gmem_get_invalidate_filter(inode);
> -
> kvm_gmem_for_each_file(f, inode)
> - __kvm_gmem_invalidate_start(f, start, end, attr_filter);
> + __kvm_gmem_invalidate_start(f, start, end, filter);
> }
>
> static void __kvm_gmem_invalidate_end(struct gmem_file *f, pgoff_t start,
> @@ -229,7 +219,8 @@ static long kvm_gmem_punch_hole(struct inode *inode, loff_t offset, loff_t len)
> */
> filemap_invalidate_lock(inode->i_mapping);
>
> - kvm_gmem_invalidate_start(inode, start, end);
> + kvm_gmem_invalidate_start(inode, start, end,
> + KVM_FILTER_SHARED | KVM_FILTER_PRIVATE);
>
> truncate_inode_pages_range(inode->i_mapping, offset, offset + len - 1);
>
> @@ -344,7 +335,7 @@ static int kvm_gmem_release(struct inode *inode, struct file *file)
> * memory, as its lifetime is associated with the inode, not the file.
> */
> __kvm_gmem_invalidate_start(f, 0, -1ul,
> - kvm_gmem_get_invalidate_filter(inode));
> + KVM_FILTER_SHARED | KVM_FILTER_PRIVATE);
> __kvm_gmem_invalidate_end(f, 0, -1ul);
>
> list_del(&f->entry);
> @@ -525,7 +516,8 @@ static int kvm_gmem_error_folio(struct address_space *mapping, struct folio *fol
> start = folio->index;
> end = start + folio_nr_pages(folio);
>
> - kvm_gmem_invalidate_start(mapping->host, start, end);
> + kvm_gmem_invalidate_start(mapping->host, start, end,
> + KVM_FILTER_SHARED | KVM_FILTER_PRIVATE);
>
> /*
> * Do not truncate the range, what action is taken in response to the
>
> --
> 2.55.0.654.g21b8a5bc05-goog
>
>