]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Merge tag 'kvm-x86-gmem-6.19' of https://github.com/kvm-x86/linux into HEAD
authorPaolo Bonzini <pbonzini@redhat.com>
Wed, 26 Nov 2025 08:32:44 +0000 (09:32 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 26 Nov 2025 08:32:44 +0000 (09:32 +0100)
KVM guest_memfd changes for 6.19:

 - Add NUMA mempolicy support for guest_memfd, and clean up a variety of
   rough edges in guest_memfd along the way.

 - Define a CLASS to automatically handle get+put when grabbing a guest_memfd
   from a memslot to make it harder to leak references.

 - Enhance KVM selftests to make it easer to develop and debug selftests like
   those added for guest_memfd NUMA support, e.g. where test and/or KVM bugs
   often result in hard-to-debug SIGBUS errors.

 - Misc cleanups.

1  2 
mm/filemap.c
virt/kvm/guest_memfd.c
virt/kvm/kvm_main.c

diff --cc mm/filemap.c
Simple merge
index ffadc5ee8e0455a280ddf5b837730fd29d3fb67a,427c0acee9d7a7b81e22fec7aed11d5d2386753b..fdaea3422c3026c9cc73be8a31bd49c4bfc49d6f
@@@ -623,53 -708,31 +708,49 @@@ err
        return r;
  }
  
- static void __kvm_gmem_unbind(struct kvm_memory_slot *slot, struct kvm_gmem *gmem)
 -void kvm_gmem_unbind(struct kvm_memory_slot *slot)
++static void __kvm_gmem_unbind(struct kvm_memory_slot *slot, struct gmem_file *f)
  {
        unsigned long start = slot->gmem.pgoff;
        unsigned long end = start + slot->npages;
 -      struct gmem_file *f;
 -
 -      /*
 -       * Nothing to do if the underlying file was already closed (or is being
 -       * closed right now), kvm_gmem_release() invalidates all bindings.
 -       */
 -      CLASS(gmem_get_file, file)(slot);
 -      if (!file)
 -              return;
 -
 -      f = file->private_data;
  
-       xa_store_range(&gmem->bindings, start, end - 1, NULL, GFP_KERNEL);
 -      filemap_invalidate_lock(file->f_mapping);
+       xa_store_range(&f->bindings, start, end - 1, NULL, GFP_KERNEL);
  
        /*
         * synchronize_srcu(&kvm->srcu) ensured that kvm_gmem_get_pfn()
         * cannot see this memslot.
         */
        WRITE_ONCE(slot->gmem.file, NULL);
-       struct file *file;
 +}
 +
 +void kvm_gmem_unbind(struct kvm_memory_slot *slot)
 +{
-       file = kvm_gmem_get_file(slot);
 +      /*
 +       * Nothing to do if the underlying file was _already_ closed, as
 +       * kvm_gmem_release() invalidates and nullifies all bindings.
 +       */
 +      if (!slot->gmem.file)
 +              return;
 +
++      CLASS(gmem_get_file, file)(slot);
 +
 +      /*
 +       * However, if the file is _being_ closed, then the bindings need to be
 +       * removed as kvm_gmem_release() might not run until after the memslot
 +       * is freed.  Note, modifying the bindings is safe even though the file
 +       * is dying as kvm_gmem_release() nullifies slot->gmem.file under
 +       * slots_lock, and only puts its reference to KVM after destroying all
 +       * bindings.  I.e. reaching this point means kvm_gmem_release() hasn't
 +       * yet destroyed the bindings or freed the gmem_file, and can't do so
 +       * until the caller drops slots_lock.
 +       */
 +      if (!file) {
 +              __kvm_gmem_unbind(slot, slot->gmem.file->private_data);
 +              return;
 +      }
 +
 +      filemap_invalidate_lock(file->f_mapping);
 +      __kvm_gmem_unbind(slot, file->private_data);
        filemap_invalidate_unlock(file->f_mapping);
-       fput(file);
  }
  
  /* Returns a locked folio on success.  */
Simple merge