From: nspmangalore@gmail.com
To: linux-cifs@vger.kernel.org, smfrench@gmail.com, pc@manguebit.org,
bharathsm@microsoft.com, dhowells@redhat.com,
henrique.carvalho@suse.com, ematsumiya@suse.de
Cc: Shyam Prasad N <sprasad@microsoft.com>
Subject: [PATCH v4 12/19] cifs: register a shrinker to manage cached_dirents
Date: Fri, 1 May 2026 16:50:15 +0530 [thread overview]
Message-ID: <20260501112023.338005-12-sprasad@microsoft.com> (raw)
In-Reply-To: <20260501112023.338005-1-sprasad@microsoft.com>
From: Shyam Prasad N <sprasad@microsoft.com>
Since the cached_dirents are now backed by folioq, we do not need
a timed cleanup of these cfids anymore. This change registers a
shrinker with the mm layer for the dircache. If mm needs to free up
memory or flush the cache, it can inform cifs about this using the
shrinker interface.
Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
---
fs/smb/client/cifsfs.c | 86 +++++++++++++++++++++++++++++++++++++++---
1 file changed, 80 insertions(+), 6 deletions(-)
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index 32d0305a1239a..ee5de358e27f8 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -29,6 +29,7 @@
#include <linux/uuid.h>
#include <linux/xattr.h>
#include <linux/mm.h>
+#include <linux/shrinker.h>
#include <linux/key-type.h>
#include <uapi/linux/magic.h>
#include <net/ipv6.h>
@@ -123,27 +124,86 @@ MODULE_PARM_DESC(dir_cache_timeout, "Number of seconds to cache directory conten
"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);
+static struct shrinker *cifs_dircache_shrinker;
/*
* 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)
+static unsigned long cifs_drop_all_dir_caches(bool wait, unsigned long nr_to_free)
{
struct TCP_Server_Info *server;
struct cifs_ses *ses;
struct cifs_tcon *tcon;
+ u64 before, after, freed_bytes = 0;
+ u64 target_bytes;
+
+ before = atomic64_read(&cifs_dircache_bytes_used);
+ if (nr_to_free == ULONG_MAX)
+ target_bytes = U64_MAX;
+ else
+ target_bytes = (u64)nr_to_free * PAGE_SIZE;
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);
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ invalidate_all_cached_dirs_nowait(tcon);
+ after = atomic64_read(&cifs_dircache_bytes_used);
+ if (after < before)
+ freed_bytes = before - after;
+ if (freed_bytes >= target_bytes)
+ goto out_unlock;
+ }
}
}
+out_unlock:
spin_unlock(&cifs_tcp_ses_lock);
+
+ if (wait)
+ flush_workqueue(cfid_put_wq);
+
+ after = atomic64_read(&cifs_dircache_bytes_used);
+ if (after >= before)
+ return 0;
+ return (unsigned long)(before - after);
+}
+
+static unsigned long cifs_dircache_shrinker_count(struct shrinker *shrink,
+ struct shrink_control *sc)
+{
+ u64 bytes = atomic64_read(&cifs_dircache_bytes_used);
+
+ (void)shrink;
+ (void)sc;
+
+ return DIV_ROUND_UP_ULL(bytes, PAGE_SIZE);
+}
+
+static unsigned long cifs_dircache_shrinker_scan(struct shrinker *shrink,
+ struct shrink_control *sc)
+{
+ unsigned long freed_bytes;
+
+ (void)shrink;
+
+ if (!sc->nr_to_scan)
+ return 0;
+
+ if (!atomic64_read(&cifs_dircache_bytes_used))
+ return SHRINK_STOP;
+
+ /*
+ * Shrinker scan can run from reclaim context, so avoid synchronously
+ * flushing worker queues here to prevent long stalls/deadlocks.
+ */
+ freed_bytes = cifs_drop_all_dir_caches(false, max_t(unsigned long, 1, sc->nr_to_scan));
+ if (!freed_bytes)
+ return SHRINK_STOP;
+
+ return DIV_ROUND_UP_ULL(freed_bytes, PAGE_SIZE);
}
static int cifs_param_set_drop_dir_cache(const char *val, const struct kernel_param *kp)
@@ -154,7 +214,7 @@ static int cifs_param_set_drop_dir_cache(const char *val, const struct kernel_pa
if (rc)
return rc;
if (bv)
- cifs_drop_all_dir_caches();
+ cifs_drop_all_dir_caches(true, ULONG_MAX);
return 0;
}
@@ -2038,10 +2098,19 @@ init_cifs(void)
if (rc)
goto out_destroy_mids;
+ cifs_dircache_shrinker = shrinker_alloc(0, "cifs-dircache");
+ if (!cifs_dircache_shrinker) {
+ rc = -ENOMEM;
+ goto out_destroy_request_bufs;
+ }
+ cifs_dircache_shrinker->count_objects = cifs_dircache_shrinker_count;
+ cifs_dircache_shrinker->scan_objects = cifs_dircache_shrinker_scan;
+ shrinker_register(cifs_dircache_shrinker);
+
#ifdef CONFIG_CIFS_DFS_UPCALL
rc = dfs_cache_init();
if (rc)
- goto out_destroy_request_bufs;
+ goto out_free_dircache_shrinker;
#endif /* CONFIG_CIFS_DFS_UPCALL */
#ifdef CONFIG_CIFS_UPCALL
rc = init_cifs_spnego();
@@ -2083,8 +2152,11 @@ init_cifs(void)
#endif
#ifdef CONFIG_CIFS_DFS_UPCALL
dfs_cache_destroy();
-out_destroy_request_bufs:
+out_free_dircache_shrinker:
#endif
+ shrinker_free(cifs_dircache_shrinker);
+ cifs_dircache_shrinker = NULL;
+out_destroy_request_bufs:
cifs_destroy_request_bufs();
out_destroy_mids:
destroy_mids();
@@ -2117,6 +2189,8 @@ exit_cifs(void)
cifs_dbg(NOISY, "exit_smb3\n");
unregister_filesystem(&cifs_fs_type);
unregister_filesystem(&smb3_fs_type);
+ shrinker_free(cifs_dircache_shrinker);
+ cifs_dircache_shrinker = NULL;
cifs_release_automount_timer();
exit_cifs_idmap();
#ifdef CONFIG_CIFS_SWN_UPCALL
--
2.43.0
next prev parent reply other threads:[~2026-05-01 11:20 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-01 11:20 [PATCH v4 01/19] cifs: change_conf needs to be called for session setup nspmangalore
2026-05-01 11:20 ` [PATCH v4 02/19] cifs: abort open_cached_dir if we don't request leases nspmangalore
2026-05-06 14:16 ` Bharath SM
2026-05-01 11:20 ` [PATCH v4 03/19] cifs: invalidate cfid on unlink/rename/rmdir nspmangalore
2026-05-01 11:20 ` [PATCH v4 04/19] cifs: define variable sized buffer for querydir responses nspmangalore
2026-05-01 11:20 ` [PATCH v4 05/19] cifs: optimize readdir for small directories nspmangalore
2026-05-01 11:20 ` [PATCH v4 06/19] cifs: optimize readdir for larger directories nspmangalore
2026-05-01 11:20 ` [PATCH v4 07/19] cifs: reorganize cached dir helpers nspmangalore
2026-05-01 11:20 ` [PATCH v4 08/19] cifs: make cfid locks more granular nspmangalore
2026-05-01 11:20 ` [PATCH v4 09/19] cifs: query dir should reuse cfid even if not fully cached nspmangalore
2026-05-01 11:20 ` [PATCH v4 10/19] cifs: back cached_dirents with page cache nspmangalore
2026-05-01 11:20 ` [PATCH v4 11/19] cifs: in place changes to cached_dirents when dir lease is held nspmangalore
2026-05-01 11:20 ` nspmangalore [this message]
2026-05-01 11:20 ` [PATCH v4 13/19] cifs: option to disable time-based eviction of cache nspmangalore
2026-05-01 15:47 ` Steve French
2026-05-04 12:28 ` Shyam Prasad N
2026-05-01 11:20 ` [PATCH v4 14/19] cifs: option to set unlimited number of cached dirs nspmangalore
2026-05-01 11:20 ` [PATCH v4 15/19] cifs: allow dcache population to happen asynchronously nspmangalore
2026-05-01 11:20 ` [PATCH v4 16/19] cifs: trace points for cached_dir operations nspmangalore
2026-05-01 11:20 ` [PATCH v4 17/19] cifs: discard functions to ensure that mid callbacks get called nspmangalore
2026-05-01 11:20 ` [PATCH v4 18/19] cifs: keep cfids in rbtree for efficient lookups nspmangalore
2026-05-01 11:20 ` [PATCH v4 19/19] cifs: invalidate cached_dirents if population aborted nspmangalore
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=20260501112023.338005-12-sprasad@microsoft.com \
--to=nspmangalore@gmail.com \
--cc=bharathsm@microsoft.com \
--cc=dhowells@redhat.com \
--cc=ematsumiya@suse.de \
--cc=henrique.carvalho@suse.com \
--cc=linux-cifs@vger.kernel.org \
--cc=pc@manguebit.org \
--cc=smfrench@gmail.com \
--cc=sprasad@microsoft.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