aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vhost/net.c
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2013-01-23 15:46:47 -0500
committerMichael S. Tsirkin <mst@redhat.com>2014-06-09 09:21:05 -0400
commit23cc5a991c7a9fb7e6d6550e65cee4f4173111c5 (patch)
treef064aee3320d1491255bc68d8ae3989e00499e0b /drivers/vhost/net.c
parent1860e379875dfe7271c649058aeddffe5afd9d0d (diff)
vhost-net: extend device allocation to vmalloc
Michael Mueller provided a patch to reduce the size of vhost-net structure as some allocations could fail under memory pressure/fragmentation. We are still left with high order allocations though. This patch is handling the problem at the core level, allowing vhost structures to use vmalloc() if kmalloc() failed. As vmalloc() adds overhead on a critical network path, add __GFP_REPEAT to kzalloc() flags to do this fallback only when really needed. People are still looking at cleaner ways to handle the problem at the API level, probably passing in multiple iovecs. This hack seems consistent with approaches taken since then by drivers/vhost/scsi.c and net/core/dev.c Based on patch by Romain Francoise. Cc: Michael Mueller <mimu@linux.vnet.ibm.com> Signed-off-by: Romain Francoise <romain@orebokech.com> Acked-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'drivers/vhost/net.c')
-rw-r--r--drivers/vhost/net.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index be414d2b2b22..e489161d0feb 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -17,6 +17,7 @@
17#include <linux/workqueue.h> 17#include <linux/workqueue.h>
18#include <linux/file.h> 18#include <linux/file.h>
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/vmalloc.h>
20 21
21#include <linux/net.h> 22#include <linux/net.h>
22#include <linux/if_packet.h> 23#include <linux/if_packet.h>
@@ -699,18 +700,30 @@ static void handle_rx_net(struct vhost_work *work)
699 handle_rx(net); 700 handle_rx(net);
700} 701}
701 702
703static void vhost_net_free(void *addr)
704{
705 if (is_vmalloc_addr(addr))
706 vfree(addr);
707 else
708 kfree(addr);
709}
710
702static int vhost_net_open(struct inode *inode, struct file *f) 711static int vhost_net_open(struct inode *inode, struct file *f)
703{ 712{
704 struct vhost_net *n = kmalloc(sizeof *n, GFP_KERNEL); 713 struct vhost_net *n;
705 struct vhost_dev *dev; 714 struct vhost_dev *dev;
706 struct vhost_virtqueue **vqs; 715 struct vhost_virtqueue **vqs;
707 int i; 716 int i;
708 717
709 if (!n) 718 n = kmalloc(sizeof *n, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
710 return -ENOMEM; 719 if (!n) {
720 n = vmalloc(sizeof *n);
721 if (!n)
722 return -ENOMEM;
723 }
711 vqs = kmalloc(VHOST_NET_VQ_MAX * sizeof(*vqs), GFP_KERNEL); 724 vqs = kmalloc(VHOST_NET_VQ_MAX * sizeof(*vqs), GFP_KERNEL);
712 if (!vqs) { 725 if (!vqs) {
713 kfree(n); 726 vhost_net_free(n);
714 return -ENOMEM; 727 return -ENOMEM;
715 } 728 }
716 729
@@ -827,7 +840,7 @@ static int vhost_net_release(struct inode *inode, struct file *f)
827 * since jobs can re-queue themselves. */ 840 * since jobs can re-queue themselves. */
828 vhost_net_flush(n); 841 vhost_net_flush(n);
829 kfree(n->dev.vqs); 842 kfree(n->dev.vqs);
830 kfree(n); 843 vhost_net_free(n);
831 return 0; 844 return 0;
832} 845}
833 846