aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/backport-5.4/080-wireguard-0131-wireguard-peer-allocate-in-kmem_cache.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/backport-5.4/080-wireguard-0131-wireguard-peer-allocate-in-kmem_cache.patch')
-rw-r--r--target/linux/generic/backport-5.4/080-wireguard-0131-wireguard-peer-allocate-in-kmem_cache.patch125
1 files changed, 125 insertions, 0 deletions
diff --git a/target/linux/generic/backport-5.4/080-wireguard-0131-wireguard-peer-allocate-in-kmem_cache.patch b/target/linux/generic/backport-5.4/080-wireguard-0131-wireguard-peer-allocate-in-kmem_cache.patch
new file mode 100644
index 0000000000..32ae327037
--- /dev/null
+++ b/target/linux/generic/backport-5.4/080-wireguard-0131-wireguard-peer-allocate-in-kmem_cache.patch
@@ -0,0 +1,125 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: "Jason A. Donenfeld" <Jason@zx2c4.com>
+Date: Fri, 4 Jun 2021 17:17:34 +0200
+Subject: [PATCH] wireguard: peer: allocate in kmem_cache
+
+commit a4e9f8e3287c9eb6bf70df982870980dd3341863 upstream.
+
+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.
+
+Fixes: 8b5553ace83c ("wireguard: queueing: get rid of per-peer ring buffers")
+Suggested-by: Arnd Bergmann <arnd@arndb.de>
+Suggested-by: Matthew Wilcox <willy@infradead.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+---
+ drivers/net/wireguard/main.c | 7 +++++++
+ drivers/net/wireguard/peer.c | 21 +++++++++++++++++----
+ drivers/net/wireguard/peer.h | 3 +++
+ 3 files changed, 27 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/wireguard/main.c
++++ b/drivers/net/wireguard/main.c
+@@ -28,6 +28,10 @@ static int __init mod_init(void)
+ #endif
+ wg_noise_init();
+
++ ret = wg_peer_init();
++ if (ret < 0)
++ goto err_peer;
++
+ ret = wg_device_init();
+ if (ret < 0)
+ goto err_device;
+@@ -44,6 +48,8 @@ static int __init mod_init(void)
+ err_netlink:
+ wg_device_uninit();
+ err_device:
++ wg_peer_uninit();
++err_peer:
+ return ret;
+ }
+
+@@ -51,6 +57,7 @@ static void __exit mod_exit(void)
+ {
+ wg_genetlink_uninit();
+ wg_device_uninit();
++ wg_peer_uninit();
+ }
+
+ module_init(mod_init);
+--- a/drivers/net/wireguard/peer.c
++++ b/drivers/net/wireguard/peer.c
+@@ -15,6 +15,7 @@
+ #include <linux/rcupdate.h>
+ #include <linux/list.h>
+
++static struct kmem_cache *peer_cache;
+ static atomic64_t peer_counter = ATOMIC64_INIT(0);
+
+ struct wg_peer *wg_peer_create(struct wg_device *wg,
+@@ -29,10 +30,10 @@ struct wg_peer *wg_peer_create(struct wg
+ if (wg->num_peers >= MAX_PEERS_PER_DEVICE)
+ return ERR_PTR(ret);
+
+- peer = kzalloc(sizeof(*peer), GFP_KERNEL);
++ peer = kmem_cache_zalloc(peer_cache, GFP_KERNEL);
+ if (unlikely(!peer))
+ return ERR_PTR(ret);
+- if (dst_cache_init(&peer->endpoint_cache, GFP_KERNEL))
++ if (unlikely(dst_cache_init(&peer->endpoint_cache, GFP_KERNEL)))
+ goto err;
+
+ peer->device = wg;
+@@ -64,7 +65,7 @@ struct wg_peer *wg_peer_create(struct wg
+ return peer;
+
+ err:
+- kfree(peer);
++ kmem_cache_free(peer_cache, peer);
+ return ERR_PTR(ret);
+ }
+
+@@ -193,7 +194,8 @@ static void rcu_release(struct rcu_head
+ /* The final zeroing takes care of clearing any remaining handshake key
+ * material and other potentially sensitive information.
+ */
+- kzfree(peer);
++ memzero_explicit(peer, sizeof(*peer));
++ kmem_cache_free(peer_cache, peer);
+ }
+
+ static void kref_release(struct kref *refcount)
+@@ -225,3 +227,14 @@ void wg_peer_put(struct wg_peer *peer)
+ return;
+ kref_put(&peer->refcount, kref_release);
+ }
++
++int __init wg_peer_init(void)
++{
++ peer_cache = KMEM_CACHE(wg_peer, 0);
++ return peer_cache ? 0 : -ENOMEM;
++}
++
++void wg_peer_uninit(void)
++{
++ kmem_cache_destroy(peer_cache);
++}
+--- a/drivers/net/wireguard/peer.h
++++ b/drivers/net/wireguard/peer.h
+@@ -80,4 +80,7 @@ void wg_peer_put(struct wg_peer *peer);
+ void wg_peer_remove(struct wg_peer *peer);
+ void wg_peer_remove_all(struct wg_device *wg);
+
++int wg_peer_init(void);
++void wg_peer_uninit(void);
++
+ #endif /* _WG_PEER_H */