From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Tue, 18 Dec 2018 09:37:08 +0800 Subject: [PATCH] Kernel/VHM: VM_list changes the lock from mutex to rw_lock to avoid sleeping VM_list records all the added vm for each DM. And it is accessed by using mutex lock. As it is accessed in created/removed and softireq tasklet, the spinlock should be used instead. And as the read is used frequently, the rwlock is used(similar to spinlock except it allows multiple readers). And when the vhm_dev_release is closed, the vhm_vm will be removed from the list and its memory is released only when its refcnt is decreased to zero. Tracked-On: projectacrn/acrn-hypervisor#2085 Signed-off-by: Zhao Yakui Reviewed-by: Shuo Liu Reviewed-by: Yin FengWei Tracked-On: PKT-1617 --- drivers/char/vhm/vhm_dev.c | 9 +++++++-- drivers/vhm/vhm_vm_mngt.c | 21 ++++----------------- include/linux/vhm/vhm_vm_mngt.h | 5 ++--- 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/drivers/char/vhm/vhm_dev.c b/drivers/char/vhm/vhm_dev.c index 30cafccb7296..2a51fadac057 100644 --- a/drivers/char/vhm/vhm_dev.c +++ b/drivers/char/vhm/vhm_dev.c @@ -130,10 +130,10 @@ static int vhm_dev_open(struct inode *inodep, struct file *filep) INIT_LIST_HEAD(&vm->ioreq_client_list); spin_lock_init(&vm->ioreq_client_lock); - vm_mutex_lock(&vhm_vm_list_lock); atomic_set(&vm->refcnt, 1); + write_lock_bh(&vhm_vm_list_lock); vm_list_add(&vm->list); - vm_mutex_unlock(&vhm_vm_list_lock); + write_unlock_bh(&vhm_vm_list_lock); filep->private_data = vm; return 0; } @@ -672,12 +672,14 @@ static void io_req_tasklet(unsigned long data) { struct vhm_vm *vm; + read_lock(&vhm_vm_list_lock); list_for_each_entry(vm, &vhm_vm_list, list) { if (!vm || !vm->req_buf) break; acrn_ioreq_distribute_request(vm); } + read_unlock(&vhm_vm_list_lock); } static void vhm_intr_handler(void) @@ -694,6 +696,9 @@ static int vhm_dev_release(struct inode *inodep, struct file *filep) 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); put_vm(vm); filep->private_data = NULL; return 0; diff --git a/drivers/vhm/vhm_vm_mngt.c b/drivers/vhm/vhm_vm_mngt.c index 6bbcb1dddf57..61207106d5de 100644 --- a/drivers/vhm/vhm_vm_mngt.c +++ b/drivers/vhm/vhm_vm_mngt.c @@ -64,21 +64,21 @@ #include LIST_HEAD(vhm_vm_list); -DEFINE_MUTEX(vhm_vm_list_lock); +DEFINE_RWLOCK(vhm_vm_list_lock); struct vhm_vm *find_get_vm(unsigned long vmid) { struct vhm_vm *vm; - mutex_lock(&vhm_vm_list_lock); + read_lock_bh(&vhm_vm_list_lock); list_for_each_entry(vm, &vhm_vm_list, list) { if (vm->vmid == vmid) { atomic_inc(&vm->refcnt); - mutex_unlock(&vhm_vm_list_lock); + read_unlock_bh(&vhm_vm_list_lock); return vm; } } - mutex_unlock(&vhm_vm_list_lock); + read_unlock_bh(&vhm_vm_list_lock); return NULL; } EXPORT_SYMBOL_GPL(find_get_vm); @@ -86,9 +86,6 @@ EXPORT_SYMBOL_GPL(find_get_vm); void put_vm(struct vhm_vm *vm) { if (atomic_dec_and_test(&vm->refcnt)) { - mutex_lock(&vhm_vm_list_lock); - list_del(&vm->list); - mutex_unlock(&vhm_vm_list_lock); free_guest_mem(vm); if (vm->req_buf && vm->pg) { @@ -167,13 +164,3 @@ void vm_list_add(struct list_head *list) { list_add(list, &vhm_vm_list); } - -void vm_mutex_lock(struct mutex *mlock) -{ - mutex_lock(mlock); -} - -void vm_mutex_unlock(struct mutex *mlock) -{ - mutex_unlock(mlock); -} diff --git a/include/linux/vhm/vhm_vm_mngt.h b/include/linux/vhm/vhm_vm_mngt.h index cf61ed0af1a9..6e61d4f80517 100644 --- a/include/linux/vhm/vhm_vm_mngt.h +++ b/include/linux/vhm/vhm_vm_mngt.h @@ -61,9 +61,10 @@ #define VHM_VM_MNGT_H #include +#include extern struct list_head vhm_vm_list; -extern struct mutex vhm_vm_list_lock; +extern rwlock_t vhm_vm_list_lock; #define HUGEPAGE_2M_HLIST_ARRAY_SIZE 16 #define HUGEPAGE_1G_HLIST_ARRAY_SIZE 1 @@ -182,7 +183,5 @@ int vhm_inject_msi(unsigned long vmid, unsigned long msi_addr, unsigned long vhm_vm_gpa2hpa(unsigned long vmid, unsigned long gpa); void vm_list_add(struct list_head *list); -void vm_mutex_lock(struct mutex *mlock); -void vm_mutex_unlock(struct mutex *mlock); #endif -- https://clearlinux.org