Skip to content

Commit bcc8880

Browse files
aaptelsmfrench
authored andcommitted
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 <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 35adffe commit bcc8880

File tree

3 files changed

+56
-2
lines changed

3 files changed

+56
-2
lines changed

fs/cifs/cifsfs.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,10 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
613613
/* convert actimeo and display it in seconds */
614614
seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
615615

616+
if (tcon->ses->chan_max > 1)
617+
seq_printf(s, ",multichannel,max_channel=%zu",
618+
tcon->ses->chan_max);
619+
616620
return 0;
617621
}
618622

fs/cifs/cifsglob.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,10 @@ struct smb_vol {
591591
bool resilient:1; /* noresilient not required since not fored for CA */
592592
bool domainauto:1;
593593
bool rdma:1;
594+
bool multichannel:1;
595+
bool use_client_guid:1;
596+
/* reuse existing guid for multichannel */
597+
u8 client_guid[SMB2_CLIENT_GUID_SIZE];
594598
unsigned int bsize;
595599
unsigned int rsize;
596600
unsigned int wsize;
@@ -607,6 +611,7 @@ struct smb_vol {
607611
__u64 snapshot_time; /* needed for timewarp tokens */
608612
__u32 handle_timeout; /* persistent and durable handle timeout in ms */
609613
unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
614+
unsigned int max_channels;
610615
__u16 compression; /* compression algorithm 0xFFFF default 0=disabled */
611616
bool rootfs:1; /* if it's a SMB root file system */
612617
};
@@ -953,6 +958,11 @@ struct cifs_server_iface {
953958
struct sockaddr_storage sockaddr;
954959
};
955960

961+
struct cifs_chan {
962+
struct TCP_Server_Info *server;
963+
__u8 signkey[SMB3_SIGN_KEY_SIZE];
964+
};
965+
956966
/*
957967
* Session structure. One of these for each uid session with a particular host
958968
*/
@@ -1002,6 +1012,12 @@ struct cifs_ses {
10021012
struct cifs_server_iface *iface_list;
10031013
size_t iface_count;
10041014
unsigned long iface_last_update; /* jiffies */
1015+
1016+
#define CIFS_MAX_CHANNELS 16
1017+
struct cifs_chan chans[CIFS_MAX_CHANNELS];
1018+
size_t chan_count;
1019+
size_t chan_max;
1020+
atomic_t chan_seq; /* round robin state */
10051021
};
10061022

10071023
static inline bool

fs/cifs/connect.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ enum {
9797
Opt_persistent, Opt_nopersistent,
9898
Opt_resilient, Opt_noresilient,
9999
Opt_domainauto, Opt_rdma, Opt_modesid, Opt_rootfs,
100+
Opt_multichannel, Opt_nomultichannel,
100101
Opt_compress,
101102

102103
/* Mount options which take numeric value */
@@ -106,7 +107,7 @@ enum {
106107
Opt_min_enc_offload,
107108
Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo,
108109
Opt_echo_interval, Opt_max_credits, Opt_handletimeout,
109-
Opt_snapshot,
110+
Opt_snapshot, Opt_max_channels,
110111

111112
/* Mount options which take string value */
112113
Opt_user, Opt_pass, Opt_ip,
@@ -199,6 +200,8 @@ static const match_table_t cifs_mount_option_tokens = {
199200
{ Opt_noresilient, "noresilienthandles"},
200201
{ Opt_domainauto, "domainauto"},
201202
{ Opt_rdma, "rdma"},
203+
{ Opt_multichannel, "multichannel" },
204+
{ Opt_nomultichannel, "nomultichannel" },
202205

203206
{ Opt_backupuid, "backupuid=%s" },
204207
{ Opt_backupgid, "backupgid=%s" },
@@ -218,6 +221,7 @@ static const match_table_t cifs_mount_option_tokens = {
218221
{ Opt_echo_interval, "echo_interval=%s" },
219222
{ Opt_max_credits, "max_credits=%s" },
220223
{ Opt_snapshot, "snapshot=%s" },
224+
{ Opt_max_channels, "max_channels=%s" },
221225
{ Opt_compress, "compress=%s" },
222226

223227
{ Opt_blank_user, "user=" },
@@ -1681,6 +1685,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
16811685

16821686
vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
16831687

1688+
/* default to no multichannel (single server connection) */
1689+
vol->multichannel = false;
1690+
vol->max_channels = 1;
1691+
16841692
if (!mountdata)
16851693
goto cifs_parse_mount_err;
16861694

@@ -1974,6 +1982,12 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
19741982
case Opt_rdma:
19751983
vol->rdma = true;
19761984
break;
1985+
case Opt_multichannel:
1986+
vol->multichannel = true;
1987+
break;
1988+
case Opt_nomultichannel:
1989+
vol->multichannel = false;
1990+
break;
19771991
case Opt_compress:
19781992
vol->compression = UNKNOWN_TYPE;
19791993
cifs_dbg(VFS,
@@ -2137,6 +2151,15 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
21372151
}
21382152
vol->max_credits = option;
21392153
break;
2154+
case Opt_max_channels:
2155+
if (get_option_ul(args, &option) || option < 1 ||
2156+
option > CIFS_MAX_CHANNELS) {
2157+
cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n",
2158+
__func__, CIFS_MAX_CHANNELS);
2159+
goto cifs_parse_mount_err;
2160+
}
2161+
vol->max_channels = option;
2162+
break;
21402163

21412164
/* String Arguments */
21422165

@@ -2781,7 +2804,11 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
27812804
sizeof(tcp_ses->srcaddr));
27822805
memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
27832806
sizeof(tcp_ses->dstaddr));
2784-
generate_random_uuid(tcp_ses->client_guid);
2807+
if (volume_info->use_client_guid)
2808+
memcpy(tcp_ses->client_guid, volume_info->client_guid,
2809+
SMB2_CLIENT_GUID_SIZE);
2810+
else
2811+
generate_random_uuid(tcp_ses->client_guid);
27852812
/*
27862813
* at this point we are the only ones with the pointer
27872814
* 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)
28702897
vol->sectype != ses->sectype)
28712898
return 0;
28722899

2900+
/*
2901+
* If an existing session is limited to less channels than
2902+
* requested, it should not be reused
2903+
*/
2904+
if (ses->chan_max < vol->max_channels)
2905+
return 0;
2906+
28732907
switch (ses->sectype) {
28742908
case Kerberos:
28752909
if (!uid_eq(vol->cred_uid, ses->cred_uid))

0 commit comments

Comments
 (0)