]> git.proxmox.com Git - pve-kernel-3.10.0.git/blobdiff - vhost-net-extend-device-allocation-to-vmalloc.patch
vhost-net: extend device allocation to vmallo
[pve-kernel-3.10.0.git] / vhost-net-extend-device-allocation-to-vmalloc.patch
diff --git a/vhost-net-extend-device-allocation-to-vmalloc.patch b/vhost-net-extend-device-allocation-to-vmalloc.patch
new file mode 100644 (file)
index 0000000..9cb5433
--- /dev/null
@@ -0,0 +1,76 @@
+vhost-net: extend device allocation to vmalloc
+
+Backport upstream commit 23cc5a991c7a9fb7e6d6550e65cee4f4173111c5 to 
+3.10 kernel.
+In upstream, this code is modified later in patch 
+d04257b07f2362d4eb550952d5bf5f4241a8046d, but it's unapplicable in 3.10 
+because there's still no open-coded kvfree() function (appeared in 
+v3.15-rc5).
+
+Should fix bug reported in forum 
+http://forum.proxmox.com/threads/19194-VM-start-problem-with-virtio-net
+
+diff -r -U 3 -p a/drivers/vhost/net.c b/drivers/vhost/net.c
+--- a/drivers/vhost/net.c      2014-07-16 22:25:31.000000000 +0400
++++ b/drivers/vhost/net.c      2014-09-04 13:56:20.101952635 +0400
+@@ -18,6 +18,7 @@
+ #include <linux/rcupdate.h>
+ #include <linux/file.h>
+ #include <linux/slab.h>
++#include <linux/vmalloc.h>
+ #include <linux/net.h>
+ #include <linux/if_packet.h>
+@@ -706,18 +707,30 @@ static void handle_rx_net(struct vhost_w
+       handle_rx(net);
+ }
++static void vhost_net_free(void *addr)
++{
++   if (is_vmalloc_addr(addr))
++       vfree(addr);
++   else
++       kfree(addr);
++}
++
+ static int vhost_net_open(struct inode *inode, struct file *f)
+ {
+-      struct vhost_net *n = kmalloc(sizeof *n, GFP_KERNEL);
++      struct vhost_net *n;
+       struct vhost_dev *dev;
+       struct vhost_virtqueue **vqs;
+       int r, i;
+-      if (!n)
+-              return -ENOMEM;
++    n = kmalloc(sizeof *n, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
++    if (!n) {
++        n = vmalloc(sizeof *n);
++        if (!n)
++            return -ENOMEM;
++   }
+       vqs = kmalloc(VHOST_NET_VQ_MAX * sizeof(*vqs), GFP_KERNEL);
+       if (!vqs) {
+-              kfree(n);
++              vhost_net_free(n);
+               return -ENOMEM;
+       }
+@@ -736,7 +749,7 @@ static int vhost_net_open(struct inode *
+       }
+       r = vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX);
+       if (r < 0) {
+-              kfree(n);
++              vhost_net_free(n);
+               kfree(vqs);
+               return r;
+       }
+@@ -841,7 +854,7 @@ static int vhost_net_release(struct inod
+        * since jobs can re-queue themselves. */
+       vhost_net_flush(n);
+       kfree(n->dev.vqs);
+-      kfree(n);
++      vhost_net_free(n);
+       return 0;
+ }