]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
smb3 client: add way to show directory leases for improved debugging
authorSteve French <stfrench@microsoft.com>
Mon, 28 Jul 2025 17:32:53 +0000 (12:32 -0500)
committerSteve French <stfrench@microsoft.com>
Thu, 31 Jul 2025 14:42:54 +0000 (09:42 -0500)
When looking at performance issues around directory caching, or debugging
directory lease issues, it is helpful to be able to display the current
directory leases (as we can e.g. or open files).  Create pseudo-file
/proc/fs/cifs/open_dirs that displays current directory leases.  Here
is sample output:

cat /proc/fs/cifs/open_dirs
 Version:1
 Format:
 <tree id> <sess id> <persistent fid> <path>
Num entries: 3
0xce4c1c68 0x7176aa54 0xd95ef58e     \dira      valid file info, valid dirents
0xce4c1c68 0x7176aa54 0xd031e211     \dir5      valid file info, valid dirents
0xce4c1c68 0x7176aa54 0x96533a90     \dir1      valid file info

Reviewed-by: Bharath SM <bharathsm@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/cached_dir.h
fs/smb/client/cifs_debug.c

index 2c262881b7b1d84c5d68324fc3e928abda03ea9b..46b5a2fdf15b5ff1ed3a36e5857b78a3d36fc43e 100644 (file)
@@ -14,7 +14,6 @@ struct cached_dirent {
        char *name;
        int namelen;
        loff_t pos;
-
        struct cifs_fattr fattr;
 };
 
index 3fdf75737d43cc84db5a9f349dc323229c9778eb..f1cea365b6f10653a4aa78e1a58db20d3fcf5c68 100644 (file)
@@ -26,6 +26,7 @@
 #include "smbdirect.h"
 #endif
 #include "cifs_swn.h"
+#include "cached_dir.h"
 
 void
 cifs_dump_mem(char *label, void *data, int length)
@@ -280,6 +281,54 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
        return 0;
 }
 
+static int cifs_debug_dirs_proc_show(struct seq_file *m, void *v)
+{
+       struct list_head *stmp, *tmp, *tmp1;
+       struct TCP_Server_Info *server;
+       struct cifs_ses *ses;
+       struct cifs_tcon *tcon;
+       struct cached_fids *cfids;
+       struct cached_fid *cfid;
+       LIST_HEAD(entry);
+
+       seq_puts(m, "# Version:1\n");
+       seq_puts(m, "# Format:\n");
+       seq_puts(m, "# <tree id> <sess id> <persistent fid> <path>\n");
+
+       spin_lock(&cifs_tcp_ses_lock);
+       list_for_each(stmp, &cifs_tcp_ses_list) {
+               server = list_entry(stmp, struct TCP_Server_Info,
+                                   tcp_ses_list);
+               list_for_each(tmp, &server->smb_ses_list) {
+                       ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
+                       list_for_each(tmp1, &ses->tcon_list) {
+                               tcon = list_entry(tmp1, struct cifs_tcon, tcon_list);
+                               cfids = tcon->cfids;
+                               spin_lock(&cfids->cfid_list_lock); /* check lock ordering */
+                               seq_printf(m, "Num entries: %d\n", cfids->num_entries);
+                               list_for_each_entry(cfid, &cfids->entries, entry) {
+                                       seq_printf(m, "0x%x 0x%llx 0x%llx     %s",
+                                               tcon->tid,
+                                               ses->Suid,
+                                               cfid->fid.persistent_fid,
+                                               cfid->path);
+                                       if (cfid->file_all_info_is_valid)
+                                               seq_printf(m, "\tvalid file info");
+                                       if (cfid->dirents.is_valid)
+                                               seq_printf(m, ", valid dirents");
+                                       seq_printf(m, "\n");
+                               }
+                               spin_unlock(&cfids->cfid_list_lock);
+
+
+                       }
+               }
+       }
+       spin_unlock(&cifs_tcp_ses_lock);
+       seq_putc(m, '\n');
+       return 0;
+}
+
 static __always_inline const char *compression_alg_str(__le16 alg)
 {
        switch (alg) {
@@ -863,6 +912,9 @@ cifs_proc_init(void)
        proc_create_single("open_files", 0400, proc_fs_cifs,
                        cifs_debug_files_proc_show);
 
+       proc_create_single("open_dirs", 0400, proc_fs_cifs,
+                       cifs_debug_dirs_proc_show);
+
        proc_create("Stats", 0644, proc_fs_cifs, &cifs_stats_proc_ops);
        proc_create("cifsFYI", 0644, proc_fs_cifs, &cifsFYI_proc_ops);
        proc_create("traceSMB", 0644, proc_fs_cifs, &traceSMB_proc_ops);
@@ -907,6 +959,7 @@ cifs_proc_clean(void)
 
        remove_proc_entry("DebugData", proc_fs_cifs);
        remove_proc_entry("open_files", proc_fs_cifs);
+       remove_proc_entry("open_dirs", proc_fs_cifs);
        remove_proc_entry("cifsFYI", proc_fs_cifs);
        remove_proc_entry("traceSMB", proc_fs_cifs);
        remove_proc_entry("Stats", proc_fs_cifs);