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