[Devel] [PATCH RHEL7 COMMIT] ms/vhost/net: extend device allocation to vmalloc

Konstantin Khorenko khorenko at virtuozzo.com
Sun Dec 13 22:05:08 PST 2015


The commit is pushed to "branch-rh7-3.10.0-229.7.2.vz7.9.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-229.7.2.vz7.9.16
------>
commit d3b33e3d7ee9916faa27f26e0bf1f66591d95397
Author: Michael S. Tsirkin <mst at redhat.com>
Date:   Mon Dec 14 10:05:08 2015 +0400

    ms/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 at linux.vnet.ibm.com>
    Signed-off-by: Romain Francoise <romain at orebokech.com>
    Acked-by: Michael S. Tsirkin <mst at redhat.com>
    
    https://jira.sw.ru/browse/PSBM-42199
    
    Signed-off-by: "Denis V. Lunev" <den at openvz.org>
---
 drivers/vhost/net.c | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index fc67228..3f4653e 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -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_work *work)
 	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 *inode, struct file *f)
 	}
 	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 inode *inode, struct file *f)
 	 * since jobs can re-queue themselves. */
 	vhost_net_flush(n);
 	kfree(n->dev.vqs);
-	kfree(n);
+	vhost_net_free(n);
 	return 0;
 }
 


More information about the Devel mailing list