Skip to content

Commit 3898da9

Browse files
bonzinirkrcmar
authored andcommitted
KVM: avoid using rcu_dereference_protected
During teardown, accesses to memslots and buses are using rcu_dereference_protected with an always-true condition because these accesses are done outside the usual mutexes. This is because the last reference is gone and there cannot be any concurrent modifications, but rcu_dereference_protected is ugly and unobvious. Instead, check the refcount in kvm_get_bus and __kvm_memslots. Signed-off-by: Paolo Bonzini <[email protected]> Signed-off-by: Radim Krčmář <[email protected]>
1 parent ebd28fc commit 3898da9

File tree

2 files changed

+8
-9
lines changed

2 files changed

+8
-9
lines changed

include/linux/kvm_host.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,8 @@ struct kvm {
477477
static inline struct kvm_io_bus *kvm_get_bus(struct kvm *kvm, enum kvm_bus idx)
478478
{
479479
return srcu_dereference_check(kvm->buses[idx], &kvm->srcu,
480-
lockdep_is_held(&kvm->slots_lock));
480+
lockdep_is_held(&kvm->slots_lock) ||
481+
!refcount_read(&kvm->users_count));
481482
}
482483

483484
static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i)
@@ -570,7 +571,8 @@ void kvm_put_kvm(struct kvm *kvm);
570571
static inline struct kvm_memslots *__kvm_memslots(struct kvm *kvm, int as_id)
571572
{
572573
return srcu_dereference_check(kvm->memslots[as_id], &kvm->srcu,
573-
lockdep_is_held(&kvm->slots_lock));
574+
lockdep_is_held(&kvm->slots_lock) ||
575+
!refcount_read(&kvm->users_count));
574576
}
575577

576578
static inline struct kvm_memslots *kvm_memslots(struct kvm *kvm)

virt/kvm/kvm_main.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -717,10 +717,9 @@ static struct kvm *kvm_create_vm(unsigned long type)
717717
hardware_disable_all();
718718
out_err_no_disable:
719719
for (i = 0; i < KVM_NR_BUSES; i++)
720-
kfree(rcu_access_pointer(kvm->buses[i]));
720+
kfree(kvm_get_bus(kvm, i));
721721
for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
722-
kvm_free_memslots(kvm,
723-
rcu_dereference_protected(kvm->memslots[i], 1));
722+
kvm_free_memslots(kvm, __kvm_memslots(kvm, i));
724723
kvm_arch_free_vm(kvm);
725724
mmdrop(current->mm);
726725
return ERR_PTR(r);
@@ -754,9 +753,8 @@ static void kvm_destroy_vm(struct kvm *kvm)
754753
spin_unlock(&kvm_lock);
755754
kvm_free_irq_routing(kvm);
756755
for (i = 0; i < KVM_NR_BUSES; i++) {
757-
struct kvm_io_bus *bus;
756+
struct kvm_io_bus *bus = kvm_get_bus(kvm, i);
758757

759-
bus = rcu_dereference_protected(kvm->buses[i], 1);
760758
if (bus)
761759
kvm_io_bus_destroy(bus);
762760
kvm->buses[i] = NULL;
@@ -770,8 +768,7 @@ static void kvm_destroy_vm(struct kvm *kvm)
770768
kvm_arch_destroy_vm(kvm);
771769
kvm_destroy_devices(kvm);
772770
for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
773-
kvm_free_memslots(kvm,
774-
rcu_dereference_protected(kvm->memslots[i], 1));
771+
kvm_free_memslots(kvm, __kvm_memslots(kvm, i));
775772
cleanup_srcu_struct(&kvm->irq_srcu);
776773
cleanup_srcu_struct(&kvm->srcu);
777774
kvm_arch_free_vm(kvm);

0 commit comments

Comments
 (0)