Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Aurelien Aptel and committed by
Steve French
bcc88801 35adffed

+56 -2
+4
fs/cifs/cifsfs.c
··· 613 613 /* convert actimeo and display it in seconds */ 614 614 seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ); 615 615 616 + if (tcon->ses->chan_max > 1) 617 + seq_printf(s, ",multichannel,max_channel=%zu", 618 + tcon->ses->chan_max); 619 + 616 620 return 0; 617 621 } 618 622
+16
fs/cifs/cifsglob.h
··· 591 591 bool resilient:1; /* noresilient not required since not fored for CA */ 592 592 bool domainauto:1; 593 593 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]; 594 598 unsigned int bsize; 595 599 unsigned int rsize; 596 600 unsigned int wsize; ··· 611 607 __u64 snapshot_time; /* needed for timewarp tokens */ 612 608 __u32 handle_timeout; /* persistent and durable handle timeout in ms */ 613 609 unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */ 610 + unsigned int max_channels; 614 611 __u16 compression; /* compression algorithm 0xFFFF default 0=disabled */ 615 612 bool rootfs:1; /* if it's a SMB root file system */ 616 613 }; ··· 958 953 struct sockaddr_storage sockaddr; 959 954 }; 960 955 956 + struct cifs_chan { 957 + struct TCP_Server_Info *server; 958 + __u8 signkey[SMB3_SIGN_KEY_SIZE]; 959 + }; 960 + 961 961 /* 962 962 * Session structure. One of these for each uid session with a particular host 963 963 */ ··· 1012 1002 struct cifs_server_iface *iface_list; 1013 1003 size_t iface_count; 1014 1004 unsigned long iface_last_update; /* jiffies */ 1005 + 1006 + #define CIFS_MAX_CHANNELS 16 1007 + struct cifs_chan chans[CIFS_MAX_CHANNELS]; 1008 + size_t chan_count; 1009 + size_t chan_max; 1010 + atomic_t chan_seq; /* round robin state */ 1015 1011 }; 1016 1012 1017 1013 static inline bool
+36 -2
fs/cifs/connect.c
··· 97 97 Opt_persistent, Opt_nopersistent, 98 98 Opt_resilient, Opt_noresilient, 99 99 Opt_domainauto, Opt_rdma, Opt_modesid, Opt_rootfs, 100 + Opt_multichannel, Opt_nomultichannel, 100 101 Opt_compress, 101 102 102 103 /* Mount options which take numeric value */ ··· 107 106 Opt_min_enc_offload, 108 107 Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo, 109 108 Opt_echo_interval, Opt_max_credits, Opt_handletimeout, 110 - Opt_snapshot, 109 + Opt_snapshot, Opt_max_channels, 111 110 112 111 /* Mount options which take string value */ 113 112 Opt_user, Opt_pass, Opt_ip, ··· 200 199 { Opt_noresilient, "noresilienthandles"}, 201 200 { Opt_domainauto, "domainauto"}, 202 201 { Opt_rdma, "rdma"}, 202 + { Opt_multichannel, "multichannel" }, 203 + { Opt_nomultichannel, "nomultichannel" }, 203 204 204 205 { Opt_backupuid, "backupuid=%s" }, 205 206 { Opt_backupgid, "backupgid=%s" }, ··· 221 218 { Opt_echo_interval, "echo_interval=%s" }, 222 219 { Opt_max_credits, "max_credits=%s" }, 223 220 { Opt_snapshot, "snapshot=%s" }, 221 + { Opt_max_channels, "max_channels=%s" }, 224 222 { Opt_compress, "compress=%s" }, 225 223 226 224 { Opt_blank_user, "user=" }, ··· 1685 1681 1686 1682 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT; 1687 1683 1684 + /* default to no multichannel (single server connection) */ 1685 + vol->multichannel = false; 1686 + vol->max_channels = 1; 1687 + 1688 1688 if (!mountdata) 1689 1689 goto cifs_parse_mount_err; 1690 1690 ··· 1982 1974 case Opt_rdma: 1983 1975 vol->rdma = true; 1984 1976 break; 1977 + case Opt_multichannel: 1978 + vol->multichannel = true; 1979 + break; 1980 + case Opt_nomultichannel: 1981 + vol->multichannel = false; 1982 + break; 1985 1983 case Opt_compress: 1986 1984 vol->compression = UNKNOWN_TYPE; 1987 1985 cifs_dbg(VFS, ··· 2150 2136 goto cifs_parse_mount_err; 2151 2137 } 2152 2138 vol->max_credits = option; 2139 + break; 2140 + case Opt_max_channels: 2141 + if (get_option_ul(args, &option) || option < 1 || 2142 + option > CIFS_MAX_CHANNELS) { 2143 + cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n", 2144 + __func__, CIFS_MAX_CHANNELS); 2145 + goto cifs_parse_mount_err; 2146 + } 2147 + vol->max_channels = option; 2153 2148 break; 2154 2149 2155 2150 /* String Arguments */ ··· 2804 2781 sizeof(tcp_ses->srcaddr)); 2805 2782 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr, 2806 2783 sizeof(tcp_ses->dstaddr)); 2807 - generate_random_uuid(tcp_ses->client_guid); 2784 + if (volume_info->use_client_guid) 2785 + memcpy(tcp_ses->client_guid, volume_info->client_guid, 2786 + SMB2_CLIENT_GUID_SIZE); 2787 + else 2788 + generate_random_uuid(tcp_ses->client_guid); 2808 2789 /* 2809 2790 * at this point we are the only ones with the pointer 2810 2791 * to the struct since the kernel thread not created yet ··· 2895 2868 { 2896 2869 if (vol->sectype != Unspecified && 2897 2870 vol->sectype != ses->sectype) 2871 + return 0; 2872 + 2873 + /* 2874 + * If an existing session is limited to less channels than 2875 + * requested, it should not be reused 2876 + */ 2877 + if (ses->chan_max < vol->max_channels) 2898 2878 return 0; 2899 2879 2900 2880 switch (ses->sectype) {