Linux CIFS filesystem development
 help / color / mirror / Atom feed
From: Namjae Jeon <linkinjeon@kernel.org>
To: linux-cifs@vger.kernel.org
Cc: smfrench@gmail.com, senozhatsky@chromium.org, tom@talpey.com,
	atteh.mailbox@gmail.com, Namjae Jeon <linkinjeon@kernel.org>
Subject: [PATCH 5/7] ksmbd: report session and open file details in procfs
Date: Thu, 16 Jul 2026 18:57:08 +0900	[thread overview]
Message-ID: <20260716095711.6228-5-linkinjeon@kernel.org> (raw)
In-Reply-To: <20260716095711.6228-1-linkinjeon@kernel.org>

Session and file proc entries lack the state needed to correlate inactive
sessions with durable or delete-pending opens.

Add the account type, dialect, idle time, open-file count, tree-connect
count, and per-channel POSIX negotiation state to session entries. Extend
the open-file table with the file state, durable timeout, create options,
share access, and descriptive flags for durable, persistent, resilient,
delete-on-close, stream, POSIX, and attribute-only opens.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
---
 fs/smb/server/mgmt/user_session.c | 82 ++++++++++++++++++++----------
 fs/smb/server/vfs_cache.c         | 84 +++++++++++++++++++++++++------
 2 files changed, 123 insertions(+), 43 deletions(-)

diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c
index 09c944a67141..b2bc8119984f 100644
--- a/fs/smb/server/mgmt/user_session.c
+++ b/fs/smb/server/mgmt/user_session.c
@@ -78,6 +78,28 @@ static const char *session_user_name(struct ksmbd_session *session)
 	return session->user->name;
 }
 
+static const char *session_account_type(struct ksmbd_session *session)
+{
+	if (user_guest(session->user))
+		return "guest";
+	if (ksmbd_anonymous_user(session->user))
+		return "anonymous";
+	return "user";
+}
+
+static unsigned int session_open_file_count(struct ksmbd_session *session)
+{
+	struct ksmbd_file *fp;
+	unsigned int count = 0;
+	unsigned int id;
+
+	read_lock(&session->file_table.lock);
+	idr_for_each_entry(session->file_table.idr, fp, id)
+		count++;
+	read_unlock(&session->file_table.lock);
+	return count;
+}
+
 static int show_proc_session(struct seq_file *m, void *v)
 {
 	struct ksmbd_session *sess;
@@ -90,9 +112,16 @@ 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));
+	seq_printf(m, "user:\t%s\n", session_user_name(sess));
+	seq_printf(m, "account_type:\t%s\n",
+		   session_account_type(sess));
+	seq_printf(m, "id:\t%llu\n", sess->id);
+	seq_printf(m, "state:\t%s\n", session_state_string(sess));
+	seq_printf(m, "dialect:\t0x%04x\n", sess->dialect);
+	seq_printf(m, "last_active_seconds:\t%lu\n",
+		   jiffies_to_msecs(jiffies - sess->last_active) / MSEC_PER_SEC);
+	seq_printf(m, "open_files:\t%u\n",
+		   session_open_file_count(sess));
 
 	i = 0;
 	down_read(&sess->chann_lock);
@@ -101,21 +130,23 @@ static int show_proc_session(struct seq_file *m, void *v)
 
 #if IS_ENABLED(CONFIG_IPV6)
 		if (chan->conn->inet_addr)
