- Add a weak reference 'vm_file' in struct kvm under CONFIG_LIVEUPDATE_GUEST_MEMFD to enable reverse file resolution without circular lifetime dependencies.
Signed-off-by: Tarun Sahu <[email protected]> --- include/linux/kvm_host.h | 12 ++++++++++++ virt/kvm/kvm_main.c | 26 ++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index d9908c19e42f..8da9589425ee 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -874,6 +874,18 @@ struct kvm { #ifdef CONFIG_KVM_GENERIC_MEMORY_ATTRIBUTES /* Protected by slots_lock (for writes) and RCU (for reads) */ struct xarray mem_attr_array; +#endif +#ifdef CONFIG_LIVEUPDATE_GUEST_MEMFD + /* + * Weak reference to the VFS file backing this KVM instance. Stored + * without incrementing the file refcount to prevent a circular lifetime + * dependency (since file->private_data already pins this struct kvm). + * Used exclusively to resolve the file pointer back from struct kvm. + * + * Written/cleared via rcu_assign_pointer() and read locklessly under + * RCU (e.g. via get_file_active() to prevent ABA races). + */ + struct file __rcu *vm_file; #endif char stats_id[KVM_STATS_NAME_SIZE]; }; diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 701d4596a91c..14c32541ae34 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1346,6 +1346,19 @@ static int kvm_vm_release(struct inode *inode, struct file *filp) { struct kvm *kvm = filp->private_data; +#ifdef CONFIG_LIVEUPDATE_GUEST_MEMFD + /* + * Clear the weak reference of the vm file. + * In case vm file is closed by userspace, but kvm still has + * other users like vCPUs, clearing this pointer ensures + * that we don't have a dangling pointer to a closed file. + * + * Cleared via rcu_assign_pointer() to ensure proper memory visibility + * for concurrent lockless readers under RCU. + */ + rcu_assign_pointer(kvm->vm_file, NULL); +#endif + kvm_irqfd_release(kvm); kvm_put_kvm(kvm); @@ -5488,6 +5501,19 @@ struct file *kvm_create_vm_file(unsigned long type, const char *fdname) return file; } +#ifdef CONFIG_LIVEUPDATE_GUEST_MEMFD + /* + * Weak reference to the file (without get_file()) to prevent a circular + * dependency. Safe because the file's release path clears this pointer + * and drops its reference to the VM. + * + * Written via rcu_assign_pointer() because the pointer can be read + * locklessly under RCU (e.g., in kvm_gmem_luo_preserve() via + * get_file_active() to prevent lockless ABA races). + */ + rcu_assign_pointer(kvm->vm_file, file); +#endif + /* * Don't call kvm_put_kvm anymore at this point; file->f_op is * already set, with ->release() being kvm_vm_release(). In error -- 2.55.0.229.g6434b31f56-goog

