This is a note to let you know that I've just added the patch titled smb3: allow controlling maximum number of cached directories to the 6.5-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: smb3-allow-controlling-maximum-number-of-cached-dire.patch and it can be found in the queue-6.5 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit 2d238af1cd45ff4fdd3b7ef161f41f686bc02756 Author: Steve French <stfrench@xxxxxxxxxxxxx> Date: Fri Sep 1 02:15:14 2023 -0500 smb3: allow controlling maximum number of cached directories [ Upstream commit 6a50d71d0ffff6791737eb502b27f74fb87d0cae ] Allow adjusting the maximum number of cached directories per share (defaults to 16) via mount parm "max_cached_dirs" Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c index 9d84c4a7bd0ce..b17f067e4ada0 100644 --- a/fs/smb/client/cached_dir.c +++ b/fs/smb/client/cached_dir.c @@ -18,7 +18,8 @@ static void smb2_close_cached_fid(struct kref *ref); static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids, const char *path, - bool lookup_only) + bool lookup_only, + __u32 max_cached_dirs) { struct cached_fid *cfid; @@ -43,7 +44,7 @@ static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids, spin_unlock(&cfids->cfid_list_lock); return NULL; } - if (cfids->num_entries >= MAX_CACHED_FIDS) { + if (cfids->num_entries >= max_cached_dirs) { spin_unlock(&cfids->cfid_list_lock); return NULL; } @@ -162,7 +163,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, if (!utf16_path) return -ENOMEM; - cfid = find_or_create_cached_dir(cfids, path, lookup_only); + cfid = find_or_create_cached_dir(cfids, path, lookup_only, tcon->max_cached_dirs); if (cfid == NULL) { kfree(utf16_path); return -ENOENT; diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h index facc9b154d009..a82ff2cea789c 100644 --- a/fs/smb/client/cached_dir.h +++ b/fs/smb/client/cached_dir.h @@ -49,7 +49,7 @@ struct cached_fid { struct cached_dirents dirents; }; -#define MAX_CACHED_FIDS 16 +/* default MAX_CACHED_FIDS is 16 */ struct cached_fids { /* Must be held when: * - accessing the cfids->entries list diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index 9a6d7e66408d1..e19df244ea7ea 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -699,6 +699,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) seq_printf(s, ",snapshot=%llu", tcon->snapshot_time); if (tcon->handle_timeout) seq_printf(s, ",handletimeout=%u", tcon->handle_timeout); + if (tcon->max_cached_dirs != MAX_CACHED_FIDS) + seq_printf(s, ",max_cached_dirs=%u", tcon->max_cached_dirs); /* * Display file and directory attribute timeout in seconds. diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index f8eb787ecffab..b4c1c4742f08a 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -1192,6 +1192,7 @@ struct cifs_tcon { __u32 max_chunks; __u32 max_bytes_chunk; __u32 max_bytes_copy; + __u32 max_cached_dirs; #ifdef CONFIG_CIFS_FSCACHE u64 resource_id; /* server resource id */ struct fscache_volume *fscache; /* cookie for share */ diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 352e251c41132..f00d02608ee46 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -2657,6 +2657,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) tcon->retry = ctx->retry; tcon->nocase = ctx->nocase; tcon->broken_sparse_sup = ctx->no_sparse; + tcon->max_cached_dirs = ctx->max_cached_dirs; if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING) tcon->nohandlecache = ctx->nohandlecache; else diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c index f12203c49b802..a3493da12ad1e 100644 --- a/fs/smb/client/fs_context.c +++ b/fs/smb/client/fs_context.c @@ -150,6 +150,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = { fsparam_u32("closetimeo", Opt_closetimeo), fsparam_u32("echo_interval", Opt_echo_interval), fsparam_u32("max_credits", Opt_max_credits), + fsparam_u32("max_cached_dirs", Opt_max_cached_dirs), fsparam_u32("handletimeout", Opt_handletimeout), fsparam_u64("snapshot", Opt_snapshot), fsparam_u32("max_channels", Opt_max_channels), @@ -1165,6 +1166,14 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, if (result.uint_32 > 1) ctx->multichannel = true; break; + case Opt_max_cached_dirs: + if (result.uint_32 < 1) { + cifs_errorf(fc, "%s: Invalid max_cached_dirs, needs to be 1 or more\n", + __func__); + goto cifs_parse_mount_err; + } + ctx->max_cached_dirs = result.uint_32; + break; case Opt_handletimeout: ctx->handle_timeout = result.uint_32; if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) { @@ -1593,7 +1602,7 @@ int smb3_init_fs_context(struct fs_context *fc) ctx->acregmax = CIFS_DEF_ACTIMEO; ctx->acdirmax = CIFS_DEF_ACTIMEO; ctx->closetimeo = SMB3_DEF_DCLOSETIMEO; - + ctx->max_cached_dirs = MAX_CACHED_FIDS; /* Most clients set timeout to 0, allows server to use its default */ ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */ diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h index f4eaf85589022..9d8d34af02114 100644 --- a/fs/smb/client/fs_context.h +++ b/fs/smb/client/fs_context.h @@ -128,6 +128,7 @@ enum cifs_param { Opt_closetimeo, Opt_echo_interval, Opt_max_credits, + Opt_max_cached_dirs, Opt_snapshot, Opt_max_channels, Opt_handletimeout, @@ -261,6 +262,7 @@ struct smb3_fs_context { __u32 handle_timeout; /* persistent and durable handle timeout in ms */ unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */ unsigned int max_channels; + unsigned int max_cached_dirs; __u16 compression; /* compression algorithm 0xFFFF default 0=disabled */ bool rootfs:1; /* if it's a SMB root file system */ bool witness:1; /* use witness protocol */ @@ -287,7 +289,7 @@ extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb); */ #define SMB3_MAX_DCLOSETIMEO (1 << 30) #define SMB3_DEF_DCLOSETIMEO (1 * HZ) /* even 1 sec enough to help eg open/write/close/open/read */ - +#define MAX_CACHED_FIDS 16 extern char *cifs_sanitize_prepath(char *prepath, gfp_t gfp); #endif