Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64...
[sfrench/cifs-2.6.git] / net / kcm / kcmproc.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/in.h>
3 #include <linux/inet.h>
4 #include <linux/list.h>
5 #include <linux/module.h>
6 #include <linux/net.h>
7 #include <linux/proc_fs.h>
8 #include <linux/rculist.h>
9 #include <linux/seq_file.h>
10 #include <linux/socket.h>
11 #include <net/inet_sock.h>
12 #include <net/kcm.h>
13 #include <net/net_namespace.h>
14 #include <net/netns/generic.h>
15 #include <net/tcp.h>
16
17 #ifdef CONFIG_PROC_FS
18 struct kcm_seq_muxinfo {
19         char                            *name;
20         const struct file_operations    *seq_fops;
21         const struct seq_operations     seq_ops;
22 };
23
24 static struct kcm_mux *kcm_get_first(struct seq_file *seq)
25 {
26         struct net *net = seq_file_net(seq);
27         struct kcm_net *knet = net_generic(net, kcm_net_id);
28
29         return list_first_or_null_rcu(&knet->mux_list,
30                                       struct kcm_mux, kcm_mux_list);
31 }
32
33 static struct kcm_mux *kcm_get_next(struct kcm_mux *mux)
34 {
35         struct kcm_net *knet = mux->knet;
36
37         return list_next_or_null_rcu(&knet->mux_list, &mux->kcm_mux_list,
38                                      struct kcm_mux, kcm_mux_list);
39 }
40
41 static struct kcm_mux *kcm_get_idx(struct seq_file *seq, loff_t pos)
42 {
43         struct net *net = seq_file_net(seq);
44         struct kcm_net *knet = net_generic(net, kcm_net_id);
45         struct kcm_mux *m;
46
47         list_for_each_entry_rcu(m, &knet->mux_list, kcm_mux_list) {
48                 if (!pos)
49                         return m;
50                 --pos;
51         }
52         return NULL;
53 }
54
55 static void *kcm_seq_next(struct seq_file *seq, void *v, loff_t *pos)
56 {
57         void *p;
58
59         if (v == SEQ_START_TOKEN)
60                 p = kcm_get_first(seq);
61         else
62                 p = kcm_get_next(v);
63         ++*pos;
64         return p;
65 }
66
67 static void *kcm_seq_start(struct seq_file *seq, loff_t *pos)
68         __acquires(rcu)
69 {
70         rcu_read_lock();
71
72         if (!*pos)
73                 return SEQ_START_TOKEN;
74         else
75                 return kcm_get_idx(seq, *pos - 1);
76 }
77
78 static void kcm_seq_stop(struct seq_file *seq, void *v)
79         __releases(rcu)
80 {
81         rcu_read_unlock();
82 }
83
84 struct kcm_proc_mux_state {
85         struct seq_net_private p;
86         int idx;
87 };
88
89 static int kcm_seq_open(struct inode *inode, struct file *file)
90 {
91         struct kcm_seq_muxinfo *muxinfo = PDE_DATA(inode);
92
93         return seq_open_net(inode, file, &muxinfo->seq_ops,
94                            sizeof(struct kcm_proc_mux_state));
95 }
96
97 static void kcm_format_mux_header(struct seq_file *seq)
98 {
99         struct net *net = seq_file_net(seq);
100         struct kcm_net *knet = net_generic(net, kcm_net_id);
101
102         seq_printf(seq,
103                    "*** KCM statistics (%d MUX) ****\n",
104                    knet->count);
105
106         seq_printf(seq,
107                    "%-14s %-10s %-16s %-10s %-16s %-8s %-8s %-8s %-8s %s",
108                    "Object",
109                    "RX-Msgs",
110                    "RX-Bytes",
111                    "TX-Msgs",
112                    "TX-Bytes",
113                    "Recv-Q",
114                    "Rmem",
115                    "Send-Q",
116                    "Smem",
117                    "Status");
118
119         /* XXX: pdsts header stuff here */
120         seq_puts(seq, "\n");
121 }
122
123 static void kcm_format_sock(struct kcm_sock *kcm, struct seq_file *seq,
124                             int i, int *len)
125 {
126         seq_printf(seq,
127                    "   kcm-%-7u %-10llu %-16llu %-10llu %-16llu %-8d %-8d %-8d %-8s ",
128                    kcm->index,
129                    kcm->stats.rx_msgs,
130                    kcm->stats.rx_bytes,
131                    kcm->stats.tx_msgs,
132                    kcm->stats.tx_bytes,
133                    kcm->sk.sk_receive_queue.qlen,
134                    sk_rmem_alloc_get(&kcm->sk),
135                    kcm->sk.sk_write_queue.qlen,
136                    "-");
137
138         if (kcm->tx_psock)
139                 seq_printf(seq, "Psck-%u ", kcm->tx_psock->index);
140
141         if (kcm->tx_wait)
142                 seq_puts(seq, "TxWait ");
143
144         if (kcm->tx_wait_more)
145                 seq_puts(seq, "WMore ");
146
147         if (kcm->rx_wait)
148                 seq_puts(seq, "RxWait ");
149
150         seq_puts(seq, "\n");
151 }
152
153 static void kcm_format_psock(struct kcm_psock *psock, struct seq_file *seq,
154                              int i, int *len)
155 {
156         seq_printf(seq,
157                    "   psock-%-5u %-10llu %-16llu %-10llu %-16llu %-8d %-8d %-8d %-8d ",
158                    psock->index,
159                    psock->strp.stats.msgs,
160                    psock->strp.stats.bytes,
161                    psock->stats.tx_msgs,
162                    psock->stats.tx_bytes,
163                    psock->sk->sk_receive_queue.qlen,
164                    atomic_read(&psock->sk->sk_rmem_alloc),
165                    psock->sk->sk_write_queue.qlen,
166                    refcount_read(&psock->sk->sk_wmem_alloc));
167
168         if (psock->done)
169                 seq_puts(seq, "Done ");
170
171         if (psock->tx_stopped)
172                 seq_puts(seq, "TxStop ");
173
174         if (psock->strp.stopped)
175                 seq_puts(seq, "RxStop ");
176
177         if (psock->tx_kcm)
178                 seq_printf(seq, "Rsvd-%d ", psock->tx_kcm->index);
179
180         if (!psock->strp.paused && !psock->ready_rx_msg) {
181                 if (psock->sk->sk_receive_queue.qlen) {
182                         if (psock->strp.need_bytes)
183                                 seq_printf(seq, "RxWait=%u ",
184                                            psock->strp.need_bytes);
185                         else
186                                 seq_printf(seq, "RxWait ");
187                 }
188         } else  {
189                 if (psock->strp.paused)
190                         seq_puts(seq, "RxPause ");
191
192                 if (psock->ready_rx_msg)
193                         seq_puts(seq, "RdyRx ");
194         }
195
196         seq_puts(seq, "\n");
197 }
198
199 static void
200 kcm_format_mux(struct kcm_mux *mux, loff_t idx, struct seq_file *seq)
201 {
202         int i, len;
203         struct kcm_sock *kcm;
204         struct kcm_psock *psock;
205
206         /* mux information */
207         seq_printf(seq,
208                    "%-6s%-8s %-10llu %-16llu %-10llu %-16llu %-8s %-8s %-8s %-8s ",
209                    "mux", "",
210                    mux->stats.rx_msgs,
211                    mux->stats.rx_bytes,
212                    mux->stats.tx_msgs,
213                    mux->stats.tx_bytes,
214                    "-", "-", "-", "-");
215
216         seq_printf(seq, "KCMs: %d, Psocks %d\n",
217                    mux->kcm_socks_cnt, mux->psocks_cnt);
218
219         /* kcm sock information */
220         i = 0;
221         spin_lock_bh(&mux->lock);
222         list_for_each_entry(kcm, &mux->kcm_socks, kcm_sock_list) {
223                 kcm_format_sock(kcm, seq, i, &len);
224                 i++;
225         }
226         i = 0;
227         list_for_each_entry(psock, &mux->psocks, psock_list) {
228                 kcm_format_psock(psock, seq, i, &len);
229                 i++;
230         }
231         spin_unlock_bh(&mux->lock);
232 }
233
234 static int kcm_seq_show(struct seq_file *seq, void *v)
235 {
236         struct kcm_proc_mux_state *mux_state;
237
238         mux_state = seq->private;
239         if (v == SEQ_START_TOKEN) {
240                 mux_state->idx = 0;
241                 kcm_format_mux_header(seq);
242         } else {
243                 kcm_format_mux(v, mux_state->idx, seq);
244                 mux_state->idx++;
245         }
246         return 0;
247 }
248
249 static const struct file_operations kcm_seq_fops = {
250         .owner          = THIS_MODULE,
251         .open           = kcm_seq_open,
252         .read           = seq_read,
253         .llseek         = seq_lseek,
254         .release        = seq_release_net,
255 };
256
257 static struct kcm_seq_muxinfo kcm_seq_muxinfo = {
258         .name           = "kcm",
259         .seq_fops       = &kcm_seq_fops,
260         .seq_ops        = {
261                 .show   = kcm_seq_show,
262                 .start  = kcm_seq_start,
263                 .next   = kcm_seq_next,
264                 .stop   = kcm_seq_stop,
265         }
266 };
267
268 static int kcm_proc_register(struct net *net, struct kcm_seq_muxinfo *muxinfo)
269 {
270         struct proc_dir_entry *p;
271         int rc = 0;
272
273         p = proc_create_data(muxinfo->name, S_IRUGO, net->proc_net,
274                              muxinfo->seq_fops, muxinfo);
275         if (!p)
276                 rc = -ENOMEM;
277         return rc;
278 }
279 EXPORT_SYMBOL(kcm_proc_register);
280
281 static void kcm_proc_unregister(struct net *net,
282                                 struct kcm_seq_muxinfo *muxinfo)
283 {
284         remove_proc_entry(muxinfo->name, net->proc_net);
285 }
286 EXPORT_SYMBOL(kcm_proc_unregister);
287
288 static int kcm_stats_seq_show(struct seq_file *seq, void *v)
289 {
290         struct kcm_psock_stats psock_stats;
291         struct kcm_mux_stats mux_stats;
292         struct strp_aggr_stats strp_stats;
293         struct kcm_mux *mux;
294         struct kcm_psock *psock;
295         struct net *net = seq->private;
296         struct kcm_net *knet = net_generic(net, kcm_net_id);
297
298         memset(&mux_stats, 0, sizeof(mux_stats));
299         memset(&psock_stats, 0, sizeof(psock_stats));
300         memset(&strp_stats, 0, sizeof(strp_stats));
301
302         mutex_lock(&knet->mutex);
303
304         aggregate_mux_stats(&knet->aggregate_mux_stats, &mux_stats);
305         aggregate_psock_stats(&knet->aggregate_psock_stats,
306                               &psock_stats);
307         aggregate_strp_stats(&knet->aggregate_strp_stats,
308                              &strp_stats);
309
310         list_for_each_entry_rcu(mux, &knet->mux_list, kcm_mux_list) {
311                 spin_lock_bh(&mux->lock);
312                 aggregate_mux_stats(&mux->stats, &mux_stats);
313                 aggregate_psock_stats(&mux->aggregate_psock_stats,
314                                       &psock_stats);
315                 aggregate_strp_stats(&mux->aggregate_strp_stats,
316                                      &strp_stats);
317                 list_for_each_entry(psock, &mux->psocks, psock_list) {
318                         aggregate_psock_stats(&psock->stats, &psock_stats);
319                         save_strp_stats(&psock->strp, &strp_stats);
320                 }
321
322                 spin_unlock_bh(&mux->lock);
323         }
324
325         mutex_unlock(&knet->mutex);
326
327         seq_printf(seq,
328                    "%-8s %-10s %-16s %-10s %-16s %-10s %-10s %-10s %-10s %-10s\n",
329                    "MUX",
330                    "RX-Msgs",
331                    "RX-Bytes",
332                    "TX-Msgs",
333                    "TX-Bytes",
334                    "TX-Retries",
335                    "Attach",
336                    "Unattach",
337                    "UnattchRsvd",
338                    "RX-RdyDrops");
339
340         seq_printf(seq,
341                    "%-8s %-10llu %-16llu %-10llu %-16llu %-10u %-10u %-10u %-10u %-10u\n",
342                    "",
343                    mux_stats.rx_msgs,
344                    mux_stats.rx_bytes,
345                    mux_stats.tx_msgs,
346                    mux_stats.tx_bytes,
347                    mux_stats.tx_retries,
348                    mux_stats.psock_attach,
349                    mux_stats.psock_unattach_rsvd,
350                    mux_stats.psock_unattach,
351                    mux_stats.rx_ready_drops);
352
353         seq_printf(seq,
354                    "%-8s %-10s %-16s %-10s %-16s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s %-10s\n",
355                    "Psock",
356                    "RX-Msgs",
357                    "RX-Bytes",
358                    "TX-Msgs",
359                    "TX-Bytes",
360                    "Reserved",
361                    "Unreserved",
362                    "RX-Aborts",
363                    "RX-Intr",
364                    "RX-Unrecov",
365                    "RX-MemFail",
366                    "RX-NeedMor",
367                    "RX-BadLen",
368                    "RX-TooBig",
369                    "RX-Timeout",
370                    "TX-Aborts");
371
372         seq_printf(seq,
373                    "%-8s %-10llu %-16llu %-10llu %-16llu %-10llu %-10llu %-10u %-10u %-10u %-10u %-10u %-10u %-10u %-10u %-10u\n",
374                    "",
375                    strp_stats.msgs,
376                    strp_stats.bytes,
377                    psock_stats.tx_msgs,
378                    psock_stats.tx_bytes,
379                    psock_stats.reserved,
380                    psock_stats.unreserved,
381                    strp_stats.aborts,
382                    strp_stats.interrupted,
383                    strp_stats.unrecov_intr,
384                    strp_stats.mem_fail,
385                    strp_stats.need_more_hdr,
386                    strp_stats.bad_hdr_len,
387                    strp_stats.msg_too_big,
388                    strp_stats.msg_timeouts,
389                    psock_stats.tx_aborts);
390
391         return 0;
392 }
393
394 static int kcm_stats_seq_open(struct inode *inode, struct file *file)
395 {
396         return single_open_net(inode, file, kcm_stats_seq_show);
397 }
398
399 static const struct file_operations kcm_stats_seq_fops = {
400         .owner   = THIS_MODULE,
401         .open    = kcm_stats_seq_open,
402         .read    = seq_read,
403         .llseek  = seq_lseek,
404         .release = single_release_net,
405 };
406
407 static int kcm_proc_init_net(struct net *net)
408 {
409         int err;
410
411         if (!proc_create("kcm_stats", S_IRUGO, net->proc_net,
412                          &kcm_stats_seq_fops)) {
413                 err = -ENOMEM;
414                 goto out_kcm_stats;
415         }
416
417         err = kcm_proc_register(net, &kcm_seq_muxinfo);
418         if (err)
419                 goto out_kcm;
420
421         return 0;
422
423 out_kcm:
424         remove_proc_entry("kcm_stats", net->proc_net);
425 out_kcm_stats:
426         return err;
427 }
428
429 static void kcm_proc_exit_net(struct net *net)
430 {
431         kcm_proc_unregister(net, &kcm_seq_muxinfo);
432         remove_proc_entry("kcm_stats", net->proc_net);
433 }
434
435 static struct pernet_operations kcm_net_ops = {
436         .init = kcm_proc_init_net,
437         .exit = kcm_proc_exit_net,
438 };
439
440 int __init kcm_proc_init(void)
441 {
442         return register_pernet_subsys(&kcm_net_ops);
443 }
444
445 void __exit kcm_proc_exit(void)
446 {
447         unregister_pernet_subsys(&kcm_net_ops);
448 }
449
450 #endif /* CONFIG_PROC_FS */