Merge tag '5.16-rc-part2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull more cifs updates from Steve French:

- improvements to reconnect and multichannel

- a performance improvement (additional use of SMB3 compounding)

- DFS code cleanup and improvements

- various trivial Coverity fixes

- two fscache fixes

- an fsync fix

* tag '5.16-rc-part2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: (23 commits)
cifs: do not duplicate fscache cookie for secondary channels
cifs: connect individual channel servers to primary channel server
cifs: protect session channel fields with chan_lock
cifs: do not negotiate session if session already exists
smb3: do not setup the fscache_super_cookie until fsinfo initialized
cifs: fix potential use-after-free bugs
cifs: fix memory leak of smb3_fs_context_dup::server_hostname
smb3: add additional null check in SMB311_posix_mkdir
cifs: release lock earlier in dequeue_mid error case
smb3: add additional null check in SMB2_tcon
smb3: add additional null check in SMB2_open
smb3: add additional null check in SMB2_ioctl
smb3: remove trivial dfs compile warning
cifs: support nested dfs links over reconnect
smb3: do not error on fsync when readonly
cifs: for compound requests, use open handle if possible
cifs: set a minimum of 120s for next dns resolution
cifs: split out dfs code from cifs_reconnect()
cifs: convert list_for_each to entry variant
cifs: introduce new helper for cifs_reconnect()
...

