On Mon, 31 Aug 2026 at 01:25, Ackerley Tng via B4 Relay <[email protected]> wrote: > > From: Sean Christopherson <[email protected]> > > When removing one or more folios from a guest_memfd instance, invalidate > both SHARED and PRIVATE mappings if in-place conversion is enabled, because > stating the obvious, KVM needs to ensure that all mappings to the folio(s) > are dropped. > > Opportunistically rename the helper to capture that it returns a filter for > all gfns in anticipation of zapping only the previous mapping types on > conversion. I.e. when doing in-place conversion to PRIVATE, only SHARED > mappings need to be zapped (ignoring that KVM would ideally not invalidate > ranges whose attributes aren't changing in the first place). > > Note, precisely zapping only the possible mapping types when in-place > conversion is disabled is important for functional correctness, not just > for performance. Specifically, if KVM zaps both when SHARED vs. PRIVATE is > tracked per-VM, then a PUNCH_HOLE operation on a PRIVATE guest_memfd will > incorrectly zap SHARED mappings that have nothing to do with that gmem > instance (because they're mapped via a VMA, not a gmem fd). > > The incorrect over-zapping of SHARED memory that doesn't belong to the gmem > fd requesting the zapping will be resolved in a later patch, where, if > in-place conversion is enabled, KVM will use both shared and private memory > from the guest_memfd. If both shared and private memory are from the > guest_memfd, invalidation will only zap memory belonging to the given gmem > instance. > > Signed-off-by: Sean Christopherson <[email protected]> > Signed-off-by: Ackerley Tng <[email protected]>
Reviewed-by: Fuad Tabba <[email protected]> Cheers, /fuad > --- > virt/kvm/guest_memfd.c | 11 ++++++----- > 1 file changed, 6 insertions(+), 5 deletions(-) > > diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c > index cd966eef45b69..0afe1468d2d9d 100644 > --- a/virt/kvm/guest_memfd.c > +++ b/virt/kvm/guest_memfd.c > @@ -139,8 +139,11 @@ 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) > +static enum kvm_gfn_range_filter kvm_gmem_get_all_gfns_filter(struct inode > *inode) > { > + if (gmem_in_place_conversion) > + return KVM_FILTER_SHARED | KVM_FILTER_PRIVATE; > + > if (GMEM_I(inode)->flags & GUEST_MEMFD_FLAG_INIT_SHARED) > return KVM_FILTER_SHARED; > > @@ -191,11 +194,9 @@ 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) > { > - enum kvm_gfn_range_filter attr_filter; > + enum kvm_gfn_range_filter attr_filter = > kvm_gmem_get_all_gfns_filter(inode); > 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); > } > @@ -347,7 +348,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_gmem_get_all_gfns_filter(inode)); > __kvm_gmem_invalidate_end(f, 0, -1ul); > > list_del(&f->entry); > > -- > 2.55.0.897.gb25b4bd76c-goog > >
