linux-cifs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [SMB CLIENT][PATCHES] directory lease debugging and configuration
@ 2025-09-30  4:30 Steve French
  2025-09-30 13:11 ` Enzo Matsumiya
  0 siblings, 1 reply; 4+ messages in thread
From: Steve French @ 2025-09-30  4:30 UTC (permalink / raw)
  To: CIFS; +Cc: Bharath S M, samba-technical

[-- Attachment #1: Type: text/plain, Size: 2664 bytes --]

4 patches from Bharath to improve directory lease handling (see
attached).  Lightly updated and rebased on current mainline, and
merged into cifs-2.6.git for-next.  Feedback/review/comments welcome

commit a50843f864205ea4576638cb32321313d9c06e54
Author: Bharath SM <bharathsm@microsoft.com>
Date:   Tue Sep 2 14:18:21 2025 +0530

    smb: client: cap smb directory cache memory via module parameter

    The CIFS directory entry cache could grow without a global
    bound across mounts. Add a module-wide cap to limit memory
    used by cached dirents and avoid unbounded growth.

    Introduce a new module parameter, dir_cache_max_memory_kb
    (KB units; 0 = unlimited). When unset and directory caching
    is enabled (dir_cache_timeout != 0), default the cap to ~10%
    of system RAM during module init. The parameter is exposed
    under: /sys/module/cifs/parameters/dir_cache_max_memory_kb.

    Signed-off-by: Bharath SM <bharathsm@microsoft.com>
    Signed-off-by: Steve French <stfrench@microsoft.com>

commit 8e2727c9292125b6373b2a1edf1da59510081251
Author: Bharath SM <bharathsm@microsoft.com>
Date:   Mon Sep 29 15:57:46 2025 -0500

    smb: client: account smb directory cache usage and per-tcon totals

    Add lightweight accounting for directory lease cache usage
    to aid debugging and limiting cache size in future. Track
    per-directory entry/byte counts and maintain per-tcon
    aggregates. Also expose the totals in /proc/fs/cifs/open_dirs.

    Signed-off-by: Bharath SM <bharathsm@microsoft.com>
    Signed-off-by: Steve French <stfrench@microsoft.com>

commit 645b07fa68f5f001ad7a457166eac31832f1290b
Author: Bharath SM <bharathsm@microsoft.com>
Date:   Tue Sep 2 16:46:03 2025 +0530

    smb: client: show lease state as R/H/W (or NONE) in open_files

    Print the lease/oplock caching state for each open file as a
    compact string of letters: R (read), H (handle), W (write).

    Signed-off-by: Bharath SM <bharathsm@microsoft.com>
    Signed-off-by: Steve French <stfrench@microsoft.com>

commit cfcf4725d2f7251232304e4780929a47e1bb3931
Author: Bharath SM <bharathsm@microsoft.com>
Date:   Tue Sep 2 01:16:00 2025 +0530

    smb: client: add drop_dir_cache module parameter to invalidate
cached dirents

    Add write-only /sys/module/cifs/parameters/drop_dir_cache. Writing a
    non-zero value iterates all tcons and calls invalidate_all_cached_dirs()
    to drop cached directory entries. This is useful to force a dirent cache
    drop across mounts for debugging and testing purpose.

    Signed-off-by: Bharath SM <bharathsm@microsoft.com>
    Signed-off-by: Steve French <stfrench@microsoft.com>

-- 
Thanks,

Steve

[-- Attachment #2: 0004-smb-client-add-drop_dir_cache-module-parameter-to-in.patch --]
[-- Type: text/x-patch, Size: 2366 bytes --]

From cfcf4725d2f7251232304e4780929a47e1bb3931 Mon Sep 17 00:00:00 2001
From: Bharath SM <bharathsm@microsoft.com>
Date: Tue, 2 Sep 2025 01:16:00 +0530
Subject: [PATCH 04/16] smb: client: add drop_dir_cache module parameter to
 invalidate cached dirents

Add write-only /sys/module/cifs/parameters/drop_dir_cache. Writing a
non-zero value iterates all tcons and calls invalidate_all_cached_dirs()
to drop cached directory entries. This is useful to force a dirent cache
drop across mounts for debugging and testing purpose.

Signed-off-by: Bharath SM <bharathsm@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
 fs/smb/client/cifsfs.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index dcb39d1b5958..9a83f528d39d 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -121,6 +121,44 @@ unsigned int dir_cache_timeout = 30;
 module_param(dir_cache_timeout, uint, 0644);
 MODULE_PARM_DESC(dir_cache_timeout, "Number of seconds to cache directory contents for which we have a lease. Default: 30 "
 				 "Range: 1 to 65000 seconds, 0 to disable caching dir contents");
+
+/*
+ * Write-only module parameter to drop all cached directory entries across
+ * all CIFS mounts. Echo a non-zero value to trigger.
+ */
+static void cifs_drop_all_dir_caches(void)
+{
+	struct TCP_Server_Info *server;
+	struct cifs_ses *ses;
+	struct cifs_tcon *tcon;
+
+	spin_lock(&cifs_tcp_ses_lock);
+	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
+		list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
+			if (cifs_ses_exiting(ses))
+				continue;
+			list_for_each_entry(tcon, &ses->tcon_list, tcon_list)
+				invalidate_all_cached_dirs(tcon);
+		}
+	}
+	spin_unlock(&cifs_tcp_ses_lock);
+}
+
+static int cifs_param_set_drop_dir_cache(const char *val, const struct kernel_param *kp)
+{
+	bool bv;
+	int rc = kstrtobool(val, &bv);
+
+	if (rc)
+		return rc;
+	if (bv)
+		cifs_drop_all_dir_caches();
+	return 0;
+}
+
+module_param_call(drop_dir_cache, cifs_param_set_drop_dir_cache, NULL, NULL, 0200);
+MODULE_PARM_DESC(drop_dir_cache, "Write 1 to drop all cached directory entries across all CIFS mounts");
+
 #ifdef CONFIG_CIFS_STATS2
 unsigned int slow_rsp_threshold = 1;
 module_param(slow_rsp_threshold, uint, 0644);
-- 
2.48.1


[-- Attachment #3: 0006-smb-client-account-smb-directory-cache-usage-and-per.patch --]
[-- Type: text/x-patch, Size: 7568 bytes --]

From 8e2727c9292125b6373b2a1edf1da59510081251 Mon Sep 17 00:00:00 2001
From: Bharath SM <bharathsm@microsoft.com>
Date: Mon, 29 Sep 2025 15:57:46 -0500
Subject: [PATCH 06/16] smb: client: account smb directory cache usage and
 per-tcon totals

Add lightweight accounting for directory lease cache usage
to aid debugging and limiting cache size in future. Track
per-directory entry/byte counts and maintain per-tcon
aggregates. Also expose the totals in /proc/fs/cifs/open_dirs.

Signed-off-by: Bharath SM <bharathsm@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
 fs/smb/client/cached_dir.c | 18 +++++++++++++++++
 fs/smb/client/cached_dir.h |  9 +++++++++
 fs/smb/client/cifs_debug.c |  8 +++++++-
 fs/smb/client/cifsfs.c     |  2 ++
 fs/smb/client/readdir.c    | 40 +++++++++++++++++++++++++-------------
 5 files changed, 63 insertions(+), 14 deletions(-)

diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
index b69daeb1301b..b6f538a1d5af 100644
--- a/fs/smb/client/cached_dir.c
+++ b/fs/smb/client/cached_dir.c
@@ -697,6 +697,21 @@ static void free_cached_dir(struct cached_fid *cfid)
 		kfree(dirent);
 	}
 
+	/* adjust tcon-level counters and reset per-dir accounting */
+	if (cfid->cfids) {
+		if (cfid->dirents.entries_count)
+			atomic_long_sub((long)cfid->dirents.entries_count,
+					&cfid->cfids->total_dirents_entries);
+		if (cfid->dirents.bytes_used) {
+			atomic64_sub((long long)cfid->dirents.bytes_used,
+					&cfid->cfids->total_dirents_bytes);
+			atomic64_sub((long long)cfid->dirents.bytes_used,
+					&cifs_dircache_bytes_used);
+		}
+	}
+	cfid->dirents.entries_count = 0;
+	cfid->dirents.bytes_used = 0;
+
 	kfree(cfid->path);
 	cfid->path = NULL;
 	kfree(cfid);
@@ -792,6 +807,9 @@ struct cached_fids *init_cached_dirs(void)
 	queue_delayed_work(cfid_put_wq, &cfids->laundromat_work,
 			   dir_cache_timeout * HZ);
 
+	atomic_long_set(&cfids->total_dirents_entries, 0);
+	atomic64_set(&cfids->total_dirents_bytes, 0);
+
 	return cfids;
 }
 
diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h
index 46b5a2fdf15b..c98f02943311 100644
--- a/fs/smb/client/cached_dir.h
+++ b/fs/smb/client/cached_dir.h
@@ -27,6 +27,9 @@ struct cached_dirents {
 	struct mutex de_mutex;
 	loff_t pos;		 /* Expected ctx->pos */
 	struct list_head entries;
+	/* accounting for cached entries in this directory */
+	unsigned long entries_count;
+	unsigned long bytes_used;
 };
 
 struct cached_fid {
@@ -62,8 +65,14 @@ struct cached_fids {
 	struct list_head dying;
 	struct work_struct invalidation_work;
 	struct delayed_work laundromat_work;
+	/* aggregate accounting for all cached dirents under this tcon */
+	atomic_long_t total_dirents_entries;
+	atomic64_t total_dirents_bytes;
 };
 
+/* Module-wide directory cache accounting (defined in cifsfs.c) */
+extern atomic64_t cifs_dircache_bytes_used; /* bytes across all mounts */
+
 extern struct cached_fids *init_cached_dirs(void);
 extern void free_cached_dirs(struct cached_fids *cfids);
 extern int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c
index 75f5f60f0bb8..1fb71d2d31b5 100644
--- a/fs/smb/client/cifs_debug.c
+++ b/fs/smb/client/cifs_debug.c
@@ -331,7 +331,10 @@ static int cifs_debug_dirs_proc_show(struct seq_file *m, void *v)
 				if (!cfids)
 					continue;
 				spin_lock(&cfids->cfid_list_lock); /* check lock ordering */
-				seq_printf(m, "Num entries: %d\n", cfids->num_entries);
+				seq_printf(m, "Num entries: %d, cached_dirents: %lu entries, %llu bytes\n",
+						cfids->num_entries,
+						(unsigned long)atomic_long_read(&cfids->total_dirents_entries),
+						(unsigned long long)atomic64_read(&cfids->total_dirents_bytes));
 				list_for_each_entry(cfid, &cfids->entries, entry) {
 					seq_printf(m, "0x%x 0x%llx 0x%llx     %s",
 						tcon->tid,
@@ -342,6 +345,9 @@ static int cifs_debug_dirs_proc_show(struct seq_file *m, void *v)
 						seq_printf(m, "\tvalid file info");
 					if (cfid->dirents.is_valid)
 						seq_printf(m, ", valid dirents");
+					if (!list_empty(&cfid->dirents.entries))
+						seq_printf(m, ", dirents: %lu entries, %lu bytes",
+						cfid->dirents.entries_count, cfid->dirents.bytes_used);
 					seq_printf(m, "\n");
 				}
 				spin_unlock(&cfids->cfid_list_lock);
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index 9a83f528d39d..1775c2b7528f 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -121,6 +121,8 @@ unsigned int dir_cache_timeout = 30;
 module_param(dir_cache_timeout, uint, 0644);
 MODULE_PARM_DESC(dir_cache_timeout, "Number of seconds to cache directory contents for which we have a lease. Default: 30 "
 				 "Range: 1 to 65000 seconds, 0 to disable caching dir contents");
+/* Module-wide total cached dirents (in bytes) across all tcons */
+atomic64_t cifs_dircache_bytes_used = ATOMIC64_INIT(0);
 
 /*
  * Write-only module parameter to drop all cached directory entries across
diff --git a/fs/smb/client/readdir.c b/fs/smb/client/readdir.c
index 4e5460206397..f0ce26622a14 100644
--- a/fs/smb/client/readdir.c
+++ b/fs/smb/client/readdir.c
@@ -874,39 +874,42 @@ static void finished_cached_dirents_count(struct cached_dirents *cde,
 	cde->is_valid = 1;
 }
 
-static void add_cached_dirent(struct cached_dirents *cde,
-			      struct dir_context *ctx,
-			      const char *name, int namelen,
-			      struct cifs_fattr *fattr,
-				  struct file *file)
+static bool add_cached_dirent(struct cached_dirents *cde,
+			      struct dir_context *ctx, const char *name,
+			      int namelen, struct cifs_fattr *fattr,
+			      struct file *file)
 {
 	struct cached_dirent *de;
 
 	if (cde->file != file)
-		return;
+		return false;
 	if (cde->is_valid || cde->is_failed)
-		return;
+		return false;
 	if (ctx->pos != cde->pos) {
 		cde->is_failed = 1;
-		return;
+		return false;
 	}
 	de = kzalloc(sizeof(*de), GFP_ATOMIC);
 	if (de == NULL) {
 		cde->is_failed = 1;
-		return;
+		return false;
 	}
 	de->namelen = namelen;
 	de->name = kstrndup(name, namelen, GFP_ATOMIC);
 	if (de->name == NULL) {
 		kfree(de);
 		cde->is_failed = 1;
-		return;
+		return false;
 	}
 	de->pos = ctx->pos;
 
 	memcpy(&de->fattr, fattr, sizeof(struct cifs_fattr));
 
 	list_add_tail(&de->entry, &cde->entries);
+	/* update accounting */
+	cde->entries_count++;
+	cde->bytes_used += sizeof(*de) + (size_t)namelen + 1;
+	return true;
 }
 
 static bool cifs_dir_emit(struct dir_context *ctx,
@@ -915,7 +918,8 @@ static bool cifs_dir_emit(struct dir_context *ctx,
 			  struct cached_fid *cfid,
 			  struct file *file)
 {
-	bool rc;
+	size_t delta_bytes = 0;
+	bool rc, added = false;
 	ino_t ino = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
 
 	rc = dir_emit(ctx, name, namelen, ino, fattr->cf_dtype);
@@ -923,10 +927,20 @@ static bool cifs_dir_emit(struct dir_context *ctx,
 		return rc;
 
 	if (cfid) {
+		/* Cost of this entry */
+		delta_bytes = sizeof(struct cached_dirent) + (size_t)namelen + 1;
+
 		mutex_lock(&cfid->dirents.de_mutex);
-		add_cached_dirent(&cfid->dirents, ctx, name, namelen,
-				  fattr, file);
+		added = add_cached_dirent(&cfid->dirents, ctx, name, namelen,
+					  fattr, file);
 		mutex_unlock(&cfid->dirents.de_mutex);
+
+		if (added) {
+			/* per-tcon then global for consistency with free path */
+			atomic64_add((long long)delta_bytes, &cfid->cfids->total_dirents_bytes);
+			atomic_long_inc(&cfid->cfids->total_dirents_entries);
+			atomic64_add((long long)delta_bytes, &cifs_dircache_bytes_used);
+		}
 	}
 
 	return rc;
-- 
2.48.1


[-- Attachment #4: 0005-smb-client-show-lease-state-as-R-H-W-or-NONE-in-open.patch --]
[-- Type: text/x-patch, Size: 2433 bytes --]

From 645b07fa68f5f001ad7a457166eac31832f1290b Mon Sep 17 00:00:00 2001
From: Bharath SM <bharathsm@microsoft.com>
Date: Tue, 2 Sep 2025 16:46:03 +0530
Subject: [PATCH 05/16] smb: client: show lease state as R/H/W (or NONE) in
 open_files

Print the lease/oplock caching state for each open file as a
compact string of letters: R (read), H (handle), W (write).

Signed-off-by: Bharath SM <bharathsm@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
 fs/smb/client/cifs_debug.c | 33 ++++++++++++++++++++++++++++-----
 1 file changed, 28 insertions(+), 5 deletions(-)

diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c
index 35c4d27d2cc0..75f5f60f0bb8 100644
--- a/fs/smb/client/cifs_debug.c
+++ b/fs/smb/client/cifs_debug.c
@@ -240,14 +240,18 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
 	struct cifs_ses *ses;
 	struct cifs_tcon *tcon;
 	struct cifsFileInfo *cfile;
+	struct inode *inode;
+	struct cifsInodeInfo *cinode;
+	char lease[4];
+	int n;
 
 	seq_puts(m, "# Version:1\n");
 	seq_puts(m, "# Format:\n");
 	seq_puts(m, "# <tree id> <ses id> <persistent fid> <flags> <count> <pid> <uid>");
 #ifdef CONFIG_CIFS_DEBUG2
-	seq_printf(m, " <filename> <mid>\n");
+	seq_puts(m, " <filename> <lease> <mid>\n");
 #else
-	seq_printf(m, " <filename>\n");
+	seq_puts(m, " <filename> <lease>\n");
 #endif /* CIFS_DEBUG2 */
 	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
@@ -267,11 +271,30 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
 						cfile->pid,
 						from_kuid(&init_user_ns, cfile->uid),
 						cfile->dentry);
+
+					/* Append lease/oplock caching state as RHW letters */
+					inode = d_inode(cfile->dentry);
+					n = 0;
+					if (inode) {
+						cinode = CIFS_I(inode);
+						if (CIFS_CACHE_READ(cinode))
+							lease[n++] = 'R';
+						if (CIFS_CACHE_HANDLE(cinode))
+							lease[n++] = 'H';
+						if (CIFS_CACHE_WRITE(cinode))
+							lease[n++] = 'W';
+					}
+					lease[n] = '\0';
+					seq_puts(m, " ");
+					if (n)
+						seq_printf(m, "%s", lease);
+					else
+						seq_puts(m, "NONE");
+
 #ifdef CONFIG_CIFS_DEBUG2
-					seq_printf(m, " %llu\n", cfile->fid.mid);
-#else
+					seq_printf(m, " %llu", cfile->fid.mid);
+#endif /* CONFIG_CIFS_DEBUG2 */
 					seq_printf(m, "\n");
-#endif /* CIFS_DEBUG2 */
 				}
 				spin_unlock(&tcon->open_file_lock);
 			}
-- 
2.48.1


[-- Attachment #5: 0007-smb-client-cap-smb-directory-cache-memory-via-module.patch --]
[-- Type: text/x-patch, Size: 4912 bytes --]

From a50843f864205ea4576638cb32321313d9c06e54 Mon Sep 17 00:00:00 2001
From: Bharath SM <bharathsm@microsoft.com>
Date: Tue, 2 Sep 2025 14:18:21 +0530
Subject: [PATCH 07/16] smb: client: cap smb directory cache memory via module
 parameter

The CIFS directory entry cache could grow without a global
bound across mounts. Add a module-wide cap to limit memory
used by cached dirents and avoid unbounded growth.

Introduce a new module parameter, dir_cache_max_memory_kb
(KB units; 0 = unlimited). When unset and directory caching
is enabled (dir_cache_timeout != 0), default the cap to ~10%
of system RAM during module init. The parameter is exposed
under: /sys/module/cifs/parameters/dir_cache_max_memory_kb.

Signed-off-by: Bharath SM <bharathsm@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
---
 fs/smb/client/cached_dir.h |  1 +
 fs/smb/client/cifsfs.c     | 15 +++++++++++++++
 fs/smb/client/readdir.c    | 25 ++++++++++++++++++++-----
 3 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h
index c98f02943311..ed58b41bf0df 100644
--- a/fs/smb/client/cached_dir.h
+++ b/fs/smb/client/cached_dir.h
@@ -72,6 +72,7 @@ struct cached_fids {
 
 /* Module-wide directory cache accounting (defined in cifsfs.c) */
 extern atomic64_t cifs_dircache_bytes_used; /* bytes across all mounts */
+extern unsigned long dir_cache_max_memory_kb; /* cap in KB; 0 = unlimited */
 
 extern struct cached_fids *init_cached_dirs(void);
 extern void free_cached_dirs(struct cached_fids *cfids);
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index 1775c2b7528f..b54740d806e9 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -121,6 +121,10 @@ unsigned int dir_cache_timeout = 30;
 module_param(dir_cache_timeout, uint, 0644);
 MODULE_PARM_DESC(dir_cache_timeout, "Number of seconds to cache directory contents for which we have a lease. Default: 30 "
 				 "Range: 1 to 65000 seconds, 0 to disable caching dir contents");
+/* Directory cache memory cap in KB (0 = unlimited). Defaults to ~10% of RAM. */
+unsigned long dir_cache_max_memory_kb;
+module_param(dir_cache_max_memory_kb, ulong, 0644);
+MODULE_PARM_DESC(dir_cache_max_memory_kb, "Module-wide memory cap for cached directory entries in KB (0 = unlimited). Default: ~10% of RAM");
 /* Module-wide total cached dirents (in bytes) across all tcons */
 atomic64_t cifs_dircache_bytes_used = ATOMIC64_INIT(0);
 
@@ -1935,6 +1939,17 @@ init_cifs(void)
 		cifs_dbg(VFS, "dir_cache_timeout set to max of 65000 seconds\n");
 	}
 
+	/* Set a default cap of ~10% of RAM if not specified (and caching isn't disabled) */
+	if (dir_cache_timeout != 0 && dir_cache_max_memory_kb == 0) {
+		u64 total_bytes;
+		unsigned long default_kb;
+
+		total_bytes = (u64)totalram_pages() << PAGE_SHIFT;
+		/* ~10% of RAM in KB */
+		default_kb = (unsigned long)((total_bytes / 10) >> 10);
+		dir_cache_max_memory_kb = default_kb;
+	}
+
 	cifsiod_wq = alloc_workqueue("cifsiod",
 				     WQ_FREEZABLE | WQ_MEM_RECLAIM | WQ_PERCPU,
 				     0);
diff --git a/fs/smb/client/readdir.c b/fs/smb/client/readdir.c
index f0ce26622a14..f75e157835b7 100644
--- a/fs/smb/client/readdir.c
+++ b/fs/smb/client/readdir.c
@@ -875,12 +875,16 @@ static void finished_cached_dirents_count(struct cached_dirents *cde,
 }
 
 static bool add_cached_dirent(struct cached_dirents *cde,
-			      struct dir_context *ctx, const char *name,
-			      int namelen, struct cifs_fattr *fattr,
-			      struct file *file)
+			  struct dir_context *ctx, const char *name,
+			  int namelen, struct cifs_fattr *fattr,
+			  struct file *file, bool can_cache)
 {
 	struct cached_dirent *de;
-
+	/* If we can't cache due to memory cap, mark cache as failed */
+	if (!can_cache) {
+		cde->is_failed = 1;
+		return false;
+	}
 	if (cde->file != file)
 		return false;
 	if (cde->is_valid || cde->is_failed)
@@ -921,6 +925,9 @@ static bool cifs_dir_emit(struct dir_context *ctx,
 	size_t delta_bytes = 0;
 	bool rc, added = false;
 	ino_t ino = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
+	u64 cap_bytes = 0;
+	u64 used_bytes = 0;
+	bool can_cache = true;
 
 	rc = dir_emit(ctx, name, namelen, ino, fattr->cf_dtype);
 	if (!rc)
@@ -930,9 +937,17 @@ static bool cifs_dir_emit(struct dir_context *ctx,
 		/* Cost of this entry */
 		delta_bytes = sizeof(struct cached_dirent) + (size_t)namelen + 1;
 
+		/* Enforce module-wide memory cap if enabled */
+		if (dir_cache_max_memory_kb) {
+			cap_bytes = (u64)dir_cache_max_memory_kb << 10;
+			used_bytes = (u64)atomic64_read(&cifs_dircache_bytes_used);
+			if (used_bytes + (u64)delta_bytes > cap_bytes)
+				can_cache = false;
+		}
+
 		mutex_lock(&cfid->dirents.de_mutex);
 		added = add_cached_dirent(&cfid->dirents, ctx, name, namelen,
-					  fattr, file);
+				fattr, file, can_cache);
 		mutex_unlock(&cfid->dirents.de_mutex);
 
 		if (added) {
-- 
2.48.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-10-24  9:14 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-30  4:30 [SMB CLIENT][PATCHES] directory lease debugging and configuration Steve French
2025-09-30 13:11 ` Enzo Matsumiya
2025-09-30 13:13   ` Enzo Matsumiya
2025-10-24  9:13   ` Bharath SM

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).