aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2013-04-25 10:11:23 -0400
committerAlexander Graf <agraf@suse.de>2013-04-26 14:27:28 -0400
commit07f0a7bdec5c4039cfb9b836482c45004d4c21cc (patch)
treeea47de6fc439dd8d20d6d1d0c4f9cd21f95c2fcb /virt
parent22e64024fb83065664160d1c28a10aa98cb5f24c (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.c29
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
585static 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
584static void kvm_destroy_vm(struct kvm *kvm) 598static 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
2198void kvm_device_get(struct kvm_device *dev)
2199{
2200 atomic_inc(&dev->users);
2201}
2202
2203void kvm_device_put(struct kvm_device *dev)
2204{
2205 if (atomic_dec_and_test(&dev->users))
2206 dev->ops->destroy(dev);
2207}
2208
2209static int kvm_device_release(struct inode *inode, struct file *filp) 2213static 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;