diff options
author | Scott Wood <scottwood@freescale.com> | 2013-04-25 10:11:23 -0400 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2013-04-26 14:27:28 -0400 |
commit | 07f0a7bdec5c4039cfb9b836482c45004d4c21cc (patch) | |
tree | ea47de6fc439dd8d20d6d1d0c4f9cd21f95c2fcb /virt | |
parent | 22e64024fb83065664160d1c28a10aa98cb5f24c (diff) |
kvm: destroy emulated devices on VM exit
The hassle of getting refcounting right was greater than the hassle
of keeping a list of devices to destroy on VM exit.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/kvm_main.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index f6cd14d2f0d9..5da9f02a2a67 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -504,6 +504,7 @@ static struct kvm *kvm_create_vm(unsigned long type) | |||
504 | mutex_init(&kvm->irq_lock); | 504 | mutex_init(&kvm->irq_lock); |
505 | mutex_init(&kvm->slots_lock); | 505 | mutex_init(&kvm->slots_lock); |
506 | atomic_set(&kvm->users_count, 1); | 506 | atomic_set(&kvm->users_count, 1); |
507 | INIT_LIST_HEAD(&kvm->devices); | ||
507 | 508 | ||
508 | r = kvm_init_mmu_notifier(kvm); | 509 | r = kvm_init_mmu_notifier(kvm); |
509 | if (r) | 510 | if (r) |
@@ -581,6 +582,19 @@ void kvm_free_physmem(struct kvm *kvm) | |||
581 | kfree(kvm->memslots); | 582 | kfree(kvm->memslots); |
582 | } | 583 | } |
583 | 584 | ||
585 | static void kvm_destroy_devices(struct kvm *kvm) | ||
586 | { | ||
587 | struct list_head *node, *tmp; | ||
588 | |||
589 | list_for_each_safe(node, tmp, &kvm->devices) { | ||
590 | struct kvm_device *dev = | ||
591 | list_entry(node, struct kvm_device, vm_node); | ||
592 | |||
593 | list_del(node); | ||
594 | dev->ops->destroy(dev); | ||
595 | } | ||
596 | } | ||
597 | |||
584 | static void kvm_destroy_vm(struct kvm *kvm) | 598 | static void kvm_destroy_vm(struct kvm *kvm) |
585 | { | 599 | { |
586 | int i; | 600 | int i; |
@@ -600,6 +614,7 @@ static void kvm_destroy_vm(struct kvm *kvm) | |||
600 | kvm_arch_flush_shadow_all(kvm); | 614 | kvm_arch_flush_shadow_all(kvm); |
601 | #endif | 615 | #endif |
602 | kvm_arch_destroy_vm(kvm); | 616 | kvm_arch_destroy_vm(kvm); |
617 | kvm_destroy_devices(kvm); | ||
603 | kvm_free_physmem(kvm); | 618 | kvm_free_physmem(kvm); |
604 | cleanup_srcu_struct(&kvm->srcu); | 619 | cleanup_srcu_struct(&kvm->srcu); |
605 | kvm_arch_free_vm(kvm); | 620 | kvm_arch_free_vm(kvm); |
@@ -2195,23 +2210,11 @@ static long kvm_device_ioctl(struct file *filp, unsigned int ioctl, | |||
2195 | } | 2210 | } |
2196 | } | 2211 | } |
2197 | 2212 | ||
2198 | void kvm_device_get(struct kvm_device *dev) | ||
2199 | { | ||
2200 | atomic_inc(&dev->users); | ||
2201 | } | ||
2202 | |||
2203 | void kvm_device_put(struct kvm_device *dev) | ||
2204 | { | ||
2205 | if (atomic_dec_and_test(&dev->users)) | ||
2206 | dev->ops->destroy(dev); | ||
2207 | } | ||
2208 | |||
2209 | static int kvm_device_release(struct inode *inode, struct file *filp) | 2213 | static int kvm_device_release(struct inode *inode, struct file *filp) |
2210 | { | 2214 | { |
2211 | struct kvm_device *dev = filp->private_data; | 2215 | struct kvm_device *dev = filp->private_data; |
2212 | struct kvm *kvm = dev->kvm; | 2216 | struct kvm *kvm = dev->kvm; |
2213 | 2217 | ||
2214 | kvm_device_put(dev); | ||
2215 | kvm_put_kvm(kvm); | 2218 | kvm_put_kvm(kvm); |
2216 | return 0; | 2219 | return 0; |
2217 | } | 2220 | } |
@@ -2257,7 +2260,6 @@ static int kvm_ioctl_create_device(struct kvm *kvm, | |||
2257 | 2260 | ||
2258 | dev->ops = ops; | 2261 | dev->ops = ops; |
2259 | dev->kvm = kvm; | 2262 | dev->kvm = kvm; |
2260 | atomic_set(&dev->users, 1); | ||
2261 | 2263 | ||
2262 | ret = ops->create(dev, cd->type); | 2264 | ret = ops->create(dev, cd->type); |
2263 | if (ret < 0) { | 2265 | if (ret < 0) { |
@@ -2271,6 +2273,7 @@ static int kvm_ioctl_create_device(struct kvm *kvm, | |||
2271 | return ret; | 2273 | return ret; |
2272 | } | 2274 | } |
2273 | 2275 | ||
2276 | list_add(&dev->vm_node, &kvm->devices); | ||
2274 | kvm_get_kvm(kvm); | 2277 | kvm_get_kvm(kvm); |
2275 | cd->fd = ret; | 2278 | cd->fd = ret; |
2276 | return 0; | 2279 | return 0; |