Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[linux-2.6-microblaze.git] / virt / kvm / kvm_main.c
index 69c318f..70e05af 100644 (file)
@@ -117,6 +117,8 @@ EXPORT_SYMBOL_GPL(kvm_debugfs_dir);
 
 static const struct file_operations stat_fops_per_vm;
 
+static struct file_operations kvm_chardev_ops;
+
 static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
                           unsigned long arg);
 #ifdef CONFIG_KVM_COMPAT
@@ -251,7 +253,8 @@ static void kvm_make_vcpu_request(struct kvm_vcpu *vcpu, unsigned int req,
 {
        int cpu;
 
-       kvm_make_request(req, vcpu);
+       if (likely(!(req & KVM_REQUEST_NO_ACTION)))
+               __kvm_make_request(req, vcpu);
 
        if (!(req & KVM_REQUEST_NO_WAKEUP) && kvm_vcpu_wake_up(vcpu))
                return;
@@ -1131,6 +1134,16 @@ static struct kvm *kvm_create_vm(unsigned long type)
        preempt_notifier_inc();
        kvm_init_pm_notifier(kvm);
 
+       /*
+        * When the fd passed to this ioctl() is opened it pins the module,
+        * but try_module_get() also prevents getting a reference if the module
+        * is in MODULE_STATE_GOING (e.g. if someone ran "rmmod --wait").
+        */
+       if (!try_module_get(kvm_chardev_ops.owner)) {
+               r = -ENODEV;
+               goto out_err;
+       }
+
        return kvm;
 
 out_err:
@@ -1220,6 +1233,7 @@ static void kvm_destroy_vm(struct kvm *kvm)
        preempt_notifier_dec();
        hardware_disable_all();
        mmdrop(mm);
+       module_put(kvm_chardev_ops.owner);
 }
 
 void kvm_get_kvm(struct kvm *kvm)
@@ -3663,7 +3677,7 @@ static int kvm_vcpu_release(struct inode *inode, struct file *filp)
        return 0;
 }
 
-static struct file_operations kvm_vcpu_fops = {
+static const struct file_operations kvm_vcpu_fops = {
        .release        = kvm_vcpu_release,
        .unlocked_ioctl = kvm_vcpu_ioctl,
        .mmap           = kvm_vcpu_mmap,
@@ -4714,7 +4728,7 @@ static long kvm_vm_compat_ioctl(struct file *filp,
 }
 #endif
 
-static struct file_operations kvm_vm_fops = {
+static const struct file_operations kvm_vm_fops = {
        .release        = kvm_vm_release,
        .unlocked_ioctl = kvm_vm_ioctl,
        .llseek         = noop_llseek,
@@ -5721,8 +5735,6 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
                goto out_free_5;
 
        kvm_chardev_ops.owner = module;
-       kvm_vm_fops.owner = module;
-       kvm_vcpu_fops.owner = module;
 
        r = misc_register(&kvm_dev);
        if (r) {