diff options
author | Sultan Alsawaf <sultan@kerneltoast.com> | 2019-02-02 14:13:03 -0800 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-02-03 18:27:33 +0100 |
commit | 75f476905a1bcd013c8bee07282fd7fb1dca738e (patch) | |
tree | 987fcd2a85f2afe63f0da292826646192bfb8eec /src/device.c | |
parent | d063dfb80911854ed273f6374b02f339a86462ba (diff) |
hashtables: decouple hashtable allocations from the main device allocation
The hashtable allocations are quite large, and cause the device allocation in
the net framework to stall sometimes while it tries to find a contiguous region
that can fit the device struct:
[<0000000000000000>] __switch_to+0x94/0xb8
[<0000000000000000>] __alloc_pages_nodemask+0x764/0x7e8
[<0000000000000000>] kmalloc_order+0x20/0x40
[<0000000000000000>] __kmalloc+0x144/0x1a0
[<0000000000000000>] alloc_netdev_mqs+0x5c/0x368
[<0000000000000000>] rtnl_create_link+0x48/0x180
[<0000000000000000>] rtnl_newlink+0x410/0x708
[<0000000000000000>] rtnetlink_rcv_msg+0x190/0x1f8
[<0000000000000000>] netlink_rcv_skb+0x4c/0xf8
[<0000000000000000>] rtnetlink_rcv+0x30/0x40
[<0000000000000000>] netlink_unicast+0x18c/0x208
[<0000000000000000>] netlink_sendmsg+0x19c/0x348
[<0000000000000000>] sock_sendmsg+0x3c/0x58
[<0000000000000000>] ___sys_sendmsg+0x290/0x2b0
[<0000000000000000>] __sys_sendmsg+0x58/0xa0
[<0000000000000000>] SyS_sendmsg+0x10/0x20
[<0000000000000000>] el0_svc_naked+0x34/0x38
[<0000000000000000>] 0xffffffffffffffff
To fix the allocation stalls, decouple the hashtable allocations from the device
allocation and allocate the hashtables with kvmalloc's implicit __GFP_NORETRY
so that the allocations fall back to vmalloc with little resistance.
Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'src/device.c')
-rw-r--r-- | src/device.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/src/device.c b/src/device.c index 4b4cca1..15911b2 100644 --- a/src/device.c +++ b/src/device.c @@ -253,6 +253,8 @@ static void wg_destruct(struct net_device *dev) free_percpu(wg->incoming_handshakes_worker); if (wg->have_creating_net_ref) put_net(wg->creating_net); + kvfree(wg->index_hashtable); + kvfree(wg->peer_hashtable); mutex_unlock(&wg->device_update_lock); pr_debug("%s: Interface deleted\n", dev->name); @@ -309,16 +311,22 @@ static int wg_newlink(struct net *src_net, struct net_device *dev, mutex_init(&wg->socket_update_lock); mutex_init(&wg->device_update_lock); skb_queue_head_init(&wg->incoming_handshakes); - wg_pubkey_hashtable_init(&wg->peer_hashtable); - wg_index_hashtable_init(&wg->index_hashtable); wg_allowedips_init(&wg->peer_allowedips); wg_cookie_checker_init(&wg->cookie_checker, wg); INIT_LIST_HEAD(&wg->peer_list); wg->device_update_gen = 1; + wg->peer_hashtable = wg_pubkey_hashtable_alloc(); + if (!wg->peer_hashtable) + return ret; + + wg->index_hashtable = wg_index_hashtable_alloc(); + if (!wg->index_hashtable) + goto err_free_peer_hashtable; + dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); if (!dev->tstats) - return ret; + goto err_free_index_hashtable; wg->incoming_handshakes_worker = wg_packet_percpu_multicore_worker_alloc( @@ -385,6 +393,10 @@ err_free_incoming_handshakes: free_percpu(wg->incoming_handshakes_worker); err_free_tstats: free_percpu(dev->tstats); +err_free_index_hashtable: + kvfree(wg->index_hashtable); +err_free_peer_hashtable: + kvfree(wg->peer_hashtable); return ret; } |