162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/* SCTP kernel implementation
362306a36Sopenharmony_ci * (C) Copyright IBM Corp. 2001, 2004
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * This file is part of the SCTP kernel implementation
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Support for memory object debugging.  This allows one to monitor the
862306a36Sopenharmony_ci * object allocations/deallocations for types instrumented for this
962306a36Sopenharmony_ci * via the proc fs.
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * Please send any bug reports or fixes you make to the
1262306a36Sopenharmony_ci * email address(es):
1362306a36Sopenharmony_ci *    lksctp developers <linux-sctp@vger.kernel.org>
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * Written or modified by:
1662306a36Sopenharmony_ci *    Jon Grimm             <jgrimm@us.ibm.com>
1762306a36Sopenharmony_ci */
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include <linux/kernel.h>
2262306a36Sopenharmony_ci#include <net/sctp/sctp.h>
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci/*
2562306a36Sopenharmony_ci * Global counters to count raw object allocation counts.
2662306a36Sopenharmony_ci * To add new counters, choose a unique suffix for the variable
2762306a36Sopenharmony_ci * name as the helper macros key off this suffix to make
2862306a36Sopenharmony_ci * life easier for the programmer.
2962306a36Sopenharmony_ci */
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ciSCTP_DBG_OBJCNT(sock);
3262306a36Sopenharmony_ciSCTP_DBG_OBJCNT(ep);
3362306a36Sopenharmony_ciSCTP_DBG_OBJCNT(transport);
3462306a36Sopenharmony_ciSCTP_DBG_OBJCNT(assoc);
3562306a36Sopenharmony_ciSCTP_DBG_OBJCNT(bind_addr);
3662306a36Sopenharmony_ciSCTP_DBG_OBJCNT(bind_bucket);
3762306a36Sopenharmony_ciSCTP_DBG_OBJCNT(chunk);
3862306a36Sopenharmony_ciSCTP_DBG_OBJCNT(addr);
3962306a36Sopenharmony_ciSCTP_DBG_OBJCNT(datamsg);
4062306a36Sopenharmony_ciSCTP_DBG_OBJCNT(keys);
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci/* An array to make it easy to pretty print the debug information
4362306a36Sopenharmony_ci * to the proc fs.
4462306a36Sopenharmony_ci */
4562306a36Sopenharmony_cistatic struct sctp_dbg_objcnt_entry sctp_dbg_objcnt[] = {
4662306a36Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(sock),
4762306a36Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(ep),
4862306a36Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(assoc),
4962306a36Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(transport),
5062306a36Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(chunk),
5162306a36Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(bind_addr),
5262306a36Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(bind_bucket),
5362306a36Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(addr),
5462306a36Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(datamsg),
5562306a36Sopenharmony_ci	SCTP_DBG_OBJCNT_ENTRY(keys),
5662306a36Sopenharmony_ci};
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci/* Callback from procfs to read out objcount information.
5962306a36Sopenharmony_ci * Walk through the entries in the sctp_dbg_objcnt array, dumping
6062306a36Sopenharmony_ci * the raw object counts for each monitored type.
6162306a36Sopenharmony_ci */
6262306a36Sopenharmony_cistatic int sctp_objcnt_seq_show(struct seq_file *seq, void *v)
6362306a36Sopenharmony_ci{
6462306a36Sopenharmony_ci	int i;
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	i = (int)*(loff_t *)v;
6762306a36Sopenharmony_ci	seq_setwidth(seq, 127);
6862306a36Sopenharmony_ci	seq_printf(seq, "%s: %d", sctp_dbg_objcnt[i].label,
6962306a36Sopenharmony_ci				atomic_read(sctp_dbg_objcnt[i].counter));
7062306a36Sopenharmony_ci	seq_pad(seq, '\n');
7162306a36Sopenharmony_ci	return 0;
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cistatic void *sctp_objcnt_seq_start(struct seq_file *seq, loff_t *pos)
7562306a36Sopenharmony_ci{
7662306a36Sopenharmony_ci	return (*pos >= ARRAY_SIZE(sctp_dbg_objcnt)) ? NULL : (void *)pos;
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic void sctp_objcnt_seq_stop(struct seq_file *seq, void *v)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cistatic void *sctp_objcnt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
8462306a36Sopenharmony_ci{
8562306a36Sopenharmony_ci	++*pos;
8662306a36Sopenharmony_ci	return (*pos >= ARRAY_SIZE(sctp_dbg_objcnt)) ? NULL : (void *)pos;
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistatic const struct seq_operations sctp_objcnt_seq_ops = {
9062306a36Sopenharmony_ci	.start = sctp_objcnt_seq_start,
9162306a36Sopenharmony_ci	.next  = sctp_objcnt_seq_next,
9262306a36Sopenharmony_ci	.stop  = sctp_objcnt_seq_stop,
9362306a36Sopenharmony_ci	.show  = sctp_objcnt_seq_show,
9462306a36Sopenharmony_ci};
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci/* Initialize the objcount in the proc filesystem.  */
9762306a36Sopenharmony_civoid sctp_dbg_objcnt_init(struct net *net)
9862306a36Sopenharmony_ci{
9962306a36Sopenharmony_ci	struct proc_dir_entry *ent;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	ent = proc_create_seq("sctp_dbg_objcnt", 0,
10262306a36Sopenharmony_ci			  net->sctp.proc_net_sctp, &sctp_objcnt_seq_ops);
10362306a36Sopenharmony_ci	if (!ent)
10462306a36Sopenharmony_ci		pr_warn("sctp_dbg_objcnt: Unable to create /proc entry.\n");
10562306a36Sopenharmony_ci}
106