Skip to content

Commit 4d8b7ed

Browse files
committed
peer: allocate in kmem_cache
With deployments having upwards of 600k peers now, this somewhat heavy structure could benefit from more fine-grained allocations. Specifically, instead of using a 2048-byte slab for a 1544-byte object, we can now use 1544-byte objects directly, thus saving almost 25% per-peer, or with 600k peers, that's a savings of 303 MiB. This also makes wireguard's memory usage more transparent in tools like slabtop and /proc/slabinfo. Suggested-by: Arnd Bergmann <arnd@arndb.de> Suggested-by: Matthew Wilcox <willy@infradead.org> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
1 parent 6fbc0e6 commit 4d8b7ed

File tree

3 files changed

+27
-4
lines changed

3 files changed

+27
-4
lines changed

src/main.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ static int __init mod_init(void)
3333
#endif
3434
wg_noise_init();
3535

36+
ret = wg_peer_init();
37+
if (ret < 0)
38+
goto err_peer;
39+
3640
ret = wg_device_init();
3741
if (ret < 0)
3842
goto err_device;
@@ -49,13 +53,16 @@ static int __init mod_init(void)
4953
err_netlink:
5054
wg_device_uninit();
5155
err_device:
56+
wg_peer_uninit();
57+
err_peer:
5258
return ret;
5359
}
5460

5561
static void __exit mod_exit(void)
5662
{
5763
wg_genetlink_uninit();
5864
wg_device_uninit();
65+
wg_peer_uninit();
5966
}
6067

6168
module_init(mod_init);

src/peer.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/rcupdate.h>
1616
#include <linux/list.h>
1717

18+
static struct kmem_cache *peer_cache;
1819
static atomic64_t peer_counter = ATOMIC64_INIT(0);
1920

2021
struct wg_peer *wg_peer_create(struct wg_device *wg,
@@ -29,10 +30,10 @@ struct wg_peer *wg_peer_create(struct wg_device *wg,
2930
if (wg->num_peers >= MAX_PEERS_PER_DEVICE)
3031
return ERR_PTR(ret);
3132

32-
peer = kzalloc(sizeof(*peer), GFP_KERNEL);
33+
peer = kmem_cache_zalloc(peer_cache, GFP_KERNEL);
3334
if (unlikely(!peer))
3435
return ERR_PTR(ret);
35-
if (dst_cache_init(&peer->endpoint_cache, GFP_KERNEL))
36+
if (unlikely(dst_cache_init(&peer->endpoint_cache, GFP_KERNEL)))
3637
goto err;
3738

3839
peer->device = wg;
@@ -64,7 +65,7 @@ struct wg_peer *wg_peer_create(struct wg_device *wg,
6465
return peer;
6566

6667
err:
67-
kfree(peer);
68+
kmem_cache_free(peer_cache, peer);
6869
return ERR_PTR(ret);
6970
}
7071

@@ -193,7 +194,8 @@ static void rcu_release(struct rcu_head *rcu)
193194
/* The final zeroing takes care of clearing any remaining handshake key
194195
* material and other potentially sensitive information.
195196
*/
196-
kfree_sensitive(peer);
197+
memzero_explicit(peer, sizeof(*peer));
198+
kmem_cache_free(peer_cache, peer);
197199
}
198200

199201
static void kref_release(struct kref *refcount)
@@ -225,3 +227,14 @@ void wg_peer_put(struct wg_peer *peer)
225227
return;
226228
kref_put(&peer->refcount, kref_release);
227229
}
230+
231+
int __init wg_peer_init(void)
232+
{
233+
peer_cache = KMEM_CACHE(wg_peer, 0);
234+
return peer_cache ? 0 : -ENOMEM;
235+
}
236+
237+
void wg_peer_uninit(void)
238+
{
239+
kmem_cache_destroy(peer_cache);
240+
}

src/peer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,7 @@ void wg_peer_put(struct wg_peer *peer);
8080
void wg_peer_remove(struct wg_peer *peer);
8181
void wg_peer_remove_all(struct wg_device *wg);
8282

83+
int wg_peer_init(void);
84+
void wg_peer_uninit(void);
85+
8386
#endif /* _WG_PEER_H */

0 commit comments

Comments
 (0)