1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* SCTP kernel implementation |
3 | * (C) Copyright IBM Corp. 2001, 2004 |
4 | * |
5 | * This file is part of the SCTP kernel implementation |
6 | * |
7 | * Support for memory object debugging. This allows one to monitor the |
8 | * object allocations/deallocations for types instrumented for this |
9 | * via the proc fs. |
10 | * |
11 | * Please send any bug reports or fixes you make to the |
12 | * email address(es): |
13 | * lksctp developers <linux-sctp@vger.kernel.org> |
14 | * |
15 | * Written or modified by: |
16 | * Jon Grimm <jgrimm@us.ibm.com> |
17 | */ |
18 | |
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
20 | |
21 | #include <linux/kernel.h> |
22 | #include <net/sctp/sctp.h> |
23 | |
24 | /* |
25 | * Global counters to count raw object allocation counts. |
26 | * To add new counters, choose a unique suffix for the variable |
27 | * name as the helper macros key off this suffix to make |
28 | * life easier for the programmer. |
29 | */ |
30 | |
31 | SCTP_DBG_OBJCNT(sock); |
32 | SCTP_DBG_OBJCNT(ep); |
33 | SCTP_DBG_OBJCNT(transport); |
34 | SCTP_DBG_OBJCNT(assoc); |
35 | SCTP_DBG_OBJCNT(bind_addr); |
36 | SCTP_DBG_OBJCNT(bind_bucket); |
37 | SCTP_DBG_OBJCNT(chunk); |
38 | SCTP_DBG_OBJCNT(addr); |
39 | SCTP_DBG_OBJCNT(datamsg); |
40 | SCTP_DBG_OBJCNT(keys); |
41 | |
42 | /* An array to make it easy to pretty print the debug information |
43 | * to the proc fs. |
44 | */ |
45 | static struct sctp_dbg_objcnt_entry sctp_dbg_objcnt[] = { |
46 | SCTP_DBG_OBJCNT_ENTRY(sock), |
47 | SCTP_DBG_OBJCNT_ENTRY(ep), |
48 | SCTP_DBG_OBJCNT_ENTRY(assoc), |
49 | SCTP_DBG_OBJCNT_ENTRY(transport), |
50 | SCTP_DBG_OBJCNT_ENTRY(chunk), |
51 | SCTP_DBG_OBJCNT_ENTRY(bind_addr), |
52 | SCTP_DBG_OBJCNT_ENTRY(bind_bucket), |
53 | SCTP_DBG_OBJCNT_ENTRY(addr), |
54 | SCTP_DBG_OBJCNT_ENTRY(datamsg), |
55 | SCTP_DBG_OBJCNT_ENTRY(keys), |
56 | }; |
57 | |
58 | /* Callback from procfs to read out objcount information. |
59 | * Walk through the entries in the sctp_dbg_objcnt array, dumping |
60 | * the raw object counts for each monitored type. |
61 | */ |
62 | static int sctp_objcnt_seq_show(struct seq_file *seq, void *v) |
63 | { |
64 | int i; |
65 | |
66 | i = (int)*(loff_t *)v; |
67 | seq_setwidth(m: seq, size: 127); |
68 | seq_printf(m: seq, fmt: "%s: %d" , sctp_dbg_objcnt[i].label, |
69 | atomic_read(v: sctp_dbg_objcnt[i].counter)); |
70 | seq_pad(m: seq, c: '\n'); |
71 | return 0; |
72 | } |
73 | |
74 | static void *sctp_objcnt_seq_start(struct seq_file *seq, loff_t *pos) |
75 | { |
76 | return (*pos >= ARRAY_SIZE(sctp_dbg_objcnt)) ? NULL : (void *)pos; |
77 | } |
78 | |
79 | static void sctp_objcnt_seq_stop(struct seq_file *seq, void *v) |
80 | { |
81 | } |
82 | |
83 | static void *sctp_objcnt_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
84 | { |
85 | ++*pos; |
86 | return (*pos >= ARRAY_SIZE(sctp_dbg_objcnt)) ? NULL : (void *)pos; |
87 | } |
88 | |
89 | static const struct seq_operations sctp_objcnt_seq_ops = { |
90 | .start = sctp_objcnt_seq_start, |
91 | .next = sctp_objcnt_seq_next, |
92 | .stop = sctp_objcnt_seq_stop, |
93 | .show = sctp_objcnt_seq_show, |
94 | }; |
95 | |
96 | /* Initialize the objcount in the proc filesystem. */ |
97 | void sctp_dbg_objcnt_init(struct net *net) |
98 | { |
99 | struct proc_dir_entry *ent; |
100 | |
101 | ent = proc_create_seq("sctp_dbg_objcnt" , 0, |
102 | net->sctp.proc_net_sctp, &sctp_objcnt_seq_ops); |
103 | if (!ent) |
104 | pr_warn("sctp_dbg_objcnt: Unable to create /proc entry.\n" ); |
105 | } |
106 | |