--- x/virt/kvm/guest_memfd.c +++ y/virt/kvm/guest_memfd.c @@ -708,23 +708,11 @@ err: return r; } -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; - filemap_invalidate_lock(file->f_mapping); xa_store_range(&f->bindings, start, end - 1, NULL, GFP_KERNEL); /* @@ -732,7 +720,36 @@ void kvm_gmem_unbind(struct kvm_memory_s * cannot see this memslot. */ WRITE_ONCE(slot->gmem.file, NULL); - filemap_invalidate_unlock(file->f_mapping); +} + +void kvm_gmem_unbind(struct kvm_memory_slot *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() can't + * concurrently destroy the bindings or free the gmem_file. + */ + 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); } /* Returns a locked folio on success. */ --- x/kernel/printk/printk_ringbuffer.c +++ y/kernel/printk/printk_ringbuffer.c @@ -1286,7 +1286,7 @@ static const char *get_data(struct prb_d } /* A valid data block will always have at least an ID. */ - if (WARN_ON_ONCE(*data_size < sizeof(db->id))) + if (*data_size < sizeof(db->id)) return NULL; /* Subtract block ID space from size to reflect data size. */