clear-pkgs-linux-iot-lts2018/1198-vhm-destroy-VM-and-rel...

154 lines
4.4 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shuo A Liu <shuo.a.liu@intel.com>
Date: Fri, 30 Nov 2018 14:06:10 +0800
Subject: [PATCH] vhm: destroy VM and release all its resources while closing
vhm device
With closing vhm device, we need release all resources hold by VM in
vhm, or we might leak resources and cannot re-create it next time.
Tracked-On: projectacrn/acrn-hypervisor#2058
Signed-off-by: Shuo A Liu <shuo.a.liu@intel.com>
Reviewed-by: Zhao Yakui <yakui.zhao@intel.com>
---
drivers/char/vhm/vhm_dev.c | 40 +++++++++++++++++++++------------
drivers/vhm/vhm_ioreq.c | 14 +++++-------
include/linux/vhm/vhm_vm_mngt.h | 16 +++++++++++--
3 files changed, 46 insertions(+), 24 deletions(-)
diff --git a/drivers/char/vhm/vhm_dev.c b/drivers/char/vhm/vhm_dev.c
index 2dcdbef01bd3..74615e0a6ab4 100644
--- a/drivers/char/vhm/vhm_dev.c
+++ b/drivers/char/vhm/vhm_dev.c
@@ -200,7 +200,8 @@ static long vhm_dev_ioctl(struct file *filep,
pr_err("vhm: invalid VM !\n");
return -EFAULT;
}
- if ((vm->vmid == ACRN_INVALID_VMID) && (ioctl_num != IC_CREATE_VM)) {
+ if (((vm->vmid == ACRN_INVALID_VMID) && (ioctl_num != IC_CREATE_VM)) ||
+ test_bit(VHM_VM_DESTROYED, &vm->flags)) {
pr_err("vhm: invalid VM ID !\n");
return -EFAULT;
}
@@ -281,15 +282,7 @@ static long vhm_dev_ioctl(struct file *filep,
}
case IC_DESTROY_VM: {
- acrn_ioeventfd_deinit(vm->vmid);
- acrn_irqfd_deinit(vm->vmid);
- acrn_ioreq_free(vm);
- ret = hcall_destroy_vm(vm->vmid);
- if (ret < 0) {
- pr_err("failed to destroy VM %ld\n", vm->vmid);
- return -EFAULT;
- }
- vm->vmid = ACRN_INVALID_VMID;
+ ret = vhm_vm_destroy(vm);
break;
}
@@ -771,6 +764,28 @@ static void vhm_intr_handler(void)
tasklet_schedule(&vhm_io_req_tasklet);
}
+int vhm_vm_destroy(struct vhm_vm *vm)
+{
+ int ret;
+
+ if (test_and_set_bit(VHM_VM_DESTROYED, &vm->flags))
+ return -ENODEV;
+
+ acrn_ioeventfd_deinit(vm->vmid);
+ acrn_irqfd_deinit(vm->vmid);
+ acrn_ioreq_free(vm);
+
+ ret = hcall_destroy_vm(vm->vmid);
+ if (ret < 0)
+ pr_err("Failed to destroy VM %ld!\n", vm->vmid);
+ write_lock_bh(&vhm_vm_list_lock);
+ list_del_init(&vm->list);
+ write_unlock_bh(&vhm_vm_list_lock);
+ vm->vmid = ACRN_INVALID_VMID;
+
+ return 0;
+}
+
static int vhm_dev_release(struct inode *inodep, struct file *filep)
{
struct vhm_vm *vm = filep->private_data;
@@ -779,10 +794,7 @@ static int vhm_dev_release(struct inode *inodep, struct file *filep)
pr_err("vhm: invalid VM !\n");
return -EFAULT;
}
- acrn_ioreq_free(vm);
- write_lock_bh(&vhm_vm_list_lock);
- list_del_init(&vm->list);
- write_unlock_bh(&vhm_vm_list_lock);
+ vhm_vm_destroy(vm);
put_vm(vm);
filep->private_data = NULL;
return 0;
diff --git a/drivers/vhm/vhm_ioreq.c b/drivers/vhm/vhm_ioreq.c
index 8aab2c3cb55d..85c7f902c781 100644
--- a/drivers/vhm/vhm_ioreq.c
+++ b/drivers/vhm/vhm_ioreq.c
@@ -1080,15 +1080,13 @@ void acrn_ioreq_free(struct vhm_vm *vm)
* The below is used to assure that the client is still released even when
* it is not called.
*/
- if (!test_and_set_bit(VHM_VM_IOREQ, &vm->flags)) {
- get_vm(vm);
- list_for_each_safe(pos, tmp, &vm->ioreq_client_list) {
- struct ioreq_client *client =
- container_of(pos, struct ioreq_client, list);
- acrn_ioreq_destroy_client(client->id);
- }
- put_vm(vm);
+ get_vm(vm);
+ list_for_each_safe(pos, tmp, &vm->ioreq_client_list) {
+ struct ioreq_client *client =
+ container_of(pos, struct ioreq_client, list);
+ acrn_ioreq_destroy_client(client->id);
}
+ put_vm(vm);
}
diff --git a/include/linux/vhm/vhm_vm_mngt.h b/include/linux/vhm/vhm_vm_mngt.h
index 6e61d4f80517..1f89f25502c6 100644
--- a/include/linux/vhm/vhm_vm_mngt.h
+++ b/include/linux/vhm/vhm_vm_mngt.h
@@ -71,8 +71,11 @@ extern rwlock_t vhm_vm_list_lock;
#define HUGEPAGE_HLIST_ARRAY_SIZE (HUGEPAGE_2M_HLIST_ARRAY_SIZE + \
HUGEPAGE_1G_HLIST_ARRAY_SIZE)
-enum VM_FREE_BITS {
- VHM_VM_IOREQ = 0,
+/**
+ * enum vhm_vm_flags - vhm vm flags definition
+ */
+enum vhm_vm_flags {
+ VHM_VM_DESTROYED = 0,
};
/**
@@ -182,6 +185,15 @@ int vhm_inject_msi(unsigned long vmid, unsigned long msi_addr,
*/
unsigned long vhm_vm_gpa2hpa(unsigned long vmid, unsigned long gpa);
+/**
+ * vhm_vm_destroy() - destroy VM and release its resources
+ *
+ * @vm: pointer to vhm_vm which identify specific guest
+ *
+ * Return: 0 on success, <0 on error
+ */
+int vhm_vm_destroy(struct vhm_vm *vm);
+
void vm_list_add(struct list_head *list);
#endif
--
https://clearlinux.org