From 563317ec3083f7e126d7e30821ff8505ac338ee5 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 8 Sep 2019 23:22:02 -0500 Subject: smb3: enable offload of decryption of large reads via mount option Disable offload of the decryption of encrypted read responses by default (equivalent to setting this new mount option "esize=0"). Allow setting the minimum encrypted read response size that we will choose to offload to a worker thread - it is now configurable via on a new mount option "esize=" Depending on which encryption mechanism (GCM vs. CCM) and the number of reads that will be issued in parallel and the performance of the network and CPU on the client, it may make sense to enable this since it can provide substantial benefit when multiple large reads are in flight at the same time. Signed-off-by: Steve French Signed-off-by: Ronnie Sahlberg --- fs/cifs/cifsfs.c | 2 ++ fs/cifs/cifsglob.h | 2 ++ fs/cifs/connect.c | 13 +++++++++++++ fs/cifs/smb2ops.c | 4 ++-- 4 files changed, 19 insertions(+), 2 deletions(-) (limited to 'fs/cifs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index b0ea332af35c..ebf85a5d95e4 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -559,6 +559,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) seq_printf(s, ",rsize=%u", cifs_sb->rsize); seq_printf(s, ",wsize=%u", cifs_sb->wsize); seq_printf(s, ",bsize=%u", cifs_sb->bsize); + if (tcon->ses->server->min_offload) + seq_printf(s, ",esize=%u", tcon->ses->server->min_offload); seq_printf(s, ",echo_interval=%lu", tcon->ses->server->echo_interval / HZ); diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index d66106ac031a..6987fbc5a24a 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -592,6 +592,7 @@ struct smb_vol { unsigned int bsize; unsigned int rsize; unsigned int wsize; + unsigned int min_offload; bool sockopt_tcp_nodelay:1; unsigned long actimeo; /* attribute cache timeout (jiffies) */ struct smb_version_operations *ops; @@ -745,6 +746,7 @@ struct TCP_Server_Info { #endif /* STATS2 */ unsigned int max_read; unsigned int max_write; + unsigned int min_offload; __le16 compress_algorithm; __le16 cipher_type; /* save initital negprot hash */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 17882cede197..e70112d67b0e 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -103,6 +103,7 @@ enum { Opt_backupuid, Opt_backupgid, Opt_uid, Opt_cruid, Opt_gid, Opt_file_mode, Opt_dirmode, Opt_port, + Opt_min_enc_offload, Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo, Opt_echo_interval, Opt_max_credits, Opt_handletimeout, Opt_snapshot, @@ -207,6 +208,7 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_dirmode, "dirmode=%s" }, { Opt_dirmode, "dir_mode=%s" }, { Opt_port, "port=%s" }, + { Opt_min_enc_offload, "esize=%s" }, { Opt_blocksize, "bsize=%s" }, { Opt_rsize, "rsize=%s" }, { Opt_wsize, "wsize=%s" }, @@ -2016,6 +2018,13 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, } port = (unsigned short)option; break; + case Opt_min_enc_offload: + if (get_option_ul(args, &option)) { + cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n"); + goto cifs_parse_mount_err; + } + vol->min_offload = option; + break; case Opt_blocksize: if (get_option_ul(args, &option)) { cifs_dbg(VFS, "%s: Invalid blocksize value\n", @@ -2616,6 +2625,9 @@ static int match_server(struct TCP_Server_Info *server, struct smb_vol *vol) if (server->ignore_signature != vol->ignore_signature) return 0; + if (server->min_offload != vol->min_offload) + return 0; + return 1; } @@ -2790,6 +2802,7 @@ smbd_connected: module_put(THIS_MODULE); goto out_err_crypto_release; } + tcp_ses->min_offload = volume_info->min_offload; tcp_ses->tcpStatus = CifsNeedNegotiate; tcp_ses->nr_targets = 1; diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index c74284484947..1cfb8d518132 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -4121,8 +4121,8 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid, * use more cores decrypting which can be expensive */ - /* TODO: make the size limit to enable decrypt offload configurable */ - if (server->pdu_size > (512 * 1024)) { + if ((server->min_offload) && + (server->pdu_size >= server->min_offload)) { dw = kmalloc(sizeof(struct smb2_decrypt_work), GFP_KERNEL); if (dw == NULL) goto non_offloaded_decrypt; -- cgit v1.2.3