[PATCH 4/7] ksmbd: expose connection runtime state in procfs

Namjae Jeon <[email protected]>
Newsgroups org.kernel.vger.linux-cifs
Message-ID <[email protected]>
The clients proc file currently shows only a small subset of the state
needed to diagnose stalled or mis-negotiated connections.

Report the transport, connection state, outstanding and total credits,
session count, lifetime request count, and negotiated signing, encryption,
compression, and POSIX features. Report each connection as a key/value
record rather than a wide fixed-width table.

Signed-off-by: Namjae Jeon <[email protected]>
---
 fs/smb/server/connection.c | 96 +++++++++++++++++++++++++++++++++-----
 1 file changed, 84 insertions(+), 12 deletions(-)

diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c
index 47f6d561e150..26e312fb6da8 100644
--- a/fs/smb/server/connection.c
+++ b/fs/smb/server/connection.c
@@ -27,33 +27,105 @@ DECLARE_RWSEM(conn_list_lock);
 #ifdef CONFIG_PROC_FS
 static struct proc_dir_entry *proc_clients;
 
+static const char *ksmbd_conn_state_string(struct ksmbd_conn *conn)
+{
+	switch (READ_ONCE(conn->status)) {
+	case KSMBD_SESS_NEW:
+		return "new";
+	case KSMBD_SESS_GOOD:
+		return "good";
+	case KSMBD_SESS_EXITING:
+		return "exiting";
+	case KSMBD_SESS_NEED_RECONNECT:
+		return "reconnect";
+	case KSMBD_SESS_NEED_NEGOTIATE:
+		return "negotiate";
+	case KSMBD_SESS_NEED_SETUP:
+		return "setup";
+	case KSMBD_SESS_RELEASING:
+		return "releasing";
+	default:
+		return "unknown";
+	}
+}
+
+static const char *ksmbd_conn_transport_string(struct ksmbd_conn *conn)
+{
+	if (conn->transport->ops->rdma_read || conn->transport->ops->rdma_write)
+		return "smbdirect";
+	return "tcp";
+}
+
+static void proc_show_conn_feature(struct seq_file *m, bool *separator,
+				   bool enabled, const char *name)
+{
+	if (!enabled)
+		return;
+	seq_printf(m, "%s%s", *separator ? "," : "", name);
+	*separator = true;
+}
+
+static void proc_show_conn_features(struct seq_file *m,
+				    struct ksmbd_conn *conn)
+{
+	bool separator = false;
+
+	proc_show_conn_feature(m, &separator,
+			       conn->sign || conn->signing_negotiated, "sign");
+	proc_show_conn_feature(m, &separator, conn->cipher_type, "encrypt");
+	proc_show_conn_feature(m, &separator,
+			       conn->compress_algorithm != SMB3_COMPRESS_NONE,
+			       "compress");
+	proc_show_conn_feature(m, &separator, conn->posix_ext_supported, "posix");
+	if (!separator)
+		seq_puts(m, "none");
+}
+
 static int proc_show_clients(struct seq_file *m, void *v)
 {
 	struct ksmbd_conn *conn;
 	struct timespec64 now, t;
 	int i;
 
-	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) {
+		unsigned int outstanding_credits, total_credits;
+		unsigned long id;
+		void *entry;
+		unsigned int sessions = 0;
+
 		jiffies_to_timespec64(jiffies - conn->last_active, &t);
 		ktime_get_real_ts64(&now);
 		t = timespec64_sub(now, t);
+
+		spin_lock(&conn->credits_lock);
+		outstanding_credits = conn->outstanding_credits;
+		total_credits = conn->total_credits;
+		spin_unlock(&conn->credits_lock);
+
+		rcu_read_lock();
+		xa_for_each(&conn->sessions, id, entry)
+			sessions++;
+		rcu_read_unlock();
 #if IS_ENABLED(CONFIG_IPV6)
 		if (!conn->inet_addr)
-			seq_printf(m, " %-40pI6c", &conn->inet6_addr);
+			seq_printf(m, "client:\t%pI6c\n", &conn->inet6_addr);
 		else
 #endif
-			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),
-			   atomic_read(&conn->req_running),
-			   &t);
+			seq_printf(m, "client:\t%pI4\n", &conn->inet_addr);
+		seq_printf(m, "transport:\t%s\n", ksmbd_conn_transport_string(conn));
+		seq_printf(m, "state:\t%s\n", ksmbd_conn_state_string(conn));
+		seq_printf(m, "dialect:\t0x%04x\n", conn->dialect);
+		seq_printf(m, "credits:\t%u/%u\n", outstanding_credits,
+			   total_credits);
+		seq_printf(m, "sessions:\t%u\n", sessions);
+		seq_printf(m, "open_files:\t%d\n",
+			   atomic_read(&conn->stats.open_files_count));
+		seq_printf(m, "requests:\t%lld\n",
+			   atomic64_read(&conn->stats.request_served));
+		seq_puts(m, "features:\t");
+		proc_show_conn_features(m, conn);
+		seq_printf(m, "\nlast_active:\t%ptT\n\n", &t);
 	}
 	up_read(&conn_list_lock);
 	return 0;
-- 
2.25.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.