cifs: Add new parameter "acregmax" for distinct file and directory metadata timeout

The new optional mount parameter "acregmax" allows a different
timeout for file metadata ("acdirmax" now allows controlling timeout
for directory metadata).  Setting "actimeo" still works as before,
and changes timeout for both files and directories, but
specifying "acregmax" or "acdirmax" allows overriding the
default more granularly which can be a big performance benefit
on some workloads. "acregmax" is already used by NFS as a mount
parameter (albeit with a larger default and thus looser caching).

Suggested-by: Tom Talpey <tom@talpey.com>
Reviewed-By: Tom Talpey <tom@talpey.com>
Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
Steve French 2021-02-24 12:12:53 -06:00
parent ddaf6d4a92
commit 5780464614
5 changed files with 37 additions and 13 deletions

View File

@ -637,9 +637,18 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_printf(s, ",snapshot=%llu", tcon->snapshot_time); seq_printf(s, ",snapshot=%llu", tcon->snapshot_time);
if (tcon->handle_timeout) if (tcon->handle_timeout)
seq_printf(s, ",handletimeout=%u", tcon->handle_timeout); seq_printf(s, ",handletimeout=%u", tcon->handle_timeout);
/* convert actimeo and directory attribute timeout and display in seconds */
seq_printf(s, ",actimeo=%lu", cifs_sb->ctx->actimeo / HZ); /*
seq_printf(s, ",acdirmax=%lu", cifs_sb->ctx->acdirmax / HZ); * Display file and directory attribute timeout in seconds.
* If file and directory attribute timeout the same then actimeo
* was likely specified on mount
*/
if (cifs_sb->ctx->acdirmax == cifs_sb->ctx->acregmax)
seq_printf(s, ",actimeo=%lu", cifs_sb->ctx->acregmax / HZ);
else {
seq_printf(s, ",acdirmax=%lu", cifs_sb->ctx->acdirmax / HZ);
seq_printf(s, ",acregmax=%lu", cifs_sb->ctx->acregmax / HZ);
}
if (tcon->ses->chan_max > 1) if (tcon->ses->chan_max > 1)
seq_printf(s, ",multichannel,max_channels=%zu", seq_printf(s, ",multichannel,max_channels=%zu",

View File

@ -2276,7 +2276,7 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
if (strcmp(old->local_nls->charset, new->local_nls->charset)) if (strcmp(old->local_nls->charset, new->local_nls->charset))
return 0; return 0;
if (old->ctx->actimeo != new->ctx->actimeo) if (old->ctx->acregmax != new->ctx->acregmax)
return 0; return 0;
if (old->ctx->acdirmax != new->ctx->acdirmax) if (old->ctx->acdirmax != new->ctx->acdirmax)
return 0; return 0;

View File

@ -141,6 +141,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
fsparam_u32("wsize", Opt_wsize), fsparam_u32("wsize", Opt_wsize),
fsparam_u32("actimeo", Opt_actimeo), fsparam_u32("actimeo", Opt_actimeo),
fsparam_u32("acdirmax", Opt_acdirmax), fsparam_u32("acdirmax", Opt_acdirmax),
fsparam_u32("acregmax", Opt_acregmax),
fsparam_u32("echo_interval", Opt_echo_interval), fsparam_u32("echo_interval", Opt_echo_interval),
fsparam_u32("max_credits", Opt_max_credits), fsparam_u32("max_credits", Opt_max_credits),
fsparam_u32("handletimeout", Opt_handletimeout), fsparam_u32("handletimeout", Opt_handletimeout),
@ -930,10 +931,10 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
ctx->wsize = result.uint_32; ctx->wsize = result.uint_32;
ctx->got_wsize = true; ctx->got_wsize = true;
break; break;
case Opt_actimeo: case Opt_acregmax:
ctx->actimeo = HZ * result.uint_32; ctx->acregmax = HZ * result.uint_32;
if (ctx->actimeo > CIFS_MAX_ACTIMEO) { if (ctx->acregmax > CIFS_MAX_ACTIMEO) {
cifs_dbg(VFS, "attribute cache timeout too large\n"); cifs_dbg(VFS, "acregmax too large\n");
goto cifs_parse_mount_err; goto cifs_parse_mount_err;
} }
break; break;
@ -944,6 +945,18 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
goto cifs_parse_mount_err; goto cifs_parse_mount_err;
} }
break; break;
case Opt_actimeo:
if (HZ * result.uint_32 > CIFS_MAX_ACTIMEO) {
cifs_dbg(VFS, "timeout too large\n");
goto cifs_parse_mount_err;
}
if ((ctx->acdirmax != CIFS_DEF_ACTIMEO) ||
(ctx->acregmax != CIFS_DEF_ACTIMEO)) {
cifs_dbg(VFS, "actimeo ignored since acregmax or acdirmax specified\n");
break;
}
ctx->acdirmax = ctx->acregmax = HZ * result.uint_32;
break;
case Opt_echo_interval: case Opt_echo_interval:
ctx->echo_interval = result.uint_32; ctx->echo_interval = result.uint_32;
break; break;
@ -1369,7 +1382,7 @@ int smb3_init_fs_context(struct fs_context *fc)
/* default is to use strict cifs caching semantics */ /* default is to use strict cifs caching semantics */
ctx->strict_io = true; ctx->strict_io = true;
ctx->actimeo = CIFS_DEF_ACTIMEO; ctx->acregmax = CIFS_DEF_ACTIMEO;
ctx->acdirmax = CIFS_DEF_ACTIMEO; ctx->acdirmax = CIFS_DEF_ACTIMEO;
/* Most clients set timeout to 0, allows server to use its default */ /* Most clients set timeout to 0, allows server to use its default */

View File

@ -119,6 +119,7 @@ enum cifs_param {
Opt_wsize, Opt_wsize,
Opt_actimeo, Opt_actimeo,
Opt_acdirmax, Opt_acdirmax,
Opt_acregmax,
Opt_echo_interval, Opt_echo_interval,
Opt_max_credits, Opt_max_credits,
Opt_snapshot, Opt_snapshot,
@ -233,8 +234,9 @@ struct smb3_fs_context {
unsigned int wsize; unsigned int wsize;
unsigned int min_offload; unsigned int min_offload;
bool sockopt_tcp_nodelay:1; bool sockopt_tcp_nodelay:1;
unsigned long actimeo; /* attribute cache timeout for files (jiffies) */ /* attribute cache timemout for files and directories in jiffies */
unsigned long acdirmax; /* attribute cache timeout for directories (jiffies) */ unsigned long acregmax;
unsigned long acdirmax;
struct smb_version_operations *ops; struct smb_version_operations *ops;
struct smb_version_values *vals; struct smb_version_values *vals;
char *prepath; char *prepath;

View File

@ -2209,10 +2209,10 @@ cifs_inode_needs_reval(struct inode *inode)
cifs_i->time + cifs_sb->ctx->acdirmax)) cifs_i->time + cifs_sb->ctx->acdirmax))
return true; return true;
} else { /* file */ } else { /* file */
if (!cifs_sb->ctx->actimeo) if (!cifs_sb->ctx->acregmax)
return true; return true;
if (!time_in_range(jiffies, cifs_i->time, if (!time_in_range(jiffies, cifs_i->time,
cifs_i->time + cifs_sb->ctx->actimeo)) cifs_i->time + cifs_sb->ctx->acregmax))
return true; return true;
} }