Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[cascardo/linux.git] / drivers / virtio / virtio_balloon.c
index f6ea8f4..4e7003d 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/oom.h>
 #include <linux/wait.h>
 #include <linux/mm.h>
+#include <linux/mount.h>
 
 /*
  * Balloon device works in 4K page units.  So each page is pointed to by
@@ -45,6 +46,10 @@ static int oom_pages = OOM_VBALLOON_DEFAULT_PAGES;
 module_param(oom_pages, int, S_IRUSR | S_IWUSR);
 MODULE_PARM_DESC(oom_pages, "pages to free on OOM");
 
+#ifdef CONFIG_BALLOON_COMPACTION
+static struct vfsmount *balloon_mnt;
+#endif
+
 struct virtio_balloon {
        struct virtio_device *vdev;
        struct virtqueue *inflate_vq, *deflate_vq, *stats_vq;
@@ -492,6 +497,24 @@ static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info,
 
        return MIGRATEPAGE_SUCCESS;
 }
+
+static struct dentry *balloon_mount(struct file_system_type *fs_type,
+               int flags, const char *dev_name, void *data)
+{
+       static const struct dentry_operations ops = {
+               .d_dname = simple_dname,
+       };
+
+       return mount_pseudo(fs_type, "balloon-kvm:", NULL, &ops,
+                               BALLOON_KVM_MAGIC);
+}
+
+static struct file_system_type balloon_fs = {
+       .name           = "balloon-kvm",
+       .mount          = balloon_mount,
+       .kill_sb        = kill_anon_super,
+};
+
 #endif /* CONFIG_BALLOON_COMPACTION */
 
 static int virtballoon_probe(struct virtio_device *vdev)
@@ -521,9 +544,6 @@ static int virtballoon_probe(struct virtio_device *vdev)
        vb->vdev = vdev;
 
        balloon_devinfo_init(&vb->vb_dev_info);
-#ifdef CONFIG_BALLOON_COMPACTION
-       vb->vb_dev_info.migratepage = virtballoon_migratepage;
-#endif
 
        err = init_vqs(vb);
        if (err)
@@ -533,13 +553,33 @@ static int virtballoon_probe(struct virtio_device *vdev)
        vb->nb.priority = VIRTBALLOON_OOM_NOTIFY_PRIORITY;
        err = register_oom_notifier(&vb->nb);
        if (err < 0)
-               goto out_oom_notify;
+               goto out_del_vqs;
+
+#ifdef CONFIG_BALLOON_COMPACTION
+       balloon_mnt = kern_mount(&balloon_fs);
+       if (IS_ERR(balloon_mnt)) {
+               err = PTR_ERR(balloon_mnt);
+               unregister_oom_notifier(&vb->nb);
+               goto out_del_vqs;
+       }
+
+       vb->vb_dev_info.migratepage = virtballoon_migratepage;
+       vb->vb_dev_info.inode = alloc_anon_inode(balloon_mnt->mnt_sb);
+       if (IS_ERR(vb->vb_dev_info.inode)) {
+               err = PTR_ERR(vb->vb_dev_info.inode);
+               kern_unmount(balloon_mnt);
+               unregister_oom_notifier(&vb->nb);
+               vb->vb_dev_info.inode = NULL;
+               goto out_del_vqs;
+       }
+       vb->vb_dev_info.inode->i_mapping->a_ops = &balloon_aops;
+#endif
 
        virtio_device_ready(vdev);
 
        return 0;
 
-out_oom_notify:
+out_del_vqs:
        vdev->config->del_vqs(vdev);
 out_free_vb:
        kfree(vb);
@@ -573,6 +613,8 @@ static void virtballoon_remove(struct virtio_device *vdev)
        cancel_work_sync(&vb->update_balloon_stats_work);
 
        remove_common(vb);
+       if (vb->vb_dev_info.inode)
+               iput(vb->vb_dev_info.inode);
        kfree(vb);
 }