From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Zhao Yakui 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 Reviewed-by: Shuo Liu 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