Commit bcc88801 authored by Aurelien Aptel's avatar Aurelien Aptel Committed by Steve French

cifs: add multichannel mount options and data structs

adds:
- [no]multichannel to enable/disable multichannel
- max_channels=N to control how many channels to create

these options are then stored in the volume struct.

- store channels and max_channels in cifs_ses
Signed-off-by: default avatarAurelien Aptel <aaptel@suse.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 35adffed
...@@ -613,6 +613,10 @@ cifs_show_options(struct seq_file *s, struct dentry *root) ...@@ -613,6 +613,10 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
/* convert actimeo and display it in seconds */ /* convert actimeo and display it in seconds */
seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ); seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
if (tcon->ses->chan_max > 1)
seq_printf(s, ",multichannel,max_channel=%zu",
tcon->ses->chan_max);
return 0; return 0;
} }
......
...@@ -591,6 +591,10 @@ struct smb_vol { ...@@ -591,6 +591,10 @@ struct smb_vol {
bool resilient:1; /* noresilient not required since not fored for CA */ bool resilient:1; /* noresilient not required since not fored for CA */
bool domainauto:1; bool domainauto:1;
bool rdma:1; bool rdma:1;
bool multichannel:1;
bool use_client_guid:1;
/* reuse existing guid for multichannel */
u8 client_guid[SMB2_CLIENT_GUID_SIZE];
unsigned int bsize; unsigned int bsize;
unsigned int rsize; unsigned int rsize;
unsigned int wsize; unsigned int wsize;
...@@ -607,6 +611,7 @@ struct smb_vol { ...@@ -607,6 +611,7 @@ struct smb_vol {
__u64 snapshot_time; /* needed for timewarp tokens */ __u64 snapshot_time; /* needed for timewarp tokens */
__u32 handle_timeout; /* persistent and durable handle timeout in ms */ __u32 handle_timeout; /* persistent and durable handle timeout in ms */
unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */ unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
unsigned int max_channels;
__u16 compression; /* compression algorithm 0xFFFF default 0=disabled */ __u16 compression; /* compression algorithm 0xFFFF default 0=disabled */
bool rootfs:1; /* if it's a SMB root file system */ bool rootfs:1; /* if it's a SMB root file system */
}; };
...@@ -953,6 +958,11 @@ struct cifs_server_iface { ...@@ -953,6 +958,11 @@ struct cifs_server_iface {
struct sockaddr_storage sockaddr; struct sockaddr_storage sockaddr;
}; };
struct cifs_chan {
struct TCP_Server_Info *server;
__u8 signkey[SMB3_SIGN_KEY_SIZE];
};
/* /*
* Session structure. One of these for each uid session with a particular host * Session structure. One of these for each uid session with a particular host
*/ */
...@@ -1002,6 +1012,12 @@ struct cifs_ses { ...@@ -1002,6 +1012,12 @@ struct cifs_ses {
struct cifs_server_iface *iface_list; struct cifs_server_iface *iface_list;
size_t iface_count; size_t iface_count;
unsigned long iface_last_update; /* jiffies */ unsigned long iface_last_update; /* jiffies */
#define CIFS_MAX_CHANNELS 16
struct cifs_chan chans[CIFS_MAX_CHANNELS];
size_t chan_count;
size_t chan_max;
atomic_t chan_seq; /* round robin state */
}; };
static inline bool static inline bool
......
...@@ -97,6 +97,7 @@ enum { ...@@ -97,6 +97,7 @@ enum {
Opt_persistent, Opt_nopersistent, Opt_persistent, Opt_nopersistent,
Opt_resilient, Opt_noresilient, Opt_resilient, Opt_noresilient,
Opt_domainauto, Opt_rdma, Opt_modesid, Opt_rootfs, Opt_domainauto, Opt_rdma, Opt_modesid, Opt_rootfs,
Opt_multichannel, Opt_nomultichannel,
Opt_compress, Opt_compress,
/* Mount options which take numeric value */ /* Mount options which take numeric value */
...@@ -106,7 +107,7 @@ enum { ...@@ -106,7 +107,7 @@ enum {
Opt_min_enc_offload, Opt_min_enc_offload,
Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo, Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo,
Opt_echo_interval, Opt_max_credits, Opt_handletimeout, Opt_echo_interval, Opt_max_credits, Opt_handletimeout,
Opt_snapshot, Opt_snapshot, Opt_max_channels,
/* Mount options which take string value */ /* Mount options which take string value */
Opt_user, Opt_pass, Opt_ip, Opt_user, Opt_pass, Opt_ip,
...@@ -199,6 +200,8 @@ static const match_table_t cifs_mount_option_tokens = { ...@@ -199,6 +200,8 @@ static const match_table_t cifs_mount_option_tokens = {
{ Opt_noresilient, "noresilienthandles"}, { Opt_noresilient, "noresilienthandles"},
{ Opt_domainauto, "domainauto"}, { Opt_domainauto, "domainauto"},
{ Opt_rdma, "rdma"}, { Opt_rdma, "rdma"},
{ Opt_multichannel, "multichannel" },
{ Opt_nomultichannel, "nomultichannel" },
{ Opt_backupuid, "backupuid=%s" }, { Opt_backupuid, "backupuid=%s" },
{ Opt_backupgid, "backupgid=%s" }, { Opt_backupgid, "backupgid=%s" },
...@@ -218,6 +221,7 @@ static const match_table_t cifs_mount_option_tokens = { ...@@ -218,6 +221,7 @@ static const match_table_t cifs_mount_option_tokens = {
{ Opt_echo_interval, "echo_interval=%s" }, { Opt_echo_interval, "echo_interval=%s" },
{ Opt_max_credits, "max_credits=%s" }, { Opt_max_credits, "max_credits=%s" },
{ Opt_snapshot, "snapshot=%s" }, { Opt_snapshot, "snapshot=%s" },
{ Opt_max_channels, "max_channels=%s" },
{ Opt_compress, "compress=%s" }, { Opt_compress, "compress=%s" },
{ Opt_blank_user, "user=" }, { Opt_blank_user, "user=" },
...@@ -1681,6 +1685,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, ...@@ -1681,6 +1685,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT; vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
/* default to no multichannel (single server connection) */
vol->multichannel = false;
vol->max_channels = 1;
if (!mountdata) if (!mountdata)
goto cifs_parse_mount_err; goto cifs_parse_mount_err;
...@@ -1974,6 +1982,12 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, ...@@ -1974,6 +1982,12 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
case Opt_rdma: case Opt_rdma:
vol->rdma = true; vol->rdma = true;
break; break;
case Opt_multichannel:
vol->multichannel = true;
break;
case Opt_nomultichannel:
vol->multichannel = false;
break;
case Opt_compress: case Opt_compress:
vol->compression = UNKNOWN_TYPE; vol->compression = UNKNOWN_TYPE;
cifs_dbg(VFS, cifs_dbg(VFS,
...@@ -2137,6 +2151,15 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, ...@@ -2137,6 +2151,15 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
} }
vol->max_credits = option; vol->max_credits = option;
break; break;
case Opt_max_channels:
if (get_option_ul(args, &option) || option < 1 ||
option > CIFS_MAX_CHANNELS) {
cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n",
__func__, CIFS_MAX_CHANNELS);
goto cifs_parse_mount_err;
}
vol->max_channels = option;
break;
/* String Arguments */ /* String Arguments */
...@@ -2781,7 +2804,11 @@ cifs_get_tcp_session(struct smb_vol *volume_info) ...@@ -2781,7 +2804,11 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
sizeof(tcp_ses->srcaddr)); sizeof(tcp_ses->srcaddr));
memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr, memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
sizeof(tcp_ses->dstaddr)); sizeof(tcp_ses->dstaddr));
generate_random_uuid(tcp_ses->client_guid); if (volume_info->use_client_guid)
memcpy(tcp_ses->client_guid, volume_info->client_guid,
SMB2_CLIENT_GUID_SIZE);
else
generate_random_uuid(tcp_ses->client_guid);
/* /*
* at this point we are the only ones with the pointer * at this point we are the only ones with the pointer
* to the struct since the kernel thread not created yet * to the struct since the kernel thread not created yet
...@@ -2870,6 +2897,13 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol) ...@@ -2870,6 +2897,13 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
vol->sectype != ses->sectype) vol->sectype != ses->sectype)
return 0; return 0;
/*
* If an existing session is limited to less channels than
* requested, it should not be reused
*/
if (ses->chan_max < vol->max_channels)
return 0;
switch (ses->sectype) { switch (ses->sectype) {
case Kerberos: case Kerberos:
if (!uid_eq(vol->cred_uid, ses->cred_uid)) if (!uid_eq(vol->cred_uid, ses->cred_uid))
......
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