The directory under /sys/kernel/debug/kvm is named <pid>-<fd>, but is
removed only together with the VM. A VM can outlive its fd: VFIO keeps
a reference to it for an open passthrough device, and QEMU's cpr-exec
closes the fd and creates a new VM in the same process, often on the
same fd number. The new VM then finds its directory taken, logs
"duplicate directory" and runs without debugfs stats. Seen on every
other live update of a vGPU VM.

Remove only the directory when the fd is released: the name belongs to
the fd, which is free to reuse from then on. The stat data stays until
kvm_destroy_vm(): an open stat file reaches it through the inode at
release, which debugfs runs even after the file was removed.

Two things change with that: the destroy uevent no longer carries
STATS_PATH, and a VM that lives on after its fd on the vcpu fds has
no stats directory for that time.

https://virtuozzo.atlassian.net/browse/VSTOR-150597
Feature: fix ms/kvm

Assisted-by: LLM
Signed-off-by: Andrey Drobyshev <[email protected]>
---
 virt/kvm/kvm_main.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 8d92a649c063..9a0ee933a6a3 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -995,21 +995,28 @@ static umode_t kvm_stats_debugfs_mode(const struct 
_kvm_stats_desc *pdesc)
 }
 
 
+static void kvm_remove_vm_debugfs(struct kvm *kvm)
+{
+       if (IS_ERR(kvm->debugfs_dentry))
+               return;
+
+       debugfs_remove_recursive(kvm->debugfs_dentry);
+       kvm->debugfs_dentry = ERR_PTR(-ENOENT);
+}
+
 static void kvm_destroy_vm_debugfs(struct kvm *kvm)
 {
        int i;
        int kvm_debugfs_num_entries = kvm_vm_stats_header.num_desc +
                                      kvm_vcpu_stats_header.num_desc;
 
-       if (IS_ERR(kvm->debugfs_dentry))
-               return;
-
-       debugfs_remove_recursive(kvm->debugfs_dentry);
+       kvm_remove_vm_debugfs(kvm);
 
        if (kvm->debugfs_stat_data) {
                for (i = 0; i < kvm_debugfs_num_entries; i++)
                        kfree(kvm->debugfs_stat_data[i]);
                kfree(kvm->debugfs_stat_data);
+               kvm->debugfs_stat_data = NULL;
        }
 }
 
@@ -1364,6 +1371,9 @@ static int kvm_vm_release(struct inode *inode, struct 
file *filp)
 
        kvm_irqfd_release(kvm);
 
+       /* The directory is named after this fd, which is free to reuse now */
+       kvm_remove_vm_debugfs(kvm);
+
        kvm_put_kvm(kvm);
        return 0;
 }
-- 
2.47.1

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to