+1212 -961
+6 -1
fs/cifs/cifs_debug.c
··· 271 c = 0; 272 spin_lock(&cifs_tcp_ses_lock); 273 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { 274 - if (server->is_channel) 275 continue; 276 277 c++; ··· 359 seq_printf(m, " signed"); 360 if (server->posix_ext_supported) 361 seq_printf(m, " posix"); 362 363 if (server->rdma) 364 seq_printf(m, "\nRDMA "); ··· 415 from_kuid(&init_user_ns, ses->linux_uid), 416 from_kuid(&init_user_ns, ses->cred_uid)); 417 418 if (ses->chan_count > 1) { 419 seq_printf(m, "\n\n\tExtra Channels: %zu ", 420 ses->chan_count-1); 421 for (j = 1; j < ses->chan_count; j++) 422 cifs_dump_channel(m, j, &ses->chans[j]); 423 } 424 425 seq_puts(m, "\n\n\tShares: "); 426 j = 0;
··· 271 c = 0; 272 spin_lock(&cifs_tcp_ses_lock); 273 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { 274 + /* channel info will be printed as a part of sessions below */ 275 + if (CIFS_SERVER_IS_CHAN(server)) 276 continue; 277 278 c++; ··· 358 seq_printf(m, " signed"); 359 if (server->posix_ext_supported) 360 seq_printf(m, " posix"); 361 + if (server->nosharesock) 362 + seq_printf(m, " nosharesock"); 363 364 if (server->rdma) 365 seq_printf(m, "\nRDMA "); ··· 412 from_kuid(&init_user_ns, ses->linux_uid), 413 from_kuid(&init_user_ns, ses->cred_uid)); 414 415 + spin_lock(&ses->chan_lock); 416 if (ses->chan_count > 1) { 417 seq_printf(m, "\n\n\tExtra Channels: %zu ", 418 ses->chan_count-1); 419 for (j = 1; j < ses->chan_count; j++) 420 cifs_dump_channel(m, j, &ses->chans[j]); 421 } 422 + spin_unlock(&ses->chan_lock); 423 424 seq_puts(m, "\n\n\tShares: "); 425 j = 0;
+2 -57
fs/cifs/cifs_dfs_ref.c
··· 307 static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt) 308 { 309 struct cifs_sb_info *cifs_sb; 310 - struct cifs_ses *ses; 311 - struct cifs_tcon *tcon; 312 void *page; 313 - char *full_path, *root_path; 314 - unsigned int xid; 315 - int rc; 316 struct vfsmount *mnt; 317 318 cifs_dbg(FYI, "in %s\n", __func__); ··· 320 * the double backslashes usually used in the UNC. This function 321 * gives us the latter, so we must adjust the result. 322 */ 323 - mnt = ERR_PTR(-ENOMEM); 324 - 325 cifs_sb = CIFS_SB(mntpt->d_sb); 326 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) { 327 mnt = ERR_PTR(-EREMOTE); ··· 335 } 336 337 convert_delimiter(full_path, '\\'); 338 - 339 cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path); 340 341 - if (!cifs_sb_master_tlink(cifs_sb)) { 342 - cifs_dbg(FYI, "%s: master tlink is NULL\n", __func__); 343 - goto free_full_path; 344 - } 345 - 346 - tcon = cifs_sb_master_tcon(cifs_sb); 347 - if (!tcon) { 348 - cifs_dbg(FYI, "%s: master tcon is NULL\n", __func__); 349 - goto free_full_path; 350 - } 351 - 352 - root_path = kstrdup(tcon->treeName, GFP_KERNEL); 353 - if (!root_path) { 354 - mnt = ERR_PTR(-ENOMEM); 355 - goto free_full_path; 356 - } 357 - cifs_dbg(FYI, "%s: root path: %s\n", __func__, root_path); 358 - 359 - ses = tcon->ses; 360 - xid = get_xid(); 361 - 362 - /* 363 - * If DFS root has been expired, then unconditionally fetch it again to 364 - * refresh DFS referral cache. 365 - */ 366 - rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), 367 - root_path + 1, NULL, NULL); 368 - if (!rc) { 369 - rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, 370 - cifs_remap(cifs_sb), full_path + 1, 371 - NULL, NULL); 372 - } 373 - 374 - free_xid(xid); 375 - 376 - if (rc) { 377 - mnt = ERR_PTR(rc); 378 - goto free_root_path; 379 - } 380 - /* 381 - * OK - we were able to get and cache a referral for @full_path. 382 - * 383 - * Now, pass it down to cifs_mount() and it will retry every available 384 - * node server in case of failures - no need to do it here. 385 - */ 386 mnt = cifs_dfs_do_mount(mntpt, cifs_sb, full_path); 387 - cifs_dbg(FYI, "%s: cifs_dfs_do_mount:%s , mnt:%p\n", __func__, 388 - full_path + 1, mnt); 389 390 - free_root_path: 391 - kfree(root_path); 392 free_full_path: 393 free_dentry_path(page); 394 cdda_exit:
··· 307 static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt) 308 { 309 struct cifs_sb_info *cifs_sb; 310 void *page; 311 + char *full_path; 312 struct vfsmount *mnt; 313 314 cifs_dbg(FYI, "in %s\n", __func__); ··· 324 * the double backslashes usually used in the UNC. This function 325 * gives us the latter, so we must adjust the result. 326 */ 327 cifs_sb = CIFS_SB(mntpt->d_sb); 328 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) { 329 mnt = ERR_PTR(-EREMOTE); ··· 341 } 342 343 convert_delimiter(full_path, '\\'); 344 cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path); 345 346 mnt = cifs_dfs_do_mount(mntpt, cifs_sb, full_path); 347 + cifs_dbg(FYI, "%s: cifs_dfs_do_mount:%s , mnt:%p\n", __func__, full_path + 1, mnt); 348 349 free_full_path: 350 free_dentry_path(page); 351 cdda_exit:
-5
fs/cifs/cifs_fs_sb.h
··· 61 /* only used when CIFS_MOUNT_USE_PREFIX_PATH is set */ 62 char *prepath; 63 64 - /* 65 - * Canonical DFS path initially provided by the mount call. We might connect to something 66 - * different via DFS but we want to keep it to do failover properly. 67 - */ 68 - char *origin_fullpath; /* \\HOST\SHARE\[OPTIONAL PATH] */ 69 /* randomly generated 128-bit number for indexing dfs mount groups in referral cache */ 70 uuid_t dfs_mount_id; 71 /*
··· 61 /* only used when CIFS_MOUNT_USE_PREFIX_PATH is set */ 62 char *prepath; 63 64 /* randomly generated 128-bit number for indexing dfs mount groups in referral cache */ 65 uuid_t dfs_mount_id; 66 /*
+44 -3
fs/cifs/cifsglob.h
··· 15 #include <linux/slab.h> 16 #include <linux/mempool.h> 17 #include <linux/workqueue.h> 18 #include "cifs_fs_sb.h" 19 #include "cifsacl.h" 20 #include <crypto/internal/hash.h> ··· 76 #define SMB_ECHO_INTERVAL_MAX 600 77 #define SMB_ECHO_INTERVAL_DEFAULT 60 78 79 - /* dns resolution interval in seconds */ 80 #define SMB_DNS_RESOLVE_INTERVAL_DEFAULT 600 81 82 /* maximum number of PDUs in one compound */ ··· 100 #ifndef XATTR_DOS_ATTRIB 101 #define XATTR_DOS_ATTRIB "user.DOSATTRIB" 102 #endif 103 104 /* 105 * CIFS vfs client Status information (based on what we know.) ··· 596 struct list_head pending_mid_q; 597 bool noblocksnd; /* use blocking sendmsg */ 598 bool noautotune; /* do not autotune send buf sizes */ 599 bool tcp_nodelay; 600 unsigned int credits; /* send no more requests at once */ 601 unsigned int max_credits; /* can override large 32000 default at mnt */ ··· 690 */ 691 int nr_targets; 692 bool noblockcnt; /* use non-blocking connect() */ 693 - bool is_channel; /* if a session channel */ 694 #ifdef CONFIG_CIFS_SWN_UPCALL 695 bool use_swn_dstaddr; 696 struct sockaddr_storage swn_dstaddr; 697 #endif 698 #ifdef CONFIG_CIFS_DFS_UPCALL 699 bool is_dfs_conn; /* if a dfs connection */ 700 #endif 701 }; 702 ··· 934 and after mount option parsing we fill it */ 935 char *domainName; 936 char *password; 937 struct session_key auth_key; 938 struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */ 939 enum securityEnum sectype; /* what security flavor was specified? */ ··· 960 * iface_lock should be taken when accessing any of these fields 961 */ 962 spinlock_t iface_lock; 963 struct cifs_server_iface *iface_list; 964 size_t iface_count; 965 unsigned long iface_last_update; /* jiffies */ 966 967 #define CIFS_MAX_CHANNELS 16 968 struct cifs_chan chans[CIFS_MAX_CHANNELS]; 969 struct cifs_chan *binding_chan; 970 size_t chan_count; 971 size_t chan_max; 972 atomic_t chan_seq; /* round robin state */ 973 }; 974 975 /* ··· 1123 struct cached_fid crfid; /* Cached root fid */ 1124 /* BB add field for back pointer to sb struct(s)? */ 1125 #ifdef CONFIG_CIFS_DFS_UPCALL 1126 - char *dfs_path; /* canonical DFS path */ 1127 struct list_head ulist; /* cache update list */ 1128 #endif 1129 }; ··· 1971 return false; 1972 return is_smb1_server(tcon->ses->server) ? tcon->Flags & SMB_SHARE_IS_IN_DFS : 1973 tcon->share_flags & (SHI1005_FLAGS_DFS | SHI1005_FLAGS_DFS_ROOT); 1974 } 1975 1976 #endif /* _CIFS_GLOB_H */
··· 15 #include <linux/slab.h> 16 #include <linux/mempool.h> 17 #include <linux/workqueue.h> 18 + #include <linux/utsname.h> 19 #include "cifs_fs_sb.h" 20 #include "cifsacl.h" 21 #include <crypto/internal/hash.h> ··· 75 #define SMB_ECHO_INTERVAL_MAX 600 76 #define SMB_ECHO_INTERVAL_DEFAULT 60 77 78 + /* dns resolution intervals in seconds */ 79 + #define SMB_DNS_RESOLVE_INTERVAL_MIN 120 80 #define SMB_DNS_RESOLVE_INTERVAL_DEFAULT 600 81 82 /* maximum number of PDUs in one compound */ ··· 98 #ifndef XATTR_DOS_ATTRIB 99 #define XATTR_DOS_ATTRIB "user.DOSATTRIB" 100 #endif 101 + 102 + #define CIFS_MAX_WORKSTATION_LEN (__NEW_UTS_LEN + 1) /* reasonable max for client */ 103 104 /* 105 * CIFS vfs client Status information (based on what we know.) ··· 592 struct list_head pending_mid_q; 593 bool noblocksnd; /* use blocking sendmsg */ 594 bool noautotune; /* do not autotune send buf sizes */ 595 + bool nosharesock; 596 bool tcp_nodelay; 597 unsigned int credits; /* send no more requests at once */ 598 unsigned int max_credits; /* can override large 32000 default at mnt */ ··· 685 */ 686 int nr_targets; 687 bool noblockcnt; /* use non-blocking connect() */ 688 + 689 + /* 690 + * If this is a session channel, 691 + * primary_server holds the ref-counted 692 + * pointer to primary channel connection for the session. 693 + */ 694 + #define CIFS_SERVER_IS_CHAN(server) (!!(server)->primary_server) 695 + struct TCP_Server_Info *primary_server; 696 + 697 #ifdef CONFIG_CIFS_SWN_UPCALL 698 bool use_swn_dstaddr; 699 struct sockaddr_storage swn_dstaddr; 700 #endif 701 #ifdef CONFIG_CIFS_DFS_UPCALL 702 bool is_dfs_conn; /* if a dfs connection */ 703 + struct mutex refpath_lock; /* protects leaf_fullpath */ 704 + /* 705 + * Canonical DFS full paths that were used to chase referrals in mount and reconnect. 706 + * 707 + * origin_fullpath: first or original referral path 708 + * leaf_fullpath: last referral path (might be changed due to nested links in reconnect) 709 + * 710 + * current_fullpath: pointer to either origin_fullpath or leaf_fullpath 711 + * NOTE: cannot be accessed outside cifs_reconnect() and smb2_reconnect() 712 + * 713 + * format: \\HOST\SHARE\[OPTIONAL PATH] 714 + */ 715 + char *origin_fullpath, *leaf_fullpath, *current_fullpath; 716 #endif 717 }; 718 ··· 908 and after mount option parsing we fill it */ 909 char *domainName; 910 char *password; 911 + char *workstation_name; 912 struct session_key auth_key; 913 struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */ 914 enum securityEnum sectype; /* what security flavor was specified? */ ··· 933 * iface_lock should be taken when accessing any of these fields 934 */ 935 spinlock_t iface_lock; 936 + /* ========= begin: protected by iface_lock ======== */ 937 struct cifs_server_iface *iface_list; 938 size_t iface_count; 939 unsigned long iface_last_update; /* jiffies */ 940 + /* ========= end: protected by iface_lock ======== */ 941 942 + spinlock_t chan_lock; 943 + /* ========= begin: protected by chan_lock ======== */ 944 #define CIFS_MAX_CHANNELS 16 945 struct cifs_chan chans[CIFS_MAX_CHANNELS]; 946 struct cifs_chan *binding_chan; 947 size_t chan_count; 948 size_t chan_max; 949 atomic_t chan_seq; /* round robin state */ 950 + /* ========= end: protected by chan_lock ======== */ 951 }; 952 953 /* ··· 1091 struct cached_fid crfid; /* Cached root fid */ 1092 /* BB add field for back pointer to sb struct(s)? */ 1093 #ifdef CONFIG_CIFS_DFS_UPCALL 1094 struct list_head ulist; /* cache update list */ 1095 #endif 1096 }; ··· 1940 return false; 1941 return is_smb1_server(tcon->ses->server) ? tcon->Flags & SMB_SHARE_IS_IN_DFS : 1942 tcon->share_flags & (SHI1005_FLAGS_DFS | SHI1005_FLAGS_DFS_ROOT); 1943 + } 1944 + 1945 + static inline bool cifs_is_referral_server(struct cifs_tcon *tcon, 1946 + const struct dfs_info3_param *ref) 1947 + { 1948 + /* 1949 + * Check if all targets are capable of handling DFS referrals as per 1950 + * MS-DFSC 2.2.4 RESP_GET_DFS_REFERRAL. 1951 + */ 1952 + return is_tcon_dfs(tcon) || (ref && (ref->flags & DFSREF_REFERRAL_SERVER)); 1953 } 1954 1955 #endif /* _CIFS_GLOB_H */
+7 -3
fs/cifs/cifsproto.h
··· 269 270 extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon, 271 const char *path); 272 - 273 - extern struct TCP_Server_Info *cifs_get_tcp_session(struct smb3_fs_context *ctx); 274 extern void cifs_put_tcp_session(struct TCP_Server_Info *server, 275 int from_reconnect); 276 extern void cifs_put_tcon(struct cifs_tcon *tcon); ··· 608 609 struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server); 610 void cifs_put_tcp_super(struct super_block *sb); 611 - int update_super_prepath(struct cifs_tcon *tcon, char *prefix); 612 char *extract_hostname(const char *unc); 613 char *extract_sharename(const char *unc); 614 ··· 634 else 635 return options; 636 } 637 638 #endif /* _CIFSPROTO_H */
··· 269 270 extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon, 271 const char *path); 272 + extern struct TCP_Server_Info * 273 + cifs_get_tcp_session(struct smb3_fs_context *ctx, 274 + struct TCP_Server_Info *primary_server); 275 extern void cifs_put_tcp_session(struct TCP_Server_Info *server, 276 int from_reconnect); 277 extern void cifs_put_tcon(struct cifs_tcon *tcon); ··· 607 608 struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server); 609 void cifs_put_tcp_super(struct super_block *sb); 610 + int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix); 611 char *extract_hostname(const char *unc); 612 char *extract_sharename(const char *unc); 613 ··· 633 else 634 return options; 635 } 636 + 637 + struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon); 638 + void cifs_put_tcon_super(struct super_block *sb); 639 640 #endif /* _CIFSPROTO_H */
+816 -708
fs/cifs/connect.c
··· 61 /* Drop the connection to not overload the server */ 62 #define NUM_STATUS_IO_TIMEOUT 5 63 64 static int ip_connect(struct TCP_Server_Info *server); 65 static int generic_ip_connect(struct TCP_Server_Info *server); 66 static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); ··· 129 * To make sure we don't use the cached entry, retry 1s 130 * after expiry. 131 */ 132 - ttl = (expiry - now + 1); 133 } 134 rc = !rc ? -1 : 0; 135 ··· 162 mutex_unlock(&server->srv_mutex); 163 } 164 165 - #ifdef CONFIG_CIFS_DFS_UPCALL 166 - /* These functions must be called with server->srv_mutex held */ 167 - static void reconn_set_next_dfs_target(struct TCP_Server_Info *server, 168 - struct cifs_sb_info *cifs_sb, 169 - struct dfs_cache_tgt_list *tgt_list, 170 - struct dfs_cache_tgt_iterator **tgt_it) 171 - { 172 - const char *name; 173 - int rc; 174 - 175 - if (!cifs_sb || !cifs_sb->origin_fullpath) 176 - return; 177 - 178 - if (!*tgt_it) { 179 - *tgt_it = dfs_cache_get_tgt_iterator(tgt_list); 180 - } else { 181 - *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it); 182 - if (!*tgt_it) 183 - *tgt_it = dfs_cache_get_tgt_iterator(tgt_list); 184 - } 185 - 186 - cifs_dbg(FYI, "%s: UNC: %s\n", __func__, cifs_sb->origin_fullpath); 187 - 188 - name = dfs_cache_get_tgt_name(*tgt_it); 189 - 190 - kfree(server->hostname); 191 - 192 - server->hostname = extract_hostname(name); 193 - if (IS_ERR(server->hostname)) { 194 - cifs_dbg(FYI, 195 - "%s: failed to extract hostname from target: %ld\n", 196 - __func__, PTR_ERR(server->hostname)); 197 - return; 198 - } 199 - 200 - rc = reconn_set_ipaddr_from_hostname(server); 201 - if (rc) { 202 - cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n", 203 - __func__, rc); 204 - } 205 - } 206 - 207 - static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb, 208 - struct dfs_cache_tgt_list *tl) 209 - { 210 - if (!cifs_sb->origin_fullpath) 211 - return -EOPNOTSUPP; 212 - return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl); 213 - } 214 - #endif 215 - 216 - /* 217 - * cifs tcp session reconnection 218 * 219 - * mark tcp session as reconnecting so temporarily locked 220 - * mark all smb sessions as reconnecting for tcp session 221 - * reconnect tcp session 222 - * wake up waiters on reconnection? - (not needed currently) 223 */ 224 - int 225 - cifs_reconnect(struct TCP_Server_Info *server) 226 { 227 - int rc = 0; 228 - struct list_head *tmp, *tmp2; 229 struct cifs_ses *ses; 230 struct cifs_tcon *tcon; 231 - struct mid_q_entry *mid_entry; 232 struct list_head retry_list; 233 - #ifdef CONFIG_CIFS_DFS_UPCALL 234 - struct super_block *sb = NULL; 235 - struct cifs_sb_info *cifs_sb = NULL; 236 - struct dfs_cache_tgt_list tgt_list = DFS_CACHE_TGT_LIST_INIT(tgt_list); 237 - struct dfs_cache_tgt_iterator *tgt_it = NULL; 238 - #endif 239 240 - spin_lock(&GlobalMid_Lock); 241 - server->nr_targets = 1; 242 - #ifdef CONFIG_CIFS_DFS_UPCALL 243 - spin_unlock(&GlobalMid_Lock); 244 - sb = cifs_get_tcp_super(server); 245 - if (IS_ERR(sb)) { 246 - rc = PTR_ERR(sb); 247 - cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n", 248 - __func__, rc); 249 - sb = NULL; 250 - } else { 251 - cifs_sb = CIFS_SB(sb); 252 - rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list); 253 - if (rc) { 254 - cifs_sb = NULL; 255 - if (rc != -EOPNOTSUPP) { 256 - cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n", 257 - __func__); 258 - } 259 - } else { 260 - server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list); 261 - } 262 - } 263 - cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__, 264 - server->nr_targets); 265 - spin_lock(&GlobalMid_Lock); 266 - #endif 267 - if (server->tcpStatus == CifsExiting) { 268 - /* the demux thread will exit normally 269 - next time through the loop */ 270 - spin_unlock(&GlobalMid_Lock); 271 - #ifdef CONFIG_CIFS_DFS_UPCALL 272 - dfs_cache_free_tgts(&tgt_list); 273 - cifs_put_tcp_super(sb); 274 - #endif 275 - wake_up(&server->response_q); 276 - return rc; 277 - } else 278 - server->tcpStatus = CifsNeedReconnect; 279 - spin_unlock(&GlobalMid_Lock); 280 server->maxBuf = 0; 281 server->max_read = 0; 282 283 cifs_dbg(FYI, "Mark tcp session as need reconnect\n"); 284 trace_smb3_reconnect(server->CurrentMid, server->conn_id, server->hostname); 285 286 - /* before reconnecting the tcp session, mark the smb session (uid) 287 - and the tid bad so they are not used until reconnected */ 288 - cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n", 289 - __func__); 290 spin_lock(&cifs_tcp_ses_lock); 291 - list_for_each(tmp, &server->smb_ses_list) { 292 - ses = list_entry(tmp, struct cifs_ses, smb_ses_list); 293 ses->need_reconnect = true; 294 - list_for_each(tmp2, &ses->tcon_list) { 295 - tcon = list_entry(tmp2, struct cifs_tcon, tcon_list); 296 tcon->need_reconnect = true; 297 - } 298 if (ses->tcon_ipc) 299 ses->tcon_ipc->need_reconnect = true; 300 } ··· 203 cifs_dbg(FYI, "%s: tearing down socket\n", __func__); 204 mutex_lock(&server->srv_mutex); 205 if (server->ssocket) { 206 - cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n", 207 - server->ssocket->state, server->ssocket->flags); 208 kernel_sock_shutdown(server->ssocket, SHUT_WR); 209 - cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n", 210 - server->ssocket->state, server->ssocket->flags); 211 sock_release(server->ssocket); 212 server->ssocket = NULL; 213 } ··· 222 INIT_LIST_HEAD(&retry_list); 223 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__); 224 spin_lock(&GlobalMid_Lock); 225 - list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { 226 - mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 227 - kref_get(&mid_entry->refcount); 228 - if (mid_entry->mid_state == MID_REQUEST_SUBMITTED) 229 - mid_entry->mid_state = MID_RETRY_NEEDED; 230 - list_move(&mid_entry->qhead, &retry_list); 231 - mid_entry->mid_flags |= MID_DELETED; 232 } 233 spin_unlock(&GlobalMid_Lock); 234 mutex_unlock(&server->srv_mutex); 235 236 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__); 237 - list_for_each_safe(tmp, tmp2, &retry_list) { 238 - mid_entry = list_entry(tmp, struct mid_q_entry, qhead); 239 - list_del_init(&mid_entry->qhead); 240 - mid_entry->callback(mid_entry); 241 - cifs_mid_q_entry_release(mid_entry); 242 } 243 244 if (cifs_rdma_enabled(server)) { ··· 244 smbd_destroy(server); 245 mutex_unlock(&server->srv_mutex); 246 } 247 248 do { 249 try_to_freeze(); 250 - 251 mutex_lock(&server->srv_mutex); 252 253 - 254 if (!cifs_swn_set_server_dstaddr(server)) { 255 - #ifdef CONFIG_CIFS_DFS_UPCALL 256 - if (cifs_sb && cifs_sb->origin_fullpath) 257 - /* 258 - * Set up next DFS target server (if any) for reconnect. If DFS 259 - * feature is disabled, then we will retry last server we 260 - * connected to before. 261 - */ 262 - reconn_set_next_dfs_target(server, cifs_sb, &tgt_list, &tgt_it); 263 - else { 264 - #endif 265 - /* 266 - * Resolve the hostname again to make sure that IP address is up-to-date. 267 - */ 268 rc = reconn_set_ipaddr_from_hostname(server); 269 - if (rc) { 270 - cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n", 271 - __func__, rc); 272 - } 273 - 274 - #ifdef CONFIG_CIFS_DFS_UPCALL 275 - } 276 - #endif 277 - 278 - 279 } 280 281 if (cifs_rdma_enabled(server)) ··· 293 else 294 rc = generic_ip_connect(server); 295 if (rc) { 296 - cifs_dbg(FYI, "reconnect error %d\n", rc); 297 mutex_unlock(&server->srv_mutex); 298 msleep(3000); 299 } else { 300 atomic_inc(&tcpSesReconnectCount); ··· 308 } 309 } while (server->tcpStatus == CifsNeedReconnect); 310 311 - #ifdef CONFIG_CIFS_DFS_UPCALL 312 - if (tgt_it) { 313 - rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1, 314 - tgt_it); 315 - if (rc) { 316 - cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n", 317 - __func__, rc); 318 - } 319 - dfs_cache_free_tgts(&tgt_list); 320 - } 321 - 322 - cifs_put_tcp_super(sb); 323 - #endif 324 if (server->tcpStatus == CifsNeedNegotiate) 325 mod_delayed_work(cifsiod_wq, &server->echo, 0); 326 327 wake_up(&server->response_q); 328 return rc; 329 } 330 331 static void 332 cifs_echo_request(struct work_struct *work) ··· 714 * Trying to handle/dequeue a mid after the send_recv() 715 * function has finished processing it is a bug. 716 */ 717 - if (mid->mid_flags & MID_DELETED) 718 pr_warn_once("trying to dequeue a deleted mid\n"); 719 - else { 720 list_del_init(&mid->qhead); 721 mid->mid_flags |= MID_DELETED; 722 } 723 - spin_unlock(&GlobalMid_Lock); 724 } 725 726 static unsigned int ··· 844 */ 845 } 846 847 kfree(server); 848 849 length = atomic_dec_return(&tcpSesAllocCount); ··· 1271 { 1272 struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr; 1273 1274 - if (ctx->nosharesock) 1275 return 0; 1276 1277 /* If multidialect negotiation see if existing sessions match one */ ··· 1343 * Skip ses channels since they're only handled in lower layers 1344 * (e.g. cifs_send_recv). 1345 */ 1346 - if (server->is_channel || !match_server(server, ctx)) 1347 continue; 1348 1349 ++server->srv_count; ··· 1374 list_del_init(&server->tcp_ses_list); 1375 spin_unlock(&cifs_tcp_ses_lock); 1376 1377 cancel_delayed_work_sync(&server->echo); 1378 cancel_delayed_work_sync(&server->resolve); 1379 ··· 1397 spin_unlock(&GlobalMid_Lock); 1398 1399 cifs_crypto_secmech_release(server); 1400 - cifs_fscache_release_client_cookie(server); 1401 1402 kfree(server->session_key.response); 1403 server->session_key.response = NULL; ··· 1413 } 1414 1415 struct TCP_Server_Info * 1416 - cifs_get_tcp_session(struct smb3_fs_context *ctx) 1417 { 1418 struct TCP_Server_Info *tcp_ses = NULL; 1419 int rc; ··· 1451 tcp_ses->in_flight = 0; 1452 tcp_ses->max_in_flight = 0; 1453 tcp_ses->credits = 1; 1454 init_waitqueue_head(&tcp_ses->response_q); 1455 init_waitqueue_head(&tcp_ses->request_q); 1456 INIT_LIST_HEAD(&tcp_ses->pending_mid_q); ··· 1475 INIT_DELAYED_WORK(&tcp_ses->resolve, cifs_resolve_server); 1476 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server); 1477 mutex_init(&tcp_ses->reconnect_mutex); 1478 memcpy(&tcp_ses->srcaddr, &ctx->srcaddr, 1479 sizeof(tcp_ses->srcaddr)); 1480 memcpy(&tcp_ses->dstaddr, &ctx->dstaddr, ··· 1556 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list); 1557 spin_unlock(&cifs_tcp_ses_lock); 1558 1559 - cifs_fscache_get_client_cookie(tcp_ses); 1560 1561 /* queue echo request delayed work */ 1562 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval); ··· 1578 1579 out_err: 1580 if (tcp_ses) { 1581 kfree(tcp_ses->hostname); 1582 if (tcp_ses->ssocket) 1583 sock_release(tcp_ses->ssocket); ··· 1598 * If an existing session is limited to less channels than 1599 * requested, it should not be reused 1600 */ 1601 - if (ses->chan_max < ctx->max_channels) 1602 return 0; 1603 1604 switch (ses->sectype) { 1605 case Kerberos: ··· 1738 void cifs_put_smb_ses(struct cifs_ses *ses) 1739 { 1740 unsigned int rc, xid; 1741 struct TCP_Server_Info *server = ses->server; 1742 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count); 1743 ··· 1780 list_del_init(&ses->smb_ses_list); 1781 spin_unlock(&cifs_tcp_ses_lock); 1782 1783 /* close any extra channels */ 1784 - if (ses->chan_count > 1) { 1785 int i; 1786 1787 - for (i = 1; i < ses->chan_count; i++) 1788 cifs_put_tcp_session(ses->chans[i].server, 0); 1789 } 1790 1791 sesInfoFree(ses); ··· 1981 ses->status); 1982 1983 mutex_lock(&ses->session_mutex); 1984 - rc = cifs_negotiate_protocol(xid, ses); 1985 - if (rc) { 1986 - mutex_unlock(&ses->session_mutex); 1987 - /* problem -- put our ses reference */ 1988 - cifs_put_smb_ses(ses); 1989 - free_xid(xid); 1990 - return ERR_PTR(rc); 1991 - } 1992 if (ses->need_reconnect) { 1993 cifs_dbg(FYI, "Session needs reconnect\n"); 1994 rc = cifs_setup_session(xid, ses, 1995 ctx->local_nls); 1996 if (rc) { ··· 2040 if (!ses->domainName) 2041 goto get_ses_fail; 2042 } 2043 if (ctx->domainauto) 2044 ses->domainAuto = ctx->domainauto; 2045 ses->cred_uid = ctx->cred_uid; ··· 2056 mutex_lock(&ses->session_mutex); 2057 2058 /* add server as first channel */ 2059 ses->chans[0].server = server; 2060 ses->chan_count = 1; 2061 ses->chan_max = ctx->multichannel ? ctx->max_channels:1; 2062 2063 rc = cifs_negotiate_protocol(xid, ses); 2064 if (!rc) ··· 2391 spin_lock(&cifs_tcp_ses_lock); 2392 list_add(&tcon->tcon_list, &ses->tcon_list); 2393 spin_unlock(&cifs_tcp_ses_lock); 2394 - 2395 - cifs_fscache_get_super_cookie(tcon); 2396 2397 return tcon; 2398 ··· 2953 } 2954 2955 /* Release all succeed connections */ 2956 - static inline void mount_put_conns(struct cifs_sb_info *cifs_sb, 2957 - unsigned int xid, 2958 - struct TCP_Server_Info *server, 2959 - struct cifs_ses *ses, struct cifs_tcon *tcon) 2960 { 2961 int rc = 0; 2962 2963 - if (tcon) 2964 - cifs_put_tcon(tcon); 2965 - else if (ses) 2966 - cifs_put_smb_ses(ses); 2967 - else if (server) 2968 - cifs_put_tcp_session(server, 0); 2969 - cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS; 2970 - free_xid(xid); 2971 } 2972 2973 /* Get connections for tcp, ses and tcon */ 2974 - static int mount_get_conns(struct smb3_fs_context *ctx, struct cifs_sb_info *cifs_sb, 2975 - unsigned int *xid, 2976 - struct TCP_Server_Info **nserver, 2977 - struct cifs_ses **nses, struct cifs_tcon **ntcon) 2978 { 2979 int rc = 0; 2980 - struct TCP_Server_Info *server; 2981 - struct cifs_ses *ses; 2982 - struct cifs_tcon *tcon; 2983 2984 - *nserver = NULL; 2985 - *nses = NULL; 2986 - *ntcon = NULL; 2987 - 2988 - *xid = get_xid(); 2989 2990 /* get a reference to a tcp session */ 2991 - server = cifs_get_tcp_session(ctx); 2992 if (IS_ERR(server)) { 2993 rc = PTR_ERR(server); 2994 - return rc; 2995 } 2996 - 2997 - *nserver = server; 2998 2999 /* get a reference to a SMB session */ 3000 ses = cifs_get_smb_ses(server, ctx); 3001 if (IS_ERR(ses)) { 3002 rc = PTR_ERR(ses); 3003 - return rc; 3004 } 3005 - 3006 - *nses = ses; 3007 3008 if ((ctx->persistent == true) && (!(ses->server->capabilities & 3009 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) { 3010 cifs_server_dbg(VFS, "persistent handles not supported by server\n"); 3011 - return -EOPNOTSUPP; 3012 } 3013 3014 /* search for existing tcon to this server share */ 3015 tcon = cifs_get_tcon(ses, ctx); 3016 if (IS_ERR(tcon)) { 3017 rc = PTR_ERR(tcon); 3018 - return rc; 3019 } 3020 - 3021 - *ntcon = tcon; 3022 3023 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */ 3024 if (tcon->posix_extensions) ··· 3021 * reset of caps checks mount to see if unix extensions disabled 3022 * for just this mount. 3023 */ 3024 - reset_cifs_unix_caps(*xid, tcon, cifs_sb, ctx); 3025 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) && 3026 (le64_to_cpu(tcon->fsUnixInfo.Capability) & 3027 - CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) 3028 - return -EACCES; 3029 } else 3030 tcon->unix_ext = 0; /* server does not support them */ 3031 3032 /* do not care if a following call succeed - informational */ 3033 if (!tcon->pipe && server->ops->qfs_tcon) { 3034 - server->ops->qfs_tcon(*xid, tcon, cifs_sb); 3035 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) { 3036 if (tcon->fsDevInfo.DeviceCharacteristics & 3037 cpu_to_le32(FILE_READ_ONLY_DEVICE)) ··· 3043 cifs_dbg(VFS, "read only mount of RW share\n"); 3044 /* no need to log a RW mount of a typical RW share */ 3045 } 3046 } 3047 3048 /* ··· 3063 (cifs_sb->ctx->rsize > server->ops->negotiate_rsize(tcon, ctx))) 3064 cifs_sb->ctx->rsize = server->ops->negotiate_rsize(tcon, ctx); 3065 3066 - return 0; 3067 } 3068 3069 static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, ··· 3099 } 3100 3101 #ifdef CONFIG_CIFS_DFS_UPCALL 3102 - static int mount_get_dfs_conns(struct smb3_fs_context *ctx, struct cifs_sb_info *cifs_sb, 3103 - unsigned int *xid, struct TCP_Server_Info **nserver, 3104 - struct cifs_ses **nses, struct cifs_tcon **ntcon) 3105 { 3106 int rc; 3107 3108 - ctx->nosharesock = true; 3109 - rc = mount_get_conns(ctx, cifs_sb, xid, nserver, nses, ntcon); 3110 - if (*nserver) { 3111 cifs_dbg(FYI, "%s: marking tcp session as a dfs connection\n", __func__); 3112 spin_lock(&cifs_tcp_ses_lock); 3113 - (*nserver)->is_dfs_conn = true; 3114 spin_unlock(&cifs_tcp_ses_lock); 3115 } 3116 return rc; ··· 3151 } 3152 3153 /* 3154 - * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb 3155 * 3156 - * If a referral is found, cifs_sb->ctx->mount_options will be (re-)allocated 3157 - * to a string containing updated options for the submount. Otherwise it 3158 - * will be left untouched. 3159 - * 3160 - * Returns the rc from get_dfs_path to the caller, which can be used to 3161 - * determine whether there were referrals. 3162 */ 3163 - static int 3164 - expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses, 3165 - struct smb3_fs_context *ctx, struct cifs_sb_info *cifs_sb, 3166 - char *ref_path) 3167 { 3168 int rc; 3169 - struct dfs_info3_param referral = {0}; 3170 - char *full_path = NULL, *mdata = NULL; 3171 3172 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) 3173 - return -EREMOTE; 3174 - 3175 - full_path = build_unc_path_to_root(ctx, cifs_sb, true); 3176 - if (IS_ERR(full_path)) 3177 - return PTR_ERR(full_path); 3178 - 3179 - rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), 3180 - ref_path, &referral, NULL); 3181 - if (!rc) { 3182 - char *fake_devname = NULL; 3183 - 3184 - mdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options, 3185 - full_path + 1, &referral, 3186 - &fake_devname); 3187 - free_dfs_info_param(&referral); 3188 - 3189 - if (IS_ERR(mdata)) { 3190 - rc = PTR_ERR(mdata); 3191 - mdata = NULL; 3192 - } else { 3193 - /* 3194 - * We can not clear out the whole structure since we 3195 - * no longer have an explicit function to parse 3196 - * a mount-string. Instead we need to clear out the 3197 - * individual fields that are no longer valid. 3198 - */ 3199 - kfree(ctx->prepath); 3200 - ctx->prepath = NULL; 3201 - rc = cifs_setup_volume_info(ctx, mdata, fake_devname); 3202 - } 3203 - kfree(fake_devname); 3204 - kfree(cifs_sb->ctx->mount_options); 3205 - cifs_sb->ctx->mount_options = mdata; 3206 - } 3207 - kfree(full_path); 3208 - return rc; 3209 - } 3210 - 3211 - static int get_next_dfs_tgt(struct dfs_cache_tgt_list *tgt_list, 3212 - struct dfs_cache_tgt_iterator **tgt_it) 3213 - { 3214 - if (!*tgt_it) 3215 - *tgt_it = dfs_cache_get_tgt_iterator(tgt_list); 3216 - else 3217 - *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it); 3218 - return !*tgt_it ? -EHOSTDOWN : 0; 3219 - } 3220 - 3221 - static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it, 3222 - struct smb3_fs_context *fake_ctx, struct smb3_fs_context *ctx) 3223 - { 3224 - const char *tgt = dfs_cache_get_tgt_name(tgt_it); 3225 - int len = strlen(tgt) + 2; 3226 - char *new_unc; 3227 - 3228 - new_unc = kmalloc(len, GFP_KERNEL); 3229 - if (!new_unc) 3230 - return -ENOMEM; 3231 - scnprintf(new_unc, len, "\\%s", tgt); 3232 - 3233 - kfree(ctx->UNC); 3234 - ctx->UNC = new_unc; 3235 - 3236 - if (fake_ctx->prepath) { 3237 - kfree(ctx->prepath); 3238 - ctx->prepath = fake_ctx->prepath; 3239 - fake_ctx->prepath = NULL; 3240 - } 3241 - memcpy(&ctx->dstaddr, &fake_ctx->dstaddr, sizeof(ctx->dstaddr)); 3242 - 3243 - return 0; 3244 - } 3245 - 3246 - static int do_dfs_failover(const char *path, const char *full_path, struct cifs_sb_info *cifs_sb, 3247 - struct smb3_fs_context *ctx, struct cifs_ses *root_ses, 3248 - unsigned int *xid, struct TCP_Server_Info **server, 3249 - struct cifs_ses **ses, struct cifs_tcon **tcon) 3250 - { 3251 - int rc; 3252 - char *npath = NULL; 3253 - struct dfs_cache_tgt_list tgt_list = DFS_CACHE_TGT_LIST_INIT(tgt_list); 3254 - struct dfs_cache_tgt_iterator *tgt_it = NULL; 3255 - struct smb3_fs_context tmp_ctx = {NULL}; 3256 - 3257 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) 3258 - return -EOPNOTSUPP; 3259 - 3260 - npath = dfs_cache_canonical_path(path, cifs_sb->local_nls, cifs_remap(cifs_sb)); 3261 - if (IS_ERR(npath)) 3262 - return PTR_ERR(npath); 3263 - 3264 - cifs_dbg(FYI, "%s: path=%s full_path=%s\n", __func__, npath, full_path); 3265 - 3266 - rc = dfs_cache_noreq_find(npath, NULL, &tgt_list); 3267 - if (rc) 3268 - goto out; 3269 - /* 3270 - * We use a 'tmp_ctx' here because we need pass it down to the mount_{get,put} functions to 3271 - * test connection against new DFS targets. 3272 - */ 3273 - rc = smb3_fs_context_dup(&tmp_ctx, ctx); 3274 - if (rc) 3275 - goto out; 3276 - 3277 - for (;;) { 3278 - struct dfs_info3_param ref = {0}; 3279 - char *fake_devname = NULL, *mdata = NULL; 3280 - 3281 - /* Get next DFS target server - if any */ 3282 - rc = get_next_dfs_tgt(&tgt_list, &tgt_it); 3283 - if (rc) 3284 - break; 3285 - 3286 - rc = dfs_cache_get_tgt_referral(npath, tgt_it, &ref); 3287 - if (rc) 3288 - break; 3289 - 3290 - cifs_dbg(FYI, "%s: old ctx: UNC=%s prepath=%s\n", __func__, tmp_ctx.UNC, 3291 - tmp_ctx.prepath); 3292 - 3293 - mdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options, full_path + 1, &ref, 3294 - &fake_devname); 3295 - free_dfs_info_param(&ref); 3296 - 3297 - if (IS_ERR(mdata)) { 3298 - rc = PTR_ERR(mdata); 3299 - mdata = NULL; 3300 - } else 3301 - rc = cifs_setup_volume_info(&tmp_ctx, mdata, fake_devname); 3302 - 3303 - kfree(mdata); 3304 - kfree(fake_devname); 3305 - 3306 - if (rc) 3307 - break; 3308 - 3309 - cifs_dbg(FYI, "%s: new ctx: UNC=%s prepath=%s\n", __func__, tmp_ctx.UNC, 3310 - tmp_ctx.prepath); 3311 - 3312 - mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon); 3313 - rc = mount_get_dfs_conns(&tmp_ctx, cifs_sb, xid, server, ses, tcon); 3314 - if (!rc || (*server && *ses)) { 3315 - /* 3316 - * We were able to connect to new target server. Update current context with 3317 - * new target server. 3318 - */ 3319 - rc = update_vol_info(tgt_it, &tmp_ctx, ctx); 3320 - break; 3321 - } 3322 - } 3323 - if (!rc) { 3324 - cifs_dbg(FYI, "%s: final ctx: UNC=%s prepath=%s\n", __func__, tmp_ctx.UNC, 3325 - tmp_ctx.prepath); 3326 /* 3327 - * Update DFS target hint in DFS referral cache with the target server we 3328 - * successfully reconnected to. 3329 */ 3330 - rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses, cifs_sb->local_nls, 3331 - cifs_remap(cifs_sb), path, tgt_it); 3332 } 3333 3334 - out: 3335 - kfree(npath); 3336 - smb3_cleanup_fs_context_contents(&tmp_ctx); 3337 - dfs_cache_free_tgts(&tgt_list); 3338 return rc; 3339 } 3340 #endif ··· 3289 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is, 3290 * otherwise 0. 3291 */ 3292 - static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx, 3293 - const unsigned int xid, 3294 - struct TCP_Server_Info *server, 3295 - struct cifs_tcon *tcon) 3296 { 3297 int rc; 3298 char *full_path; 3299 3300 if (!server->ops->is_path_accessible) ··· 3334 } 3335 3336 #ifdef CONFIG_CIFS_DFS_UPCALL 3337 - static void set_root_ses(struct cifs_sb_info *cifs_sb, const uuid_t *mount_id, struct cifs_ses *ses, 3338 - struct cifs_ses **root_ses) 3339 { 3340 - if (ses) { 3341 spin_lock(&cifs_tcp_ses_lock); 3342 - ses->ses_count++; 3343 spin_unlock(&cifs_tcp_ses_lock); 3344 - dfs_cache_add_refsrv_session(mount_id, ses); 3345 } 3346 - *root_ses = ses; 3347 } 3348 3349 - /* Set up next dfs prefix path in @dfs_path */ 3350 - static int next_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx, 3351 - const unsigned int xid, struct TCP_Server_Info *server, 3352 - struct cifs_tcon *tcon, char **dfs_path) 3353 - { 3354 - char *path, *npath; 3355 - int added_treename = is_tcon_dfs(tcon); 3356 - int rc; 3357 - 3358 - path = cifs_build_path_to_root(ctx, cifs_sb, tcon, added_treename); 3359 - if (!path) 3360 - return -ENOMEM; 3361 - 3362 - rc = is_path_remote(cifs_sb, ctx, xid, server, tcon); 3363 - if (rc == -EREMOTE) { 3364 - struct smb3_fs_context v = {NULL}; 3365 - /* if @path contains a tree name, skip it in the prefix path */ 3366 - if (added_treename) { 3367 - rc = smb3_parse_devname(path, &v); 3368 - if (rc) 3369 - goto out; 3370 - npath = build_unc_path_to_root(&v, cifs_sb, true); 3371 - smb3_cleanup_fs_context_contents(&v); 3372 - } else { 3373 - v.UNC = ctx->UNC; 3374 - v.prepath = path + 1; 3375 - npath = build_unc_path_to_root(&v, cifs_sb, true); 3376 - } 3377 - 3378 - if (IS_ERR(npath)) { 3379 - rc = PTR_ERR(npath); 3380 - goto out; 3381 - } 3382 - 3383 - kfree(*dfs_path); 3384 - *dfs_path = npath; 3385 - rc = -EREMOTE; 3386 - } 3387 - 3388 - out: 3389 - kfree(path); 3390 - return rc; 3391 - } 3392 - 3393 - /* Check if resolved targets can handle any DFS referrals */ 3394 - static int is_referral_server(const char *ref_path, struct cifs_sb_info *cifs_sb, 3395 - struct cifs_tcon *tcon, bool *ref_server) 3396 { 3397 int rc; 3398 - struct dfs_info3_param ref = {0}; 3399 3400 - cifs_dbg(FYI, "%s: ref_path=%s\n", __func__, ref_path); 3401 3402 - if (is_tcon_dfs(tcon)) { 3403 - *ref_server = true; 3404 - } else { 3405 - char *npath; 3406 - 3407 - npath = dfs_cache_canonical_path(ref_path, cifs_sb->local_nls, cifs_remap(cifs_sb)); 3408 - if (IS_ERR(npath)) 3409 - return PTR_ERR(npath); 3410 - 3411 - rc = dfs_cache_noreq_find(npath, &ref, NULL); 3412 - kfree(npath); 3413 - if (rc) { 3414 - cifs_dbg(VFS, "%s: dfs_cache_noreq_find: failed (rc=%d)\n", __func__, rc); 3415 - return rc; 3416 - } 3417 - cifs_dbg(FYI, "%s: ref.flags=0x%x\n", __func__, ref.flags); 3418 - /* 3419 - * Check if all targets are capable of handling DFS referrals as per 3420 - * MS-DFSC 2.2.4 RESP_GET_DFS_REFERRAL. 3421 - */ 3422 - *ref_server = !!(ref.flags & DFSREF_REFERRAL_SERVER); 3423 - free_dfs_info_param(&ref); 3424 - } 3425 - return 0; 3426 - } 3427 - 3428 - int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx) 3429 - { 3430 - int rc = 0; 3431 - unsigned int xid; 3432 - struct TCP_Server_Info *server = NULL; 3433 - struct cifs_ses *ses = NULL, *root_ses = NULL; 3434 - struct cifs_tcon *tcon = NULL; 3435 - int count = 0; 3436 - uuid_t mount_id = {0}; 3437 - char *ref_path = NULL, *full_path = NULL; 3438 - char *oldmnt = NULL; 3439 - bool ref_server = false; 3440 - 3441 - rc = mount_get_conns(ctx, cifs_sb, &xid, &server, &ses, &tcon); 3442 /* 3443 * If called with 'nodfs' mount option, then skip DFS resolving. Otherwise unconditionally 3444 * try to get an DFS referral (even cached) to determine whether it is an DFS mount. ··· 3362 * to respond with PATH_NOT_COVERED to requests that include the prefix. 3363 */ 3364 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) || 3365 - dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), ctx->UNC + 1, NULL, 3366 - NULL)) { 3367 if (rc) 3368 - goto error; 3369 /* Check if it is fully accessible and then mount it */ 3370 - rc = is_path_remote(cifs_sb, ctx, xid, server, tcon); 3371 if (!rc) 3372 - goto out; 3373 - if (rc != -EREMOTE) 3374 - goto error; 3375 } 3376 3377 - mount_put_conns(cifs_sb, xid, server, ses, tcon); 3378 - /* 3379 - * Ignore error check here because we may failover to other targets from cached a 3380 - * referral. 3381 - */ 3382 - (void)mount_get_dfs_conns(ctx, cifs_sb, &xid, &server, &ses, &tcon); 3383 3384 - /* Get path of DFS root */ 3385 - ref_path = build_unc_path_to_root(ctx, cifs_sb, false); 3386 - if (IS_ERR(ref_path)) { 3387 - rc = PTR_ERR(ref_path); 3388 - ref_path = NULL; 3389 - goto error; 3390 } 3391 3392 - uuid_gen(&mount_id); 3393 - set_root_ses(cifs_sb, &mount_id, ses, &root_ses); 3394 - do { 3395 - /* Save full path of last DFS path we used to resolve final target server */ 3396 - kfree(full_path); 3397 - full_path = build_unc_path_to_root(ctx, cifs_sb, !!count); 3398 - if (IS_ERR(full_path)) { 3399 - rc = PTR_ERR(full_path); 3400 - full_path = NULL; 3401 break; 3402 } 3403 - /* Chase referral */ 3404 - oldmnt = cifs_sb->ctx->mount_options; 3405 - rc = expand_dfs_referral(xid, root_ses, ctx, cifs_sb, ref_path + 1); 3406 - if (rc) 3407 - break; 3408 - /* Connect to new DFS target only if we were redirected */ 3409 - if (oldmnt != cifs_sb->ctx->mount_options) { 3410 - mount_put_conns(cifs_sb, xid, server, ses, tcon); 3411 - rc = mount_get_dfs_conns(ctx, cifs_sb, &xid, &server, &ses, &tcon); 3412 - } 3413 - if (rc && !server && !ses) { 3414 - /* Failed to connect. Try to connect to other targets in the referral. */ 3415 - rc = do_dfs_failover(ref_path + 1, full_path, cifs_sb, ctx, root_ses, &xid, 3416 - &server, &ses, &tcon); 3417 - } 3418 - if (rc == -EACCES || rc == -EOPNOTSUPP || !server || !ses) 3419 - break; 3420 - if (!tcon) 3421 - continue; 3422 3423 - /* Make sure that requests go through new root servers */ 3424 - rc = is_referral_server(ref_path + 1, cifs_sb, tcon, &ref_server); 3425 - if (rc) 3426 - break; 3427 - if (ref_server) 3428 - set_root_ses(cifs_sb, &mount_id, ses, &root_ses); 3429 - 3430 - /* Get next dfs path and then continue chasing them if -EREMOTE */ 3431 - rc = next_dfs_prepath(cifs_sb, ctx, xid, server, tcon, &ref_path); 3432 - /* Prevent recursion on broken link referrals */ 3433 - if (rc == -EREMOTE && ++count > MAX_NESTED_LINKS) 3434 - rc = -ELOOP; 3435 - } while (rc == -EREMOTE); 3436 - 3437 - if (rc || !tcon || !ses) 3438 - goto error; 3439 - 3440 - kfree(ref_path); 3441 - /* 3442 - * Store DFS full path in both superblock and tree connect structures. 3443 - * 3444 - * For DFS root mounts, the prefix path (cifs_sb->prepath) is preserved during reconnect so 3445 - * only the root path is set in cifs_sb->origin_fullpath and tcon->dfs_path. And for DFS 3446 - * links, the prefix path is included in both and may be changed during reconnect. See 3447 - * cifs_tree_connect(). 3448 - */ 3449 - ref_path = dfs_cache_canonical_path(full_path, cifs_sb->local_nls, cifs_remap(cifs_sb)); 3450 kfree(full_path); 3451 - full_path = NULL; 3452 3453 - if (IS_ERR(ref_path)) { 3454 - rc = PTR_ERR(ref_path); 3455 - ref_path = NULL; 3456 - goto error; 3457 } 3458 - cifs_sb->origin_fullpath = ref_path; 3459 3460 - ref_path = kstrdup(cifs_sb->origin_fullpath, GFP_KERNEL); 3461 - if (!ref_path) { 3462 - rc = -ENOMEM; 3463 - goto error; 3464 } 3465 - spin_lock(&cifs_tcp_ses_lock); 3466 - tcon->dfs_path = ref_path; 3467 - ref_path = NULL; 3468 - spin_unlock(&cifs_tcp_ses_lock); 3469 3470 /* 3471 - * After reconnecting to a different server, unique ids won't 3472 - * match anymore, so we disable serverino. This prevents 3473 - * dentry revalidation to think the dentry are stale (ESTALE). 3474 */ 3475 cifs_autodisable_serverino(cifs_sb); 3476 /* 3477 - * Force the use of prefix path to support failover on DFS paths that 3478 - * resolve to targets that have different prefix paths. 3479 */ 3480 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; 3481 kfree(cifs_sb->prepath); 3482 cifs_sb->prepath = ctx->prepath; 3483 ctx->prepath = NULL; 3484 - uuid_copy(&cifs_sb->dfs_mount_id, &mount_id); 3485 3486 out: 3487 - free_xid(xid); 3488 - cifs_try_adding_channels(cifs_sb, ses); 3489 - return mount_setup_tlink(cifs_sb, ses, tcon); 3490 3491 error: 3492 - kfree(ref_path); 3493 - kfree(full_path); 3494 - kfree(cifs_sb->origin_fullpath); 3495 - dfs_cache_put_refsrv_sessions(&mount_id); 3496 - mount_put_conns(cifs_sb, xid, server, ses, tcon); 3497 return rc; 3498 } 3499 #else 3500 int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx) 3501 { 3502 int rc = 0; 3503 - unsigned int xid; 3504 - struct cifs_ses *ses; 3505 - struct cifs_tcon *tcon; 3506 - struct TCP_Server_Info *server; 3507 3508 - rc = mount_get_conns(ctx, cifs_sb, &xid, &server, &ses, &tcon); 3509 if (rc) 3510 goto error; 3511 3512 - if (tcon) { 3513 - rc = is_path_remote(cifs_sb, ctx, xid, server, tcon); 3514 if (rc == -EREMOTE) 3515 rc = -EOPNOTSUPP; 3516 if (rc) 3517 goto error; 3518 } 3519 3520 - free_xid(xid); 3521 - 3522 - return mount_setup_tlink(cifs_sb, ses, tcon); 3523 3524 error: 3525 - mount_put_conns(cifs_sb, xid, server, ses, tcon); 3526 return rc; 3527 } 3528 #endif ··· 3785 kfree(cifs_sb->prepath); 3786 #ifdef CONFIG_CIFS_DFS_UPCALL 3787 dfs_cache_put_refsrv_sessions(&cifs_sb->dfs_mount_id); 3788 - kfree(cifs_sb->origin_fullpath); 3789 #endif 3790 call_rcu(&cifs_sb->rcu, delayed_free); 3791 } ··· 4111 } 4112 4113 #ifdef CONFIG_CIFS_DFS_UPCALL 4114 int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc) 4115 { 4116 int rc; 4117 struct TCP_Server_Info *server = tcon->ses->server; 4118 const struct smb_version_operations *ops = server->ops; 4119 - struct dfs_cache_tgt_list tl; 4120 - struct dfs_cache_tgt_iterator *it = NULL; 4121 char *tree; 4122 - const char *tcp_host; 4123 - size_t tcp_host_len; 4124 - const char *dfs_host; 4125 - size_t dfs_host_len; 4126 - char *share = NULL, *prefix = NULL; 4127 struct dfs_info3_param ref = {0}; 4128 - bool isroot; 4129 4130 tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL); 4131 if (!tree) 4132 return -ENOMEM; 4133 4134 - /* If it is not dfs or there was no cached dfs referral, then reconnect to same share */ 4135 - if (!tcon->dfs_path || dfs_cache_noreq_find(tcon->dfs_path + 1, &ref, &tl)) { 4136 - if (tcon->ipc) { 4137 - scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname); 4138 - rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc); 4139 - } else { 4140 - rc = ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc); 4141 - } 4142 goto out; 4143 } 4144 4145 - isroot = ref.server_type == DFS_TYPE_ROOT; 4146 free_dfs_info_param(&ref); 4147 4148 - extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len); 4149 - 4150 - for (it = dfs_cache_get_tgt_iterator(&tl); it; it = dfs_cache_get_next_tgt(&tl, it)) { 4151 - bool target_match; 4152 - 4153 - kfree(share); 4154 - kfree(prefix); 4155 - share = NULL; 4156 - prefix = NULL; 4157 - 4158 - rc = dfs_cache_get_tgt_share(tcon->dfs_path + 1, it, &share, &prefix); 4159 - if (rc) { 4160 - cifs_dbg(VFS, "%s: failed to parse target share %d\n", 4161 - __func__, rc); 4162 - continue; 4163 - } 4164 - 4165 - extract_unc_hostname(share, &dfs_host, &dfs_host_len); 4166 - 4167 - if (dfs_host_len != tcp_host_len 4168 - || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) { 4169 - cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len, 4170 - dfs_host, (int)tcp_host_len, tcp_host); 4171 - 4172 - rc = match_target_ip(server, dfs_host, dfs_host_len, &target_match); 4173 - if (rc) { 4174 - cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc); 4175 - break; 4176 - } 4177 - 4178 - if (!target_match) { 4179 - cifs_dbg(FYI, "%s: skipping target\n", __func__); 4180 - continue; 4181 - } 4182 - } 4183 - 4184 - if (tcon->ipc) { 4185 - scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", share); 4186 - rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc); 4187 - } else { 4188 - scnprintf(tree, MAX_TREE_SIZE, "\\%s", share); 4189 - rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc); 4190 - /* Only handle prefix paths of DFS link targets */ 4191 - if (!rc && !isroot) { 4192 - rc = update_super_prepath(tcon, prefix); 4193 - break; 4194 - } 4195 - } 4196 - if (rc == -EREMOTE) 4197 - break; 4198 - } 4199 - 4200 - kfree(share); 4201 - kfree(prefix); 4202 - 4203 - if (!rc) { 4204 - if (it) 4205 - rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1, it); 4206 - else 4207 - rc = -ENOENT; 4208 - } 4209 - dfs_cache_free_tgts(&tl); 4210 out: 4211 kfree(tree); 4212 return rc; 4213 } 4214 #else
··· 61 /* Drop the connection to not overload the server */ 62 #define NUM_STATUS_IO_TIMEOUT 5 63 64 + struct mount_ctx { 65 + struct cifs_sb_info *cifs_sb; 66 + struct smb3_fs_context *fs_ctx; 67 + unsigned int xid; 68 + struct TCP_Server_Info *server; 69 + struct cifs_ses *ses; 70 + struct cifs_tcon *tcon; 71 + #ifdef CONFIG_CIFS_DFS_UPCALL 72 + struct cifs_ses *root_ses; 73 + uuid_t mount_id; 74 + char *origin_fullpath, *leaf_fullpath; 75 + #endif 76 + }; 77 + 78 static int ip_connect(struct TCP_Server_Info *server); 79 static int generic_ip_connect(struct TCP_Server_Info *server); 80 static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); ··· 115 * To make sure we don't use the cached entry, retry 1s 116 * after expiry. 117 */ 118 + ttl = max_t(unsigned long, expiry - now, SMB_DNS_RESOLVE_INTERVAL_MIN) + 1; 119 } 120 rc = !rc ? -1 : 0; 121 ··· 148 mutex_unlock(&server->srv_mutex); 149 } 150 151 + /** 152 + * Mark all sessions and tcons for reconnect. 153 * 154 + * @server needs to be previously set to CifsNeedReconnect. 155 */ 156 + static void cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server) 157 { 158 struct cifs_ses *ses; 159 struct cifs_tcon *tcon; 160 + struct mid_q_entry *mid, *nmid; 161 struct list_head retry_list; 162 + struct TCP_Server_Info *pserver; 163 164 server->maxBuf = 0; 165 server->max_read = 0; 166 167 cifs_dbg(FYI, "Mark tcp session as need reconnect\n"); 168 trace_smb3_reconnect(server->CurrentMid, server->conn_id, server->hostname); 169 + /* 170 + * before reconnecting the tcp session, mark the smb session (uid) and the tid bad so they 171 + * are not used until reconnected. 172 + */ 173 + cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n", __func__); 174 175 + /* If server is a channel, select the primary channel */ 176 + pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server; 177 + 178 spin_lock(&cifs_tcp_ses_lock); 179 + list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { 180 ses->need_reconnect = true; 181 + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) 182 tcon->need_reconnect = true; 183 if (ses->tcon_ipc) 184 ses->tcon_ipc->need_reconnect = true; 185 } ··· 290 cifs_dbg(FYI, "%s: tearing down socket\n", __func__); 291 mutex_lock(&server->srv_mutex); 292 if (server->ssocket) { 293 + cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n", server->ssocket->state, 294 + server->ssocket->flags); 295 kernel_sock_shutdown(server->ssocket, SHUT_WR); 296 + cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n", server->ssocket->state, 297 + server->ssocket->flags); 298 sock_release(server->ssocket); 299 server->ssocket = NULL; 300 } ··· 309 INIT_LIST_HEAD(&retry_list); 310 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__); 311 spin_lock(&GlobalMid_Lock); 312 + list_for_each_entry_safe(mid, nmid, &server->pending_mid_q, qhead) { 313 + kref_get(&mid->refcount); 314 + if (mid->mid_state == MID_REQUEST_SUBMITTED) 315 + mid->mid_state = MID_RETRY_NEEDED; 316 + list_move(&mid->qhead, &retry_list); 317 + mid->mid_flags |= MID_DELETED; 318 } 319 spin_unlock(&GlobalMid_Lock); 320 mutex_unlock(&server->srv_mutex); 321 322 cifs_dbg(FYI, "%s: issuing mid callbacks\n", __func__); 323 + list_for_each_entry_safe(mid, nmid, &retry_list, qhead) { 324 + list_del_init(&mid->qhead); 325 + mid->callback(mid); 326 + cifs_mid_q_entry_release(mid); 327 } 328 329 if (cifs_rdma_enabled(server)) { ··· 333 smbd_destroy(server); 334 mutex_unlock(&server->srv_mutex); 335 } 336 + } 337 + 338 + static bool cifs_tcp_ses_needs_reconnect(struct TCP_Server_Info *server, int num_targets) 339 + { 340 + spin_lock(&GlobalMid_Lock); 341 + server->nr_targets = num_targets; 342 + if (server->tcpStatus == CifsExiting) { 343 + /* the demux thread will exit normally next time through the loop */ 344 + spin_unlock(&GlobalMid_Lock); 345 + wake_up(&server->response_q); 346 + return false; 347 + } 348 + server->tcpStatus = CifsNeedReconnect; 349 + spin_unlock(&GlobalMid_Lock); 350 + return true; 351 + } 352 + 353 + /* 354 + * cifs tcp session reconnection 355 + * 356 + * mark tcp session as reconnecting so temporarily locked 357 + * mark all smb sessions as reconnecting for tcp session 358 + * reconnect tcp session 359 + * wake up waiters on reconnection? - (not needed currently) 360 + */ 361 + static int __cifs_reconnect(struct TCP_Server_Info *server) 362 + { 363 + int rc = 0; 364 + 365 + if (!cifs_tcp_ses_needs_reconnect(server, 1)) 366 + return 0; 367 + 368 + cifs_mark_tcp_ses_conns_for_reconnect(server); 369 370 do { 371 try_to_freeze(); 372 mutex_lock(&server->srv_mutex); 373 374 if (!cifs_swn_set_server_dstaddr(server)) { 375 + /* resolve the hostname again to make sure that IP address is up-to-date */ 376 rc = reconn_set_ipaddr_from_hostname(server); 377 + cifs_dbg(FYI, "%s: reconn_set_ipaddr_from_hostname: rc=%d\n", __func__, rc); 378 } 379 380 if (cifs_rdma_enabled(server)) ··· 372 else 373 rc = generic_ip_connect(server); 374 if (rc) { 375 mutex_unlock(&server->srv_mutex); 376 + cifs_dbg(FYI, "%s: reconnect error %d\n", __func__, rc); 377 msleep(3000); 378 } else { 379 atomic_inc(&tcpSesReconnectCount); ··· 387 } 388 } while (server->tcpStatus == CifsNeedReconnect); 389 390 if (server->tcpStatus == CifsNeedNegotiate) 391 mod_delayed_work(cifsiod_wq, &server->echo, 0); 392 393 wake_up(&server->response_q); 394 return rc; 395 } 396 + 397 + #ifdef CONFIG_CIFS_DFS_UPCALL 398 + static int __reconnect_target_unlocked(struct TCP_Server_Info *server, const char *target) 399 + { 400 + int rc; 401 + char *hostname; 402 + 403 + if (!cifs_swn_set_server_dstaddr(server)) { 404 + if (server->hostname != target) { 405 + hostname = extract_hostname(target); 406 + if (!IS_ERR(hostname)) { 407 + kfree(server->hostname); 408 + server->hostname = hostname; 409 + } else { 410 + cifs_dbg(FYI, "%s: couldn't extract hostname or address from dfs target: %ld\n", 411 + __func__, PTR_ERR(hostname)); 412 + cifs_dbg(FYI, "%s: default to last target server: %s\n", __func__, 413 + server->hostname); 414 + } 415 + } 416 + /* resolve the hostname again to make sure that IP address is up-to-date. */ 417 + rc = reconn_set_ipaddr_from_hostname(server); 418 + cifs_dbg(FYI, "%s: reconn_set_ipaddr_from_hostname: rc=%d\n", __func__, rc); 419 + } 420 + /* Reconnect the socket */ 421 + if (cifs_rdma_enabled(server)) 422 + rc = smbd_reconnect(server); 423 + else 424 + rc = generic_ip_connect(server); 425 + 426 + return rc; 427 + } 428 + 429 + static int reconnect_target_unlocked(struct TCP_Server_Info *server, struct dfs_cache_tgt_list *tl, 430 + struct dfs_cache_tgt_iterator **target_hint) 431 + { 432 + int rc; 433 + struct dfs_cache_tgt_iterator *tit; 434 + 435 + *target_hint = NULL; 436 + 437 + /* If dfs target list is empty, then reconnect to last server */ 438 + tit = dfs_cache_get_tgt_iterator(tl); 439 + if (!tit) 440 + return __reconnect_target_unlocked(server, server->hostname); 441 + 442 + /* Otherwise, try every dfs target in @tl */ 443 + for (; tit; tit = dfs_cache_get_next_tgt(tl, tit)) { 444 + rc = __reconnect_target_unlocked(server, dfs_cache_get_tgt_name(tit)); 445 + if (!rc) { 446 + *target_hint = tit; 447 + break; 448 + } 449 + } 450 + return rc; 451 + } 452 + 453 + static int reconnect_dfs_server(struct TCP_Server_Info *server) 454 + { 455 + int rc = 0; 456 + const char *refpath = server->current_fullpath + 1; 457 + struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl); 458 + struct dfs_cache_tgt_iterator *target_hint = NULL; 459 + int num_targets = 0; 460 + 461 + /* 462 + * Determine the number of dfs targets the referral path in @cifs_sb resolves to. 463 + * 464 + * smb2_reconnect() needs to know how long it should wait based upon the number of dfs 465 + * targets (server->nr_targets). It's also possible that the cached referral was cleared 466 + * through /proc/fs/cifs/dfscache or the target list is empty due to server settings after 467 + * refreshing the referral, so, in this case, default it to 1. 468 + */ 469 + if (!dfs_cache_noreq_find(refpath, NULL, &tl)) 470 + num_targets = dfs_cache_get_nr_tgts(&tl); 471 + if (!num_targets) 472 + num_targets = 1; 473 + 474 + if (!cifs_tcp_ses_needs_reconnect(server, num_targets)) 475 + return 0; 476 + 477 + cifs_mark_tcp_ses_conns_for_reconnect(server); 478 + 479 + do { 480 + try_to_freeze(); 481 + mutex_lock(&server->srv_mutex); 482 + 483 + rc = reconnect_target_unlocked(server, &tl, &target_hint); 484 + if (rc) { 485 + /* Failed to reconnect socket */ 486 + mutex_unlock(&server->srv_mutex); 487 + cifs_dbg(FYI, "%s: reconnect error %d\n", __func__, rc); 488 + msleep(3000); 489 + continue; 490 + } 491 + /* 492 + * Socket was created. Update tcp session status to CifsNeedNegotiate so that a 493 + * process waiting for reconnect will know it needs to re-establish session and tcon 494 + * through the reconnected target server. 495 + */ 496 + atomic_inc(&tcpSesReconnectCount); 497 + set_credits(server, 1); 498 + spin_lock(&GlobalMid_Lock); 499 + if (server->tcpStatus != CifsExiting) 500 + server->tcpStatus = CifsNeedNegotiate; 501 + spin_unlock(&GlobalMid_Lock); 502 + cifs_swn_reset_server_dstaddr(server); 503 + mutex_unlock(&server->srv_mutex); 504 + } while (server->tcpStatus == CifsNeedReconnect); 505 + 506 + if (target_hint) 507 + dfs_cache_noreq_update_tgthint(refpath, target_hint); 508 + 509 + dfs_cache_free_tgts(&tl); 510 + 511 + /* Need to set up echo worker again once connection has been established */ 512 + if (server->tcpStatus == CifsNeedNegotiate) 513 + mod_delayed_work(cifsiod_wq, &server->echo, 0); 514 + 515 + wake_up(&server->response_q); 516 + return rc; 517 + } 518 + 519 + int cifs_reconnect(struct TCP_Server_Info *server) 520 + { 521 + /* If tcp session is not an dfs connection, then reconnect to last target server */ 522 + spin_lock(&cifs_tcp_ses_lock); 523 + if (!server->is_dfs_conn || !server->origin_fullpath || !server->leaf_fullpath) { 524 + spin_unlock(&cifs_tcp_ses_lock); 525 + return __cifs_reconnect(server); 526 + } 527 + spin_unlock(&cifs_tcp_ses_lock); 528 + 529 + return reconnect_dfs_server(server); 530 + } 531 + #else 532 + int cifs_reconnect(struct TCP_Server_Info *server) 533 + { 534 + return __cifs_reconnect(server); 535 + } 536 + #endif 537 538 static void 539 cifs_echo_request(struct work_struct *work) ··· 665 * Trying to handle/dequeue a mid after the send_recv() 666 * function has finished processing it is a bug. 667 */ 668 + if (mid->mid_flags & MID_DELETED) { 669 + spin_unlock(&GlobalMid_Lock); 670 pr_warn_once("trying to dequeue a deleted mid\n"); 671 + } else { 672 list_del_init(&mid->qhead); 673 mid->mid_flags |= MID_DELETED; 674 + spin_unlock(&GlobalMid_Lock); 675 } 676 } 677 678 static unsigned int ··· 794 */ 795 } 796 797 + #ifdef CONFIG_CIFS_DFS_UPCALL 798 + kfree(server->origin_fullpath); 799 + kfree(server->leaf_fullpath); 800 + #endif 801 kfree(server); 802 803 length = atomic_dec_return(&tcpSesAllocCount); ··· 1217 { 1218 struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr; 1219 1220 + if (ctx->nosharesock) { 1221 + server->nosharesock = true; 1222 + return 0; 1223 + } 1224 + 1225 + /* this server does not share socket */ 1226 + if (server->nosharesock) 1227 return 0; 1228 1229 /* If multidialect negotiation see if existing sessions match one */ ··· 1283 * Skip ses channels since they're only handled in lower layers 1284 * (e.g. cifs_send_recv). 1285 */ 1286 + if (CIFS_SERVER_IS_CHAN(server) || !match_server(server, ctx)) 1287 continue; 1288 1289 ++server->srv_count; ··· 1314 list_del_init(&server->tcp_ses_list); 1315 spin_unlock(&cifs_tcp_ses_lock); 1316 1317 + /* For secondary channels, we pick up ref-count on the primary server */ 1318 + if (CIFS_SERVER_IS_CHAN(server)) 1319 + cifs_put_tcp_session(server->primary_server, from_reconnect); 1320 + 1321 cancel_delayed_work_sync(&server->echo); 1322 cancel_delayed_work_sync(&server->resolve); 1323 ··· 1333 spin_unlock(&GlobalMid_Lock); 1334 1335 cifs_crypto_secmech_release(server); 1336 + 1337 + /* fscache server cookies are based on primary channel only */ 1338 + if (!CIFS_SERVER_IS_CHAN(server)) 1339 + cifs_fscache_release_client_cookie(server); 1340 1341 kfree(server->session_key.response); 1342 server->session_key.response = NULL; ··· 1346 } 1347 1348 struct TCP_Server_Info * 1349 + cifs_get_tcp_session(struct smb3_fs_context *ctx, 1350 + struct TCP_Server_Info *primary_server) 1351 { 1352 struct TCP_Server_Info *tcp_ses = NULL; 1353 int rc; ··· 1383 tcp_ses->in_flight = 0; 1384 tcp_ses->max_in_flight = 0; 1385 tcp_ses->credits = 1; 1386 + if (primary_server) { 1387 + ++primary_server->srv_count; 1388 + tcp_ses->primary_server = primary_server; 1389 + } 1390 init_waitqueue_head(&tcp_ses->response_q); 1391 init_waitqueue_head(&tcp_ses->request_q); 1392 INIT_LIST_HEAD(&tcp_ses->pending_mid_q); ··· 1403 INIT_DELAYED_WORK(&tcp_ses->resolve, cifs_resolve_server); 1404 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server); 1405 mutex_init(&tcp_ses->reconnect_mutex); 1406 + #ifdef CONFIG_CIFS_DFS_UPCALL 1407 + mutex_init(&tcp_ses->refpath_lock); 1408 + #endif 1409 memcpy(&tcp_ses->srcaddr, &ctx->srcaddr, 1410 sizeof(tcp_ses->srcaddr)); 1411 memcpy(&tcp_ses->dstaddr, &ctx->dstaddr, ··· 1481 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list); 1482 spin_unlock(&cifs_tcp_ses_lock); 1483 1484 + /* fscache server cookies are based on primary channel only */ 1485 + if (!CIFS_SERVER_IS_CHAN(tcp_ses)) 1486 + cifs_fscache_get_client_cookie(tcp_ses); 1487 1488 /* queue echo request delayed work */ 1489 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval); ··· 1501 1502 out_err: 1503 if (tcp_ses) { 1504 + if (CIFS_SERVER_IS_CHAN(tcp_ses)) 1505 + cifs_put_tcp_session(tcp_ses->primary_server, false); 1506 kfree(tcp_ses->hostname); 1507 if (tcp_ses->ssocket) 1508 sock_release(tcp_ses->ssocket); ··· 1519 * If an existing session is limited to less channels than 1520 * requested, it should not be reused 1521 */ 1522 + spin_lock(&ses->chan_lock); 1523 + if (ses->chan_max < ctx->max_channels) { 1524 + spin_unlock(&ses->chan_lock); 1525 return 0; 1526 + } 1527 + spin_unlock(&ses->chan_lock); 1528 1529 switch (ses->sectype) { 1530 case Kerberos: ··· 1655 void cifs_put_smb_ses(struct cifs_ses *ses) 1656 { 1657 unsigned int rc, xid; 1658 + unsigned int chan_count; 1659 struct TCP_Server_Info *server = ses->server; 1660 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count); 1661 ··· 1696 list_del_init(&ses->smb_ses_list); 1697 spin_unlock(&cifs_tcp_ses_lock); 1698 1699 + spin_lock(&ses->chan_lock); 1700 + chan_count = ses->chan_count; 1701 + spin_unlock(&ses->chan_lock); 1702 + 1703 /* close any extra channels */ 1704 + if (chan_count > 1) { 1705 int i; 1706 1707 + for (i = 1; i < chan_count; i++) { 1708 + /* 1709 + * note: for now, we're okay accessing ses->chans 1710 + * without chan_lock. But when chans can go away, we'll 1711 + * need to introduce ref counting to make sure that chan 1712 + * is not freed from under us. 1713 + */ 1714 cifs_put_tcp_session(ses->chans[i].server, 0); 1715 + ses->chans[i].server = NULL; 1716 + } 1717 } 1718 1719 sesInfoFree(ses); ··· 1885 ses->status); 1886 1887 mutex_lock(&ses->session_mutex); 1888 if (ses->need_reconnect) { 1889 cifs_dbg(FYI, "Session needs reconnect\n"); 1890 + 1891 + rc = cifs_negotiate_protocol(xid, ses); 1892 + if (rc) { 1893 + mutex_unlock(&ses->session_mutex); 1894 + /* problem -- put our ses reference */ 1895 + cifs_put_smb_ses(ses); 1896 + free_xid(xid); 1897 + return ERR_PTR(rc); 1898 + } 1899 + 1900 rc = cifs_setup_session(xid, ses, 1901 ctx->local_nls); 1902 if (rc) { ··· 1942 if (!ses->domainName) 1943 goto get_ses_fail; 1944 } 1945 + if (ctx->workstation_name) { 1946 + ses->workstation_name = kstrdup(ctx->workstation_name, 1947 + GFP_KERNEL); 1948 + if (!ses->workstation_name) 1949 + goto get_ses_fail; 1950 + } 1951 if (ctx->domainauto) 1952 ses->domainAuto = ctx->domainauto; 1953 ses->cred_uid = ctx->cred_uid; ··· 1952 mutex_lock(&ses->session_mutex); 1953 1954 /* add server as first channel */ 1955 + spin_lock(&ses->chan_lock); 1956 ses->chans[0].server = server; 1957 ses->chan_count = 1; 1958 ses->chan_max = ctx->multichannel ? ctx->max_channels:1; 1959 + spin_unlock(&ses->chan_lock); 1960 1961 rc = cifs_negotiate_protocol(xid, ses); 1962 if (!rc) ··· 2285 spin_lock(&cifs_tcp_ses_lock); 2286 list_add(&tcon->tcon_list, &ses->tcon_list); 2287 spin_unlock(&cifs_tcp_ses_lock); 2288 2289 return tcon; 2290 ··· 2849 } 2850 2851 /* Release all succeed connections */ 2852 + static inline void mount_put_conns(struct mount_ctx *mnt_ctx) 2853 { 2854 int rc = 0; 2855 2856 + if (mnt_ctx->tcon) 2857 + cifs_put_tcon(mnt_ctx->tcon); 2858 + else if (mnt_ctx->ses) 2859 + cifs_put_smb_ses(mnt_ctx->ses); 2860 + else if (mnt_ctx->server) 2861 + cifs_put_tcp_session(mnt_ctx->server, 0); 2862 + mnt_ctx->cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS; 2863 + free_xid(mnt_ctx->xid); 2864 } 2865 2866 /* Get connections for tcp, ses and tcon */ 2867 + static int mount_get_conns(struct mount_ctx *mnt_ctx) 2868 { 2869 int rc = 0; 2870 + struct TCP_Server_Info *server = NULL; 2871 + struct cifs_ses *ses = NULL; 2872 + struct cifs_tcon *tcon = NULL; 2873 + struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; 2874 + struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb; 2875 + unsigned int xid; 2876 2877 + xid = get_xid(); 2878 2879 /* get a reference to a tcp session */ 2880 + server = cifs_get_tcp_session(ctx, NULL); 2881 if (IS_ERR(server)) { 2882 rc = PTR_ERR(server); 2883 + server = NULL; 2884 + goto out; 2885 } 2886 2887 /* get a reference to a SMB session */ 2888 ses = cifs_get_smb_ses(server, ctx); 2889 if (IS_ERR(ses)) { 2890 rc = PTR_ERR(ses); 2891 + ses = NULL; 2892 + goto out; 2893 } 2894 2895 if ((ctx->persistent == true) && (!(ses->server->capabilities & 2896 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) { 2897 cifs_server_dbg(VFS, "persistent handles not supported by server\n"); 2898 + rc = -EOPNOTSUPP; 2899 + goto out; 2900 } 2901 2902 /* search for existing tcon to this server share */ 2903 tcon = cifs_get_tcon(ses, ctx); 2904 if (IS_ERR(tcon)) { 2905 rc = PTR_ERR(tcon); 2906 + tcon = NULL; 2907 + goto out; 2908 } 2909 2910 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */ 2911 if (tcon->posix_extensions) ··· 2926 * reset of caps checks mount to see if unix extensions disabled 2927 * for just this mount. 2928 */ 2929 + reset_cifs_unix_caps(xid, tcon, cifs_sb, ctx); 2930 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) && 2931 (le64_to_cpu(tcon->fsUnixInfo.Capability) & 2932 + CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) { 2933 + rc = -EACCES; 2934 + goto out; 2935 + } 2936 } else 2937 tcon->unix_ext = 0; /* server does not support them */ 2938 2939 /* do not care if a following call succeed - informational */ 2940 if (!tcon->pipe && server->ops->qfs_tcon) { 2941 + server->ops->qfs_tcon(xid, tcon, cifs_sb); 2942 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) { 2943 if (tcon->fsDevInfo.DeviceCharacteristics & 2944 cpu_to_le32(FILE_READ_ONLY_DEVICE)) ··· 2946 cifs_dbg(VFS, "read only mount of RW share\n"); 2947 /* no need to log a RW mount of a typical RW share */ 2948 } 2949 + /* 2950 + * The cookie is initialized from volume info returned above. 2951 + * Inside cifs_fscache_get_super_cookie it checks 2952 + * that we do not get super cookie twice. 2953 + */ 2954 + cifs_fscache_get_super_cookie(tcon); 2955 } 2956 2957 /* ··· 2960 (cifs_sb->ctx->rsize > server->ops->negotiate_rsize(tcon, ctx))) 2961 cifs_sb->ctx->rsize = server->ops->negotiate_rsize(tcon, ctx); 2962 2963 + out: 2964 + mnt_ctx->server = server; 2965 + mnt_ctx->ses = ses; 2966 + mnt_ctx->tcon = tcon; 2967 + mnt_ctx->xid = xid; 2968 + 2969 + return rc; 2970 } 2971 2972 static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, ··· 2990 } 2991 2992 #ifdef CONFIG_CIFS_DFS_UPCALL 2993 + /* Get unique dfs connections */ 2994 + static int mount_get_dfs_conns(struct mount_ctx *mnt_ctx) 2995 { 2996 int rc; 2997 2998 + mnt_ctx->fs_ctx->nosharesock = true; 2999 + rc = mount_get_conns(mnt_ctx); 3000 + if (mnt_ctx->server) { 3001 cifs_dbg(FYI, "%s: marking tcp session as a dfs connection\n", __func__); 3002 spin_lock(&cifs_tcp_ses_lock); 3003 + mnt_ctx->server->is_dfs_conn = true; 3004 spin_unlock(&cifs_tcp_ses_lock); 3005 } 3006 return rc; ··· 3043 } 3044 3045 /* 3046 + * expand_dfs_referral - Update cifs_sb from dfs referral path 3047 * 3048 + * cifs_sb->ctx->mount_options will be (re-)allocated to a string containing updated options for the 3049 + * submount. Otherwise it will be left untouched. 3050 */ 3051 + static int expand_dfs_referral(struct mount_ctx *mnt_ctx, const char *full_path, 3052 + struct dfs_info3_param *referral) 3053 { 3054 int rc; 3055 + struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb; 3056 + struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; 3057 + char *fake_devname = NULL, *mdata = NULL; 3058 3059 + mdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options, full_path + 1, referral, 3060 + &fake_devname); 3061 + if (IS_ERR(mdata)) { 3062 + rc = PTR_ERR(mdata); 3063 + mdata = NULL; 3064 + } else { 3065 /* 3066 + * We can not clear out the whole structure since we no longer have an explicit 3067 + * function to parse a mount-string. Instead we need to clear out the individual 3068 + * fields that are no longer valid. 3069 */ 3070 + kfree(ctx->prepath); 3071 + ctx->prepath = NULL; 3072 + rc = cifs_setup_volume_info(ctx, mdata, fake_devname); 3073 } 3074 + kfree(fake_devname); 3075 + kfree(cifs_sb->ctx->mount_options); 3076 + cifs_sb->ctx->mount_options = mdata; 3077 3078 return rc; 3079 } 3080 #endif ··· 3333 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is, 3334 * otherwise 0. 3335 */ 3336 + static int is_path_remote(struct mount_ctx *mnt_ctx) 3337 { 3338 int rc; 3339 + struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb; 3340 + struct TCP_Server_Info *server = mnt_ctx->server; 3341 + unsigned int xid = mnt_ctx->xid; 3342 + struct cifs_tcon *tcon = mnt_ctx->tcon; 3343 + struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; 3344 char *full_path; 3345 3346 if (!server->ops->is_path_accessible) ··· 3376 } 3377 3378 #ifdef CONFIG_CIFS_DFS_UPCALL 3379 + static void set_root_ses(struct mount_ctx *mnt_ctx) 3380 { 3381 + if (mnt_ctx->ses) { 3382 spin_lock(&cifs_tcp_ses_lock); 3383 + mnt_ctx->ses->ses_count++; 3384 spin_unlock(&cifs_tcp_ses_lock); 3385 + dfs_cache_add_refsrv_session(&mnt_ctx->mount_id, mnt_ctx->ses); 3386 } 3387 + mnt_ctx->root_ses = mnt_ctx->ses; 3388 } 3389 3390 + static int is_dfs_mount(struct mount_ctx *mnt_ctx, bool *isdfs, struct dfs_cache_tgt_list *root_tl) 3391 { 3392 int rc; 3393 + struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb; 3394 + struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; 3395 3396 + *isdfs = true; 3397 3398 + rc = mount_get_conns(mnt_ctx); 3399 /* 3400 * If called with 'nodfs' mount option, then skip DFS resolving. Otherwise unconditionally 3401 * try to get an DFS referral (even cached) to determine whether it is an DFS mount. ··· 3489 * to respond with PATH_NOT_COVERED to requests that include the prefix. 3490 */ 3491 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) || 3492 + dfs_cache_find(mnt_ctx->xid, mnt_ctx->ses, cifs_sb->local_nls, cifs_remap(cifs_sb), 3493 + ctx->UNC + 1, NULL, root_tl)) { 3494 if (rc) 3495 + return rc; 3496 /* Check if it is fully accessible and then mount it */ 3497 + rc = is_path_remote(mnt_ctx); 3498 if (!rc) 3499 + *isdfs = false; 3500 + else if (rc != -EREMOTE) 3501 + return rc; 3502 + } 3503 + return 0; 3504 + } 3505 + 3506 + static int connect_dfs_target(struct mount_ctx *mnt_ctx, const char *full_path, 3507 + const char *ref_path, struct dfs_cache_tgt_iterator *tit) 3508 + { 3509 + int rc; 3510 + struct dfs_info3_param ref = {}; 3511 + struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb; 3512 + char *oldmnt = cifs_sb->ctx->mount_options; 3513 + 3514 + rc = dfs_cache_get_tgt_referral(ref_path, tit, &ref); 3515 + if (rc) 3516 + goto out; 3517 + 3518 + rc = expand_dfs_referral(mnt_ctx, full_path, &ref); 3519 + if (rc) 3520 + goto out; 3521 + 3522 + /* Connect to new target only if we were redirected (e.g. mount options changed) */ 3523 + if (oldmnt != cifs_sb->ctx->mount_options) { 3524 + mount_put_conns(mnt_ctx); 3525 + rc = mount_get_dfs_conns(mnt_ctx); 3526 + } 3527 + if (!rc) { 3528 + if (cifs_is_referral_server(mnt_ctx->tcon, &ref)) 3529 + set_root_ses(mnt_ctx); 3530 + rc = dfs_cache_update_tgthint(mnt_ctx->xid, mnt_ctx->root_ses, cifs_sb->local_nls, 3531 + cifs_remap(cifs_sb), ref_path, tit); 3532 } 3533 3534 + out: 3535 + free_dfs_info_param(&ref); 3536 + return rc; 3537 + } 3538 3539 + static int connect_dfs_root(struct mount_ctx *mnt_ctx, struct dfs_cache_tgt_list *root_tl) 3540 + { 3541 + int rc; 3542 + char *full_path; 3543 + struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb; 3544 + struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; 3545 + struct dfs_cache_tgt_iterator *tit; 3546 + 3547 + /* Put initial connections as they might be shared with other mounts. We need unique dfs 3548 + * connections per mount to properly failover, so mount_get_dfs_conns() must be used from 3549 + * now on. 3550 + */ 3551 + mount_put_conns(mnt_ctx); 3552 + mount_get_dfs_conns(mnt_ctx); 3553 + 3554 + full_path = build_unc_path_to_root(ctx, cifs_sb, true); 3555 + if (IS_ERR(full_path)) 3556 + return PTR_ERR(full_path); 3557 + 3558 + mnt_ctx->origin_fullpath = dfs_cache_canonical_path(ctx->UNC, cifs_sb->local_nls, 3559 + cifs_remap(cifs_sb)); 3560 + if (IS_ERR(mnt_ctx->origin_fullpath)) { 3561 + rc = PTR_ERR(mnt_ctx->origin_fullpath); 3562 + mnt_ctx->origin_fullpath = NULL; 3563 + goto out; 3564 } 3565 3566 + /* Try all dfs root targets */ 3567 + for (rc = -ENOENT, tit = dfs_cache_get_tgt_iterator(root_tl); 3568 + tit; tit = dfs_cache_get_next_tgt(root_tl, tit)) { 3569 + rc = connect_dfs_target(mnt_ctx, full_path, mnt_ctx->origin_fullpath + 1, tit); 3570 + if (!rc) { 3571 + mnt_ctx->leaf_fullpath = kstrdup(mnt_ctx->origin_fullpath, GFP_KERNEL); 3572 + if (!mnt_ctx->leaf_fullpath) 3573 + rc = -ENOMEM; 3574 break; 3575 } 3576 + } 3577 3578 + out: 3579 kfree(full_path); 3580 + return rc; 3581 + } 3582 3583 + static int __follow_dfs_link(struct mount_ctx *mnt_ctx) 3584 + { 3585 + int rc; 3586 + struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb; 3587 + struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; 3588 + char *full_path; 3589 + struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl); 3590 + struct dfs_cache_tgt_iterator *tit; 3591 + 3592 + full_path = build_unc_path_to_root(ctx, cifs_sb, true); 3593 + if (IS_ERR(full_path)) 3594 + return PTR_ERR(full_path); 3595 + 3596 + kfree(mnt_ctx->leaf_fullpath); 3597 + mnt_ctx->leaf_fullpath = dfs_cache_canonical_path(full_path, cifs_sb->local_nls, 3598 + cifs_remap(cifs_sb)); 3599 + if (IS_ERR(mnt_ctx->leaf_fullpath)) { 3600 + rc = PTR_ERR(mnt_ctx->leaf_fullpath); 3601 + mnt_ctx->leaf_fullpath = NULL; 3602 + goto out; 3603 } 3604 3605 + /* Get referral from dfs link */ 3606 + rc = dfs_cache_find(mnt_ctx->xid, mnt_ctx->root_ses, cifs_sb->local_nls, 3607 + cifs_remap(cifs_sb), mnt_ctx->leaf_fullpath + 1, NULL, &tl); 3608 + if (rc) 3609 + goto out; 3610 + 3611 + /* Try all dfs link targets */ 3612 + for (rc = -ENOENT, tit = dfs_cache_get_tgt_iterator(&tl); 3613 + tit; tit = dfs_cache_get_next_tgt(&tl, tit)) { 3614 + rc = connect_dfs_target(mnt_ctx, full_path, mnt_ctx->leaf_fullpath + 1, tit); 3615 + if (!rc) { 3616 + rc = is_path_remote(mnt_ctx); 3617 + break; 3618 + } 3619 } 3620 3621 + out: 3622 + kfree(full_path); 3623 + dfs_cache_free_tgts(&tl); 3624 + return rc; 3625 + } 3626 + 3627 + static int follow_dfs_link(struct mount_ctx *mnt_ctx) 3628 + { 3629 + int rc; 3630 + struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb; 3631 + struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; 3632 + char *full_path; 3633 + int num_links = 0; 3634 + 3635 + full_path = build_unc_path_to_root(ctx, cifs_sb, true); 3636 + if (IS_ERR(full_path)) 3637 + return PTR_ERR(full_path); 3638 + 3639 + kfree(mnt_ctx->origin_fullpath); 3640 + mnt_ctx->origin_fullpath = dfs_cache_canonical_path(full_path, cifs_sb->local_nls, 3641 + cifs_remap(cifs_sb)); 3642 + kfree(full_path); 3643 + 3644 + if (IS_ERR(mnt_ctx->origin_fullpath)) { 3645 + rc = PTR_ERR(mnt_ctx->origin_fullpath); 3646 + mnt_ctx->origin_fullpath = NULL; 3647 + return rc; 3648 + } 3649 + 3650 + do { 3651 + rc = __follow_dfs_link(mnt_ctx); 3652 + if (!rc || rc != -EREMOTE) 3653 + break; 3654 + } while (rc = -ELOOP, ++num_links < MAX_NESTED_LINKS); 3655 + 3656 + return rc; 3657 + } 3658 + 3659 + /* Set up DFS referral paths for failover */ 3660 + static void setup_server_referral_paths(struct mount_ctx *mnt_ctx) 3661 + { 3662 + struct TCP_Server_Info *server = mnt_ctx->server; 3663 + 3664 + server->origin_fullpath = mnt_ctx->origin_fullpath; 3665 + server->leaf_fullpath = mnt_ctx->leaf_fullpath; 3666 + server->current_fullpath = mnt_ctx->leaf_fullpath; 3667 + mnt_ctx->origin_fullpath = mnt_ctx->leaf_fullpath = NULL; 3668 + } 3669 + 3670 + int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx) 3671 + { 3672 + int rc; 3673 + struct mount_ctx mnt_ctx = { .cifs_sb = cifs_sb, .fs_ctx = ctx, }; 3674 + struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl); 3675 + bool isdfs; 3676 + 3677 + rc = is_dfs_mount(&mnt_ctx, &isdfs, &tl); 3678 + if (rc) 3679 + goto error; 3680 + if (!isdfs) 3681 + goto out; 3682 + 3683 + uuid_gen(&mnt_ctx.mount_id); 3684 + rc = connect_dfs_root(&mnt_ctx, &tl); 3685 + dfs_cache_free_tgts(&tl); 3686 + 3687 + if (rc) 3688 + goto error; 3689 + 3690 + rc = is_path_remote(&mnt_ctx); 3691 + if (rc == -EREMOTE) 3692 + rc = follow_dfs_link(&mnt_ctx); 3693 + if (rc) 3694 + goto error; 3695 + 3696 + setup_server_referral_paths(&mnt_ctx); 3697 /* 3698 + * After reconnecting to a different server, unique ids won't match anymore, so we disable 3699 + * serverino. This prevents dentry revalidation to think the dentry are stale (ESTALE). 3700 */ 3701 cifs_autodisable_serverino(cifs_sb); 3702 /* 3703 + * Force the use of prefix path to support failover on DFS paths that resolve to targets 3704 + * that have different prefix paths. 3705 */ 3706 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; 3707 kfree(cifs_sb->prepath); 3708 cifs_sb->prepath = ctx->prepath; 3709 ctx->prepath = NULL; 3710 + uuid_copy(&cifs_sb->dfs_mount_id, &mnt_ctx.mount_id); 3711 3712 out: 3713 + free_xid(mnt_ctx.xid); 3714 + cifs_try_adding_channels(cifs_sb, mnt_ctx.ses); 3715 + return mount_setup_tlink(cifs_sb, mnt_ctx.ses, mnt_ctx.tcon); 3716 3717 error: 3718 + dfs_cache_put_refsrv_sessions(&mnt_ctx.mount_id); 3719 + kfree(mnt_ctx.origin_fullpath); 3720 + kfree(mnt_ctx.leaf_fullpath); 3721 + mount_put_conns(&mnt_ctx); 3722 return rc; 3723 } 3724 #else 3725 int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx) 3726 { 3727 int rc = 0; 3728 + struct mount_ctx mnt_ctx = { .cifs_sb = cifs_sb, .fs_ctx = ctx, }; 3729 3730 + rc = mount_get_conns(&mnt_ctx); 3731 if (rc) 3732 goto error; 3733 3734 + if (mnt_ctx.tcon) { 3735 + rc = is_path_remote(&mnt_ctx); 3736 if (rc == -EREMOTE) 3737 rc = -EOPNOTSUPP; 3738 if (rc) 3739 goto error; 3740 } 3741 3742 + free_xid(mnt_ctx.xid); 3743 + return mount_setup_tlink(cifs_sb, mnt_ctx.ses, mnt_ctx.tcon); 3744 3745 error: 3746 + mount_put_conns(&mnt_ctx); 3747 return rc; 3748 } 3749 #endif ··· 3818 kfree(cifs_sb->prepath); 3819 #ifdef CONFIG_CIFS_DFS_UPCALL 3820 dfs_cache_put_refsrv_sessions(&cifs_sb->dfs_mount_id); 3821 #endif 3822 call_rcu(&cifs_sb->rcu, delayed_free); 3823 } ··· 4145 } 4146 4147 #ifdef CONFIG_CIFS_DFS_UPCALL 4148 + static void mark_tcon_tcp_ses_for_reconnect(struct cifs_tcon *tcon) 4149 + { 4150 + int i; 4151 + 4152 + for (i = 0; i < tcon->ses->chan_count; i++) { 4153 + spin_lock(&GlobalMid_Lock); 4154 + if (tcon->ses->chans[i].server->tcpStatus != CifsExiting) 4155 + tcon->ses->chans[i].server->tcpStatus = CifsNeedReconnect; 4156 + spin_unlock(&GlobalMid_Lock); 4157 + } 4158 + } 4159 + 4160 + /* Update dfs referral path of superblock */ 4161 + static int update_server_fullpath(struct TCP_Server_Info *server, struct cifs_sb_info *cifs_sb, 4162 + const char *target) 4163 + { 4164 + int rc = 0; 4165 + size_t len = strlen(target); 4166 + char *refpath, *npath; 4167 + 4168 + if (unlikely(len < 2 || *target != '\\')) 4169 + return -EINVAL; 4170 + 4171 + if (target[1] == '\\') { 4172 + len += 1; 4173 + refpath = kmalloc(len, GFP_KERNEL); 4174 + if (!refpath) 4175 + return -ENOMEM; 4176 + 4177 + scnprintf(refpath, len, "%s", target); 4178 + } else { 4179 + len += sizeof("\\"); 4180 + refpath = kmalloc(len, GFP_KERNEL); 4181 + if (!refpath) 4182 + return -ENOMEM; 4183 + 4184 + scnprintf(refpath, len, "\\%s", target); 4185 + } 4186 + 4187 + npath = dfs_cache_canonical_path(refpath, cifs_sb->local_nls, cifs_remap(cifs_sb)); 4188 + kfree(refpath); 4189 + 4190 + if (IS_ERR(npath)) { 4191 + rc = PTR_ERR(npath); 4192 + } else { 4193 + mutex_lock(&server->refpath_lock); 4194 + kfree(server->leaf_fullpath); 4195 + server->leaf_fullpath = npath; 4196 + mutex_unlock(&server->refpath_lock); 4197 + server->current_fullpath = server->leaf_fullpath; 4198 + } 4199 + return rc; 4200 + } 4201 + 4202 + static int target_share_matches_server(struct TCP_Server_Info *server, const char *tcp_host, 4203 + size_t tcp_host_len, char *share, bool *target_match) 4204 + { 4205 + int rc = 0; 4206 + const char *dfs_host; 4207 + size_t dfs_host_len; 4208 + 4209 + *target_match = true; 4210 + extract_unc_hostname(share, &dfs_host, &dfs_host_len); 4211 + 4212 + /* Check if hostnames or addresses match */ 4213 + if (dfs_host_len != tcp_host_len || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) { 4214 + cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len, 4215 + dfs_host, (int)tcp_host_len, tcp_host); 4216 + rc = match_target_ip(server, dfs_host, dfs_host_len, target_match); 4217 + if (rc) 4218 + cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc); 4219 + } 4220 + return rc; 4221 + } 4222 + 4223 + static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *tcon, 4224 + struct cifs_sb_info *cifs_sb, char *tree, bool islink, 4225 + struct dfs_cache_tgt_list *tl) 4226 + { 4227 + int rc; 4228 + struct TCP_Server_Info *server = tcon->ses->server; 4229 + const struct smb_version_operations *ops = server->ops; 4230 + struct cifs_tcon *ipc = tcon->ses->tcon_ipc; 4231 + char *share = NULL, *prefix = NULL; 4232 + const char *tcp_host; 4233 + size_t tcp_host_len; 4234 + struct dfs_cache_tgt_iterator *tit; 4235 + bool target_match; 4236 + 4237 + extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len); 4238 + 4239 + tit = dfs_cache_get_tgt_iterator(tl); 4240 + if (!tit) { 4241 + rc = -ENOENT; 4242 + goto out; 4243 + } 4244 + 4245 + /* Try to tree connect to all dfs targets */ 4246 + for (; tit; tit = dfs_cache_get_next_tgt(tl, tit)) { 4247 + const char *target = dfs_cache_get_tgt_name(tit); 4248 + struct dfs_cache_tgt_list ntl = DFS_CACHE_TGT_LIST_INIT(ntl); 4249 + 4250 + kfree(share); 4251 + kfree(prefix); 4252 + share = prefix = NULL; 4253 + 4254 + /* Check if share matches with tcp ses */ 4255 + rc = dfs_cache_get_tgt_share(server->current_fullpath + 1, tit, &share, &prefix); 4256 + if (rc) { 4257 + cifs_dbg(VFS, "%s: failed to parse target share: %d\n", __func__, rc); 4258 + break; 4259 + } 4260 + 4261 + rc = target_share_matches_server(server, tcp_host, tcp_host_len, share, 4262 + &target_match); 4263 + if (rc) 4264 + break; 4265 + if (!target_match) { 4266 + rc = -EHOSTUNREACH; 4267 + continue; 4268 + } 4269 + 4270 + if (ipc->need_reconnect) { 4271 + scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname); 4272 + rc = ops->tree_connect(xid, ipc->ses, tree, ipc, cifs_sb->local_nls); 4273 + if (rc) 4274 + break; 4275 + } 4276 + 4277 + scnprintf(tree, MAX_TREE_SIZE, "\\%s", share); 4278 + if (!islink) { 4279 + rc = ops->tree_connect(xid, tcon->ses, tree, tcon, cifs_sb->local_nls); 4280 + break; 4281 + } 4282 + /* 4283 + * If no dfs referrals were returned from link target, then just do a TREE_CONNECT 4284 + * to it. Otherwise, cache the dfs referral and then mark current tcp ses for 4285 + * reconnect so either the demultiplex thread or the echo worker will reconnect to 4286 + * newly resolved target. 4287 + */ 4288 + if (dfs_cache_find(xid, tcon->ses, cifs_sb->local_nls, cifs_remap(cifs_sb), target, 4289 + NULL, &ntl)) { 4290 + rc = ops->tree_connect(xid, tcon->ses, tree, tcon, cifs_sb->local_nls); 4291 + if (rc) 4292 + continue; 4293 + rc = dfs_cache_noreq_update_tgthint(server->current_fullpath + 1, tit); 4294 + if (!rc) 4295 + rc = cifs_update_super_prepath(cifs_sb, prefix); 4296 + } else { 4297 + /* Target is another dfs share */ 4298 + rc = update_server_fullpath(server, cifs_sb, target); 4299 + dfs_cache_free_tgts(tl); 4300 + 4301 + if (!rc) { 4302 + rc = -EREMOTE; 4303 + list_replace_init(&ntl.tl_list, &tl->tl_list); 4304 + } else 4305 + dfs_cache_free_tgts(&ntl); 4306 + } 4307 + break; 4308 + } 4309 + 4310 + out: 4311 + kfree(share); 4312 + kfree(prefix); 4313 + 4314 + return rc; 4315 + } 4316 + 4317 + static int tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *tcon, 4318 + struct cifs_sb_info *cifs_sb, char *tree, bool islink, 4319 + struct dfs_cache_tgt_list *tl) 4320 + { 4321 + int rc; 4322 + int num_links = 0; 4323 + struct TCP_Server_Info *server = tcon->ses->server; 4324 + 4325 + do { 4326 + rc = __tree_connect_dfs_target(xid, tcon, cifs_sb, tree, islink, tl); 4327 + if (!rc || rc != -EREMOTE) 4328 + break; 4329 + } while (rc = -ELOOP, ++num_links < MAX_NESTED_LINKS); 4330 + /* 4331 + * If we couldn't tree connect to any targets from last referral path, then retry from 4332 + * original referral path. 4333 + */ 4334 + if (rc && server->current_fullpath != server->origin_fullpath) { 4335 + server->current_fullpath = server->origin_fullpath; 4336 + mark_tcon_tcp_ses_for_reconnect(tcon); 4337 + } 4338 + 4339 + dfs_cache_free_tgts(tl); 4340 + return rc; 4341 + } 4342 + 4343 int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc) 4344 { 4345 int rc; 4346 struct TCP_Server_Info *server = tcon->ses->server; 4347 const struct smb_version_operations *ops = server->ops; 4348 + struct super_block *sb = NULL; 4349 + struct cifs_sb_info *cifs_sb; 4350 + struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl); 4351 char *tree; 4352 struct dfs_info3_param ref = {0}; 4353 4354 tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL); 4355 if (!tree) 4356 return -ENOMEM; 4357 4358 + if (tcon->ipc) { 4359 + scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname); 4360 + rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc); 4361 goto out; 4362 } 4363 4364 + sb = cifs_get_tcp_super(server); 4365 + if (IS_ERR(sb)) { 4366 + rc = PTR_ERR(sb); 4367 + cifs_dbg(VFS, "%s: could not find superblock: %d\n", __func__, rc); 4368 + goto out; 4369 + } 4370 + 4371 + cifs_sb = CIFS_SB(sb); 4372 + 4373 + /* If it is not dfs or there was no cached dfs referral, then reconnect to same share */ 4374 + if (!server->current_fullpath || 4375 + dfs_cache_noreq_find(server->current_fullpath + 1, &ref, &tl)) { 4376 + rc = ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, cifs_sb->local_nls); 4377 + goto out; 4378 + } 4379 + 4380 + rc = tree_connect_dfs_target(xid, tcon, cifs_sb, tree, ref.server_type == DFS_TYPE_LINK, 4381 + &tl); 4382 free_dfs_info_param(&ref); 4383 4384 out: 4385 kfree(tree); 4386 + cifs_put_tcp_super(sb); 4387 + 4388 return rc; 4389 } 4390 #else
+37 -9
fs/cifs/dfs_cache.c
··· 283 seq_printf(m, 284 "cache entry: path=%s,type=%s,ttl=%d,etime=%ld,hdr_flags=0x%x,ref_flags=0x%x,interlink=%s,path_consumed=%d,expired=%s\n", 285 ce->path, ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", 286 - ce->ttl, ce->etime.tv_nsec, ce->ref_flags, ce->hdr_flags, 287 IS_DFS_INTERLINK(ce->hdr_flags) ? "yes" : "no", 288 ce->path_consumed, cache_entry_expired(ce) ? "yes" : "no"); 289 ··· 1364 } 1365 1366 /* Refresh dfs referral of tcon and mark it for reconnect if needed */ 1367 - static int refresh_tcon(struct cifs_ses **sessions, struct cifs_tcon *tcon, bool force_refresh) 1368 { 1369 - const char *path = tcon->dfs_path + 1; 1370 struct cifs_ses *ses; 1371 struct cache_entry *ce; 1372 struct dfs_info3_param *refs = NULL; ··· 1422 return rc; 1423 } 1424 1425 /** 1426 * dfs_cache_remount_fs - remount a DFS share 1427 * ··· 1449 int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb) 1450 { 1451 struct cifs_tcon *tcon; 1452 struct mount_group *mg; 1453 struct cifs_ses *sessions[CACHE_MAX_ENTRIES + 1] = {NULL}; 1454 int rc; ··· 1458 return -EINVAL; 1459 1460 tcon = cifs_sb_master_tcon(cifs_sb); 1461 - if (!tcon->dfs_path) { 1462 - cifs_dbg(FYI, "%s: not a dfs tcon\n", __func__); 1463 return 0; 1464 } 1465 1466 if (uuid_is_null(&cifs_sb->dfs_mount_id)) { 1467 - cifs_dbg(FYI, "%s: tcon has no dfs mount group id\n", __func__); 1468 return -EINVAL; 1469 } 1470 ··· 1474 mg = find_mount_group_locked(&cifs_sb->dfs_mount_id); 1475 if (IS_ERR(mg)) { 1476 mutex_unlock(&mount_group_list_lock); 1477 - cifs_dbg(FYI, "%s: tcon has ipc session to refresh referral\n", __func__); 1478 return PTR_ERR(mg); 1479 } 1480 kref_get(&mg->refcount); ··· 1515 1516 spin_lock(&cifs_tcp_ses_lock); 1517 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { 1518 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { 1519 list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { 1520 - if (tcon->dfs_path) { 1521 tcon->tc_count++; 1522 list_add_tail(&tcon->ulist, &tcons); 1523 } ··· 1530 spin_unlock(&cifs_tcp_ses_lock); 1531 1532 list_for_each_entry_safe(tcon, ntcon, &tcons, ulist) { 1533 list_del_init(&tcon->ulist); 1534 - refresh_tcon(sessions, tcon, false); 1535 cifs_put_tcon(tcon); 1536 } 1537 }
··· 283 seq_printf(m, 284 "cache entry: path=%s,type=%s,ttl=%d,etime=%ld,hdr_flags=0x%x,ref_flags=0x%x,interlink=%s,path_consumed=%d,expired=%s\n", 285 ce->path, ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", 286 + ce->ttl, ce->etime.tv_nsec, ce->hdr_flags, ce->ref_flags, 287 IS_DFS_INTERLINK(ce->hdr_flags) ? "yes" : "no", 288 ce->path_consumed, cache_entry_expired(ce) ? "yes" : "no"); 289 ··· 1364 } 1365 1366 /* Refresh dfs referral of tcon and mark it for reconnect if needed */ 1367 + static int __refresh_tcon(const char *path, struct cifs_ses **sessions, struct cifs_tcon *tcon, 1368 + bool force_refresh) 1369 { 1370 struct cifs_ses *ses; 1371 struct cache_entry *ce; 1372 struct dfs_info3_param *refs = NULL; ··· 1422 return rc; 1423 } 1424 1425 + static int refresh_tcon(struct cifs_ses **sessions, struct cifs_tcon *tcon, bool force_refresh) 1426 + { 1427 + struct TCP_Server_Info *server = tcon->ses->server; 1428 + 1429 + mutex_lock(&server->refpath_lock); 1430 + if (strcasecmp(server->leaf_fullpath, server->origin_fullpath)) 1431 + __refresh_tcon(server->leaf_fullpath + 1, sessions, tcon, force_refresh); 1432 + mutex_unlock(&server->refpath_lock); 1433 + 1434 + __refresh_tcon(server->origin_fullpath + 1, sessions, tcon, force_refresh); 1435 + 1436 + return 0; 1437 + } 1438 + 1439 /** 1440 * dfs_cache_remount_fs - remount a DFS share 1441 * ··· 1435 int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb) 1436 { 1437 struct cifs_tcon *tcon; 1438 + struct TCP_Server_Info *server; 1439 struct mount_group *mg; 1440 struct cifs_ses *sessions[CACHE_MAX_ENTRIES + 1] = {NULL}; 1441 int rc; ··· 1443 return -EINVAL; 1444 1445 tcon = cifs_sb_master_tcon(cifs_sb); 1446 + server = tcon->ses->server; 1447 + 1448 + if (!server->origin_fullpath) { 1449 + cifs_dbg(FYI, "%s: not a dfs mount\n", __func__); 1450 return 0; 1451 } 1452 1453 if (uuid_is_null(&cifs_sb->dfs_mount_id)) { 1454 + cifs_dbg(FYI, "%s: no dfs mount group id\n", __func__); 1455 return -EINVAL; 1456 } 1457 ··· 1457 mg = find_mount_group_locked(&cifs_sb->dfs_mount_id); 1458 if (IS_ERR(mg)) { 1459 mutex_unlock(&mount_group_list_lock); 1460 + cifs_dbg(FYI, "%s: no ipc session for refreshing referral\n", __func__); 1461 return PTR_ERR(mg); 1462 } 1463 kref_get(&mg->refcount); ··· 1498 1499 spin_lock(&cifs_tcp_ses_lock); 1500 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { 1501 + if (!server->is_dfs_conn) 1502 + continue; 1503 + 1504 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { 1505 list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { 1506 + if (!tcon->ipc && !tcon->need_reconnect) { 1507 tcon->tc_count++; 1508 list_add_tail(&tcon->ulist, &tcons); 1509 } ··· 1510 spin_unlock(&cifs_tcp_ses_lock); 1511 1512 list_for_each_entry_safe(tcon, ntcon, &tcons, ulist) { 1513 + struct TCP_Server_Info *server = tcon->ses->server; 1514 + 1515 list_del_init(&tcon->ulist); 1516 + 1517 + mutex_lock(&server->refpath_lock); 1518 + if (strcasecmp(server->leaf_fullpath, server->origin_fullpath)) 1519 + __refresh_tcon(server->leaf_fullpath + 1, sessions, tcon, false); 1520 + mutex_unlock(&server->refpath_lock); 1521 + 1522 + __refresh_tcon(server->origin_fullpath + 1, sessions, tcon, false); 1523 cifs_put_tcon(tcon); 1524 } 1525 }
+29 -6
fs/cifs/file.c
··· 2692 tcon = tlink_tcon(smbfile->tlink); 2693 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { 2694 server = tcon->ses->server; 2695 - if (server->ops->flush) 2696 - rc = server->ops->flush(xid, tcon, &smbfile->fid); 2697 - else 2698 rc = -ENOSYS; 2699 } 2700 2701 free_xid(xid); 2702 return rc; 2703 } ··· 2720 struct cifs_tcon *tcon; 2721 struct TCP_Server_Info *server; 2722 struct cifsFileInfo *smbfile = file->private_data; 2723 struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file); 2724 2725 rc = file_write_and_wait_range(file, start, end); ··· 2737 tcon = tlink_tcon(smbfile->tlink); 2738 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { 2739 server = tcon->ses->server; 2740 - if (server->ops->flush) 2741 - rc = server->ops->flush(xid, tcon, &smbfile->fid); 2742 - else 2743 rc = -ENOSYS; 2744 } 2745 2746 free_xid(xid); 2747 return rc; 2748 }
··· 2692 tcon = tlink_tcon(smbfile->tlink); 2693 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { 2694 server = tcon->ses->server; 2695 + if (server->ops->flush == NULL) { 2696 rc = -ENOSYS; 2697 + goto strict_fsync_exit; 2698 + } 2699 + 2700 + if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) { 2701 + smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY); 2702 + if (smbfile) { 2703 + rc = server->ops->flush(xid, tcon, &smbfile->fid); 2704 + cifsFileInfo_put(smbfile); 2705 + } else 2706 + cifs_dbg(FYI, "ignore fsync for file not open for write\n"); 2707 + } else 2708 + rc = server->ops->flush(xid, tcon, &smbfile->fid); 2709 } 2710 2711 + strict_fsync_exit: 2712 free_xid(xid); 2713 return rc; 2714 } ··· 2709 struct cifs_tcon *tcon; 2710 struct TCP_Server_Info *server; 2711 struct cifsFileInfo *smbfile = file->private_data; 2712 + struct inode *inode = file_inode(file); 2713 struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file); 2714 2715 rc = file_write_and_wait_range(file, start, end); ··· 2725 tcon = tlink_tcon(smbfile->tlink); 2726 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { 2727 server = tcon->ses->server; 2728 + if (server->ops->flush == NULL) { 2729 rc = -ENOSYS; 2730 + goto fsync_exit; 2731 + } 2732 + 2733 + if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) { 2734 + smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY); 2735 + if (smbfile) { 2736 + rc = server->ops->flush(xid, tcon, &smbfile->fid); 2737 + cifsFileInfo_put(smbfile); 2738 + } else 2739 + cifs_dbg(FYI, "ignore fsync for file not open for write\n"); 2740 + } else 2741 + rc = server->ops->flush(xid, tcon, &smbfile->fid); 2742 } 2743 2744 + fsync_exit: 2745 free_xid(xid); 2746 return rc; 2747 }
+33 -3
fs/cifs/fs_context.c
··· 308 new_ctx->nodename = NULL; 309 new_ctx->username = NULL; 310 new_ctx->password = NULL; 311 new_ctx->domainname = NULL; 312 new_ctx->UNC = NULL; 313 new_ctx->source = NULL; 314 new_ctx->iocharset = NULL; ··· 325 DUP_CTX_STR(UNC); 326 DUP_CTX_STR(source); 327 DUP_CTX_STR(domainname); 328 DUP_CTX_STR(nodename); 329 DUP_CTX_STR(iocharset); 330 ··· 462 return -EINVAL; 463 464 /* record the server hostname */ 465 ctx->server_hostname = kstrndup(devname + 2, pos - devname - 2, GFP_KERNEL); 466 if (!ctx->server_hostname) 467 return -ENOMEM; ··· 724 cifs_errorf(fc, "can not change domainname during remount\n"); 725 return -EINVAL; 726 } 727 if (new_ctx->nodename && 728 (!old_ctx->nodename || strcmp(new_ctx->nodename, old_ctx->nodename))) { 729 cifs_errorf(fc, "can not change nodename during remount\n"); ··· 762 return rc; 763 764 /* 765 - * We can not change UNC/username/password/domainname/nodename/iocharset 766 * during reconnect so ignore what we have in the new context and 767 * just use what we already have in cifs_sb->ctx. 768 */ ··· 772 STEAL_STRING(cifs_sb, ctx, username); 773 STEAL_STRING(cifs_sb, ctx, password); 774 STEAL_STRING(cifs_sb, ctx, domainname); 775 STEAL_STRING(cifs_sb, ctx, nodename); 776 STEAL_STRING(cifs_sb, ctx, iocharset); 777 ··· 1425 1426 int smb3_init_fs_context(struct fs_context *fc) 1427 { 1428 struct smb3_fs_context *ctx; 1429 char *nodename = utsname()->nodename; 1430 int i; 1431 1432 ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL); 1433 - if (unlikely(!ctx)) 1434 - return -ENOMEM; 1435 1436 /* 1437 * does not have to be perfect mapping since field is ··· 1513 fc->fs_private = ctx; 1514 fc->ops = &smb3_fs_context_ops; 1515 return 0; 1516 } 1517 1518 void ··· 1546 ctx->source = NULL; 1547 kfree(ctx->domainname); 1548 ctx->domainname = NULL; 1549 kfree(ctx->nodename); 1550 ctx->nodename = NULL; 1551 kfree(ctx->iocharset);
··· 308 new_ctx->nodename = NULL; 309 new_ctx->username = NULL; 310 new_ctx->password = NULL; 311 + new_ctx->server_hostname = NULL; 312 new_ctx->domainname = NULL; 313 + new_ctx->workstation_name = NULL; 314 new_ctx->UNC = NULL; 315 new_ctx->source = NULL; 316 new_ctx->iocharset = NULL; ··· 323 DUP_CTX_STR(UNC); 324 DUP_CTX_STR(source); 325 DUP_CTX_STR(domainname); 326 + DUP_CTX_STR(workstation_name); 327 DUP_CTX_STR(nodename); 328 DUP_CTX_STR(iocharset); 329 ··· 459 return -EINVAL; 460 461 /* record the server hostname */ 462 + kfree(ctx->server_hostname); 463 ctx->server_hostname = kstrndup(devname + 2, pos - devname - 2, GFP_KERNEL); 464 if (!ctx->server_hostname) 465 return -ENOMEM; ··· 720 cifs_errorf(fc, "can not change domainname during remount\n"); 721 return -EINVAL; 722 } 723 + if (new_ctx->workstation_name && 724 + (!old_ctx->workstation_name || strcmp(new_ctx->workstation_name, old_ctx->workstation_name))) { 725 + cifs_errorf(fc, "can not change workstation_name during remount\n"); 726 + return -EINVAL; 727 + } 728 if (new_ctx->nodename && 729 (!old_ctx->nodename || strcmp(new_ctx->nodename, old_ctx->nodename))) { 730 cifs_errorf(fc, "can not change nodename during remount\n"); ··· 753 return rc; 754 755 /* 756 + * We can not change UNC/username/password/domainname/ 757 + * workstation_name/nodename/iocharset 758 * during reconnect so ignore what we have in the new context and 759 * just use what we already have in cifs_sb->ctx. 760 */ ··· 762 STEAL_STRING(cifs_sb, ctx, username); 763 STEAL_STRING(cifs_sb, ctx, password); 764 STEAL_STRING(cifs_sb, ctx, domainname); 765 + STEAL_STRING(cifs_sb, ctx, workstation_name); 766 STEAL_STRING(cifs_sb, ctx, nodename); 767 STEAL_STRING(cifs_sb, ctx, iocharset); 768 ··· 1414 1415 int smb3_init_fs_context(struct fs_context *fc) 1416 { 1417 + int rc; 1418 struct smb3_fs_context *ctx; 1419 char *nodename = utsname()->nodename; 1420 int i; 1421 1422 ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL); 1423 + if (unlikely(!ctx)) { 1424 + rc = -ENOMEM; 1425 + goto err_exit; 1426 + } 1427 + 1428 + ctx->workstation_name = kstrdup(nodename, GFP_KERNEL); 1429 + if (unlikely(!ctx->workstation_name)) { 1430 + rc = -ENOMEM; 1431 + goto err_exit; 1432 + } 1433 1434 /* 1435 * does not have to be perfect mapping since field is ··· 1493 fc->fs_private = ctx; 1494 fc->ops = &smb3_fs_context_ops; 1495 return 0; 1496 + 1497 + err_exit: 1498 + if (ctx) { 1499 + kfree(ctx->workstation_name); 1500 + kfree(ctx); 1501 + } 1502 + 1503 + return rc; 1504 } 1505 1506 void ··· 1518 ctx->source = NULL; 1519 kfree(ctx->domainname); 1520 ctx->domainname = NULL; 1521 + kfree(ctx->workstation_name); 1522 + ctx->workstation_name = NULL; 1523 kfree(ctx->nodename); 1524 ctx->nodename = NULL; 1525 kfree(ctx->iocharset);
+1
fs/cifs/fs_context.h
··· 170 char *server_hostname; 171 char *UNC; 172 char *nodename; 173 char *iocharset; /* local code page for mapping to and from Unicode */ 174 char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */ 175 char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
··· 170 char *server_hostname; 171 char *UNC; 172 char *nodename; 173 + char *workstation_name; 174 char *iocharset; /* local code page for mapping to and from Unicode */ 175 char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */ 176 char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
+8
fs/cifs/fscache.c
··· 87 char *sharename; 88 struct cifs_fscache_super_auxdata auxdata; 89 90 sharename = extract_sharename(tcon->treeName); 91 if (IS_ERR(sharename)) { 92 cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
··· 87 char *sharename; 88 struct cifs_fscache_super_auxdata auxdata; 89 90 + /* 91 + * Check if cookie was already initialized so don't reinitialize it. 92 + * In the future, as we integrate with newer fscache features, 93 + * we may want to instead add a check if cookie has changed 94 + */ 95 + if (tcon->fscache == NULL) 96 + return; 97 + 98 sharename = extract_sharename(tcon->treeName); 99 if (IS_ERR(sharename)) { 100 cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
+7 -57
fs/cifs/misc.c
··· 75 INIT_LIST_HEAD(&ret_buf->tcon_list); 76 mutex_init(&ret_buf->session_mutex); 77 spin_lock_init(&ret_buf->iface_lock); 78 } 79 return ret_buf; 80 } ··· 95 kfree_sensitive(buf_to_free->password); 96 kfree(buf_to_free->user_name); 97 kfree(buf_to_free->domainName); 98 kfree_sensitive(buf_to_free->auth_key.response); 99 kfree(buf_to_free->iface_list); 100 kfree_sensitive(buf_to_free); ··· 140 kfree(buf_to_free->nativeFileSystem); 141 kfree_sensitive(buf_to_free->password); 142 kfree(buf_to_free->crfid.fid); 143 - #ifdef CONFIG_CIFS_DFS_UPCALL 144 - kfree(buf_to_free->dfs_path); 145 - #endif 146 kfree(buf_to_free); 147 } 148 ··· 1286 return rc; 1287 } 1288 1289 - static void tcon_super_cb(struct super_block *sb, void *arg) 1290 { 1291 - struct super_cb_data *sd = arg; 1292 - struct cifs_tcon *tcon = sd->data; 1293 - struct cifs_sb_info *cifs_sb; 1294 - 1295 - if (sd->sb) 1296 - return; 1297 - 1298 - cifs_sb = CIFS_SB(sb); 1299 - if (tcon->dfs_path && cifs_sb->origin_fullpath && 1300 - !strcasecmp(tcon->dfs_path, cifs_sb->origin_fullpath)) 1301 - sd->sb = sb; 1302 - } 1303 - 1304 - static inline struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon) 1305 - { 1306 - return __cifs_get_super(tcon_super_cb, tcon); 1307 - } 1308 - 1309 - static inline void cifs_put_tcon_super(struct super_block *sb) 1310 - { 1311 - __cifs_put_super(sb); 1312 - } 1313 - #else 1314 - static inline struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon) 1315 - { 1316 - return ERR_PTR(-EOPNOTSUPP); 1317 - } 1318 - 1319 - static inline void cifs_put_tcon_super(struct super_block *sb) 1320 - { 1321 - } 1322 - #endif 1323 - 1324 - int update_super_prepath(struct cifs_tcon *tcon, char *prefix) 1325 - { 1326 - struct super_block *sb; 1327 - struct cifs_sb_info *cifs_sb; 1328 - int rc = 0; 1329 - 1330 - sb = cifs_get_tcon_super(tcon); 1331 - if (IS_ERR(sb)) 1332 - return PTR_ERR(sb); 1333 - 1334 - cifs_sb = CIFS_SB(sb); 1335 - 1336 kfree(cifs_sb->prepath); 1337 1338 if (prefix && *prefix) { 1339 cifs_sb->prepath = kstrdup(prefix, GFP_ATOMIC); 1340 - if (!cifs_sb->prepath) { 1341 - rc = -ENOMEM; 1342 - goto out; 1343 - } 1344 1345 convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb)); 1346 } else 1347 cifs_sb->prepath = NULL; 1348 1349 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; 1350 - 1351 - out: 1352 - cifs_put_tcon_super(sb); 1353 - return rc; 1354 }
··· 75 INIT_LIST_HEAD(&ret_buf->tcon_list); 76 mutex_init(&ret_buf->session_mutex); 77 spin_lock_init(&ret_buf->iface_lock); 78 + spin_lock_init(&ret_buf->chan_lock); 79 } 80 return ret_buf; 81 } ··· 94 kfree_sensitive(buf_to_free->password); 95 kfree(buf_to_free->user_name); 96 kfree(buf_to_free->domainName); 97 + kfree(buf_to_free->workstation_name); 98 kfree_sensitive(buf_to_free->auth_key.response); 99 kfree(buf_to_free->iface_list); 100 kfree_sensitive(buf_to_free); ··· 138 kfree(buf_to_free->nativeFileSystem); 139 kfree_sensitive(buf_to_free->password); 140 kfree(buf_to_free->crfid.fid); 141 kfree(buf_to_free); 142 } 143 ··· 1287 return rc; 1288 } 1289 1290 + int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix) 1291 { 1292 kfree(cifs_sb->prepath); 1293 1294 if (prefix && *prefix) { 1295 cifs_sb->prepath = kstrdup(prefix, GFP_ATOMIC); 1296 + if (!cifs_sb->prepath) 1297 + return -ENOMEM; 1298 1299 convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb)); 1300 } else 1301 cifs_sb->prepath = NULL; 1302 1303 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; 1304 + return 0; 1305 } 1306 + #endif
+3 -1
fs/cifs/ntlmssp.h
··· 119 */ 120 121 int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses); 122 - void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, struct cifs_ses *ses); 123 int build_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen, 124 struct cifs_ses *ses, 125 const struct nls_table *nls_cp);
··· 119 */ 120 121 int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses); 122 + int build_ntlmssp_negotiate_blob(unsigned char **pbuffer, u16 *buflen, 123 + struct cifs_ses *ses, 124 + const struct nls_table *nls_cp); 125 int build_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen, 126 struct cifs_ses *ses, 127 const struct nls_table *nls_cp);
+155 -85
fs/cifs/sess.c
··· 54 { 55 int i; 56 57 for (i = 0; i < ses->chan_count; i++) { 58 - if (is_server_using_iface(ses->chans[i].server, iface)) 59 return true; 60 } 61 return false; 62 } 63 64 /* returns number of channels added */ 65 int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses) 66 { 67 - int old_chan_count = ses->chan_count; 68 - int left = ses->chan_max - ses->chan_count; 69 int i = 0; 70 int rc = 0; 71 int tries = 0; 72 struct cifs_server_iface *ifaces = NULL; 73 size_t iface_count; 74 75 if (left <= 0) { 76 cifs_dbg(FYI, 77 "ses already at max_channels (%zu), nothing to open\n", 78 ses->chan_max); 79 - return 0; 80 - } 81 - 82 - if (ses->server->dialect < SMB30_PROT_ID) { 83 - cifs_dbg(VFS, "multichannel is not supported on this protocol version, use 3.0 or above\n"); 84 return 0; 85 } 86 87 if (!(ses->server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) { 88 cifs_dbg(VFS, "server %s does not support multichannel\n", ses->server->hostname); 89 ses->chan_max = 1; 90 return 0; 91 } 92 93 /* 94 * Make a copy of the iface list at the time and use that ··· 154 cifs_dbg(FYI, "successfully opened new channel on iface#%d\n", 155 i); 156 left--; 157 } 158 159 kfree(ifaces); 160 - return ses->chan_count - old_chan_count; 161 } 162 163 /* ··· 170 { 171 int i; 172 173 for (i = 0; i < ses->chan_count; i++) { 174 - if (ses->chans[i].server == server) 175 return &ses->chans[i]; 176 } 177 return NULL; 178 } 179 ··· 185 cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, 186 struct cifs_server_iface *iface) 187 { 188 struct cifs_chan *chan; 189 struct smb3_fs_context ctx = {NULL}; 190 static const char unc_fmt[] = "\\%s\\foo"; ··· 258 SMB2_CLIENT_GUID_SIZE); 259 ctx.use_client_guid = true; 260 261 - mutex_lock(&ses->session_mutex); 262 263 chan = ses->binding_chan = &ses->chans[ses->chan_count]; 264 - chan->server = cifs_get_tcp_session(&ctx); 265 if (IS_ERR(chan->server)) { 266 rc = PTR_ERR(chan->server); 267 chan->server = NULL; 268 goto out; 269 } 270 - spin_lock(&cifs_tcp_ses_lock); 271 - chan->server->is_channel = true; 272 - spin_unlock(&cifs_tcp_ses_lock); 273 274 /* 275 * We need to allocate the server crypto now as we will need ··· 302 * ses to the new server. 303 */ 304 305 ses->chan_count++; 306 atomic_set(&ses->chan_seq, 0); 307 out: 308 ses->binding = false; 309 ses->binding_chan = NULL; ··· 621 return 0; 622 } 623 624 /* BB Move to ntlmssp.c eventually */ 625 626 - /* We do not malloc the blob, it is passed in pbuffer, because 627 - it is fixed size, and small, making this approach cleaner */ 628 - void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, 629 - struct cifs_ses *ses) 630 { 631 struct TCP_Server_Info *server = cifs_ses_server(ses); 632 - NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer; 633 __u32 flags; 634 635 - memset(pbuffer, 0, sizeof(NEGOTIATE_MESSAGE)); 636 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); 637 sec_blob->MessageType = NtLmNegotiate; 638 ··· 713 if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess) 714 flags |= NTLMSSP_NEGOTIATE_KEY_XCH; 715 716 sec_blob->NegotiateFlags = cpu_to_le32(flags); 717 718 - sec_blob->WorkstationName.BufferOffset = 0; 719 - sec_blob->WorkstationName.Length = 0; 720 - sec_blob->WorkstationName.MaximumLength = 0; 721 722 - /* Domain name is sent on the Challenge not Negotiate NTLMSSP request */ 723 - sec_blob->DomainName.BufferOffset = 0; 724 - sec_blob->DomainName.Length = 0; 725 - sec_blob->DomainName.MaximumLength = 0; 726 - } 727 728 - static int size_of_ntlmssp_blob(struct cifs_ses *ses) 729 - { 730 - int sz = sizeof(AUTHENTICATE_MESSAGE) + ses->auth_key.len 731 - - CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2; 732 - 733 - if (ses->domainName) 734 - sz += 2 * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN); 735 - else 736 - sz += 2; 737 - 738 - if (ses->user_name) 739 - sz += 2 * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN); 740 - else 741 - sz += 2; 742 - 743 - return sz; 744 } 745 746 int build_ntlmssp_auth_blob(unsigned char **pbuffer, ··· 743 AUTHENTICATE_MESSAGE *sec_blob; 744 __u32 flags; 745 unsigned char *tmp; 746 747 rc = setup_ntlmv2_rsp(ses, nls_cp); 748 if (rc) { ··· 751 *buflen = 0; 752 goto setup_ntlmv2_ret; 753 } 754 - *pbuffer = kmalloc(size_of_ntlmssp_blob(ses), GFP_KERNEL); 755 if (!*pbuffer) { 756 rc = -ENOMEM; 757 cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc); ··· 769 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | 770 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | 771 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC | 772 - NTLMSSP_NEGOTIATE_SEAL; 773 if (ses->server->sign) 774 flags |= NTLMSSP_NEGOTIATE_SIGN; 775 if (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess) ··· 802 sec_blob->NtChallengeResponse.MaximumLength = 0; 803 } 804 805 - if (ses->domainName == NULL) { 806 - sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer); 807 - sec_blob->DomainName.Length = 0; 808 - sec_blob->DomainName.MaximumLength = 0; 809 - tmp += 2; 810 - } else { 811 - int len; 812 - len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName, 813 - CIFS_MAX_DOMAINNAME_LEN, nls_cp); 814 - len *= 2; /* unicode is 2 bytes each */ 815 - sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer); 816 - sec_blob->DomainName.Length = cpu_to_le16(len); 817 - sec_blob->DomainName.MaximumLength = cpu_to_le16(len); 818 - tmp += len; 819 - } 820 821 - if (ses->user_name == NULL) { 822 - sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer); 823 - sec_blob->UserName.Length = 0; 824 - sec_blob->UserName.MaximumLength = 0; 825 - tmp += 2; 826 - } else { 827 - int len; 828 - len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name, 829 - CIFS_MAX_USERNAME_LEN, nls_cp); 830 - len *= 2; /* unicode is 2 bytes each */ 831 - sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer); 832 - sec_blob->UserName.Length = cpu_to_le16(len); 833 - sec_blob->UserName.MaximumLength = cpu_to_le16(len); 834 - tmp += len; 835 - } 836 837 - sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - *pbuffer); 838 - sec_blob->WorkstationName.Length = 0; 839 - sec_blob->WorkstationName.MaximumLength = 0; 840 - tmp += 2; 841 842 if (((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) || 843 (ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) ··· 1294 struct cifs_ses *ses = sess_data->ses; 1295 __u16 bytes_remaining; 1296 char *bcc_ptr; 1297 u16 blob_len; 1298 1299 cifs_dbg(FYI, "rawntlmssp session setup negotiate phase\n"); ··· 1318 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base; 1319 1320 /* Build security blob before we assemble the request */ 1321 - build_ntlmssp_negotiate_blob(pSMB->req.SecurityBlob, ses); 1322 - sess_data->iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); 1323 - sess_data->iov[1].iov_base = pSMB->req.SecurityBlob; 1324 - pSMB->req.SecurityBlobLength = cpu_to_le16(sizeof(NEGOTIATE_MESSAGE)); 1325 1326 rc = _sess_auth_rawntlmssp_assemble_req(sess_data); 1327 if (rc)
··· 54 { 55 int i; 56 57 + spin_lock(&ses->chan_lock); 58 for (i = 0; i < ses->chan_count; i++) { 59 + if (is_server_using_iface(ses->chans[i].server, iface)) { 60 + spin_unlock(&ses->chan_lock); 61 return true; 62 + } 63 } 64 + spin_unlock(&ses->chan_lock); 65 return false; 66 } 67 68 /* returns number of channels added */ 69 int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses) 70 { 71 + int old_chan_count, new_chan_count; 72 + int left; 73 int i = 0; 74 int rc = 0; 75 int tries = 0; 76 struct cifs_server_iface *ifaces = NULL; 77 size_t iface_count; 78 79 + if (ses->server->dialect < SMB30_PROT_ID) { 80 + cifs_dbg(VFS, "multichannel is not supported on this protocol version, use 3.0 or above\n"); 81 + return 0; 82 + } 83 + 84 + spin_lock(&ses->chan_lock); 85 + 86 + new_chan_count = old_chan_count = ses->chan_count; 87 + left = ses->chan_max - ses->chan_count; 88 + 89 if (left <= 0) { 90 cifs_dbg(FYI, 91 "ses already at max_channels (%zu), nothing to open\n", 92 ses->chan_max); 93 + spin_unlock(&ses->chan_lock); 94 return 0; 95 } 96 97 if (!(ses->server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) { 98 cifs_dbg(VFS, "server %s does not support multichannel\n", ses->server->hostname); 99 ses->chan_max = 1; 100 + spin_unlock(&ses->chan_lock); 101 return 0; 102 } 103 + spin_unlock(&ses->chan_lock); 104 105 /* 106 * Make a copy of the iface list at the time and use that ··· 142 cifs_dbg(FYI, "successfully opened new channel on iface#%d\n", 143 i); 144 left--; 145 + new_chan_count++; 146 } 147 148 kfree(ifaces); 149 + return new_chan_count - old_chan_count; 150 } 151 152 /* ··· 157 { 158 int i; 159 160 + spin_lock(&ses->chan_lock); 161 for (i = 0; i < ses->chan_count; i++) { 162 + if (ses->chans[i].server == server) { 163 + spin_unlock(&ses->chan_lock); 164 return &ses->chans[i]; 165 + } 166 } 167 + spin_unlock(&ses->chan_lock); 168 return NULL; 169 } 170 ··· 168 cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, 169 struct cifs_server_iface *iface) 170 { 171 + struct TCP_Server_Info *chan_server; 172 struct cifs_chan *chan; 173 struct smb3_fs_context ctx = {NULL}; 174 static const char unc_fmt[] = "\\%s\\foo"; ··· 240 SMB2_CLIENT_GUID_SIZE); 241 ctx.use_client_guid = true; 242 243 + chan_server = cifs_get_tcp_session(&ctx, ses->server); 244 245 + mutex_lock(&ses->session_mutex); 246 + spin_lock(&ses->chan_lock); 247 chan = ses->binding_chan = &ses->chans[ses->chan_count]; 248 + chan->server = chan_server; 249 if (IS_ERR(chan->server)) { 250 rc = PTR_ERR(chan->server); 251 chan->server = NULL; 252 + spin_unlock(&ses->chan_lock); 253 goto out; 254 } 255 + spin_unlock(&ses->chan_lock); 256 257 /* 258 * We need to allocate the server crypto now as we will need ··· 283 * ses to the new server. 284 */ 285 286 + spin_lock(&ses->chan_lock); 287 ses->chan_count++; 288 atomic_set(&ses->chan_seq, 0); 289 + spin_unlock(&ses->chan_lock); 290 + 291 out: 292 ses->binding = false; 293 ses->binding_chan = NULL; ··· 599 return 0; 600 } 601 602 + static int size_of_ntlmssp_blob(struct cifs_ses *ses, int base_size) 603 + { 604 + int sz = base_size + ses->auth_key.len 605 + - CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2; 606 + 607 + if (ses->domainName) 608 + sz += sizeof(__le16) * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN); 609 + else 610 + sz += sizeof(__le16); 611 + 612 + if (ses->user_name) 613 + sz += sizeof(__le16) * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN); 614 + else 615 + sz += sizeof(__le16); 616 + 617 + sz += sizeof(__le16) * strnlen(ses->workstation_name, CIFS_MAX_WORKSTATION_LEN); 618 + 619 + return sz; 620 + } 621 + 622 + static inline void cifs_security_buffer_from_str(SECURITY_BUFFER *pbuf, 623 + char *str_value, 624 + int str_length, 625 + unsigned char *pstart, 626 + unsigned char **pcur, 627 + const struct nls_table *nls_cp) 628 + { 629 + unsigned char *tmp = pstart; 630 + int len; 631 + 632 + if (!pbuf) 633 + return; 634 + 635 + if (!pcur) 636 + pcur = &tmp; 637 + 638 + if (!str_value) { 639 + pbuf->BufferOffset = cpu_to_le32(*pcur - pstart); 640 + pbuf->Length = 0; 641 + pbuf->MaximumLength = 0; 642 + *pcur += sizeof(__le16); 643 + } else { 644 + len = cifs_strtoUTF16((__le16 *)*pcur, 645 + str_value, 646 + str_length, 647 + nls_cp); 648 + len *= sizeof(__le16); 649 + pbuf->BufferOffset = cpu_to_le32(*pcur - pstart); 650 + pbuf->Length = cpu_to_le16(len); 651 + pbuf->MaximumLength = cpu_to_le16(len); 652 + *pcur += len; 653 + } 654 + } 655 + 656 /* BB Move to ntlmssp.c eventually */ 657 658 + int build_ntlmssp_negotiate_blob(unsigned char **pbuffer, 659 + u16 *buflen, 660 + struct cifs_ses *ses, 661 + const struct nls_table *nls_cp) 662 { 663 + int rc = 0; 664 struct TCP_Server_Info *server = cifs_ses_server(ses); 665 + NEGOTIATE_MESSAGE *sec_blob; 666 __u32 flags; 667 + unsigned char *tmp; 668 + int len; 669 670 + len = size_of_ntlmssp_blob(ses, sizeof(NEGOTIATE_MESSAGE)); 671 + *pbuffer = kmalloc(len, GFP_KERNEL); 672 + if (!*pbuffer) { 673 + rc = -ENOMEM; 674 + cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc); 675 + *buflen = 0; 676 + goto setup_ntlm_neg_ret; 677 + } 678 + sec_blob = (NEGOTIATE_MESSAGE *)*pbuffer; 679 + 680 + memset(*pbuffer, 0, sizeof(NEGOTIATE_MESSAGE)); 681 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); 682 sec_blob->MessageType = NtLmNegotiate; 683 ··· 624 if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess) 625 flags |= NTLMSSP_NEGOTIATE_KEY_XCH; 626 627 + tmp = *pbuffer + sizeof(NEGOTIATE_MESSAGE); 628 sec_blob->NegotiateFlags = cpu_to_le32(flags); 629 630 + /* these fields should be null in negotiate phase MS-NLMP 3.1.5.1.1 */ 631 + cifs_security_buffer_from_str(&sec_blob->DomainName, 632 + NULL, 633 + CIFS_MAX_DOMAINNAME_LEN, 634 + *pbuffer, &tmp, 635 + nls_cp); 636 637 + cifs_security_buffer_from_str(&sec_blob->WorkstationName, 638 + NULL, 639 + CIFS_MAX_WORKSTATION_LEN, 640 + *pbuffer, &tmp, 641 + nls_cp); 642 643 + *buflen = tmp - *pbuffer; 644 + setup_ntlm_neg_ret: 645 + return rc; 646 } 647 648 int build_ntlmssp_auth_blob(unsigned char **pbuffer, ··· 663 AUTHENTICATE_MESSAGE *sec_blob; 664 __u32 flags; 665 unsigned char *tmp; 666 + int len; 667 668 rc = setup_ntlmv2_rsp(ses, nls_cp); 669 if (rc) { ··· 670 *buflen = 0; 671 goto setup_ntlmv2_ret; 672 } 673 + 674 + len = size_of_ntlmssp_blob(ses, sizeof(AUTHENTICATE_MESSAGE)); 675 + *pbuffer = kmalloc(len, GFP_KERNEL); 676 if (!*pbuffer) { 677 rc = -ENOMEM; 678 cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc); ··· 686 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | 687 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | 688 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC | 689 + NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED; 690 if (ses->server->sign) 691 flags |= NTLMSSP_NEGOTIATE_SIGN; 692 if (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess) ··· 719 sec_blob->NtChallengeResponse.MaximumLength = 0; 720 } 721 722 + cifs_security_buffer_from_str(&sec_blob->DomainName, 723 + ses->domainName, 724 + CIFS_MAX_DOMAINNAME_LEN, 725 + *pbuffer, &tmp, 726 + nls_cp); 727 728 + cifs_security_buffer_from_str(&sec_blob->UserName, 729 + ses->user_name, 730 + CIFS_MAX_USERNAME_LEN, 731 + *pbuffer, &tmp, 732 + nls_cp); 733 734 + cifs_security_buffer_from_str(&sec_blob->WorkstationName, 735 + ses->workstation_name, 736 + CIFS_MAX_WORKSTATION_LEN, 737 + *pbuffer, &tmp, 738 + nls_cp); 739 740 if (((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) || 741 (ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) ··· 1230 struct cifs_ses *ses = sess_data->ses; 1231 __u16 bytes_remaining; 1232 char *bcc_ptr; 1233 + unsigned char *ntlmsspblob = NULL; 1234 u16 blob_len; 1235 1236 cifs_dbg(FYI, "rawntlmssp session setup negotiate phase\n"); ··· 1253 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base; 1254 1255 /* Build security blob before we assemble the request */ 1256 + rc = build_ntlmssp_negotiate_blob(&ntlmsspblob, 1257 + &blob_len, ses, 1258 + sess_data->nls_cp); 1259 + if (rc) 1260 + goto out; 1261 + 1262 + sess_data->iov[1].iov_len = blob_len; 1263 + sess_data->iov[1].iov_base = ntlmsspblob; 1264 + pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len); 1265 1266 rc = _sess_auth_rawntlmssp_assemble_req(sess_data); 1267 if (rc)
+17 -5
fs/cifs/smb2inode.c
··· 46 struct smb2_file_link_info link_info; 47 }; 48 49 static int 50 smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, 51 struct cifs_sb_info *cifs_sb, const char *full_path, ··· 540 create_options |= OPEN_REPARSE_POINT; 541 542 /* Failed on a symbolic link - query a reparse point info */ 543 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 544 FILE_READ_ATTRIBUTES, FILE_OPEN, 545 create_options, ACL_NO_MODE, 546 - smb2_data, SMB2_OP_QUERY_INFO, NULL); 547 } 548 if (rc) 549 goto out; ··· 592 create_options |= OPEN_REPARSE_POINT; 593 594 /* Failed on a symbolic link - query a reparse point info */ 595 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 596 FILE_READ_ATTRIBUTES, FILE_OPEN, 597 create_options, ACL_NO_MODE, 598 - smb2_data, SMB2_OP_POSIX_QUERY_INFO, NULL); 599 } 600 if (rc) 601 goto out; ··· 713 struct cifs_sb_info *cifs_sb, bool set_alloc) 714 { 715 __le64 eof = cpu_to_le64(size); 716 717 return smb2_compound_op(xid, tcon, cifs_sb, full_path, 718 FILE_WRITE_DATA, FILE_OPEN, 0, ACL_NO_MODE, 719 - &eof, SMB2_OP_SET_EOF, NULL); 720 } 721 722 int ··· 727 { 728 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 729 struct tcon_link *tlink; 730 int rc; 731 732 if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) && ··· 739 tlink = cifs_sb_tlink(cifs_sb); 740 if (IS_ERR(tlink)) 741 return PTR_ERR(tlink); 742 743 - rc = smb2_compound_op(xid, tlink_tcon(tlink), cifs_sb, full_path, 744 FILE_WRITE_ATTRIBUTES, FILE_OPEN, 745 - 0, ACL_NO_MODE, buf, SMB2_OP_SET_INFO, NULL); 746 cifs_put_tlink(tlink); 747 return rc; 748 }
··· 46 struct smb2_file_link_info link_info; 47 }; 48 49 + /* 50 + * note: If cfile is passed, the reference to it is dropped here. 51 + * So make sure that you do not reuse cfile after return from this func. 52 + */ 53 static int 54 smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, 55 struct cifs_sb_info *cifs_sb, const char *full_path, ··· 536 create_options |= OPEN_REPARSE_POINT; 537 538 /* Failed on a symbolic link - query a reparse point info */ 539 + cifs_get_readable_path(tcon, full_path, &cfile); 540 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 541 FILE_READ_ATTRIBUTES, FILE_OPEN, 542 create_options, ACL_NO_MODE, 543 + smb2_data, SMB2_OP_QUERY_INFO, cfile); 544 } 545 if (rc) 546 goto out; ··· 587 create_options |= OPEN_REPARSE_POINT; 588 589 /* Failed on a symbolic link - query a reparse point info */ 590 + cifs_get_readable_path(tcon, full_path, &cfile); 591 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 592 FILE_READ_ATTRIBUTES, FILE_OPEN, 593 create_options, ACL_NO_MODE, 594 + smb2_data, SMB2_OP_POSIX_QUERY_INFO, cfile); 595 } 596 if (rc) 597 goto out; ··· 707 struct cifs_sb_info *cifs_sb, bool set_alloc) 708 { 709 __le64 eof = cpu_to_le64(size); 710 + struct cifsFileInfo *cfile; 711 712 + cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); 713 return smb2_compound_op(xid, tcon, cifs_sb, full_path, 714 FILE_WRITE_DATA, FILE_OPEN, 0, ACL_NO_MODE, 715 + &eof, SMB2_OP_SET_EOF, cfile); 716 } 717 718 int ··· 719 { 720 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 721 struct tcon_link *tlink; 722 + struct cifs_tcon *tcon; 723 + struct cifsFileInfo *cfile; 724 int rc; 725 726 if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) && ··· 729 tlink = cifs_sb_tlink(cifs_sb); 730 if (IS_ERR(tlink)) 731 return PTR_ERR(tlink); 732 + tcon = tlink_tcon(tlink); 733 734 + cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); 735 + rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 736 FILE_WRITE_ATTRIBUTES, FILE_OPEN, 737 + 0, ACL_NO_MODE, buf, SMB2_OP_SET_INFO, cfile); 738 cifs_put_tlink(tlink); 739 return rc; 740 }
+7 -3
fs/cifs/smb2ops.c
··· 2844 struct fsctl_get_dfs_referral_req *dfs_req = NULL; 2845 struct get_dfs_referral_rsp *dfs_rsp = NULL; 2846 u32 dfs_req_size = 0, dfs_rsp_size = 0; 2847 2848 cifs_dbg(FYI, "%s: path: %s\n", __func__, search_name); 2849 ··· 2896 true /* is_fsctl */, 2897 (char *)dfs_req, dfs_req_size, CIFSMaxBufSize, 2898 (char **)&dfs_rsp, &dfs_rsp_size); 2899 - } while (rc == -EAGAIN); 2900 2901 if (rc) { 2902 - if ((rc != -ENOENT) && (rc != -EOPNOTSUPP)) 2903 - cifs_tcon_dbg(VFS, "ioctl error in %s rc=%d\n", __func__, rc); 2904 goto out; 2905 } 2906
··· 2844 struct fsctl_get_dfs_referral_req *dfs_req = NULL; 2845 struct get_dfs_referral_rsp *dfs_rsp = NULL; 2846 u32 dfs_req_size = 0, dfs_rsp_size = 0; 2847 + int retry_count = 0; 2848 2849 cifs_dbg(FYI, "%s: path: %s\n", __func__, search_name); 2850 ··· 2895 true /* is_fsctl */, 2896 (char *)dfs_req, dfs_req_size, CIFSMaxBufSize, 2897 (char **)&dfs_rsp, &dfs_rsp_size); 2898 + if (!is_retryable_error(rc)) 2899 + break; 2900 + usleep_range(512, 2048); 2901 + } while (++retry_count < 5); 2902 2903 if (rc) { 2904 + if (!is_retryable_error(rc) && rc != -ENOENT && rc != -EOPNOTSUPP) 2905 + cifs_tcon_dbg(VFS, "%s: ioctl error: rc=%d\n", __func__, rc); 2906 goto out; 2907 } 2908
+37 -15
fs/cifs/smb2pdu.c
··· 155 if (tcon == NULL) 156 return 0; 157 158 - if (smb2_command == SMB2_TREE_CONNECT) 159 return 0; 160 161 if (tcon->tidStatus == CifsExiting) { ··· 257 /* 258 * If we are reconnecting an extra channel, bind 259 */ 260 - if (server->is_channel) { 261 ses->binding = true; 262 ses->binding_chan = cifs_ses_find_chan(ses, server); 263 } ··· 1460 int rc; 1461 struct cifs_ses *ses = sess_data->ses; 1462 struct smb2_sess_setup_rsp *rsp = NULL; 1463 - char *ntlmssp_blob = NULL; 1464 bool use_spnego = false; /* else use raw ntlmssp */ 1465 u16 blob_length = 0; 1466 ··· 1479 if (rc) 1480 goto out_err; 1481 1482 - ntlmssp_blob = kmalloc(sizeof(struct _NEGOTIATE_MESSAGE), 1483 - GFP_KERNEL); 1484 - if (ntlmssp_blob == NULL) { 1485 - rc = -ENOMEM; 1486 - goto out; 1487 - } 1488 1489 - build_ntlmssp_negotiate_blob(ntlmssp_blob, ses); 1490 if (use_spnego) { 1491 /* BB eventually need to add this */ 1492 cifs_dbg(VFS, "spnego not supported for SMB2 yet\n"); 1493 rc = -EOPNOTSUPP; 1494 goto out; 1495 - } else { 1496 - blob_length = sizeof(struct _NEGOTIATE_MESSAGE); 1497 - /* with raw NTLMSSP we don't encapsulate in SPNEGO */ 1498 } 1499 sess_data->iov[1].iov_base = ntlmssp_blob; 1500 sess_data->iov[1].iov_len = blob_length; ··· 1840 cifs_small_buf_release(req); 1841 rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base; 1842 trace_smb3_tcon(xid, tcon->tid, ses->Suid, tree, rc); 1843 - if (rc != 0) { 1844 cifs_stats_fail_inc(tcon, SMB2_TREE_CONNECT_HE); 1845 tcon->need_reconnect = true; 1846 goto tcon_error_exit; ··· 2668 goto err_free_rsp_buf; 2669 } 2670 2671 rsp = (struct smb2_create_rsp *)rsp_iov.iov_base; 2672 trace_smb3_posix_mkdir_done(xid, le64_to_cpu(rsp->PersistentFileId), 2673 tcon->tid, 2674 ses->Suid, CREATE_NOT_FILE, ··· 2952 tcon->need_reconnect = true; 2953 } 2954 goto creat_exit; 2955 - } else 2956 trace_smb3_open_done(xid, le64_to_cpu(rsp->PersistentFileId), 2957 tcon->tid, 2958 ses->Suid, oparms->create_options, ··· 3174 /* check if caller wants to look at return data or just return rc */ 3175 if ((plen == NULL) || (out_data == NULL)) 3176 goto ioctl_exit; 3177 3178 *plen = le32_to_cpu(rsp->OutputCount); 3179
··· 155 if (tcon == NULL) 156 return 0; 157 158 + /* 159 + * Need to also skip SMB2_IOCTL because it is used for checking nested dfs links in 160 + * cifs_tree_connect(). 161 + */ 162 + if (smb2_command == SMB2_TREE_CONNECT || smb2_command == SMB2_IOCTL) 163 return 0; 164 165 if (tcon->tidStatus == CifsExiting) { ··· 253 /* 254 * If we are reconnecting an extra channel, bind 255 */ 256 + if (CIFS_SERVER_IS_CHAN(server)) { 257 ses->binding = true; 258 ses->binding_chan = cifs_ses_find_chan(ses, server); 259 } ··· 1456 int rc; 1457 struct cifs_ses *ses = sess_data->ses; 1458 struct smb2_sess_setup_rsp *rsp = NULL; 1459 + unsigned char *ntlmssp_blob = NULL; 1460 bool use_spnego = false; /* else use raw ntlmssp */ 1461 u16 blob_length = 0; 1462 ··· 1475 if (rc) 1476 goto out_err; 1477 1478 + rc = build_ntlmssp_negotiate_blob(&ntlmssp_blob, 1479 + &blob_length, ses, 1480 + sess_data->nls_cp); 1481 + if (rc) 1482 + goto out_err; 1483 1484 if (use_spnego) { 1485 /* BB eventually need to add this */ 1486 cifs_dbg(VFS, "spnego not supported for SMB2 yet\n"); 1487 rc = -EOPNOTSUPP; 1488 goto out; 1489 } 1490 sess_data->iov[1].iov_base = ntlmssp_blob; 1491 sess_data->iov[1].iov_len = blob_length; ··· 1841 cifs_small_buf_release(req); 1842 rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base; 1843 trace_smb3_tcon(xid, tcon->tid, ses->Suid, tree, rc); 1844 + if ((rc != 0) || (rsp == NULL)) { 1845 cifs_stats_fail_inc(tcon, SMB2_TREE_CONNECT_HE); 1846 tcon->need_reconnect = true; 1847 goto tcon_error_exit; ··· 2669 goto err_free_rsp_buf; 2670 } 2671 2672 + /* 2673 + * Although unlikely to be possible for rsp to be null and rc not set, 2674 + * adding check below is slightly safer long term (and quiets Coverity 2675 + * warning) 2676 + */ 2677 rsp = (struct smb2_create_rsp *)rsp_iov.iov_base; 2678 + if (rsp == NULL) { 2679 + rc = -EIO; 2680 + kfree(pc_buf); 2681 + goto err_free_req; 2682 + } 2683 + 2684 trace_smb3_posix_mkdir_done(xid, le64_to_cpu(rsp->PersistentFileId), 2685 tcon->tid, 2686 ses->Suid, CREATE_NOT_FILE, ··· 2942 tcon->need_reconnect = true; 2943 } 2944 goto creat_exit; 2945 + } else if (rsp == NULL) /* unlikely to happen, but safer to check */ 2946 + goto creat_exit; 2947 + else 2948 trace_smb3_open_done(xid, le64_to_cpu(rsp->PersistentFileId), 2949 tcon->tid, 2950 ses->Suid, oparms->create_options, ··· 3162 /* check if caller wants to look at return data or just return rc */ 3163 if ((plen == NULL) || (out_data == NULL)) 3164 goto ioctl_exit; 3165 + 3166 + /* 3167 + * Although unlikely to be possible for rsp to be null and rc not set, 3168 + * adding check below is slightly safer long term (and quiets Coverity 3169 + * warning) 3170 + */ 3171 + if (rsp == NULL) { 3172 + rc = -EIO; 3173 + goto ioctl_exit; 3174 + } 3175 3176 *plen = le32_to_cpu(rsp->OutputCount); 3177
+3
fs/cifs/transport.c
··· 1044 if (!ses) 1045 return NULL; 1046 1047 if (!ses->binding) { 1048 /* round robin */ 1049 if (ses->chan_count > 1) { 1050 index = (uint)atomic_inc_return(&ses->chan_seq); 1051 index %= ses->chan_count; 1052 } 1053 return ses->chans[index].server; 1054 } else { 1055 return cifs_ses_server(ses); 1056 } 1057 }
··· 1044 if (!ses) 1045 return NULL; 1046 1047 + spin_lock(&ses->chan_lock); 1048 if (!ses->binding) { 1049 /* round robin */ 1050 if (ses->chan_count > 1) { 1051 index = (uint)atomic_inc_return(&ses->chan_seq); 1052 index %= ses->chan_count; 1053 } 1054 + spin_unlock(&ses->chan_lock); 1055 return ses->chans[index].server; 1056 } else { 1057 + spin_unlock(&ses->chan_lock); 1058 return cifs_ses_server(ses); 1059 } 1060 }