diff options
author | Paul Mackerras <paulus@samba.org> | 2014-06-30 06:51:11 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-08-05 08:26:20 -0400 |
commit | 9957c86d659a4d5a2bed25ccbd3bfc9c3f25e658 (patch) | |
tree | 27bd3fc644da983d63e34bb1ed54c8dcdab5fe0d /virt/kvm/eventfd.c | |
parent | 8ba918d488caded2c4368b0b922eb905fe3bb101 (diff) |
KVM: Move all accesses to kvm::irq_routing into irqchip.c
Now that struct _irqfd does not keep a reference to storage pointed
to by the irq_routing field of struct kvm, we can move the statement
that updates it out from under the irqfds.lock and put it in
kvm_set_irq_routing() instead. That means we then have to take a
srcu_read_lock on kvm->irq_srcu around the irqfd_update call in
kvm_irqfd_assign(), since holding the kvm->irqfds.lock no longer
ensures that that the routing can't change.
Combined with changing kvm_irq_map_gsi() and kvm_irq_map_chip_pin()
to take a struct kvm * argument instead of the pointer to the routing
table, this allows us to to move all references to kvm->irq_routing
into irqchip.c. That in turn allows us to move the definition of the
kvm_irq_routing_table struct into irqchip.c as well.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Tested-by: Eric Auger <eric.auger@linaro.org>
Tested-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'virt/kvm/eventfd.c')
-rw-r--r-- | virt/kvm/eventfd.c | 22 |
1 files changed, 9 insertions, 13 deletions
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c index 15fa9488b2d0..f0075ffb0c35 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c | |||
@@ -278,14 +278,13 @@ irqfd_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh, | |||
278 | } | 278 | } |
279 | 279 | ||
280 | /* Must be called under irqfds.lock */ | 280 | /* Must be called under irqfds.lock */ |
281 | static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd, | 281 | static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd) |
282 | struct kvm_irq_routing_table *irq_rt) | ||
283 | { | 282 | { |
284 | struct kvm_kernel_irq_routing_entry *e; | 283 | struct kvm_kernel_irq_routing_entry *e; |
285 | struct kvm_kernel_irq_routing_entry entries[KVM_NR_IRQCHIPS]; | 284 | struct kvm_kernel_irq_routing_entry entries[KVM_NR_IRQCHIPS]; |
286 | int i, n_entries; | 285 | int i, n_entries; |
287 | 286 | ||
288 | n_entries = kvm_irq_map_gsi(entries, irq_rt, irqfd->gsi); | 287 | n_entries = kvm_irq_map_gsi(kvm, entries, irqfd->gsi); |
289 | 288 | ||
290 | write_seqcount_begin(&irqfd->irq_entry_sc); | 289 | write_seqcount_begin(&irqfd->irq_entry_sc); |
291 | 290 | ||
@@ -304,12 +303,12 @@ static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd, | |||
304 | static int | 303 | static int |
305 | kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) | 304 | kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) |
306 | { | 305 | { |
307 | struct kvm_irq_routing_table *irq_rt; | ||
308 | struct _irqfd *irqfd, *tmp; | 306 | struct _irqfd *irqfd, *tmp; |
309 | struct fd f; | 307 | struct fd f; |
310 | struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL; | 308 | struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL; |
311 | int ret; | 309 | int ret; |
312 | unsigned int events; | 310 | unsigned int events; |
311 | int idx; | ||
313 | 312 | ||
314 | irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL); | 313 | irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL); |
315 | if (!irqfd) | 314 | if (!irqfd) |
@@ -403,9 +402,9 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) | |||
403 | goto fail; | 402 | goto fail; |
404 | } | 403 | } |
405 | 404 | ||
406 | irq_rt = rcu_dereference_protected(kvm->irq_routing, | 405 | idx = srcu_read_lock(&kvm->irq_srcu); |
407 | lockdep_is_held(&kvm->irqfds.lock)); | 406 | irqfd_update(kvm, irqfd); |
408 | irqfd_update(kvm, irqfd, irq_rt); | 407 | srcu_read_unlock(&kvm->irq_srcu, idx); |
409 | 408 | ||
410 | list_add_tail(&irqfd->list, &kvm->irqfds.items); | 409 | list_add_tail(&irqfd->list, &kvm->irqfds.items); |
411 | 410 | ||
@@ -539,20 +538,17 @@ kvm_irqfd_release(struct kvm *kvm) | |||
539 | } | 538 | } |
540 | 539 | ||
541 | /* | 540 | /* |
542 | * Change irq_routing and irqfd. | 541 | * Take note of a change in irq routing. |
543 | * Caller must invoke synchronize_srcu(&kvm->irq_srcu) afterwards. | 542 | * Caller must invoke synchronize_srcu(&kvm->irq_srcu) afterwards. |
544 | */ | 543 | */ |
545 | void kvm_irq_routing_update(struct kvm *kvm, | 544 | void kvm_irq_routing_update(struct kvm *kvm) |
546 | struct kvm_irq_routing_table *irq_rt) | ||
547 | { | 545 | { |
548 | struct _irqfd *irqfd; | 546 | struct _irqfd *irqfd; |
549 | 547 | ||
550 | spin_lock_irq(&kvm->irqfds.lock); | 548 | spin_lock_irq(&kvm->irqfds.lock); |
551 | 549 | ||
552 | rcu_assign_pointer(kvm->irq_routing, irq_rt); | ||
553 | |||
554 | list_for_each_entry(irqfd, &kvm->irqfds.items, list) | 550 | list_for_each_entry(irqfd, &kvm->irqfds.items, list) |
555 | irqfd_update(kvm, irqfd, irq_rt); | 551 | irqfd_update(kvm, irqfd); |
556 | 552 | ||
557 | spin_unlock_irq(&kvm->irqfds.lock); | 553 | spin_unlock_irq(&kvm->irqfds.lock); |
558 | } | 554 | } |