108 lines
3.6 KiB
Diff
108 lines
3.6 KiB
Diff
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: Mingqiang Chi <mingqiang.chi@intel.com>
|
||
|
Date: Fri, 26 Jul 2019 15:10:11 +0800
|
||
|
Subject: [PATCH] kernel:fix acrn-dm can not exit in some case
|
||
|
|
||
|
the acrn-dm process will be stuck if launch UOS
|
||
|
with 0 core,the DM will call vm_destroy via ioctl,
|
||
|
the ioreq_client_thread will exit before entering while loop
|
||
|
because the client_id has been removed in this case,
|
||
|
then it cannot set IOREQ_CLIENT_EXIT flag, it will check the flag
|
||
|
in acrn_ioreq_destroy_client_pervm(),
|
||
|
it will cause the acrn-dm process stuck,
|
||
|
this patch add IOREQ_THREAD_START flag to avoid dead loop
|
||
|
|
||
|
Tracked-On: projectacrn/acrn-hypervisor#3491
|
||
|
Signed-off-by: Mingqiang Chi <mingqiang.chi@intel.com>
|
||
|
Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
|
||
|
Reviewed-by: Yin Fengwei <fengwei.yin@intel.com>
|
||
|
Reviewed-by: Zhao Yakui <yakui.zhao@intel.com>
|
||
|
---
|
||
|
drivers/vhm/vhm_ioreq.c | 21 +++++++++++++++++----
|
||
|
1 file changed, 17 insertions(+), 4 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/vhm/vhm_ioreq.c b/drivers/vhm/vhm_ioreq.c
|
||
|
index 85c7f902c781..c8cc09766610 100644
|
||
|
--- a/drivers/vhm/vhm_ioreq.c
|
||
|
+++ b/drivers/vhm/vhm_ioreq.c
|
||
|
@@ -81,6 +81,7 @@ struct ioreq_range {
|
||
|
enum IOREQ_CLIENT_BITS {
|
||
|
IOREQ_CLIENT_DESTROYING = 0,
|
||
|
IOREQ_CLIENT_EXIT,
|
||
|
+ IOREQ_THREAD_START,
|
||
|
};
|
||
|
|
||
|
struct ioreq_client {
|
||
|
@@ -355,8 +356,7 @@ int acrn_ioreq_create_fallback_client(unsigned long vmid, char *name)
|
||
|
return client_id;
|
||
|
}
|
||
|
|
||
|
-/* When one client is removed from VM, the refcnt is decreased */
|
||
|
-static void acrn_ioreq_destroy_client_pervm(struct ioreq_client *client,
|
||
|
+static void acrn_ioreq_remove_client_pervm(struct ioreq_client *client,
|
||
|
struct vhm_vm *vm)
|
||
|
{
|
||
|
struct list_head *pos, *tmp;
|
||
|
@@ -364,7 +364,9 @@ static void acrn_ioreq_destroy_client_pervm(struct ioreq_client *client,
|
||
|
set_bit(IOREQ_CLIENT_DESTROYING, &client->flags);
|
||
|
acrn_ioreq_notify_client(client);
|
||
|
|
||
|
- while (client->vhm_create_kthread && !test_bit(IOREQ_CLIENT_EXIT, &client->flags))
|
||
|
+ while (client->vhm_create_kthread &&
|
||
|
+ !test_bit(IOREQ_CLIENT_EXIT, &client->flags)
|
||
|
+ && test_bit(IOREQ_THREAD_START, &client->flags))
|
||
|
msleep(10);
|
||
|
|
||
|
spin_lock_bh(&client->range_lock);
|
||
|
@@ -383,6 +385,9 @@ static void acrn_ioreq_destroy_client_pervm(struct ioreq_client *client,
|
||
|
if (client->id == vm->ioreq_fallback_client)
|
||
|
vm->ioreq_fallback_client = -1;
|
||
|
|
||
|
+ /* When one client is removed from VM, the refcnt is decreased
|
||
|
+ * it is pair with acrn_ioreq_get_client in acrn_ioreq_create_client
|
||
|
+ */
|
||
|
acrn_ioreq_put_client(client);
|
||
|
}
|
||
|
|
||
|
@@ -395,6 +400,9 @@ void acrn_ioreq_destroy_client(int client_id)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
+ /* Remove client id from IDR to avoid some invalid ioreq
|
||
|
+ * during destroying client
|
||
|
+ */
|
||
|
spin_lock_bh(&client_lock);
|
||
|
client = idr_remove(&idr_client, client_id);
|
||
|
spin_unlock_bh(&client_lock);
|
||
|
@@ -408,7 +416,10 @@ void acrn_ioreq_destroy_client(int client_id)
|
||
|
|
||
|
might_sleep();
|
||
|
|
||
|
- acrn_ioreq_destroy_client_pervm(client, client->ref_vm);
|
||
|
+ acrn_ioreq_remove_client_pervm(client, client->ref_vm);
|
||
|
+ /* it will free client, it is pair with alloc_client
|
||
|
+ * in acrn_ioreq_destroy_client
|
||
|
+ */
|
||
|
acrn_ioreq_put_client(client);
|
||
|
}
|
||
|
EXPORT_SYMBOL_GPL(acrn_ioreq_destroy_client);
|
||
|
@@ -574,6 +585,7 @@ static int ioreq_client_thread(void *data)
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
+ set_bit(IOREQ_THREAD_START, &client->flags);
|
||
|
while (1) {
|
||
|
if (is_destroying(client)) {
|
||
|
pr_info("vhm-ioreq: client destroying->stop thread\n");
|
||
|
@@ -598,6 +610,7 @@ static int ioreq_client_thread(void *data)
|
||
|
}
|
||
|
|
||
|
set_bit(IOREQ_CLIENT_EXIT, &client->flags);
|
||
|
+ clear_bit(IOREQ_THREAD_START, &client->flags);
|
||
|
acrn_ioreq_put_client(client);
|
||
|
return 0;
|
||
|
}
|
||
|
--
|
||
|
https://clearlinux.org
|
||
|
|