mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 21:51:40 +00:00
9f78bf330a
When we try to start AF_XDP on some machines with long running time, due to the machine's memory fragmentation problem, there is no sufficient contiguous physical memory that will cause the start failure. If the size of the queue is 8 * 1024, then the size of the desc[] is 8 * 1024 * 8 = 16 * PAGE, but we also add struct xdp_ring size, so it is 16page+. This is necessary to apply for a 4-order memory. If there are a lot of queues, it is difficult to these machine with long running time. Here, that we actually waste 15 pages. 4-Order memory is 32 pages, but we only use 17 pages. This patch replaces __get_free_pages() by vmalloc() to allocate memory to solve these problems. Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> Acked-by: Magnus Karlsson <magnus.karlsson@intel.com> Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
57 lines
1.0 KiB
C
57 lines
1.0 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* XDP user-space ring structure
|
|
* Copyright(c) 2018 Intel Corporation.
|
|
*/
|
|
|
|
#include <linux/log2.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/overflow.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <net/xdp_sock_drv.h>
|
|
|
|
#include "xsk_queue.h"
|
|
|
|
static size_t xskq_get_ring_size(struct xsk_queue *q, bool umem_queue)
|
|
{
|
|
struct xdp_umem_ring *umem_ring;
|
|
struct xdp_rxtx_ring *rxtx_ring;
|
|
|
|
if (umem_queue)
|
|
return struct_size(umem_ring, desc, q->nentries);
|
|
return struct_size(rxtx_ring, desc, q->nentries);
|
|
}
|
|
|
|
struct xsk_queue *xskq_create(u32 nentries, bool umem_queue)
|
|
{
|
|
struct xsk_queue *q;
|
|
size_t size;
|
|
|
|
q = kzalloc(sizeof(*q), GFP_KERNEL);
|
|
if (!q)
|
|
return NULL;
|
|
|
|
q->nentries = nentries;
|
|
q->ring_mask = nentries - 1;
|
|
|
|
size = xskq_get_ring_size(q, umem_queue);
|
|
size = PAGE_ALIGN(size);
|
|
|
|
q->ring = vmalloc_user(size);
|
|
if (!q->ring) {
|
|
kfree(q);
|
|
return NULL;
|
|
}
|
|
|
|
q->ring_vmalloc_size = size;
|
|
return q;
|
|
}
|
|
|
|
void xskq_destroy(struct xsk_queue *q)
|
|
{
|
|
if (!q)
|
|
return;
|
|
|
|
vfree(q->ring);
|
|
kfree(q);
|
|
}
|