[PATCH 3/7] ksmbd: fix malformed procfs status output
Namjae Jeon <[email protected]>
| Newsgroups | org.kernel.vger.linux-cifs |
|---|---|
| Message-ID | <[email protected]> |
The ksmbd procfs monitoring files produce misleading or malformed output. The constant-name helper uses a bitwise test for enum values. This omits zero-valued constants and can print multiple names for one lease state. It also unconditionally emits a newline, splitting entries in the open-file table across two lines. Session capabilities are printed as numeric flag values even though a table of descriptive names is available. Use exact matching for enum values. Print flag names as a comma-separated list, preserving unknown bits as hexadecimal values. Let callers control line termination so each open-file entry remains on one line. Print common session properties once, and report signing and encryption independently. Adjust client and open-file column widths for IPv6 addresses and 64-bit file IDs, and fix the misspelled OPLOCK_EXCLUSIVE name. Also expose and maintain the total request count alongside the per-command counters. Signed-off-by: Namjae Jeon <[email protected]> --- fs/smb/server/connection.c | 12 ++--- fs/smb/server/mgmt/user_session.c | 75 +++++++++++++------------------ fs/smb/server/misc.h | 7 +-- fs/smb/server/proc.c | 38 ++++++++++++++++ fs/smb/server/stats.h | 4 +- fs/smb/server/vfs_cache.c | 16 ++++--- 6 files changed, 89 insertions(+), 63 deletions(-) diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c index 3d2b8f243a22..47f6d561e150 100644 --- a/fs/smb/server/connection.c +++ b/fs/smb/server/connection.c @@ -33,9 +33,9 @@ static int proc_show_clients(struct seq_file *m, void *v) struct timespec64 now, t; int i; - seq_printf(m, "#%-20s %-10s %-10s %-10s %-10s %-10s\n", - "<name>", "<dialect>", "<credits>", "<open files>", - "<requests>", "<last active>"); + seq_printf(m, "#%-40s %-10s %-10s %-12s %-10s %s\n", + "<client>", "<dialect>", "<credits>", "<open files>", + "<requests>", "<last active>"); down_read(&conn_list_lock); hash_for_each(conn_list, i, conn, hlist) { @@ -44,11 +44,11 @@ static int proc_show_clients(struct seq_file *m, void *v) t = timespec64_sub(now, t); #if IS_ENABLED(CONFIG_IPV6) if (!conn->inet_addr) - seq_printf(m, "%-20pI6c", &conn->inet6_addr); + seq_printf(m, " %-40pI6c", &conn->inet6_addr); else #endif - seq_printf(m, "%-20pI4", &conn->inet_addr); - seq_printf(m, " 0x%-10x %-10u %-12d %-10d %ptT\n", + seq_printf(m, " %-40pI4", &conn->inet_addr); + seq_printf(m, " 0x%-8x %-10u %-12d %-10d %ptT\n", conn->dialect, conn->total_credits, atomic_read(&conn->stats.open_files_count), diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c index cbe00f00f3f6..09c944a67141 100644 --- a/fs/smb/server/mgmt/user_session.c +++ b/fs/smb/server/mgmt/user_session.c @@ -90,9 +90,15 @@ static int show_proc_session(struct seq_file *m, void *v) sess = (struct ksmbd_session *)m->private; ksmbd_user_session_get(sess); + seq_printf(m, "%-20s\t%s\n", "user", session_user_name(sess)); + seq_printf(m, "%-20s\t%llu\n", "id", sess->id); + seq_printf(m, "%-20s\t%s\n", "state", session_state_string(sess)); + i = 0; down_read(&sess->chann_lock); xa_for_each(&sess->ksmbd_chann_list, id, chan) { + const char *name; + #if IS_ENABLED(CONFIG_IPV6) if (chan->conn->inet_addr) seq_printf(m, "%-20s\t%pI4\n", "client", @@ -104,29 +110,37 @@ static int show_proc_session(struct seq_file *m, void *v) seq_printf(m, "%-20s\t%pI4\n", "client", &chan->conn->inet_addr); #endif - seq_printf(m, "%-20s\t%s\n", "user", session_user_name(sess)); - seq_printf(m, "%-20s\t%llu\n", "id", sess->id); - seq_printf(m, "%-20s\t%s\n", "state", - session_state_string(sess)); - seq_printf(m, "%-20s\t", "capabilities"); ksmbd_proc_show_flag_names(m, ksmbd_sess_cap_const_names, ARRAY_SIZE(ksmbd_sess_cap_const_names), chan->conn->vals->req_capabilities); + seq_putc(m, '\n'); if (sess->sign) { - seq_printf(m, "%-20s\t", "signing"); - ksmbd_proc_show_const_name(m, "%s\t", - ksmbd_signing_const_names, - ARRAY_SIZE(ksmbd_signing_const_names), - le16_to_cpu(chan->conn->signing_algorithm)); - } else if (sess->enc) { - seq_printf(m, "%-20s\t", "encryption"); - ksmbd_proc_show_const_name(m, "%s\t", - ksmbd_cipher_const_names, - ARRAY_SIZE(ksmbd_cipher_const_names), - le16_to_cpu(chan->conn->cipher_type)); + unsigned int algorithm = + le16_to_cpu(chan->conn->signing_algorithm); + + name = ksmbd_proc_const_name(ksmbd_signing_const_names, + ARRAY_SIZE(ksmbd_signing_const_names), + algorithm); + if (name) + seq_printf(m, "%-20s\t%s\n", "signing", name); + else + seq_printf(m, "%-20s\t0x%04x\n", "signing", + algorithm); + } + if (sess->enc) { + unsigned int cipher = le16_to_cpu(chan->conn->cipher_type); + + name = ksmbd_proc_const_name(ksmbd_cipher_const_names, + ARRAY_SIZE(ksmbd_cipher_const_names), + cipher); + if (name) + seq_printf(m, "%-20s\t%s\n", "encryption", name); + else + seq_printf(m, "%-20s\t0x%04x\n", "encryption", + cipher); } i++; } @@ -152,35 +166,6 @@ static int show_proc_session(struct seq_file *m, void *v) return 0; } -void ksmbd_proc_show_flag_names(struct seq_file *m, - const struct ksmbd_const_name *table, - int count, - unsigned int flags) -{ - int i; - - for (i = 0; i < count; i++) { - if (table[i].const_value & flags) - seq_printf(m, "0x%08x\t", table[i].const_value); - } - seq_putc(m, '\n'); -} - -void ksmbd_proc_show_const_name(struct seq_file *m, - const char *format, - const struct ksmbd_const_name *table, - int count, - unsigned int const_value) -{ - int i; - - for (i = 0; i < count; i++) { - if (table[i].const_value & const_value) - seq_printf(m, format, table[i].name); - } - seq_putc(m, '\n'); -} - static int create_proc_session(struct ksmbd_session *sess) { char name[30]; diff --git a/fs/smb/server/misc.h b/fs/smb/server/misc.h index 3909104e18ad..680375a966c5 100644 --- a/fs/smb/server/misc.h +++ b/fs/smb/server/misc.h @@ -53,11 +53,8 @@ void ksmbd_proc_show_flag_names(struct seq_file *m, const struct ksmbd_const_name *table, int count, unsigned int flags); -void ksmbd_proc_show_const_name(struct seq_file *m, - const char *format, - const struct ksmbd_const_name *table, - int count, - unsigned int const_value); +const char *ksmbd_proc_const_name(const struct ksmbd_const_name *table, + int count, unsigned int const_value); #else static inline void ksmbd_proc_init(void) {} static inline void ksmbd_proc_cleanup(void) {} diff --git a/fs/smb/server/proc.c b/fs/smb/server/proc.c index 101a2cc45a44..b41490142480 100644 --- a/fs/smb/server/proc.c +++ b/fs/smb/server/proc.c @@ -27,6 +27,42 @@ struct proc_dir_entry *ksmbd_proc_create(const char *name, show, v); } +void ksmbd_proc_show_flag_names(struct seq_file *m, + const struct ksmbd_const_name *table, + int count, unsigned int flags) +{ + unsigned int remaining = flags; + bool separator = false; + int i; + + for (i = 0; i < count; i++) { + unsigned int flag = table[i].const_value; + + if (!flag || (remaining & flag) != flag) + continue; + seq_printf(m, "%s%s", separator ? "," : "", table[i].name); + separator = true; + remaining &= ~flag; + } + + if (remaining) + seq_printf(m, "%s0x%08x", separator ? "," : "", remaining); + else if (!separator) + seq_puts(m, "none"); +} + +const char *ksmbd_proc_const_name(const struct ksmbd_const_name *table, + int count, unsigned int const_value) +{ + int i; + + for (i = 0; i < count; i++) { + if (table[i].const_value == const_value) + return table[i].name; + } + return NULL; +} + struct ksmbd_const_smb2_process_req { unsigned int const_value; const char *name; @@ -71,6 +107,8 @@ static int proc_show_ksmbd_stats(struct seq_file *m, void *v) ksmbd_counter_sum(KSMBD_COUNTER_SESSIONS)); seq_printf(m, "tree connects: %lld\n", ksmbd_counter_sum(KSMBD_COUNTER_TREE_CONNS)); + seq_printf(m, "requests: %lld\n", + ksmbd_counter_sum(KSMBD_COUNTER_REQUESTS)); seq_printf(m, "read bytes: %lld\n", ksmbd_counter_sum(KSMBD_COUNTER_READ_BYTES)); seq_printf(m, "written bytes: %lld\n", diff --git a/fs/smb/server/stats.h b/fs/smb/server/stats.h index b60c30c69077..08ee66f91eaa 100644 --- a/fs/smb/server/stats.h +++ b/fs/smb/server/stats.h @@ -52,8 +52,10 @@ static inline void ksmbd_counter_sub(int type, s64 value) static inline void ksmbd_counter_inc_reqs(unsigned int cmd) { - if (cmd < KSMBD_COUNTER_MAX_REQS) + if (cmd < KSMBD_COUNTER_MAX_REQS) { + percpu_counter_inc(&ksmbd_counters.counters[KSMBD_COUNTER_REQUESTS]); percpu_counter_inc(&ksmbd_counters.counters[KSMBD_COUNTER_FIRST_REQ + cmd]); + } } static inline s64 ksmbd_counter_sum(int type) diff --git a/fs/smb/server/vfs_cache.c b/fs/smb/server/vfs_cache.c index c0dbb5ef3bcd..c867cf32ae9c 100644 --- a/fs/smb/server/vfs_cache.c +++ b/fs/smb/server/vfs_cache.c @@ -66,7 +66,7 @@ static const struct ksmbd_const_name ksmbd_lease_const_names[] = { static const struct ksmbd_const_name ksmbd_oplock_const_names[] = { {SMB2_OPLOCK_LEVEL_NONE, "OPLOCK_NONE"}, {SMB2_OPLOCK_LEVEL_II, "OPLOCK_II"}, - {SMB2_OPLOCK_LEVEL_EXCLUSIVE, "OPLOCK_EXECL"}, + {SMB2_OPLOCK_LEVEL_EXCLUSIVE, "OPLOCK_EXCLUSIVE"}, {SMB2_OPLOCK_LEVEL_BATCH, "OPLOCK_BATCH"}, }; @@ -76,14 +76,14 @@ static int proc_show_files(struct seq_file *m, void *v) unsigned int id; struct oplock_info *opinfo; - seq_printf(m, "#%-10s %-10s %-10s %-10s %-15s %-10s %-10s %s\n", + seq_printf(m, "#%-10s %-18s %-18s %-10s %-16s %-10s %-10s %s\n", "<tree id>", "<pid>", "<vid>", "<refcnt>", "<oplock>", "<daccess>", "<saccess>", "<name>"); read_lock(&global_ft.lock); idr_for_each_entry(global_ft.idr, fp, id) { - seq_printf(m, "%#-10x %#-10llx %#-10llx %#-10x", + seq_printf(m, " %#-10x %#-18llx %#-18llx %#-10x", fp->tcon ? fp->tcon->id : 0, fp->persistent_id, fp->volatile_id, @@ -93,6 +93,7 @@ static int proc_show_files(struct seq_file *m, void *v) opinfo = rcu_dereference(fp->f_opinfo); if (opinfo) { const struct ksmbd_const_name *const_names; + const char *name; int count; unsigned int level; @@ -106,11 +107,14 @@ static int proc_show_files(struct seq_file *m, void *v) level = opinfo->level; } rcu_read_unlock(); - ksmbd_proc_show_const_name(m, " %-15s", - const_names, count, level); + name = ksmbd_proc_const_name(const_names, count, level); + if (name) + seq_printf(m, " %-16s", name); + else + seq_printf(m, " 0x%-14x", level); } else { rcu_read_unlock(); - seq_printf(m, " %-15s", " "); + seq_printf(m, " %-16s", " "); } seq_printf(m, " %#010x %#010x %s\n", -- 2.25.1