All of lore.kernel.org
 help / color / mirror / Atom feed
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>


             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.