[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250902-netpoll_untangle_v3-v1-5-51a03d6411be@debian.org>
Date: Tue, 02 Sep 2025 07:36:27 -0700
From: Breno Leitao <leitao@...ian.org>
To: Andrew Lunn <andrew+netdev@...n.ch>,
"David S. Miller" <davem@...emloft.net>, Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>, Paolo Abeni <pabeni@...hat.com>,
Simon Horman <horms@...nel.org>,
Sebastian Andrzej Siewior <bigeasy@...utronix.de>,
Clark Williams <clrkwllms@...nel.org>, Steven Rostedt <rostedt@...dmis.org>
Cc: netdev@...r.kernel.org, linux-kernel@...r.kernel.org,
linux-rt-devel@...ts.linux.dev, kernel-team@...a.com, efault@....de,
calvin@...nvd.org, Breno Leitao <leitao@...ian.org>
Subject: [PATCH 5/7] netpoll: Move SKBs pool to netconsole side
Since netconsole is the sole user of the SKBs pool within netpoll, move
the pool management into the netconsole driver.
This change prevents other netpoll users from allocating and holding
onto skb pool memory unnecessarily, thereby reducing memory usage when
the pool is not required (which is all the cases except netconsole).
The skb poll struct is still attached to the netpoll, but, eventually
this should move to the netconsole target, since it has nothing to do
with netpoll.
Signed-off-by: Breno Leitao <leitao@...ian.org>
---
drivers/net/netconsole.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++--
net/core/netpoll.c | 44 ------------------------------------
2 files changed, 56 insertions(+), 46 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 90e359b87469a..3fe55db07cfe5 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -57,6 +57,19 @@ MODULE_LICENSE("GPL");
#define MAX_EXTRADATA_ITEMS 16
#define MAX_PRINT_CHUNK 1000
+/*
+ * We maintain a small pool of fully-sized skbs, to make sure the
+ * message gets out even in extreme OOM situations.
+ */
+
+#define MAX_SKBS 32
+#define MAX_UDP_CHUNK 1460
+#define MAX_SKB_SIZE \
+ (sizeof(struct ethhdr) + \
+ sizeof(struct iphdr) + \
+ sizeof(struct udphdr) + \
+ MAX_UDP_CHUNK)
+
static char config[MAX_PARAM_LENGTH];
module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0);
MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]");
@@ -172,6 +185,33 @@ struct netconsole_target {
char buf[MAX_PRINT_CHUNK];
};
+static void refill_skbs(struct netpoll *np)
+{
+ struct sk_buff_head *skb_pool;
+ struct sk_buff *skb;
+ unsigned long flags;
+
+ skb_pool = &np->skb_pool;
+
+ spin_lock_irqsave(&skb_pool->lock, flags);
+ while (skb_pool->qlen < MAX_SKBS) {
+ skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
+ if (!skb)
+ break;
+
+ __skb_queue_tail(skb_pool, skb);
+ }
+ spin_unlock_irqrestore(&skb_pool->lock, flags);
+}
+
+static void refill_skbs_work_handler(struct work_struct *work)
+{
+ struct netpoll *np =
+ container_of(work, struct netpoll, refill_wq);
+
+ refill_skbs(np);
+}
+
#ifdef CONFIG_NETCONSOLE_DYNAMIC
static struct configfs_subsystem netconsole_subsys;
@@ -341,6 +381,20 @@ static int netpoll_parse_ip_addr(const char *str, union inet_addr *addr)
return -1;
}
+static int setup_netpoll(struct netpoll *np)
+{
+ int err;
+
+ err = netpoll_setup(np);
+ if (err)
+ return err;
+
+ refill_skbs(np);
+ INIT_WORK(&np->refill_wq, refill_skbs_work_handler);
+
+ return 0;
+}
+
#ifdef CONFIG_NETCONSOLE_DYNAMIC
/*
@@ -615,7 +669,7 @@ static ssize_t enabled_store(struct config_item *item,
*/
netconsole_print_banner(&nt->np);
- ret = netpoll_setup(&nt->np);
+ ret = setup_netpoll(&nt->np);
if (ret)
goto out_unlock;
@@ -2036,7 +2090,7 @@ static struct netconsole_target *alloc_param_target(char *target_config,
if (err)
goto fail;
- err = netpoll_setup(&nt->np);
+ err = setup_netpoll(&nt->np);
if (err) {
pr_err("Not enabling netconsole for %s%d. Netpoll setup failed\n",
NETCONSOLE_PARAM_TARGET_PREFIX, cmdline_count);
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 04a55ec392fd2..94c75f39787bb 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -35,21 +35,8 @@
#include <trace/events/napi.h>
#include <linux/kconfig.h>
-/*
- * We maintain a small pool of fully-sized skbs, to make sure the
- * message gets out even in extreme OOM situations.
- */
-
-#define MAX_UDP_CHUNK 1460
-#define MAX_SKBS 32
#define USEC_PER_POLL 50
-#define MAX_SKB_SIZE \
- (sizeof(struct ethhdr) + \
- sizeof(struct iphdr) + \
- sizeof(struct udphdr) + \
- MAX_UDP_CHUNK)
-
static unsigned int carrier_timeout = 4;
module_param(carrier_timeout, uint, 0644);
@@ -219,25 +206,6 @@ void netpoll_poll_enable(struct net_device *dev)
up(&ni->dev_lock);
}
-static void refill_skbs(struct netpoll *np)
-{
- struct sk_buff_head *skb_pool;
- struct sk_buff *skb;
- unsigned long flags;
-
- skb_pool = &np->skb_pool;
-
- spin_lock_irqsave(&skb_pool->lock, flags);
- while (skb_pool->qlen < MAX_SKBS) {
- skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
- if (!skb)
- break;
-
- __skb_queue_tail(skb_pool, skb);
- }
- spin_unlock_irqrestore(&skb_pool->lock, flags);
-}
-
void zap_completion_queue(void)
{
unsigned long flags;
@@ -395,14 +363,6 @@ static void skb_pool_flush(struct netpoll *np)
skb_queue_purge_reason(skb_pool, SKB_CONSUMED);
}
-static void refill_skbs_work_handler(struct work_struct *work)
-{
- struct netpoll *np =
- container_of(work, struct netpoll, refill_wq);
-
- refill_skbs(np);
-}
-
int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
{
struct netpoll_info *npinfo;
@@ -446,10 +406,6 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
strscpy(np->dev_name, ndev->name, IFNAMSIZ);
npinfo->netpoll = np;
- /* fill up the skb queue */
- refill_skbs(np);
- INIT_WORK(&np->refill_wq, refill_skbs_work_handler);
-
/* last thing to do is link it to the net device structure */
rcu_assign_pointer(ndev->npinfo, npinfo);
--
2.47.3
Powered by blists - more mailing lists