Re: [PATCH 1/1] KVM: mark kvm->busses as rcu protected

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 07/07/2017 12:58, Christian Borntraeger wrote:
> mark kvm->busses as rcu protected and use the correct access
> function everywhere.
> 
> found by sparse
> virt/kvm/kvm_main.c:3490:15: error: incompatible types in comparison expression (different address spaces)
> virt/kvm/kvm_main.c:3509:15: error: incompatible types in comparison expression (different address spaces)
> virt/kvm/kvm_main.c:3561:15: error: incompatible types in comparison expression (different address spaces)
> virt/kvm/kvm_main.c:3644:15: error: incompatible types in comparison expression (different address spaces)
> 
> Signed-off-by: Christian Borntraeger <borntraeger@xxxxxxxxxx>
> ---
>  include/linux/kvm_host.h |  2 +-
>  virt/kvm/eventfd.c       |  8 +++++---
>  virt/kvm/kvm_main.c      | 17 ++++++++++-------
>  3 files changed, 16 insertions(+), 11 deletions(-)
> 
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 7c32905..220f251 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -404,7 +404,7 @@ struct kvm {
>  	int last_boosted_vcpu;
>  	struct list_head vm_list;
>  	struct mutex lock;
> -	struct kvm_io_bus *buses[KVM_NR_BUSES];
> +	struct kvm_io_bus __rcu *buses[KVM_NR_BUSES];
>  #ifdef CONFIG_HAVE_KVM_EVENTFD
>  	struct {
>  		spinlock_t        lock;
> diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
> index a8d5403..3e08b43 100644
> --- a/virt/kvm/eventfd.c
> +++ b/virt/kvm/eventfd.c
> @@ -825,7 +825,7 @@ static int kvm_assign_ioeventfd_idx(struct kvm *kvm,
>  	if (ret < 0)
>  		goto unlock_fail;
>  
> -	kvm->buses[bus_idx]->ioeventfd_count++;
> +	rcu_dereference_protected(kvm->buses[bus_idx], 1)->ioeventfd_count++;

Whenever possible, we should use (s)rcu_dereference_check and a better 
predicate than "1".  In this case:

static inline struct kvm_io_bus *kvm_get_bus(struct kvm *kvm, int i)
{
	struct kvm_io_bus **buses =
		srcu_dereference_check(kvm->buses, &kvm->srcu,
				       lockdep_is_held(&kvm->slots_lock));
	return buses[i];
}

(since you are at it, __kvm_memslots should also use srcu_dereference_check
instead of rcu_dereference_check!).

Paolo

>  	list_add_tail(&p->list, &kvm->ioeventfds);
>  
>  	mutex_unlock(&kvm->slots_lock);
> @@ -848,6 +848,7 @@ kvm_deassign_ioeventfd_idx(struct kvm *kvm, enum kvm_bus bus_idx,
>  {
>  	struct _ioeventfd        *p, *tmp;
>  	struct eventfd_ctx       *eventfd;
> +	struct kvm_io_bus	 *bus;
>  	int                       ret = -ENOENT;
>  
>  	eventfd = eventfd_ctx_fdget(args->fd);
> @@ -870,8 +871,9 @@ kvm_deassign_ioeventfd_idx(struct kvm *kvm, enum kvm_bus bus_idx,
>  			continue;
>  
>  		kvm_io_bus_unregister_dev(kvm, bus_idx, &p->dev);
> -		if (kvm->buses[bus_idx])
> -			kvm->buses[bus_idx]->ioeventfd_count--;
> +		bus = rcu_dereference_protected(kvm->buses[bus_idx], 1);
> +		if (bus)
> +			bus->ioeventfd_count--;
>  		ioeventfd_release(p);
>  		ret = 0;
>  		break;
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index e3e6fec..e5ae3eb 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -679,8 +679,8 @@ static struct kvm *kvm_create_vm(unsigned long type)
>  	if (init_srcu_struct(&kvm->irq_srcu))
>  		goto out_err_no_irq_srcu;
>  	for (i = 0; i < KVM_NR_BUSES; i++) {
> -		kvm->buses[i] = kzalloc(sizeof(struct kvm_io_bus),
> -					GFP_KERNEL);
> +		rcu_assign_pointer(kvm->buses[i],
> +			kzalloc(sizeof(struct kvm_io_bus), GFP_KERNEL));
>  		if (!kvm->buses[i])
>  			goto out_err;
>  	}
> @@ -705,7 +705,7 @@ static struct kvm *kvm_create_vm(unsigned long type)
>  	hardware_disable_all();
>  out_err_no_disable:
>  	for (i = 0; i < KVM_NR_BUSES; i++)
> -		kfree(kvm->buses[i]);
> +		kfree(rcu_access_pointer(kvm->buses[i]));
>  	for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
>  		kvm_free_memslots(kvm,
>  			rcu_dereference_protected(kvm->memslots[i], 1));
> @@ -741,8 +741,11 @@ static void kvm_destroy_vm(struct kvm *kvm)
>  	spin_unlock(&kvm_lock);
>  	kvm_free_irq_routing(kvm);
>  	for (i = 0; i < KVM_NR_BUSES; i++) {
> -		if (kvm->buses[i])
> -			kvm_io_bus_destroy(kvm->buses[i]);
> +		struct kvm_io_bus *bus;
> +
> +		bus = (rcu_dereference_protected(kvm->buses[i], 1));
> +		if (bus)
> +			kvm_io_bus_destroy(bus);
>  		kvm->buses[i] = NULL;
>  	}
>  	kvm_coalesced_mmio_free(kvm);
> @@ -3572,7 +3575,7 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr,
>  {
>  	struct kvm_io_bus *new_bus, *bus;
>  
> -	bus = kvm->buses[bus_idx];
> +	bus = rcu_dereference_protected(kvm->buses[bus_idx], 1);
>  	if (!bus)
>  		return -ENOMEM;
>  
> @@ -3601,7 +3604,7 @@ void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx,
>  	int i;
>  	struct kvm_io_bus *new_bus, *bus;
>  
> -	bus = kvm->buses[bus_idx];
> +	bus = rcu_dereference_protected(kvm->buses[bus_idx], 1);
>  	if (!bus)
>  		return;
>  
> 



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux