132 lines
3.8 KiB
Diff
132 lines
3.8 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Zhao Yakui <yakui.zhao@intel.com>
|
|
Date: Tue, 18 Dec 2018 09:37:04 +0800
|
|
Subject: [PATCH] kernel/VHM: Add the vm owner for each ioreq_client to release
|
|
vhm_vm after releasing client
|
|
|
|
Currently it will use the ioreq_client->vmid to find the corresponding vm.
|
|
But if the corresponding vmid is removed from the acrn_vm_list, it will
|
|
fail. And the lock is also acquired to get the corresponding vm from vmid.
|
|
So the vm_owner is added for ioreq_client so that it can get the
|
|
vm_owner directly for each client.
|
|
|
|
When the ioreq_client needs to be released, it will try to decrease
|
|
the refcnt of vhm_vm.
|
|
|
|
Tracked-On: projectacrn/acrn-hypervisor#2085
|
|
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
|
|
Reviewed-by: Shuo Liu <shuo.a.liu@intel.com>
|
|
Tracked-On: PKT-1617
|
|
---
|
|
drivers/vhm/vhm_ioreq.c | 34 +++++++++-------------------------
|
|
1 file changed, 9 insertions(+), 25 deletions(-)
|
|
|
|
diff --git a/drivers/vhm/vhm_ioreq.c b/drivers/vhm/vhm_ioreq.c
|
|
index 2f37ef958094..3f8bd4abe757 100644
|
|
--- a/drivers/vhm/vhm_ioreq.c
|
|
+++ b/drivers/vhm/vhm_ioreq.c
|
|
@@ -132,6 +132,8 @@ struct ioreq_client {
|
|
int pci_dev;
|
|
int pci_func;
|
|
atomic_t refcnt;
|
|
+ /* Add the vhm_vm that contains the ioreq_client */
|
|
+ struct vhm_vm *ref_vm;
|
|
};
|
|
|
|
#define MAX_CLIENT 1024
|
|
@@ -192,9 +194,11 @@ static struct ioreq_client *acrn_ioreq_get_client(int client_id)
|
|
static void acrn_ioreq_put_client(struct ioreq_client *client)
|
|
{
|
|
if (atomic_dec_and_test(&client->refcnt)) {
|
|
+ struct vhm_vm *ref_vm = client->ref_vm;
|
|
/* The client should be released when refcnt = 0 */
|
|
/* TBD: Do we need to free the other resources? */
|
|
kfree(client);
|
|
+ put_vm(ref_vm);
|
|
}
|
|
}
|
|
|
|
@@ -242,6 +246,7 @@ int acrn_ioreq_create_client(unsigned long vmid, ioreq_handler_t handler,
|
|
}
|
|
|
|
client->vmid = vmid;
|
|
+ client->ref_vm = vm;
|
|
if (name)
|
|
strncpy(client->name, name, sizeof(client->name) - 1);
|
|
spin_lock_init(&client->range_lock);
|
|
@@ -380,12 +385,10 @@ static void acrn_ioreq_destroy_client_pervm(struct ioreq_client *client,
|
|
vm->ioreq_fallback_client = -1;
|
|
|
|
acrn_ioreq_put_client(client);
|
|
- put_vm(vm);
|
|
}
|
|
|
|
void acrn_ioreq_destroy_client(int client_id)
|
|
{
|
|
- struct vhm_vm *vm;
|
|
struct ioreq_client *client;
|
|
|
|
if (client_id < 0 || client_id >= MAX_CLIENT) {
|
|
@@ -403,18 +406,8 @@ void acrn_ioreq_destroy_client(int client_id)
|
|
|
|
might_sleep();
|
|
|
|
- vm = find_get_vm(client->vmid);
|
|
- if (unlikely(vm == NULL)) {
|
|
- pr_err("vhm-ioreq: failed to find vm from vmid %ld\n",
|
|
- client->vmid);
|
|
- acrn_ioreq_put_client(client);
|
|
- return;
|
|
- }
|
|
-
|
|
- acrn_ioreq_destroy_client_pervm(client, vm);
|
|
+ acrn_ioreq_destroy_client_pervm(client, client->ref_vm);
|
|
acrn_ioreq_put_client(client);
|
|
-
|
|
- put_vm(vm);
|
|
}
|
|
EXPORT_SYMBOL_GPL(acrn_ioreq_destroy_client);
|
|
|
|
@@ -552,19 +545,11 @@ struct vhm_request *acrn_ioreq_get_reqbuf(int client_id)
|
|
pr_err("vhm-ioreq: no client for id %d\n", client_id);
|
|
return NULL;
|
|
}
|
|
- vm = find_get_vm(client->vmid);
|
|
- if (unlikely(vm == NULL)) {
|
|
- pr_err("vhm-ioreq: failed to find vm from vmid %ld\n",
|
|
- client->vmid);
|
|
- acrn_ioreq_put_client(client);
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- if (vm->req_buf == NULL) {
|
|
+ vm = client->ref_vm;
|
|
+ if (unlikely(vm == NULL || vm->req_buf == NULL)) {
|
|
pr_warn("vhm-ioreq: the req buf page not ready yet "
|
|
"for vmid %ld\n", client->vmid);
|
|
}
|
|
- put_vm(vm);
|
|
acrn_ioreq_put_client(client);
|
|
return (struct vhm_request *)vm->req_buf;
|
|
}
|
|
@@ -581,7 +566,7 @@ static int ioreq_client_thread(void *data)
|
|
if (!client)
|
|
return 0;
|
|
|
|
- vm = find_get_vm(client->vmid);
|
|
+ vm = client->ref_vm;
|
|
if (unlikely(vm == NULL)) {
|
|
pr_err("vhm-ioreq: failed to find vm from vmid %ld\n",
|
|
client->vmid);
|
|
@@ -614,7 +599,6 @@ static int ioreq_client_thread(void *data)
|
|
|
|
set_bit(IOREQ_CLIENT_EXIT, &client->flags);
|
|
acrn_ioreq_put_client(client);
|
|
- put_vm(vm);
|
|
return 0;
|
|
}
|
|
|
|
--
|
|
https://clearlinux.org
|
|
|