Commit 5efdd912 authored by Steve French's avatar Steve French

smb3: allow deferred close timeout to be configurable

Deferred close can be a very useful feature for allowing
caching data for read, and for minimizing the number of
reopens needed for a file that is repeatedly opened and
close but there are workloads where its default (1 second,
similar to actimeo/acregmax) is much too small.

Allow the user to configure the amount of time we can
defer sending the final smb3 close when we have a
handle lease on the file (rather than forcing it to depend
on value of actimeo which is often unrelated, and less safe).

Adds new mount parameter "closetimeo=" which is the maximum
number of seconds we can wait before sending an SMB3
close when we have a handle lease for it.  Default value
also is set to slightly larger at 5 seconds (although some
other clients use larger default this should still help).
Suggested-by: default avatarBharath SM <bharathsm@microsoft.com>
Reviewed-by: default avatarBharath SM <bharathsm@microsoft.com>
Reviewed-by: default avatarShyam Prasad N <sprasad@microsoft.com>
Reviewed-by: default avatarPaulo Alcantara (SUSE) <pc@cjr.nz>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent dcb45fd7
...@@ -693,6 +693,7 @@ cifs_show_options(struct seq_file *s, struct dentry *root) ...@@ -693,6 +693,7 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_printf(s, ",acdirmax=%lu", cifs_sb->ctx->acdirmax / HZ); seq_printf(s, ",acdirmax=%lu", cifs_sb->ctx->acdirmax / HZ);
seq_printf(s, ",acregmax=%lu", cifs_sb->ctx->acregmax / HZ); seq_printf(s, ",acregmax=%lu", cifs_sb->ctx->acregmax / HZ);
} }
seq_printf(s, ",closetimeo=%lu", cifs_sb->ctx->closetimeo / 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",
......
...@@ -2681,6 +2681,8 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data) ...@@ -2681,6 +2681,8 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
return 0; return 0;
if (old->ctx->acdirmax != new->ctx->acdirmax) if (old->ctx->acdirmax != new->ctx->acdirmax)
return 0; return 0;
if (old->ctx->closetimeo != new->ctx->closetimeo)
return 0;
return 1; return 1;
} }
......
...@@ -964,12 +964,12 @@ int cifs_close(struct inode *inode, struct file *file) ...@@ -964,12 +964,12 @@ int cifs_close(struct inode *inode, struct file *file)
* So, Increase the ref count to avoid use-after-free. * So, Increase the ref count to avoid use-after-free.
*/ */
if (!mod_delayed_work(deferredclose_wq, if (!mod_delayed_work(deferredclose_wq,
&cfile->deferred, cifs_sb->ctx->acregmax)) &cfile->deferred, cifs_sb->ctx->closetimeo))
cifsFileInfo_get(cfile); cifsFileInfo_get(cfile);
} else { } else {
/* Deferred close for files */ /* Deferred close for files */
queue_delayed_work(deferredclose_wq, queue_delayed_work(deferredclose_wq,
&cfile->deferred, cifs_sb->ctx->acregmax); &cfile->deferred, cifs_sb->ctx->closetimeo);
cfile->deferred_close_scheduled = true; cfile->deferred_close_scheduled = true;
spin_unlock(&cinode->deferred_lock); spin_unlock(&cinode->deferred_lock);
return 0; return 0;
......
...@@ -147,6 +147,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = { ...@@ -147,6 +147,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
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("acregmax", Opt_acregmax),
fsparam_u32("closetimeo", Opt_closetimeo),
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),
...@@ -1074,6 +1075,13 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, ...@@ -1074,6 +1075,13 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
} }
ctx->acdirmax = ctx->acregmax = HZ * result.uint_32; ctx->acdirmax = ctx->acregmax = HZ * result.uint_32;
break; break;
case Opt_closetimeo:
ctx->closetimeo = HZ * result.uint_32;
if (ctx->closetimeo > SMB3_MAX_DCLOSETIMEO) {
cifs_errorf(fc, "closetimeo too large\n");
goto cifs_parse_mount_err;
}
break;
case Opt_echo_interval: case Opt_echo_interval:
ctx->echo_interval = result.uint_32; ctx->echo_interval = result.uint_32;
break; break;
...@@ -1521,6 +1529,7 @@ int smb3_init_fs_context(struct fs_context *fc) ...@@ -1521,6 +1529,7 @@ int smb3_init_fs_context(struct fs_context *fc)
ctx->acregmax = CIFS_DEF_ACTIMEO; ctx->acregmax = CIFS_DEF_ACTIMEO;
ctx->acdirmax = CIFS_DEF_ACTIMEO; ctx->acdirmax = CIFS_DEF_ACTIMEO;
ctx->closetimeo = SMB3_DEF_DCLOSETIMEO;
/* Most clients set timeout to 0, allows server to use its default */ /* 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 */ ctx->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
......
...@@ -125,6 +125,7 @@ enum cifs_param { ...@@ -125,6 +125,7 @@ enum cifs_param {
Opt_actimeo, Opt_actimeo,
Opt_acdirmax, Opt_acdirmax,
Opt_acregmax, Opt_acregmax,
Opt_closetimeo,
Opt_echo_interval, Opt_echo_interval,
Opt_max_credits, Opt_max_credits,
Opt_snapshot, Opt_snapshot,
...@@ -247,6 +248,8 @@ struct smb3_fs_context { ...@@ -247,6 +248,8 @@ struct smb3_fs_context {
/* attribute cache timemout for files and directories in jiffies */ /* attribute cache timemout for files and directories in jiffies */
unsigned long acregmax; unsigned long acregmax;
unsigned long acdirmax; unsigned long acdirmax;
/* timeout for deferred close of files in jiffies */
unsigned long closetimeo;
struct smb_version_operations *ops; struct smb_version_operations *ops;
struct smb_version_values *vals; struct smb_version_values *vals;
char *prepath; char *prepath;
...@@ -279,4 +282,9 @@ static inline struct smb3_fs_context *smb3_fc2context(const struct fs_context *f ...@@ -279,4 +282,9 @@ static inline struct smb3_fs_context *smb3_fc2context(const struct fs_context *f
extern int smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx); extern int smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx);
extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb); extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb);
/*
* max deferred close timeout (jiffies) - 2^30
*/
#define SMB3_MAX_DCLOSETIMEO (1 << 30)
#define SMB3_DEF_DCLOSETIMEO (5 * HZ) /* Can increase later, other clients use larger */
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment