Skip to content

Commit d89a274

Browse files
committed
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>
1 parent 96b2e73 commit d89a274

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

drivers/vhost/net.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/workqueue.h>
1818
#include <linux/file.h>
1919
#include <linux/slab.h>
20+
#include <linux/vmalloc.h>
2021

2122
#include <linux/net.h>
2223
#include <linux/if_packet.h>
@@ -699,18 +700,30 @@ static void handle_rx_net(struct vhost_work *work)
699700
handle_rx(net);
700701
}
701702

703+
static void vhost_net_free(void *addr)
704+
{
705+
if (is_vmalloc_addr(addr))
706+
vfree(addr);
707+
else
708+
kfree(addr);
709+
}
710+
702711
static int vhost_net_open(struct inode *inode, struct file *f)
703712
{
704-
struct vhost_net *n = kmalloc(sizeof *n, GFP_KERNEL);
713+
struct vhost_net *n;
705714
struct vhost_dev *dev;
706715
struct vhost_virtqueue **vqs;
707716
int i;
708717

709-
if (!n)
710-
return -ENOMEM;
718+
n = kmalloc(sizeof *n, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
719+
if (!n) {
720+
n = vmalloc(sizeof *n);
721+
if (!n)
722+
return -ENOMEM;
723+
}
711724
vqs = kmalloc(VHOST_NET_VQ_MAX * sizeof(*vqs), GFP_KERNEL);
712725
if (!vqs) {
713-
kfree(n);
726+
vhost_net_free(n);
714727
return -ENOMEM;
715728
}
716729

@@ -827,7 +840,7 @@ static int vhost_net_release(struct inode *inode, struct file *f)
827840
* since jobs can re-queue themselves. */
828841
vhost_net_flush(n);
829842
kfree(n->dev.vqs);
830-
kfree(n);
843+
vhost_net_free(n);
831844
return 0;
832845
}
833846

0 commit comments

Comments
 (0)