smb3: allow deferred close timeout to be configurable
authorSteve French <stfrench@microsoft.com>
Thu, 11 Aug 2022 05:53:00 +0000 (00:53 -0500)
committerSteve French <stfrench@microsoft.com>
Fri, 12 Aug 2022 01:03:04 +0000 (20:03 -0500)
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: Bharath SM <bharathsm@microsoft.com>
Reviewed-by: Bharath SM <bharathsm@microsoft.com>
Reviewed-by: Shyam Prasad N <sprasad@microsoft.com>
Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifs/cifsfs.c
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/fs_context.c
fs/cifs/fs_context.h

index 945fb083cea7a9e456c3bef0871d4c7d9d99b358..f54d8bf2732a50d361b057beca89434440db4c6c 100644 (file)
@@ -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, ",acregmax=%lu", cifs_sb->ctx->acregmax / HZ);
        }
+       seq_printf(s, ",closetimeo=%lu", cifs_sb->ctx->closetimeo / HZ);
 
        if (tcon->ses->chan_max > 1)
                seq_printf(s, ",multichannel,max_channels=%zu",
index 7f205a9a2de4bdb99cf890e38e2eac34d5b5aef3..9111c025bcb8eaeb4da9e3d39c8b061e3e6d95b6 100644 (file)
@@ -2681,6 +2681,8 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
                return 0;
        if (old->ctx->acdirmax != new->ctx->acdirmax)
                return 0;
+       if (old->ctx->closetimeo != new->ctx->closetimeo)
+               return 0;
 
        return 1;
 }
index 42f2639a1a66ac33fec8c98a2d286358c1c70e2a..2c5eae7d31f42202f065d34e6004080f08148f96 100644 (file)
@@ -964,12 +964,12 @@ int cifs_close(struct inode *inode, struct file *file)
                                 * So, Increase the ref count to avoid use-after-free.
                                 */
                                if (!mod_delayed_work(deferredclose_wq,
-                                               &cfile->deferred, cifs_sb->ctx->acregmax))
+                                               &cfile->deferred, cifs_sb->ctx->closetimeo))
                                        cifsFileInfo_get(cfile);
                        } else {
                                /* Deferred close for files */
                                queue_delayed_work(deferredclose_wq,
-                                               &cfile->deferred, cifs_sb->ctx->acregmax);
+                                               &cfile->deferred, cifs_sb->ctx->closetimeo);
                                cfile->deferred_close_scheduled = true;
                                spin_unlock(&cinode->deferred_lock);
                                return 0;
index 8dc0d923ef6a98bb279d883ee01f2b03b6ca2a1a..0e13dec86b252736047b5017437b00e56dfe2803 100644 (file)
@@ -147,6 +147,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
        fsparam_u32("actimeo", Opt_actimeo),
        fsparam_u32("acdirmax", Opt_acdirmax),
        fsparam_u32("acregmax", Opt_acregmax),
+       fsparam_u32("closetimeo", Opt_closetimeo),
        fsparam_u32("echo_interval", Opt_echo_interval),
        fsparam_u32("max_credits", Opt_max_credits),
        fsparam_u32("handletimeout", Opt_handletimeout),
@@ -1074,6 +1075,13 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
                }
                ctx->acdirmax = ctx->acregmax = HZ * result.uint_32;
                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:
                ctx->echo_interval = result.uint_32;
                break;
@@ -1521,6 +1529,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;
 
        /* 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 */
index 5f093cb7e9b98ef791de8c01857c7f4136bbe9c5..bbaee4c2281f8857a74bff6d1be87196767b3dbb 100644 (file)
@@ -125,6 +125,7 @@ enum cifs_param {
        Opt_actimeo,
        Opt_acdirmax,
        Opt_acregmax,
+       Opt_closetimeo,
        Opt_echo_interval,
        Opt_max_credits,
        Opt_snapshot,
@@ -247,6 +248,8 @@ struct smb3_fs_context {
        /* attribute cache timemout for files and directories in jiffies */
        unsigned long acregmax;
        unsigned long acdirmax;
+       /* timeout for deferred close of files in jiffies */
+       unsigned long closetimeo;
        struct smb_version_operations *ops;
        struct smb_version_values *vals;
        char *prepath;
@@ -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 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