clear-pkgs-linux-iot-lts2018/1220-kernel-fix-acrn-dm-can...

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