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