-			seq_printf(m, "%-20s\t%pI4\n", "client",
+			seq_printf(m, "client:\t%pI4\n",
 					&chan->conn->inet_addr);
 		else
-			seq_printf(m, "%-20s\t%pI6c\n", "client",
+			seq_printf(m, "client:\t%pI6c\n",
 					&chan->conn->inet6_addr);
 #else
-		seq_printf(m, "%-20s\t%pI4\n", "client",
+		seq_printf(m, "client:\t%pI4\n",
 				&chan->conn->inet_addr);
 #endif
-		seq_printf(m, "%-20s\t", "capabilities");
+		seq_puts(m, "capabilities:\t");
 		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');
+		seq_printf(m, "posix_extensions:\t%s\n",
+			   chan->conn->posix_ext_supported ? "yes" : "no");
 
 		if (sess->sign) {
 			unsigned int algorithm =
@@ -125,9 +156,9 @@ static int show_proc_session(struct seq_file *m, void *v)
 						     ARRAY_SIZE(ksmbd_signing_const_names),
 						     algorithm);
 			if (name)
-				seq_printf(m, "%-20s\t%s\n", "signing", name);
+				seq_printf(m, "signing:\t%s\n", name);
 			else
-				seq_printf(m, "%-20s\t0x%04x\n", "signing",
+				seq_printf(m, "signing:\t0x%04x\n",
 					   algorithm);
 		}
 		if (sess->enc) {
@@ -137,30 +168,30 @@ static int show_proc_session(struct seq_file *m, void *v)
 						     ARRAY_SIZE(ksmbd_cipher_const_names),
 						     cipher);
 			if (name)
-				seq_printf(m, "%-20s\t%s\n", "encryption", name);
+				seq_printf(m, "encryption:\t%s\n", name);
 			else
-				seq_printf(m, "%-20s\t0x%04x\n", "encryption",
+				seq_printf(m, "encryption:\t0x%04x\n",
 					   cipher);
 		}
 		i++;
 	}
 	up_read(&sess->chann_lock);
 
-	seq_printf(m, "%-20s\t%d\n", "channels", i);
+	seq_printf(m, "channels:\t%d\n", i);
 
 	i = 0;
 	down_read(&sess->tree_conns_lock);
 	xa_for_each(&sess->tree_conns, id, tree_conn) {
 		share_conf = tree_conn->share_conf;
-		seq_printf(m, "%-20s\t%s\t%8d", "share",
-			   share_conf->name, tree_conn->id);
-		if (test_share_config_flag(share_conf, KSMBD_SHARE_FLAG_PIPE))
-			seq_printf(m, " %s ", "pipe");
-		else
-			seq_printf(m, " %s ", "disk");
-		seq_putc(m, '\n');
+		seq_printf(m, "share:\t%s\n", share_conf->name);
+		seq_printf(m, "tree_id:\t%d\n", tree_conn->id);
+		seq_printf(m, "share_type:\t%s\n",
+			   test_share_config_flag(share_conf, KSMBD_SHARE_FLAG_PIPE) ?
+			   "pipe" : "disk");
+		i++;
 	}
 	up_read(&sess->tree_conns_lock);
+	seq_printf(m, "tree_connects:\t%d\n", i);
 
 	ksmbd_user_session_put(sess);
 	return 0;
@@ -189,9 +220,6 @@ static int show_proc_sessions(struct seq_file *m, void *v)
 	int i;
 	unsigned long id;
 
-	seq_printf(m, "#%-40s %-15s %-10s %-10s\n",
-		   "<client>", "<user>", "<sess_id>", "<state>");
-
 	down_read(&sessions_table_lock);
 	hash_for_each(sessions_table, i, session, hlist) {
 		down_read(&session->chann_lock);
@@ -201,13 +229,13 @@ static int show_proc_sessions(struct seq_file *m, void *v)
 
 #if IS_ENABLED(CONFIG_IPV6)
 			if (!chan->conn->inet_addr)
-				seq_printf(m, " %-40pI6c", &chan->conn->inet6_addr);
+				seq_printf(m, "client:\t%pI6c\n", &chan->conn->inet6_addr);
 			else
 #endif
-				seq_printf(m, " %-40pI4", &chan->conn->inet_addr);
-			seq_printf(m, " %-15s %-10llu %-10s\n",
-				   session_user_name(session),
-				   session->id,
+				seq_printf(m, "client:\t%pI4\n", &chan->conn->inet_addr);
+			seq_printf(m, "user:\t%s\n", session_user_name(session));
+			seq_printf(m, "id:\t%llu\n", session->id);
+			seq_printf(m, "state:\t%s\n\n",
 				   session_state_string(session));
 
 			ksmbd_user_session_put(session);
diff --git a/fs/smb/server/vfs_cache.c b/fs/smb/server/vfs_cache.c
index c867cf32ae9c..5c1929a81234 100644
--- a/fs/smb/server/vfs_cache.c
+++ b/fs/smb/server/vfs_cache.c
@@ -70,24 +70,63 @@ static const struct ksmbd_const_name ksmbd_oplock_const_names[] = {
 	{SMB2_OPLOCK_LEVEL_BATCH, "OPLOCK_BATCH"},
 };
 
+static const struct ksmbd_const_name ksmbd_file_state_names[] = {
+	{FP_NEW, "new"},
+	{FP_INITED, "open"},
+	{FP_CLOSED, "closed"},
+};
+
+#define KSMBD_PROC_FILE_DURABLE		BIT(0)
+#define KSMBD_PROC_FILE_PERSISTENT	BIT(1)
+#define KSMBD_PROC_FILE_RESILIENT	BIT(2)
+#define KSMBD_PROC_FILE_DELETE_ON_CLOSE	BIT(3)
+#define KSMBD_PROC_FILE_STREAM		BIT(4)
+#define KSMBD_PROC_FILE_POSIX		BIT(5)
+#define KSMBD_PROC_FILE_ATTRIB_ONLY	BIT(6)
+
+static const struct ksmbd_const_name ksmbd_file_flag_names[] = {
+	{KSMBD_PROC_FILE_DURABLE, "durable"},
+	{KSMBD_PROC_FILE_PERSISTENT, "persistent"},
+	{KSMBD_PROC_FILE_RESILIENT, "resilient"},
+	{KSMBD_PROC_FILE_DELETE_ON_CLOSE, "delete-on-close"},
+	{KSMBD_PROC_FILE_STREAM, "stream"},
+	{KSMBD_PROC_FILE_POSIX, "posix"},
+	{KSMBD_PROC_FILE_ATTRIB_ONLY, "attrib-only"},
+};
+
+static unsigned int ksmbd_proc_file_flags(struct ksmbd_file *fp)
+{
+	unsigned int flags = 0;
+
+	if (fp->is_durable)
+		flags |= KSMBD_PROC_FILE_DURABLE;
+	if (fp->is_persistent)
+		flags |= KSMBD_PROC_FILE_PERSISTENT;
+	if (fp->is_resilient)
+		flags |= KSMBD_PROC_FILE_RESILIENT;
+	if (fp->coption & FILE_DELETE_ON_CLOSE_LE)
+		flags |= KSMBD_PROC_FILE_DELETE_ON_CLOSE;
+	if (fp->stream.name)
+		flags |= KSMBD_PROC_FILE_STREAM;
+	if (fp->is_posix_ctxt)
+		flags |= KSMBD_PROC_FILE_POSIX;
+	if (fp->attrib_only)
+		flags |= KSMBD_PROC_FILE_ATTRIB_ONLY;
+	return flags;
+}
+
 static int proc_show_files(struct seq_file *m, void *v)
 {
 	struct ksmbd_file *fp = NULL;
 	unsigned int id;
 	struct oplock_info *opinfo;
 
-	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 %#-18llx %#-18llx %#-10x",
-			   fp->tcon ? fp->tcon->id : 0,
-			   fp->persistent_id,
-			   fp->volatile_id,
-			   atomic_read(&fp->refcount));
+		seq_printf(m, "tree_id:\t0x%x\n", fp->tcon ? fp->tcon->id : 0);
+		seq_printf(m, "persistent_id:\t0x%llx\n", fp->persistent_id);
+		seq_printf(m, "volatile_id:\t0x%llx\n", fp->volatile_id);
+		seq_printf(m, "refcount:\t%d\n", atomic_read(&fp->refcount));
 
 		rcu_read_lock();
 		opinfo = rcu_dereference(fp->f_opinfo);
@@ -109,17 +148,30 @@ static int proc_show_files(struct seq_file *m, void *v)
 			rcu_read_unlock();
 			name = ksmbd_proc_const_name(const_names, count, level);
 			if (name)
-				seq_printf(m, " %-16s", name);
+				seq_printf(m, "oplock:\t%s\n", name);
 			else
-				seq_printf(m, " 0x%-14x", level);
+				seq_printf(m, "oplock:\t0x%x\n", level);
 		} else {
 			rcu_read_unlock();
-			seq_printf(m, " %-16s", " ");
+			seq_puts(m, "oplock:\tnone\n");
 		}
 
-		seq_printf(m, " %#010x %#010x %s\n",
-			   le32_to_cpu(fp->daccess),
-			   le32_to_cpu(fp->saccess),
+		seq_printf(m, "state:\t%s\n",
+			   ksmbd_proc_const_name(ksmbd_file_state_names,
+						 ARRAY_SIZE(ksmbd_file_state_names),
+						 fp->f_state));
+		seq_printf(m, "durable_timeout:\t%u\n", fp->durable_timeout);
+		seq_printf(m, "create_options:\t0x%08x\n",
+			   le32_to_cpu(fp->coption));
+		seq_printf(m, "desired_access:\t0x%08x\n",
+			   le32_to_cpu(fp->daccess));
+		seq_printf(m, "share_access:\t0x%08x\n",
+			   le32_to_cpu(fp->saccess));
+		seq_puts(m, "flags:\t");
+		ksmbd_proc_show_flag_names(m, ksmbd_file_flag_names,
+					   ARRAY_SIZE(ksmbd_file_flag_names),
+					   ksmbd_proc_file_flags(fp));
+		seq_printf(m, "\nname:\t%s\n\n",
 			   fp->filp->f_path.dentry->d_name.name);
 	}
 	read_unlock(&global_ft.lock);
-- 
2.25.1


  parent reply	other threads:[~2026-07-16  9:57 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-16  9:57 [PATCH 1/7] ksmbd: implement the command sequence window Namjae Jeon
2026-07-16  9:57 ` [PATCH 2/7] ksmbd: add SMB3 request replay support Namjae Jeon
2026-07-16  9:57 ` [PATCH 3/7] ksmbd: fix malformed procfs status output Namjae Jeon
2026-07-16  9:57 ` [PATCH 4/7] ksmbd: expose connection runtime state in procfs Namjae Jeon
2026-07-16  9:57 ` Namjae Jeon [this message]
2026-07-16  9:57 ` [PATCH 6/7] ksmbd: add procfs monitoring for active shares Namjae Jeon
2026-07-16  9:57 ` [PATCH 7/7] ksmbd: extend procfs server statistics Namjae Jeon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260716095711.6228-5-linkinjeon@kernel.org \
    --to=linkinjeon@kernel.org \
    --cc=atteh.mailbox@gmail.com \
    --cc=linux-cifs@vger.kernel.org \
    --cc=senozhatsky@chromium.org \
    --cc=smfrench@gmail.com \
    --cc=tom@talpey.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox