From: Jeff Layton <jlayton@kernel.org>
To: "David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
Jeff Layton <jlayton@kernel.org>
Subject: [PATCH] net: add a debugfs files for showing netns refcount tracking info
Date: Mon, 24 Mar 2025 16:24:47 -0400 [thread overview]
Message-ID: <20250324-netns-debugfs-v1-1-c75e9d5a6266@kernel.org> (raw)
CONFIG_NET_NS_REFCNT_TRACKER currently has no convenient way to display
its tracking info. Add a new net_ns directory in debugfs. Have a
directory in there for every net, with refcnt and notrefcnt files that
show the currently tracked active and passive references.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
Recently, I had a need to track down some long-held netns references,
and discovered CONFIG_NET_NS_REFCNT_TRACKER. The main thing that seemed
to be missing from it though is a simple way to view the currently held
references on the netns. This adds files in debugfs for this.
---
net/core/net_namespace.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 151 insertions(+)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 4303f2a4926243e2c0ff0c0387383cd8e0658019..b7ce8c7621bdf6055fa4aaa5cbfce111ca86b047 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -1512,3 +1512,154 @@ const struct proc_ns_operations netns_operations = {
.owner = netns_owner,
};
#endif
+
+#ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_NET_NS_REFCNT_TRACKER
+
+#include <linux/debugfs.h>
+
+static struct dentry *ns_debug_dir;
+static unsigned int ns_debug_net_id;
+
+struct ns_debug_net {
+ struct dentry *netdir;
+ struct dentry *refcnt;
+ struct dentry *notrefcnt;
+};
+
+#define MAX_NS_DEBUG_BUFSIZE (32 * PAGE_SIZE)
+
+static int
+ns_debug_tracker_show(struct seq_file *f, void *v)
+{
+ struct ref_tracker_dir *tracker = f->private;
+ int len, bufsize = PAGE_SIZE;
+ char *buf;
+
+ for (;;) {
+ buf = kvmalloc(bufsize, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ len = ref_tracker_dir_snprint(tracker, buf, bufsize);
+ if (len < bufsize)
+ break;
+
+ kvfree(buf);
+ bufsize *= 2;
+ if (bufsize > MAX_NS_DEBUG_BUFSIZE)
+ return -ENOBUFS;
+ }
+ seq_write(f, buf, len);
+ kvfree(buf);
+ return 0;
+}
+
+static int
+ns_debug_ref_open(struct inode *inode, struct file *filp)
+{
+ int ret;
+ struct net *net = inode->i_private;
+
+ ret = single_open(filp, ns_debug_tracker_show, &net->refcnt_tracker);
+ if (!ret)
+ net_passive_inc(net);
+ return ret;
+}
+
+static int
+ns_debug_notref_open(struct inode *inode, struct file *filp)
+{
+ int ret;
+ struct net *net = inode->i_private;
+
+ ret = single_open(filp, ns_debug_tracker_show, &net->notrefcnt_tracker);
+ if (!ret)
+ net_passive_inc(net);
+ return ret;
+}
+
+static int
+ns_debug_ref_release(struct inode *inode, struct file *filp)
+{
+ struct net *net = inode->i_private;
+
+ net_passive_dec(net);
+ return single_release(inode, filp);
+}
+
+static const struct file_operations ns_debug_ref_fops = {
+ .owner = THIS_MODULE,
+ .open = ns_debug_ref_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = ns_debug_ref_release,
+};
+
+static const struct file_operations ns_debug_notref_fops = {
+ .owner = THIS_MODULE,
+ .open = ns_debug_notref_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = ns_debug_ref_release,
+};
+
+static int
+ns_debug_init_net(struct net *net)
+{
+ struct ns_debug_net *dnet = net_generic(net, ns_debug_net_id);
+ char name[11]; /* 10 decimal digits + NULL term */
+ int len;
+
+ len = snprintf(name, sizeof(name), "%u", net->ns.inum);
+ if (len >= sizeof(name))
+ return -EOVERFLOW;
+
+ dnet->netdir = debugfs_create_dir(name, ns_debug_dir);
+ if (IS_ERR(dnet->netdir))
+ return PTR_ERR(dnet->netdir);
+
+ dnet->refcnt = debugfs_create_file("refcnt", S_IFREG | 0400, dnet->netdir,
+ net, &ns_debug_ref_fops);
+ if (IS_ERR(dnet->refcnt)) {
+ debugfs_remove(dnet->netdir);
+ return PTR_ERR(dnet->refcnt);
+ }
+
+ dnet->notrefcnt = debugfs_create_file("notrefcnt", S_IFREG | 0400, dnet->netdir,
+ net, &ns_debug_notref_fops);
+ if (IS_ERR(dnet->notrefcnt)) {
+ debugfs_remove_recursive(dnet->netdir);
+ return PTR_ERR(dnet->notrefcnt);
+ }
+
+ return 0;
+}
+
+static void
+ns_debug_exit_net(struct net *net)
+{
+ struct ns_debug_net *dnet = net_generic(net, ns_debug_net_id);
+
+ debugfs_remove_recursive(dnet->netdir);
+}
+
+static struct pernet_operations ns_debug_net_ops = {
+ .init = ns_debug_init_net,
+ .exit = ns_debug_exit_net,
+ .id = &ns_debug_net_id,
+ .size = sizeof(struct ns_debug_net),
+};
+
+static int __init ns_debug_init(void)
+{
+ ns_debug_dir = debugfs_create_dir("net_ns", NULL);
+ if (IS_ERR(ns_debug_dir))
+ return PTR_ERR(ns_debug_dir);
+
+ register_pernet_subsys(&ns_debug_net_ops);
+ return 0;
+}
+late_initcall(ns_debug_init);
+#endif /* CONFIG_NET_NS_REFCNT_TRACKER */
+#endif /* CONFIG_DEBUG_FS */
---
base-commit: 695caca9345a160ecd9645abab8e70cfe849e9ff
change-id: 20250324-netns-debugfs-df213b2ab9ce
Best regards,
--
Jeff Layton <jlayton@kernel.org>
next reply other threads:[~2025-03-24 20:24 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-24 20:24 Jeff Layton [this message]
2025-03-24 20:50 ` [PATCH] net: add a debugfs files for showing netns refcount tracking info Andrew Lunn
2025-03-25 0:37 ` Jeff Layton
2025-03-25 13:00 ` Andrew Lunn
2025-03-25 5:21 ` Eric Dumazet
2025-03-25 11:47 ` Jeff Layton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250324-netns-debugfs-v1-1-c75e9d5a6266@kernel.org \
--to=jlayton@kernel.org \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.