]> www.infradead.org Git - users/willy/xarray.git/commitdiff
x86,hyperv: Convert conn_to_evt to XArray
authorMatthew Wilcox <willy@infradead.org>
Sun, 6 Jan 2019 20:23:54 +0000 (15:23 -0500)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Fri, 9 Aug 2019 01:38:14 +0000 (21:38 -0400)
This IDR wasn't being used to allocate IDs, just as somewhere to store
pointers.  It moves out from under the protection of the mutex to its
own spinlock.

Signed-off-by: Matthew Wilcox <willy@infradead.org>
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/hyperv.c

index 7b0a4ee7731312730338343bcb97c73fcdfed38e..8be6ec45e3871a39e27b3bcafe010382b3c6b49f 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/clocksource.h>
 #include <linux/irqbypass.h>
 #include <linux/hyperv.h>
+#include <linux/xarray.h>
 
 #include <asm/apic.h>
 #include <asm/pvclock-abi.h>
@@ -833,7 +834,7 @@ struct kvm_hv {
 
        HV_REFERENCE_TSC_PAGE tsc_ref;
 
-       struct idr conn_to_evt;
+       struct xarray conn_to_evt;
 
        u64 hv_reenlightenment_control;
        u64 hv_tsc_emulation_control;
index c10a8b10b203b706ce2b84b28e45fa0042bb1d77..0e595158a2dd6bec4489f6354fcd9e638bf4cc97 100644 (file)
@@ -1579,10 +1579,7 @@ static u16 kvm_hvcall_signal_event(struct kvm_vcpu *vcpu, bool fast, u64 param)
        if (param & ~KVM_HYPERV_CONN_ID_MASK)
                return HV_STATUS_INVALID_HYPERCALL_INPUT;
 
-       /* the eventfd is protected by vcpu->kvm->srcu, but conn_to_evt isn't */
-       rcu_read_lock();
-       eventfd = idr_find(&vcpu->kvm->arch.hyperv.conn_to_evt, param);
-       rcu_read_unlock();
+       eventfd = xa_load(&vcpu->kvm->arch.hyperv.conn_to_evt, param);
        if (!eventfd)
                return HV_STATUS_INVALID_PORT_ID;
 
@@ -1713,17 +1710,17 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
 void kvm_hv_init_vm(struct kvm *kvm)
 {
        mutex_init(&kvm->arch.hyperv.hv_lock);
-       idr_init(&kvm->arch.hyperv.conn_to_evt);
+       xa_init(&kvm->arch.hyperv.conn_to_evt);
 }
 
 void kvm_hv_destroy_vm(struct kvm *kvm)
 {
        struct eventfd_ctx *eventfd;
-       int i;
+       unsigned long i;
 
-       idr_for_each_entry(&kvm->arch.hyperv.conn_to_evt, eventfd, i)
+       xa_for_each(&kvm->arch.hyperv.conn_to_evt, i, eventfd)
                eventfd_ctx_put(eventfd);
-       idr_destroy(&kvm->arch.hyperv.conn_to_evt);
+       xa_destroy(&kvm->arch.hyperv.conn_to_evt);
 }
 
 static int kvm_hv_eventfd_assign(struct kvm *kvm, u32 conn_id, int fd)
@@ -1736,17 +1733,10 @@ static int kvm_hv_eventfd_assign(struct kvm *kvm, u32 conn_id, int fd)
        if (IS_ERR(eventfd))
                return PTR_ERR(eventfd);
 
-       mutex_lock(&hv->hv_lock);
-       ret = idr_alloc(&hv->conn_to_evt, eventfd, conn_id, conn_id + 1,
-                       GFP_KERNEL_ACCOUNT);
-       mutex_unlock(&hv->hv_lock);
-
-       if (ret >= 0)
-               return 0;
+       ret = xa_insert(&hv->conn_to_evt, conn_id, eventfd, GFP_KERNEL_ACCOUNT);
+       if (ret < 0)
+               eventfd_ctx_put(eventfd);
 
-       if (ret == -ENOSPC)
-               ret = -EEXIST;
-       eventfd_ctx_put(eventfd);
        return ret;
 }
 
@@ -1755,10 +1745,7 @@ static int kvm_hv_eventfd_deassign(struct kvm *kvm, u32 conn_id)
        struct kvm_hv *hv = &kvm->arch.hyperv;
        struct eventfd_ctx *eventfd;
 
-       mutex_lock(&hv->hv_lock);
-       eventfd = idr_remove(&hv->conn_to_evt, conn_id);
-       mutex_unlock(&hv->hv_lock);
-
+       eventfd = xa_erase(&hv->conn_to_evt, conn_id);
        if (!eventfd)
                return -ENOENT;