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: Aurelien Aptel <aaptel@suse.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
35adffed07
commit
bcc8880115
|
@ -613,6 +613,10 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
|
|||
/* convert actimeo and display it in seconds */
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -591,6 +591,10 @@ struct smb_vol {
|
|||
bool resilient:1; /* noresilient not required since not fored for CA */
|
||||
bool domainauto: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 rsize;
|
||||
unsigned int wsize;
|
||||
|
@ -607,6 +611,7 @@ struct smb_vol {
|
|||
__u64 snapshot_time; /* needed for timewarp tokens */
|
||||
__u32 handle_timeout; /* persistent and durable handle timeout in ms */
|
||||
unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
|
||||
unsigned int max_channels;
|
||||
__u16 compression; /* compression algorithm 0xFFFF default 0=disabled */
|
||||
bool rootfs:1; /* if it's a SMB root file system */
|
||||
};
|
||||
|
@ -953,6 +958,11 @@ struct cifs_server_iface {
|
|||
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
|
||||
*/
|
||||
|
@ -1002,6 +1012,12 @@ struct cifs_ses {
|
|||
struct cifs_server_iface *iface_list;
|
||||
size_t iface_count;
|
||||
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
|
||||
|
|
|
@ -97,6 +97,7 @@ enum {
|
|||
Opt_persistent, Opt_nopersistent,
|
||||
Opt_resilient, Opt_noresilient,
|
||||
Opt_domainauto, Opt_rdma, Opt_modesid, Opt_rootfs,
|
||||
Opt_multichannel, Opt_nomultichannel,
|
||||
Opt_compress,
|
||||
|
||||
/* Mount options which take numeric value */
|
||||
|
@ -106,7 +107,7 @@ enum {
|
|||
Opt_min_enc_offload,
|
||||
Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo,
|
||||
Opt_echo_interval, Opt_max_credits, Opt_handletimeout,
|
||||
Opt_snapshot,
|
||||
Opt_snapshot, Opt_max_channels,
|
||||
|
||||
/* Mount options which take string value */
|
||||
Opt_user, Opt_pass, Opt_ip,
|
||||
|
@ -199,6 +200,8 @@ static const match_table_t cifs_mount_option_tokens = {
|
|||
{ Opt_noresilient, "noresilienthandles"},
|
||||
{ Opt_domainauto, "domainauto"},
|
||||
{ Opt_rdma, "rdma"},
|
||||
{ Opt_multichannel, "multichannel" },
|
||||
{ Opt_nomultichannel, "nomultichannel" },
|
||||
|
||||
{ Opt_backupuid, "backupuid=%s" },
|
||||
{ Opt_backupgid, "backupgid=%s" },
|
||||
|
@ -218,6 +221,7 @@ static const match_table_t cifs_mount_option_tokens = {
|
|||
{ Opt_echo_interval, "echo_interval=%s" },
|
||||
{ Opt_max_credits, "max_credits=%s" },
|
||||
{ Opt_snapshot, "snapshot=%s" },
|
||||
{ Opt_max_channels, "max_channels=%s" },
|
||||
{ Opt_compress, "compress=%s" },
|
||||
|
||||
{ Opt_blank_user, "user=" },
|
||||
|
@ -1681,6 +1685,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
|||
|
||||
vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
|
||||
|
||||
/* default to no multichannel (single server connection) */
|
||||
vol->multichannel = false;
|
||||
vol->max_channels = 1;
|
||||
|
||||
if (!mountdata)
|
||||
goto cifs_parse_mount_err;
|
||||
|
||||
|
@ -1974,6 +1982,12 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
|||
case Opt_rdma:
|
||||
vol->rdma = true;
|
||||
break;
|
||||
case Opt_multichannel:
|
||||
vol->multichannel = true;
|
||||
break;
|
||||
case Opt_nomultichannel:
|
||||
vol->multichannel = false;
|
||||
break;
|
||||
case Opt_compress:
|
||||
vol->compression = UNKNOWN_TYPE;
|
||||
cifs_dbg(VFS,
|
||||
|
@ -2137,6 +2151,15 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
|
|||
}
|
||||
vol->max_credits = option;
|
||||
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 */
|
||||
|
||||
|
@ -2781,6 +2804,10 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
|
|||
sizeof(tcp_ses->srcaddr));
|
||||
memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
|
||||
sizeof(tcp_ses->dstaddr));
|
||||
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
|
||||
|
@ -2870,6 +2897,13 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
|
|||
vol->sectype != ses->sectype)
|
||||
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) {
|
||||
case Kerberos:
|
||||
if (!uid_eq(vol->cred_uid, ses->cred_uid))
|
||||
|
|
Loading…
Reference in New Issue