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/noise.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/noise.c')
-rw-r--r-- | src/noise.c | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/src/noise.c b/src/noise.c index 1a85723..e1d4519 100644 --- a/src/noise.c +++ b/src/noise.c @@ -93,13 +93,13 @@ static void handshake_zero(struct noise_handshake *handshake) void wg_noise_handshake_clear(struct noise_handshake *handshake) { wg_index_hashtable_remove( - &handshake->entry.peer->device->index_hashtable, + handshake->entry.peer->device->index_hashtable, &handshake->entry); down_write(&handshake->lock); handshake_zero(handshake); up_write(&handshake->lock); wg_index_hashtable_remove( - &handshake->entry.peer->device->index_hashtable, + handshake->entry.peer->device->index_hashtable, &handshake->entry); } @@ -130,7 +130,7 @@ static void keypair_free_kref(struct kref *kref) keypair->entry.peer->device->dev->name, keypair->internal_id, keypair->entry.peer->internal_id); - wg_index_hashtable_remove(&keypair->entry.peer->device->index_hashtable, + wg_index_hashtable_remove(keypair->entry.peer->device->index_hashtable, &keypair->entry); call_rcu_bh(&keypair->rcu, keypair_free_rcu); } @@ -141,7 +141,7 @@ void wg_noise_keypair_put(struct noise_keypair *keypair, bool unreference_now) return; if (unlikely(unreference_now)) wg_index_hashtable_remove( - &keypair->entry.peer->device->index_hashtable, + keypair->entry.peer->device->index_hashtable, &keypair->entry); kref_put(&keypair->refcount, keypair_free_kref); } @@ -520,7 +520,7 @@ wg_noise_handshake_create_initiation(struct message_handshake_initiation *dst, NOISE_TIMESTAMP_LEN, key, handshake->hash); dst->sender_index = wg_index_hashtable_insert( - &handshake->entry.peer->device->index_hashtable, + handshake->entry.peer->device->index_hashtable, &handshake->entry); handshake->state = HANDSHAKE_CREATED_INITIATION; @@ -566,7 +566,7 @@ wg_noise_handshake_consume_initiation(struct message_handshake_initiation *src, goto out; /* Lookup which peer we're actually talking to */ - peer = wg_pubkey_hashtable_lookup(&wg->peer_hashtable, s); + peer = wg_pubkey_hashtable_lookup(wg->peer_hashtable, s); if (!peer) goto out; handshake = &peer->handshake; @@ -660,7 +660,7 @@ bool wg_noise_handshake_create_response(struct message_handshake_response *dst, message_encrypt(dst->encrypted_nothing, NULL, 0, key, handshake->hash); dst->sender_index = wg_index_hashtable_insert( - &handshake->entry.peer->device->index_hashtable, + handshake->entry.peer->device->index_hashtable, &handshake->entry); handshake->state = HANDSHAKE_CREATED_RESPONSE; @@ -693,7 +693,7 @@ wg_noise_handshake_consume_response(struct message_handshake_response *src, goto out; handshake = (struct noise_handshake *)wg_index_hashtable_lookup( - &wg->index_hashtable, INDEX_HASHTABLE_HANDSHAKE, + wg->index_hashtable, INDEX_HASHTABLE_HANDSHAKE, src->receiver_index, &peer); if (unlikely(!handshake)) goto out; @@ -793,7 +793,7 @@ bool wg_noise_handshake_begin_session(struct noise_handshake *handshake, new_keypair->internal_id, handshake->entry.peer->internal_id); ret = wg_index_hashtable_replace( - &handshake->entry.peer->device->index_hashtable, + handshake->entry.peer->device->index_hashtable, &handshake->entry, &new_keypair->entry); } else { kzfree(new_keypair); |