1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2025, LG Electronics.
4 * Author(s): Hyunchul Lee <hyc.lee@gmail.com>
5 * Copyright (C) 2025, Samsung Electronics.
6 * Author(s): Vedansh Bhardwaj <v.bhardwaj@samsung.com>
7 */
8
9 #include <linux/module.h>
10 #include <linux/proc_fs.h>
11 #include <linux/seq_file.h>
12
13 #include "misc.h"
14 #include "server.h"
15 #include "stats.h"
16 #include "smb_common.h"
17 #include "smb2pdu.h"
18
19 static struct proc_dir_entry *ksmbd_proc_fs;
20 struct ksmbd_counters ksmbd_counters;
21
ksmbd_proc_create(const char * name,int (* show)(struct seq_file * m,void * v),void * v)22 struct proc_dir_entry *ksmbd_proc_create(const char *name,
23 int (*show)(struct seq_file *m, void *v),
24 void *v)
25 {
26 return proc_create_single_data(name, 0400, ksmbd_proc_fs,
27 show, v);
28 }
29
30 struct ksmbd_const_smb2_process_req {
31 unsigned int const_value;
32 const char *name;
33 };
34
35 static const struct ksmbd_const_smb2_process_req smb2_process_req[KSMBD_COUNTER_MAX_REQS] = {
36 {le16_to_cpu(SMB2_NEGOTIATE), "SMB2_NEGOTIATE"},
37 {le16_to_cpu(SMB2_SESSION_SETUP), "SMB2_SESSION_SETUP"},
38 {le16_to_cpu(SMB2_LOGOFF), "SMB2_LOGOFF"},
39 {le16_to_cpu(SMB2_TREE_CONNECT), "SMB2_TREE_CONNECT"},
40 {le16_to_cpu(SMB2_TREE_DISCONNECT), "SMB2_TREE_DISCONNECT"},
41 {le16_to_cpu(SMB2_CREATE), "SMB2_CREATE"},
42 {le16_to_cpu(SMB2_CLOSE), "SMB2_CLOSE"},
43 {le16_to_cpu(SMB2_FLUSH), "SMB2_FLUSH"},
44 {le16_to_cpu(SMB2_READ), "SMB2_READ"},
45 {le16_to_cpu(SMB2_WRITE), "SMB2_WRITE"},
46 {le16_to_cpu(SMB2_LOCK), "SMB2_LOCK"},
47 {le16_to_cpu(SMB2_IOCTL), "SMB2_IOCTL"},
48 {le16_to_cpu(SMB2_CANCEL), "SMB2_CANCEL"},
49 {le16_to_cpu(SMB2_ECHO), "SMB2_ECHO"},
50 {le16_to_cpu(SMB2_QUERY_DIRECTORY), "SMB2_QUERY_DIRECTORY"},
51 {le16_to_cpu(SMB2_CHANGE_NOTIFY), "SMB2_CHANGE_NOTIFY"},
52 {le16_to_cpu(SMB2_QUERY_INFO), "SMB2_QUERY_INFO"},
53 {le16_to_cpu(SMB2_SET_INFO), "SMB2_SET_INFO"},
54 {le16_to_cpu(SMB2_OPLOCK_BREAK), "SMB2_OPLOCK_BREAK"},
55 };
56
proc_show_ksmbd_stats(struct seq_file * m,void * v)57 static int proc_show_ksmbd_stats(struct seq_file *m, void *v)
58 {
59 int i;
60
61 seq_puts(m, "Server\n");
62 seq_printf(m, "name: %s\n", ksmbd_server_string());
63 seq_printf(m, "netbios: %s\n", ksmbd_netbios_name());
64 seq_printf(m, "work group: %s\n", ksmbd_work_group());
65 seq_printf(m, "min protocol: %s\n", ksmbd_get_protocol_string(server_conf.min_protocol));
66 seq_printf(m, "max protocol: %s\n", ksmbd_get_protocol_string(server_conf.max_protocol));
67 seq_printf(m, "flags: 0x%08x\n", server_conf.flags);
68 seq_printf(m, "share_fake_fscaps: 0x%08x\n",
69 server_conf.share_fake_fscaps);
70 seq_printf(m, "sessions: %lld\n",
71 ksmbd_counter_sum(KSMBD_COUNTER_SESSIONS));
72 seq_printf(m, "tree connects: %lld\n",
73 ksmbd_counter_sum(KSMBD_COUNTER_TREE_CONNS));
74 seq_printf(m, "read bytes: %lld\n",
75 ksmbd_counter_sum(KSMBD_COUNTER_READ_BYTES));
76 seq_printf(m, "written bytes: %lld\n",
77 ksmbd_counter_sum(KSMBD_COUNTER_WRITE_BYTES));
78
79 seq_puts(m, "\nSMB2\n");
80 for (i = 0; i < KSMBD_COUNTER_MAX_REQS; i++)
81 seq_printf(m, "%-20s:\t%lld\n", smb2_process_req[i].name,
82 ksmbd_counter_sum(KSMBD_COUNTER_FIRST_REQ + i));
83 return 0;
84 }
85
ksmbd_proc_cleanup(void)86 void ksmbd_proc_cleanup(void)
87 {
88 int i;
89
90 if (!ksmbd_proc_fs)
91 return;
92
93 proc_remove(ksmbd_proc_fs);
94
95 for (i = 0; i < ARRAY_SIZE(ksmbd_counters.counters); i++)
96 percpu_counter_destroy(&ksmbd_counters.counters[i]);
97
98 ksmbd_proc_fs = NULL;
99 }
100
ksmbd_proc_reset(void)101 void ksmbd_proc_reset(void)
102 {
103 int i;
104
105 for (i = 0; i < ARRAY_SIZE(ksmbd_counters.counters); i++)
106 percpu_counter_set(&ksmbd_counters.counters[i], 0);
107 }
108
ksmbd_proc_init(void)109 void ksmbd_proc_init(void)
110 {
111 int i;
112 int retval;
113
114 ksmbd_proc_fs = proc_mkdir("fs/ksmbd", NULL);
115 if (!ksmbd_proc_fs)
116 return;
117
118 if (!proc_mkdir_mode("sessions", 0400, ksmbd_proc_fs))
119 goto err_out;
120
121 for (i = 0; i < ARRAY_SIZE(ksmbd_counters.counters); i++) {
122 retval = percpu_counter_init(&ksmbd_counters.counters[i], 0, GFP_KERNEL);
123 if (retval)
124 goto err_out;
125 }
126
127 if (!ksmbd_proc_create("server", proc_show_ksmbd_stats, NULL))
128 goto err_out;
129
130 ksmbd_proc_reset();
131 return;
132 err_out:
133 ksmbd_proc_cleanup();
134 }
135