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 271 c = 0; 272 272 spin_lock(&cifs_tcp_ses_lock); 273 273 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { 274 - if (server->is_channel) 274 + /* channel info will be printed as a part of sessions below */ 275 + if (CIFS_SERVER_IS_CHAN(server)) 275 276 continue; 276 277 277 278 c++; ··· 359 358 seq_printf(m, " signed"); 360 359 if (server->posix_ext_supported) 361 360 seq_printf(m, " posix"); 361 + if (server->nosharesock) 362 + seq_printf(m, " nosharesock"); 362 363 363 364 if (server->rdma) 364 365 seq_printf(m, "\nRDMA "); ··· 415 412 from_kuid(&init_user_ns, ses->linux_uid), 416 413 from_kuid(&init_user_ns, ses->cred_uid)); 417 414 415 + spin_lock(&ses->chan_lock); 418 416 if (ses->chan_count > 1) { 419 417 seq_printf(m, "\n\n\tExtra Channels: %zu ", 420 418 ses->chan_count-1); 421 419 for (j = 1; j < ses->chan_count; j++) 422 420 cifs_dump_channel(m, j, &ses->chans[j]); 423 421 } 422 + spin_unlock(&ses->chan_lock); 424 423 425 424 seq_puts(m, "\n\n\tShares: "); 426 425 j = 0;
+2 -57
fs/cifs/cifs_dfs_ref.c
··· 307 307 static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt) 308 308 { 309 309 struct cifs_sb_info *cifs_sb; 310 - struct cifs_ses *ses; 311 - struct cifs_tcon *tcon; 312 310 void *page; 313 - char *full_path, *root_path; 314 - unsigned int xid; 315 - int rc; 311 + char *full_path; 316 312 struct vfsmount *mnt; 317 313 318 314 cifs_dbg(FYI, "in %s\n", __func__); ··· 320 324 * the double backslashes usually used in the UNC. This function 321 325 * gives us the latter, so we must adjust the result. 322 326 */ 323 - mnt = ERR_PTR(-ENOMEM); 324 - 325 327 cifs_sb = CIFS_SB(mntpt->d_sb); 326 328 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) { 327 329 mnt = ERR_PTR(-EREMOTE); ··· 335 341 } 336 342 337 343 convert_delimiter(full_path, '\\'); 338 - 339 344 cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path); 340 345 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 346 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); 347 + cifs_dbg(FYI, "%s: cifs_dfs_do_mount:%s , mnt:%p\n", __func__, full_path + 1, mnt); 389 348 390 - free_root_path: 391 - kfree(root_path); 392 349 free_full_path: 393 350 free_dentry_path(page); 394 351 cdda_exit:
-5
fs/cifs/cifs_fs_sb.h
··· 61 61 /* only used when CIFS_MOUNT_USE_PREFIX_PATH is set */ 62 62 char *prepath; 63 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 64 /* randomly generated 128-bit number for indexing dfs mount groups in referral cache */ 70 65 uuid_t dfs_mount_id; 71 66 /*
+44 -3
fs/cifs/cifsglob.h
··· 15 15 #include <linux/slab.h> 16 16 #include <linux/mempool.h> 17 17 #include <linux/workqueue.h> 18 + #include <linux/utsname.h> 18 19 #include "cifs_fs_sb.h" 19 20 #include "cifsacl.h" 20 21 #include <crypto/internal/hash.h> ··· 76 75 #define SMB_ECHO_INTERVAL_MAX 600 77 76 #define SMB_ECHO_INTERVAL_DEFAULT 60 78 77 79 - /* dns resolution interval in seconds */ 78 + /* dns resolution intervals in seconds */ 79 + #define SMB_DNS_RESOLVE_INTERVAL_MIN 120 80 80 #define SMB_DNS_RESOLVE_INTERVAL_DEFAULT 600 81 81 82 82 /* maximum number of PDUs in one compound */ ··· 100 98 #ifndef XATTR_DOS_ATTRIB 101 99 #define XATTR_DOS_ATTRIB "user.DOSATTRIB" 102 100 #endif 101 + 102 + #define CIFS_MAX_WORKSTATION_LEN (__NEW_UTS_LEN + 1) /* reasonable max for client */ 103 103 104 104 /* 105 105 * CIFS vfs client Status information (based on what we know.) ··· 596 592 struct list_head pending_mid_q; 597 593 bool noblocksnd; /* use blocking sendmsg */ 598 594 bool noautotune; /* do not autotune send buf sizes */ 595 + bool nosharesock; 599 596 bool tcp_nodelay; 600 597 unsigned int credits; /* send no more requests at once */ 601 598 unsigned int max_credits; /* can override large 32000 default at mnt */ ··· 690 685 */ 691 686 int nr_targets; 692 687 bool noblockcnt; /* use non-blocking connect() */ 693 - bool is_channel; /* if a session channel */ 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 + 694 697 #ifdef CONFIG_CIFS_SWN_UPCALL 695 698 bool use_swn_dstaddr; 696 699 struct sockaddr_storage swn_dstaddr; 697 700 #endif 698 701 #ifdef CONFIG_CIFS_DFS_UPCALL 699 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; 700 716 #endif 701 717 }; 702 718 ··· 934 908 and after mount option parsing we fill it */ 935 909 char *domainName; 936 910 char *password; 911 + char *workstation_name; 937 912 struct session_key auth_key; 938 913 struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */ 939 914 enum securityEnum sectype; /* what security flavor was specified? */ ··· 960 933 * iface_lock should be taken when accessing any of these fields 961 934 */ 962 935 spinlock_t iface_lock; 936 + /* ========= begin: protected by iface_lock ======== */ 963 937 struct cifs_server_iface *iface_list; 964 938 size_t iface_count; 965 939 unsigned long iface_last_update; /* jiffies */ 940 + /* ========= end: protected by iface_lock ======== */ 966 941 942 + spinlock_t chan_lock; 943 + /* ========= begin: protected by chan_lock ======== */ 967 944 #define CIFS_MAX_CHANNELS 16 968 945 struct cifs_chan chans[CIFS_MAX_CHANNELS]; 969 946 struct cifs_chan *binding_chan; 970 947 size_t chan_count; 971 948 size_t chan_max; 972 949 atomic_t chan_seq; /* round robin state */ 950 + /* ========= end: protected by chan_lock ======== */ 973 951 }; 974 952 975 953 /* ··· 1123 1091 struct cached_fid crfid; /* Cached root fid */ 1124 1092 /* BB add field for back pointer to sb struct(s)? */ 1125 1093 #ifdef CONFIG_CIFS_DFS_UPCALL 1126 - char *dfs_path; /* canonical DFS path */ 1127 1094 struct list_head ulist; /* cache update list */ 1128 1095 #endif 1129 1096 }; ··· 1971 1940 return false; 1972 1941 return is_smb1_server(tcon->ses->server) ? tcon->Flags & SMB_SHARE_IS_IN_DFS : 1973 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)); 1974 1953 } 1975 1954 1976 1955 #endif /* _CIFS_GLOB_H */
+7 -3
fs/cifs/cifsproto.h
··· 269 269 270 270 extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon, 271 271 const char *path); 272 - 273 - extern struct TCP_Server_Info *cifs_get_tcp_session(struct smb3_fs_context *ctx); 272 + extern struct TCP_Server_Info * 273 + cifs_get_tcp_session(struct smb3_fs_context *ctx, 274 + struct TCP_Server_Info *primary_server); 274 275 extern void cifs_put_tcp_session(struct TCP_Server_Info *server, 275 276 int from_reconnect); 276 277 extern void cifs_put_tcon(struct cifs_tcon *tcon); ··· 608 607 609 608 struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server); 610 609 void cifs_put_tcp_super(struct super_block *sb); 611 - int update_super_prepath(struct cifs_tcon *tcon, char *prefix); 610 + int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix); 612 611 char *extract_hostname(const char *unc); 613 612 char *extract_sharename(const char *unc); 614 613 ··· 634 633 else 635 634 return options; 636 635 } 636 + 637 + struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon); 638 + void cifs_put_tcon_super(struct super_block *sb); 637 639 638 640 #endif /* _CIFSPROTO_H */
+816 -708
fs/cifs/connect.c
··· 61 61 /* Drop the connection to not overload the server */ 62 62 #define NUM_STATUS_IO_TIMEOUT 5 63 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 + 64 78 static int ip_connect(struct TCP_Server_Info *server); 65 79 static int generic_ip_connect(struct TCP_Server_Info *server); 66 80 static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); ··· 129 115 * To make sure we don't use the cached entry, retry 1s 130 116 * after expiry. 131 117 */ 132 - ttl = (expiry - now + 1); 118 + ttl = max_t(unsigned long, expiry - now, SMB_DNS_RESOLVE_INTERVAL_MIN) + 1; 133 119 } 134 120 rc = !rc ? -1 : 0; 135 121 ··· 162 148 mutex_unlock(&server->srv_mutex); 163 149 } 164 150 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 151 + /** 152 + * Mark all sessions and tcons for reconnect. 218 153 * 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) 154 + * @server needs to be previously set to CifsNeedReconnect. 223 155 */ 224 - int 225 - cifs_reconnect(struct TCP_Server_Info *server) 156 + static void cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server) 226 157 { 227 - int rc = 0; 228 - struct list_head *tmp, *tmp2; 229 158 struct cifs_ses *ses; 230 159 struct cifs_tcon *tcon; 231 - struct mid_q_entry *mid_entry; 160 + struct mid_q_entry *mid, *nmid; 232 161 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 162 + struct TCP_Server_Info *pserver; 239 163 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 164 server->maxBuf = 0; 281 165 server->max_read = 0; 282 166 283 167 cifs_dbg(FYI, "Mark tcp session as need reconnect\n"); 284 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__); 285 174 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__); 175 + /* If server is a channel, select the primary channel */ 176 + pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server; 177 + 290 178 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); 179 + list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { 293 180 ses->need_reconnect = true; 294 - list_for_each(tmp2, &ses->tcon_list) { 295 - tcon = list_entry(tmp2, struct cifs_tcon, tcon_list); 181 + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) 296 182 tcon->need_reconnect = true; 297 - } 298 183 if (ses->tcon_ipc) 299 184 ses->tcon_ipc->need_reconnect = true; 300 185 } ··· 203 290 cifs_dbg(FYI, "%s: tearing down socket\n", __func__); 204 291 mutex_lock(&server->srv_mutex); 205 292 if (server->ssocket) { 206 - cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n", 207 - server->ssocket->state, server->ssocket->flags); 293 + cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n", server->ssocket->state, 294 + server->ssocket->flags); 208 295 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); 296 + cifs_dbg(FYI, "Post shutdown state: 0x%x Flags: 0x%lx\n", server->ssocket->state, 297 + server->ssocket->flags); 211 298 sock_release(server->ssocket); 212 299 server->ssocket = NULL; 213 300 } ··· 222 309 INIT_LIST_HEAD(&retry_list); 223 310 cifs_dbg(FYI, "%s: moving mids to private list\n", __func__); 224 311 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; 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; 232 318 } 233 319 spin_unlock(&GlobalMid_Lock); 234 320 mutex_unlock(&server->srv_mutex); 235 321 236 322 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); 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); 242 327 } 243 328 244 329 if (cifs_rdma_enabled(server)) { ··· 244 333 smbd_destroy(server); 245 334 mutex_unlock(&server->srv_mutex); 246 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); 247 369 248 370 do { 249 371 try_to_freeze(); 250 - 251 372 mutex_lock(&server->srv_mutex); 252 373 253 - 254 374 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 - */ 375 + /* resolve the hostname again to make sure that IP address is up-to-date */ 268 376 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 - 377 + cifs_dbg(FYI, "%s: reconn_set_ipaddr_from_hostname: rc=%d\n", __func__, rc); 279 378 } 280 379 281 380 if (cifs_rdma_enabled(server)) ··· 293 372 else 294 373 rc = generic_ip_connect(server); 295 374 if (rc) { 296 - cifs_dbg(FYI, "reconnect error %d\n", rc); 297 375 mutex_unlock(&server->srv_mutex); 376 + cifs_dbg(FYI, "%s: reconnect error %d\n", __func__, rc); 298 377 msleep(3000); 299 378 } else { 300 379 atomic_inc(&tcpSesReconnectCount); ··· 308 387 } 309 388 } while (server->tcpStatus == CifsNeedReconnect); 310 389 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 390 if (server->tcpStatus == CifsNeedNegotiate) 325 391 mod_delayed_work(cifsiod_wq, &server->echo, 0); 326 392 327 393 wake_up(&server->response_q); 328 394 return rc; 329 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 330 537 331 538 static void 332 539 cifs_echo_request(struct work_struct *work) ··· 714 665 * Trying to handle/dequeue a mid after the send_recv() 715 666 * function has finished processing it is a bug. 716 667 */ 717 - if (mid->mid_flags & MID_DELETED) 668 + if (mid->mid_flags & MID_DELETED) { 669 + spin_unlock(&GlobalMid_Lock); 718 670 pr_warn_once("trying to dequeue a deleted mid\n"); 719 - else { 671 + } else { 720 672 list_del_init(&mid->qhead); 721 673 mid->mid_flags |= MID_DELETED; 674 + spin_unlock(&GlobalMid_Lock); 722 675 } 723 - spin_unlock(&GlobalMid_Lock); 724 676 } 725 677 726 678 static unsigned int ··· 844 794 */ 845 795 } 846 796 797 + #ifdef CONFIG_CIFS_DFS_UPCALL 798 + kfree(server->origin_fullpath); 799 + kfree(server->leaf_fullpath); 800 + #endif 847 801 kfree(server); 848 802 849 803 length = atomic_dec_return(&tcpSesAllocCount); ··· 1271 1217 { 1272 1218 struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr; 1273 1219 1274 - if (ctx->nosharesock) 1220 + if (ctx->nosharesock) { 1221 + server->nosharesock = true; 1222 + return 0; 1223 + } 1224 + 1225 + /* this server does not share socket */ 1226 + if (server->nosharesock) 1275 1227 return 0; 1276 1228 1277 1229 /* If multidialect negotiation see if existing sessions match one */ ··· 1343 1283 * Skip ses channels since they're only handled in lower layers 1344 1284 * (e.g. cifs_send_recv). 1345 1285 */ 1346 - if (server->is_channel || !match_server(server, ctx)) 1286 + if (CIFS_SERVER_IS_CHAN(server) || !match_server(server, ctx)) 1347 1287 continue; 1348 1288 1349 1289 ++server->srv_count; ··· 1374 1314 list_del_init(&server->tcp_ses_list); 1375 1315 spin_unlock(&cifs_tcp_ses_lock); 1376 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 + 1377 1321 cancel_delayed_work_sync(&server->echo); 1378 1322 cancel_delayed_work_sync(&server->resolve); 1379 1323 ··· 1397 1333 spin_unlock(&GlobalMid_Lock); 1398 1334 1399 1335 cifs_crypto_secmech_release(server); 1400 - cifs_fscache_release_client_cookie(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); 1401 1340 1402 1341 kfree(server->session_key.response); 1403 1342 server->session_key.response = NULL; ··· 1413 1346 } 1414 1347 1415 1348 struct TCP_Server_Info * 1416 - cifs_get_tcp_session(struct smb3_fs_context *ctx) 1349 + cifs_get_tcp_session(struct smb3_fs_context *ctx, 1350 + struct TCP_Server_Info *primary_server) 1417 1351 { 1418 1352 struct TCP_Server_Info *tcp_ses = NULL; 1419 1353 int rc; ··· 1451 1383 tcp_ses->in_flight = 0; 1452 1384 tcp_ses->max_in_flight = 0; 1453 1385 tcp_ses->credits = 1; 1386 + if (primary_server) { 1387 + ++primary_server->srv_count; 1388 + tcp_ses->primary_server = primary_server; 1389 + } 1454 1390 init_waitqueue_head(&tcp_ses->response_q); 1455 1391 init_waitqueue_head(&tcp_ses->request_q); 1456 1392 INIT_LIST_HEAD(&tcp_ses->pending_mid_q); ··· 1475 1403 INIT_DELAYED_WORK(&tcp_ses->resolve, cifs_resolve_server); 1476 1404 INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server); 1477 1405 mutex_init(&tcp_ses->reconnect_mutex); 1406 + #ifdef CONFIG_CIFS_DFS_UPCALL 1407 + mutex_init(&tcp_ses->refpath_lock); 1408 + #endif 1478 1409 memcpy(&tcp_ses->srcaddr, &ctx->srcaddr, 1479 1410 sizeof(tcp_ses->srcaddr)); 1480 1411 memcpy(&tcp_ses->dstaddr, &ctx->dstaddr, ··· 1556 1481 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list); 1557 1482 spin_unlock(&cifs_tcp_ses_lock); 1558 1483 1559 - cifs_fscache_get_client_cookie(tcp_ses); 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); 1560 1487 1561 1488 /* queue echo request delayed work */ 1562 1489 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval); ··· 1578 1501 1579 1502 out_err: 1580 1503 if (tcp_ses) { 1504 + if (CIFS_SERVER_IS_CHAN(tcp_ses)) 1505 + cifs_put_tcp_session(tcp_ses->primary_server, false); 1581 1506 kfree(tcp_ses->hostname); 1582 1507 if (tcp_ses->ssocket) 1583 1508 sock_release(tcp_ses->ssocket); ··· 1598 1519 * If an existing session is limited to less channels than 1599 1520 * requested, it should not be reused 1600 1521 */ 1601 - if (ses->chan_max < ctx->max_channels) 1522 + spin_lock(&ses->chan_lock); 1523 + if (ses->chan_max < ctx->max_channels) { 1524 + spin_unlock(&ses->chan_lock); 1602 1525 return 0; 1526 + } 1527 + spin_unlock(&ses->chan_lock); 1603 1528 1604 1529 switch (ses->sectype) { 1605 1530 case Kerberos: ··· 1738 1655 void cifs_put_smb_ses(struct cifs_ses *ses) 1739 1656 { 1740 1657 unsigned int rc, xid; 1658 + unsigned int chan_count; 1741 1659 struct TCP_Server_Info *server = ses->server; 1742 1660 cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count); 1743 1661 ··· 1780 1696 list_del_init(&ses->smb_ses_list); 1781 1697 spin_unlock(&cifs_tcp_ses_lock); 1782 1698 1699 + spin_lock(&ses->chan_lock); 1700 + chan_count = ses->chan_count; 1701 + spin_unlock(&ses->chan_lock); 1702 + 1783 1703 /* close any extra channels */ 1784 - if (ses->chan_count > 1) { 1704 + if (chan_count > 1) { 1785 1705 int i; 1786 1706 1787 - for (i = 1; i < ses->chan_count; i++) 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 + */ 1788 1714 cifs_put_tcp_session(ses->chans[i].server, 0); 1715 + ses->chans[i].server = NULL; 1716 + } 1789 1717 } 1790 1718 1791 1719 sesInfoFree(ses); ··· 1981 1885 ses->status); 1982 1886 1983 1887 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 1888 if (ses->need_reconnect) { 1993 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 + 1994 1900 rc = cifs_setup_session(xid, ses, 1995 1901 ctx->local_nls); 1996 1902 if (rc) { ··· 2040 1942 if (!ses->domainName) 2041 1943 goto get_ses_fail; 2042 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 + } 2043 1951 if (ctx->domainauto) 2044 1952 ses->domainAuto = ctx->domainauto; 2045 1953 ses->cred_uid = ctx->cred_uid; ··· 2056 1952 mutex_lock(&ses->session_mutex); 2057 1953 2058 1954 /* add server as first channel */ 1955 + spin_lock(&ses->chan_lock); 2059 1956 ses->chans[0].server = server; 2060 1957 ses->chan_count = 1; 2061 1958 ses->chan_max = ctx->multichannel ? ctx->max_channels:1; 1959 + spin_unlock(&ses->chan_lock); 2062 1960 2063 1961 rc = cifs_negotiate_protocol(xid, ses); 2064 1962 if (!rc) ··· 2391 2285 spin_lock(&cifs_tcp_ses_lock); 2392 2286 list_add(&tcon->tcon_list, &ses->tcon_list); 2393 2287 spin_unlock(&cifs_tcp_ses_lock); 2394 - 2395 - cifs_fscache_get_super_cookie(tcon); 2396 2288 2397 2289 return tcon; 2398 2290 ··· 2953 2849 } 2954 2850 2955 2851 /* 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) 2852 + static inline void mount_put_conns(struct mount_ctx *mnt_ctx) 2960 2853 { 2961 2854 int rc = 0; 2962 2855 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); 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); 2971 2864 } 2972 2865 2973 2866 /* 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) 2867 + static int mount_get_conns(struct mount_ctx *mnt_ctx) 2978 2868 { 2979 2869 int rc = 0; 2980 - struct TCP_Server_Info *server; 2981 - struct cifs_ses *ses; 2982 - struct cifs_tcon *tcon; 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; 2983 2876 2984 - *nserver = NULL; 2985 - *nses = NULL; 2986 - *ntcon = NULL; 2987 - 2988 - *xid = get_xid(); 2877 + xid = get_xid(); 2989 2878 2990 2879 /* get a reference to a tcp session */ 2991 - server = cifs_get_tcp_session(ctx); 2880 + server = cifs_get_tcp_session(ctx, NULL); 2992 2881 if (IS_ERR(server)) { 2993 2882 rc = PTR_ERR(server); 2994 - return rc; 2883 + server = NULL; 2884 + goto out; 2995 2885 } 2996 - 2997 - *nserver = server; 2998 2886 2999 2887 /* get a reference to a SMB session */ 3000 2888 ses = cifs_get_smb_ses(server, ctx); 3001 2889 if (IS_ERR(ses)) { 3002 2890 rc = PTR_ERR(ses); 3003 - return rc; 2891 + ses = NULL; 2892 + goto out; 3004 2893 } 3005 - 3006 - *nses = ses; 3007 2894 3008 2895 if ((ctx->persistent == true) && (!(ses->server->capabilities & 3009 2896 SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) { 3010 2897 cifs_server_dbg(VFS, "persistent handles not supported by server\n"); 3011 - return -EOPNOTSUPP; 2898 + rc = -EOPNOTSUPP; 2899 + goto out; 3012 2900 } 3013 2901 3014 2902 /* search for existing tcon to this server share */ 3015 2903 tcon = cifs_get_tcon(ses, ctx); 3016 2904 if (IS_ERR(tcon)) { 3017 2905 rc = PTR_ERR(tcon); 3018 - return rc; 2906 + tcon = NULL; 2907 + goto out; 3019 2908 } 3020 - 3021 - *ntcon = tcon; 3022 2909 3023 2910 /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */ 3024 2911 if (tcon->posix_extensions) ··· 3021 2926 * reset of caps checks mount to see if unix extensions disabled 3022 2927 * for just this mount. 3023 2928 */ 3024 - reset_cifs_unix_caps(*xid, tcon, cifs_sb, ctx); 2929 + reset_cifs_unix_caps(xid, tcon, cifs_sb, ctx); 3025 2930 if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) && 3026 2931 (le64_to_cpu(tcon->fsUnixInfo.Capability) & 3027 - CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) 3028 - return -EACCES; 2932 + CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) { 2933 + rc = -EACCES; 2934 + goto out; 2935 + } 3029 2936 } else 3030 2937 tcon->unix_ext = 0; /* server does not support them */ 3031 2938 3032 2939 /* do not care if a following call succeed - informational */ 3033 2940 if (!tcon->pipe && server->ops->qfs_tcon) { 3034 - server->ops->qfs_tcon(*xid, tcon, cifs_sb); 2941 + server->ops->qfs_tcon(xid, tcon, cifs_sb); 3035 2942 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) { 3036 2943 if (tcon->fsDevInfo.DeviceCharacteristics & 3037 2944 cpu_to_le32(FILE_READ_ONLY_DEVICE)) ··· 3043 2946 cifs_dbg(VFS, "read only mount of RW share\n"); 3044 2947 /* no need to log a RW mount of a typical RW share */ 3045 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); 3046 2955 } 3047 2956 3048 2957 /* ··· 3063 2960 (cifs_sb->ctx->rsize > server->ops->negotiate_rsize(tcon, ctx))) 3064 2961 cifs_sb->ctx->rsize = server->ops->negotiate_rsize(tcon, ctx); 3065 2962 3066 - return 0; 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; 3067 2970 } 3068 2971 3069 2972 static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, ··· 3099 2990 } 3100 2991 3101 2992 #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) 2993 + /* Get unique dfs connections */ 2994 + static int mount_get_dfs_conns(struct mount_ctx *mnt_ctx) 3105 2995 { 3106 2996 int rc; 3107 2997 3108 - ctx->nosharesock = true; 3109 - rc = mount_get_conns(ctx, cifs_sb, xid, nserver, nses, ntcon); 3110 - if (*nserver) { 2998 + mnt_ctx->fs_ctx->nosharesock = true; 2999 + rc = mount_get_conns(mnt_ctx); 3000 + if (mnt_ctx->server) { 3111 3001 cifs_dbg(FYI, "%s: marking tcp session as a dfs connection\n", __func__); 3112 3002 spin_lock(&cifs_tcp_ses_lock); 3113 - (*nserver)->is_dfs_conn = true; 3003 + mnt_ctx->server->is_dfs_conn = true; 3114 3004 spin_unlock(&cifs_tcp_ses_lock); 3115 3005 } 3116 3006 return rc; ··· 3151 3043 } 3152 3044 3153 3045 /* 3154 - * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb 3046 + * expand_dfs_referral - Update cifs_sb from dfs referral path 3155 3047 * 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. 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. 3162 3050 */ 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) 3051 + static int expand_dfs_referral(struct mount_ctx *mnt_ctx, const char *full_path, 3052 + struct dfs_info3_param *referral) 3167 3053 { 3168 3054 int rc; 3169 - struct dfs_info3_param referral = {0}; 3170 - char *full_path = NULL, *mdata = NULL; 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; 3171 3058 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); 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 { 3326 3065 /* 3327 - * Update DFS target hint in DFS referral cache with the target server we 3328 - * successfully reconnected to. 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. 3329 3069 */ 3330 - rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses, cifs_sb->local_nls, 3331 - cifs_remap(cifs_sb), path, tgt_it); 3070 + kfree(ctx->prepath); 3071 + ctx->prepath = NULL; 3072 + rc = cifs_setup_volume_info(ctx, mdata, fake_devname); 3332 3073 } 3074 + kfree(fake_devname); 3075 + kfree(cifs_sb->ctx->mount_options); 3076 + cifs_sb->ctx->mount_options = mdata; 3333 3077 3334 - out: 3335 - kfree(npath); 3336 - smb3_cleanup_fs_context_contents(&tmp_ctx); 3337 - dfs_cache_free_tgts(&tgt_list); 3338 3078 return rc; 3339 3079 } 3340 3080 #endif ··· 3289 3333 * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is, 3290 3334 * otherwise 0. 3291 3335 */ 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) 3336 + static int is_path_remote(struct mount_ctx *mnt_ctx) 3296 3337 { 3297 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; 3298 3344 char *full_path; 3299 3345 3300 3346 if (!server->ops->is_path_accessible) ··· 3334 3376 } 3335 3377 3336 3378 #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) 3379 + static void set_root_ses(struct mount_ctx *mnt_ctx) 3339 3380 { 3340 - if (ses) { 3381 + if (mnt_ctx->ses) { 3341 3382 spin_lock(&cifs_tcp_ses_lock); 3342 - ses->ses_count++; 3383 + mnt_ctx->ses->ses_count++; 3343 3384 spin_unlock(&cifs_tcp_ses_lock); 3344 - dfs_cache_add_refsrv_session(mount_id, ses); 3385 + dfs_cache_add_refsrv_session(&mnt_ctx->mount_id, mnt_ctx->ses); 3345 3386 } 3346 - *root_ses = ses; 3387 + mnt_ctx->root_ses = mnt_ctx->ses; 3347 3388 } 3348 3389 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) 3390 + static int is_dfs_mount(struct mount_ctx *mnt_ctx, bool *isdfs, struct dfs_cache_tgt_list *root_tl) 3396 3391 { 3397 3392 int rc; 3398 - struct dfs_info3_param ref = {0}; 3393 + struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb; 3394 + struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; 3399 3395 3400 - cifs_dbg(FYI, "%s: ref_path=%s\n", __func__, ref_path); 3396 + *isdfs = true; 3401 3397 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); 3398 + rc = mount_get_conns(mnt_ctx); 3442 3399 /* 3443 3400 * If called with 'nodfs' mount option, then skip DFS resolving. Otherwise unconditionally 3444 3401 * try to get an DFS referral (even cached) to determine whether it is an DFS mount. ··· 3362 3489 * to respond with PATH_NOT_COVERED to requests that include the prefix. 3363 3490 */ 3364 3491 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)) { 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)) { 3367 3494 if (rc) 3368 - goto error; 3495 + return rc; 3369 3496 /* Check if it is fully accessible and then mount it */ 3370 - rc = is_path_remote(cifs_sb, ctx, xid, server, tcon); 3497 + rc = is_path_remote(mnt_ctx); 3371 3498 if (!rc) 3372 - goto out; 3373 - if (rc != -EREMOTE) 3374 - goto error; 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); 3375 3532 } 3376 3533 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); 3534 + out: 3535 + free_dfs_info_param(&ref); 3536 + return rc; 3537 + } 3383 3538 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; 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; 3390 3564 } 3391 3565 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; 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; 3401 3574 break; 3402 3575 } 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; 3576 + } 3422 3577 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)); 3578 + out: 3450 3579 kfree(full_path); 3451 - full_path = NULL; 3580 + return rc; 3581 + } 3452 3582 3453 - if (IS_ERR(ref_path)) { 3454 - rc = PTR_ERR(ref_path); 3455 - ref_path = NULL; 3456 - goto error; 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; 3457 3603 } 3458 - cifs_sb->origin_fullpath = ref_path; 3459 3604 3460 - ref_path = kstrdup(cifs_sb->origin_fullpath, GFP_KERNEL); 3461 - if (!ref_path) { 3462 - rc = -ENOMEM; 3463 - goto error; 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 + } 3464 3619 } 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 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); 3470 3697 /* 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). 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). 3474 3700 */ 3475 3701 cifs_autodisable_serverino(cifs_sb); 3476 3702 /* 3477 - * Force the use of prefix path to support failover on DFS paths that 3478 - * resolve to targets that have different prefix paths. 3703 + * Force the use of prefix path to support failover on DFS paths that resolve to targets 3704 + * that have different prefix paths. 3479 3705 */ 3480 3706 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; 3481 3707 kfree(cifs_sb->prepath); 3482 3708 cifs_sb->prepath = ctx->prepath; 3483 3709 ctx->prepath = NULL; 3484 - uuid_copy(&cifs_sb->dfs_mount_id, &mount_id); 3710 + uuid_copy(&cifs_sb->dfs_mount_id, &mnt_ctx.mount_id); 3485 3711 3486 3712 out: 3487 - free_xid(xid); 3488 - cifs_try_adding_channels(cifs_sb, ses); 3489 - return mount_setup_tlink(cifs_sb, ses, tcon); 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); 3490 3716 3491 3717 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); 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); 3497 3722 return rc; 3498 3723 } 3499 3724 #else 3500 3725 int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx) 3501 3726 { 3502 3727 int rc = 0; 3503 - unsigned int xid; 3504 - struct cifs_ses *ses; 3505 - struct cifs_tcon *tcon; 3506 - struct TCP_Server_Info *server; 3728 + struct mount_ctx mnt_ctx = { .cifs_sb = cifs_sb, .fs_ctx = ctx, }; 3507 3729 3508 - rc = mount_get_conns(ctx, cifs_sb, &xid, &server, &ses, &tcon); 3730 + rc = mount_get_conns(&mnt_ctx); 3509 3731 if (rc) 3510 3732 goto error; 3511 3733 3512 - if (tcon) { 3513 - rc = is_path_remote(cifs_sb, ctx, xid, server, tcon); 3734 + if (mnt_ctx.tcon) { 3735 + rc = is_path_remote(&mnt_ctx); 3514 3736 if (rc == -EREMOTE) 3515 3737 rc = -EOPNOTSUPP; 3516 3738 if (rc) 3517 3739 goto error; 3518 3740 } 3519 3741 3520 - free_xid(xid); 3521 - 3522 - return mount_setup_tlink(cifs_sb, ses, tcon); 3742 + free_xid(mnt_ctx.xid); 3743 + return mount_setup_tlink(cifs_sb, mnt_ctx.ses, mnt_ctx.tcon); 3523 3744 3524 3745 error: 3525 - mount_put_conns(cifs_sb, xid, server, ses, tcon); 3746 + mount_put_conns(&mnt_ctx); 3526 3747 return rc; 3527 3748 } 3528 3749 #endif ··· 3785 3818 kfree(cifs_sb->prepath); 3786 3819 #ifdef CONFIG_CIFS_DFS_UPCALL 3787 3820 dfs_cache_put_refsrv_sessions(&cifs_sb->dfs_mount_id); 3788 - kfree(cifs_sb->origin_fullpath); 3789 3821 #endif 3790 3822 call_rcu(&cifs_sb->rcu, delayed_free); 3791 3823 } ··· 4111 4145 } 4112 4146 4113 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 + 4114 4343 int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc) 4115 4344 { 4116 4345 int rc; 4117 4346 struct TCP_Server_Info *server = tcon->ses->server; 4118 4347 const struct smb_version_operations *ops = server->ops; 4119 - struct dfs_cache_tgt_list tl; 4120 - struct dfs_cache_tgt_iterator *it = NULL; 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); 4121 4351 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 4352 struct dfs_info3_param ref = {0}; 4128 - bool isroot; 4129 4353 4130 4354 tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL); 4131 4355 if (!tree) 4132 4356 return -ENOMEM; 4133 4357 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 - } 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); 4142 4361 goto out; 4143 4362 } 4144 4363 4145 - isroot = ref.server_type == DFS_TYPE_ROOT; 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); 4146 4382 free_dfs_info_param(&ref); 4147 4383 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 4384 out: 4211 4385 kfree(tree); 4386 + cifs_put_tcp_super(sb); 4387 + 4212 4388 return rc; 4213 4389 } 4214 4390 #else
+37 -9
fs/cifs/dfs_cache.c
··· 283 283 seq_printf(m, 284 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 285 ce->path, ce->srvtype == DFS_TYPE_ROOT ? "root" : "link", 286 - ce->ttl, ce->etime.tv_nsec, ce->ref_flags, ce->hdr_flags, 286 + ce->ttl, ce->etime.tv_nsec, ce->hdr_flags, ce->ref_flags, 287 287 IS_DFS_INTERLINK(ce->hdr_flags) ? "yes" : "no", 288 288 ce->path_consumed, cache_entry_expired(ce) ? "yes" : "no"); 289 289 ··· 1364 1364 } 1365 1365 1366 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) 1367 + static int __refresh_tcon(const char *path, struct cifs_ses **sessions, struct cifs_tcon *tcon, 1368 + bool force_refresh) 1368 1369 { 1369 - const char *path = tcon->dfs_path + 1; 1370 1370 struct cifs_ses *ses; 1371 1371 struct cache_entry *ce; 1372 1372 struct dfs_info3_param *refs = NULL; ··· 1422 1422 return rc; 1423 1423 } 1424 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 + 1425 1439 /** 1426 1440 * dfs_cache_remount_fs - remount a DFS share 1427 1441 * ··· 1449 1435 int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb) 1450 1436 { 1451 1437 struct cifs_tcon *tcon; 1438 + struct TCP_Server_Info *server; 1452 1439 struct mount_group *mg; 1453 1440 struct cifs_ses *sessions[CACHE_MAX_ENTRIES + 1] = {NULL}; 1454 1441 int rc; ··· 1458 1443 return -EINVAL; 1459 1444 1460 1445 tcon = cifs_sb_master_tcon(cifs_sb); 1461 - if (!tcon->dfs_path) { 1462 - cifs_dbg(FYI, "%s: not a dfs tcon\n", __func__); 1446 + server = tcon->ses->server; 1447 + 1448 + if (!server->origin_fullpath) { 1449 + cifs_dbg(FYI, "%s: not a dfs mount\n", __func__); 1463 1450 return 0; 1464 1451 } 1465 1452 1466 1453 if (uuid_is_null(&cifs_sb->dfs_mount_id)) { 1467 - cifs_dbg(FYI, "%s: tcon has no dfs mount group id\n", __func__); 1454 + cifs_dbg(FYI, "%s: no dfs mount group id\n", __func__); 1468 1455 return -EINVAL; 1469 1456 } 1470 1457 ··· 1474 1457 mg = find_mount_group_locked(&cifs_sb->dfs_mount_id); 1475 1458 if (IS_ERR(mg)) { 1476 1459 mutex_unlock(&mount_group_list_lock); 1477 - cifs_dbg(FYI, "%s: tcon has ipc session to refresh referral\n", __func__); 1460 + cifs_dbg(FYI, "%s: no ipc session for refreshing referral\n", __func__); 1478 1461 return PTR_ERR(mg); 1479 1462 } 1480 1463 kref_get(&mg->refcount); ··· 1515 1498 1516 1499 spin_lock(&cifs_tcp_ses_lock); 1517 1500 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { 1501 + if (!server->is_dfs_conn) 1502 + continue; 1503 + 1518 1504 list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { 1519 1505 list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { 1520 - if (tcon->dfs_path) { 1506 + if (!tcon->ipc && !tcon->need_reconnect) { 1521 1507 tcon->tc_count++; 1522 1508 list_add_tail(&tcon->ulist, &tcons); 1523 1509 } ··· 1530 1510 spin_unlock(&cifs_tcp_ses_lock); 1531 1511 1532 1512 list_for_each_entry_safe(tcon, ntcon, &tcons, ulist) { 1513 + struct TCP_Server_Info *server = tcon->ses->server; 1514 + 1533 1515 list_del_init(&tcon->ulist); 1534 - refresh_tcon(sessions, tcon, false); 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); 1535 1523 cifs_put_tcon(tcon); 1536 1524 } 1537 1525 }
+29 -6
fs/cifs/file.c
··· 2692 2692 tcon = tlink_tcon(smbfile->tlink); 2693 2693 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { 2694 2694 server = tcon->ses->server; 2695 - if (server->ops->flush) 2696 - rc = server->ops->flush(xid, tcon, &smbfile->fid); 2697 - else 2695 + if (server->ops->flush == NULL) { 2698 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); 2699 2709 } 2700 2710 2711 + strict_fsync_exit: 2701 2712 free_xid(xid); 2702 2713 return rc; 2703 2714 } ··· 2720 2709 struct cifs_tcon *tcon; 2721 2710 struct TCP_Server_Info *server; 2722 2711 struct cifsFileInfo *smbfile = file->private_data; 2712 + struct inode *inode = file_inode(file); 2723 2713 struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file); 2724 2714 2725 2715 rc = file_write_and_wait_range(file, start, end); ··· 2737 2725 tcon = tlink_tcon(smbfile->tlink); 2738 2726 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { 2739 2727 server = tcon->ses->server; 2740 - if (server->ops->flush) 2741 - rc = server->ops->flush(xid, tcon, &smbfile->fid); 2742 - else 2728 + if (server->ops->flush == NULL) { 2743 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); 2744 2742 } 2745 2743 2744 + fsync_exit: 2746 2745 free_xid(xid); 2747 2746 return rc; 2748 2747 }
+33 -3
fs/cifs/fs_context.c
··· 308 308 new_ctx->nodename = NULL; 309 309 new_ctx->username = NULL; 310 310 new_ctx->password = NULL; 311 + new_ctx->server_hostname = NULL; 311 312 new_ctx->domainname = NULL; 313 + new_ctx->workstation_name = NULL; 312 314 new_ctx->UNC = NULL; 313 315 new_ctx->source = NULL; 314 316 new_ctx->iocharset = NULL; ··· 325 323 DUP_CTX_STR(UNC); 326 324 DUP_CTX_STR(source); 327 325 DUP_CTX_STR(domainname); 326 + DUP_CTX_STR(workstation_name); 328 327 DUP_CTX_STR(nodename); 329 328 DUP_CTX_STR(iocharset); 330 329 ··· 462 459 return -EINVAL; 463 460 464 461 /* record the server hostname */ 462 + kfree(ctx->server_hostname); 465 463 ctx->server_hostname = kstrndup(devname + 2, pos - devname - 2, GFP_KERNEL); 466 464 if (!ctx->server_hostname) 467 465 return -ENOMEM; ··· 724 720 cifs_errorf(fc, "can not change domainname during remount\n"); 725 721 return -EINVAL; 726 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 + } 727 728 if (new_ctx->nodename && 728 729 (!old_ctx->nodename || strcmp(new_ctx->nodename, old_ctx->nodename))) { 729 730 cifs_errorf(fc, "can not change nodename during remount\n"); ··· 762 753 return rc; 763 754 764 755 /* 765 - * We can not change UNC/username/password/domainname/nodename/iocharset 756 + * We can not change UNC/username/password/domainname/ 757 + * workstation_name/nodename/iocharset 766 758 * during reconnect so ignore what we have in the new context and 767 759 * just use what we already have in cifs_sb->ctx. 768 760 */ ··· 772 762 STEAL_STRING(cifs_sb, ctx, username); 773 763 STEAL_STRING(cifs_sb, ctx, password); 774 764 STEAL_STRING(cifs_sb, ctx, domainname); 765 + STEAL_STRING(cifs_sb, ctx, workstation_name); 775 766 STEAL_STRING(cifs_sb, ctx, nodename); 776 767 STEAL_STRING(cifs_sb, ctx, iocharset); 777 768 ··· 1425 1414 1426 1415 int smb3_init_fs_context(struct fs_context *fc) 1427 1416 { 1417 + int rc; 1428 1418 struct smb3_fs_context *ctx; 1429 1419 char *nodename = utsname()->nodename; 1430 1420 int i; 1431 1421 1432 1422 ctx = kzalloc(sizeof(struct smb3_fs_context), GFP_KERNEL); 1433 - if (unlikely(!ctx)) 1434 - return -ENOMEM; 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 + } 1435 1433 1436 1434 /* 1437 1435 * does not have to be perfect mapping since field is ··· 1513 1493 fc->fs_private = ctx; 1514 1494 fc->ops = &smb3_fs_context_ops; 1515 1495 return 0; 1496 + 1497 + err_exit: 1498 + if (ctx) { 1499 + kfree(ctx->workstation_name); 1500 + kfree(ctx); 1501 + } 1502 + 1503 + return rc; 1516 1504 } 1517 1505 1518 1506 void ··· 1546 1518 ctx->source = NULL; 1547 1519 kfree(ctx->domainname); 1548 1520 ctx->domainname = NULL; 1521 + kfree(ctx->workstation_name); 1522 + ctx->workstation_name = NULL; 1549 1523 kfree(ctx->nodename); 1550 1524 ctx->nodename = NULL; 1551 1525 kfree(ctx->iocharset);
+1
fs/cifs/fs_context.h
··· 170 170 char *server_hostname; 171 171 char *UNC; 172 172 char *nodename; 173 + char *workstation_name; 173 174 char *iocharset; /* local code page for mapping to and from Unicode */ 174 175 char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */ 175 176 char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
+8
fs/cifs/fscache.c
··· 87 87 char *sharename; 88 88 struct cifs_fscache_super_auxdata auxdata; 89 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 + 90 98 sharename = extract_sharename(tcon->treeName); 91 99 if (IS_ERR(sharename)) { 92 100 cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
+7 -57
fs/cifs/misc.c
··· 75 75 INIT_LIST_HEAD(&ret_buf->tcon_list); 76 76 mutex_init(&ret_buf->session_mutex); 77 77 spin_lock_init(&ret_buf->iface_lock); 78 + spin_lock_init(&ret_buf->chan_lock); 78 79 } 79 80 return ret_buf; 80 81 } ··· 95 94 kfree_sensitive(buf_to_free->password); 96 95 kfree(buf_to_free->user_name); 97 96 kfree(buf_to_free->domainName); 97 + kfree(buf_to_free->workstation_name); 98 98 kfree_sensitive(buf_to_free->auth_key.response); 99 99 kfree(buf_to_free->iface_list); 100 100 kfree_sensitive(buf_to_free); ··· 140 138 kfree(buf_to_free->nativeFileSystem); 141 139 kfree_sensitive(buf_to_free->password); 142 140 kfree(buf_to_free->crfid.fid); 143 - #ifdef CONFIG_CIFS_DFS_UPCALL 144 - kfree(buf_to_free->dfs_path); 145 - #endif 146 141 kfree(buf_to_free); 147 142 } 148 143 ··· 1286 1287 return rc; 1287 1288 } 1288 1289 1289 - static void tcon_super_cb(struct super_block *sb, void *arg) 1290 + int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix) 1290 1291 { 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 1292 kfree(cifs_sb->prepath); 1337 1293 1338 1294 if (prefix && *prefix) { 1339 1295 cifs_sb->prepath = kstrdup(prefix, GFP_ATOMIC); 1340 - if (!cifs_sb->prepath) { 1341 - rc = -ENOMEM; 1342 - goto out; 1343 - } 1296 + if (!cifs_sb->prepath) 1297 + return -ENOMEM; 1344 1298 1345 1299 convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb)); 1346 1300 } else 1347 1301 cifs_sb->prepath = NULL; 1348 1302 1349 1303 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; 1350 - 1351 - out: 1352 - cifs_put_tcon_super(sb); 1353 - return rc; 1304 + return 0; 1354 1305 } 1306 + #endif
+3 -1
fs/cifs/ntlmssp.h
··· 119 119 */ 120 120 121 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); 122 + int build_ntlmssp_negotiate_blob(unsigned char **pbuffer, u16 *buflen, 123 + struct cifs_ses *ses, 124 + const struct nls_table *nls_cp); 123 125 int build_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen, 124 126 struct cifs_ses *ses, 125 127 const struct nls_table *nls_cp);
+155 -85
fs/cifs/sess.c
··· 54 54 { 55 55 int i; 56 56 57 + spin_lock(&ses->chan_lock); 57 58 for (i = 0; i < ses->chan_count; i++) { 58 - if (is_server_using_iface(ses->chans[i].server, iface)) 59 + if (is_server_using_iface(ses->chans[i].server, iface)) { 60 + spin_unlock(&ses->chan_lock); 59 61 return true; 62 + } 60 63 } 64 + spin_unlock(&ses->chan_lock); 61 65 return false; 62 66 } 63 67 64 68 /* returns number of channels added */ 65 69 int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses) 66 70 { 67 - int old_chan_count = ses->chan_count; 68 - int left = ses->chan_max - ses->chan_count; 71 + int old_chan_count, new_chan_count; 72 + int left; 69 73 int i = 0; 70 74 int rc = 0; 71 75 int tries = 0; 72 76 struct cifs_server_iface *ifaces = NULL; 73 77 size_t iface_count; 74 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 + 75 89 if (left <= 0) { 76 90 cifs_dbg(FYI, 77 91 "ses already at max_channels (%zu), nothing to open\n", 78 92 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"); 93 + spin_unlock(&ses->chan_lock); 84 94 return 0; 85 95 } 86 96 87 97 if (!(ses->server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) { 88 98 cifs_dbg(VFS, "server %s does not support multichannel\n", ses->server->hostname); 89 99 ses->chan_max = 1; 100 + spin_unlock(&ses->chan_lock); 90 101 return 0; 91 102 } 103 + spin_unlock(&ses->chan_lock); 92 104 93 105 /* 94 106 * Make a copy of the iface list at the time and use that ··· 154 142 cifs_dbg(FYI, "successfully opened new channel on iface#%d\n", 155 143 i); 156 144 left--; 145 + new_chan_count++; 157 146 } 158 147 159 148 kfree(ifaces); 160 - return ses->chan_count - old_chan_count; 149 + return new_chan_count - old_chan_count; 161 150 } 162 151 163 152 /* ··· 170 157 { 171 158 int i; 172 159 160 + spin_lock(&ses->chan_lock); 173 161 for (i = 0; i < ses->chan_count; i++) { 174 - if (ses->chans[i].server == server) 162 + if (ses->chans[i].server == server) { 163 + spin_unlock(&ses->chan_lock); 175 164 return &ses->chans[i]; 165 + } 176 166 } 167 + spin_unlock(&ses->chan_lock); 177 168 return NULL; 178 169 } 179 170 ··· 185 168 cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, 186 169 struct cifs_server_iface *iface) 187 170 { 171 + struct TCP_Server_Info *chan_server; 188 172 struct cifs_chan *chan; 189 173 struct smb3_fs_context ctx = {NULL}; 190 174 static const char unc_fmt[] = "\\%s\\foo"; ··· 258 240 SMB2_CLIENT_GUID_SIZE); 259 241 ctx.use_client_guid = true; 260 242 261 - mutex_lock(&ses->session_mutex); 243 + chan_server = cifs_get_tcp_session(&ctx, ses->server); 262 244 245 + mutex_lock(&ses->session_mutex); 246 + spin_lock(&ses->chan_lock); 263 247 chan = ses->binding_chan = &ses->chans[ses->chan_count]; 264 - chan->server = cifs_get_tcp_session(&ctx); 248 + chan->server = chan_server; 265 249 if (IS_ERR(chan->server)) { 266 250 rc = PTR_ERR(chan->server); 267 251 chan->server = NULL; 252 + spin_unlock(&ses->chan_lock); 268 253 goto out; 269 254 } 270 - spin_lock(&cifs_tcp_ses_lock); 271 - chan->server->is_channel = true; 272 - spin_unlock(&cifs_tcp_ses_lock); 255 + spin_unlock(&ses->chan_lock); 273 256 274 257 /* 275 258 * We need to allocate the server crypto now as we will need ··· 302 283 * ses to the new server. 303 284 */ 304 285 286 + spin_lock(&ses->chan_lock); 305 287 ses->chan_count++; 306 288 atomic_set(&ses->chan_seq, 0); 289 + spin_unlock(&ses->chan_lock); 290 + 307 291 out: 308 292 ses->binding = false; 309 293 ses->binding_chan = NULL; ··· 621 599 return 0; 622 600 } 623 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 + 624 656 /* BB Move to ntlmssp.c eventually */ 625 657 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) 658 + int build_ntlmssp_negotiate_blob(unsigned char **pbuffer, 659 + u16 *buflen, 660 + struct cifs_ses *ses, 661 + const struct nls_table *nls_cp) 630 662 { 663 + int rc = 0; 631 664 struct TCP_Server_Info *server = cifs_ses_server(ses); 632 - NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer; 665 + NEGOTIATE_MESSAGE *sec_blob; 633 666 __u32 flags; 667 + unsigned char *tmp; 668 + int len; 634 669 635 - memset(pbuffer, 0, sizeof(NEGOTIATE_MESSAGE)); 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)); 636 681 memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); 637 682 sec_blob->MessageType = NtLmNegotiate; 638 683 ··· 713 624 if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess) 714 625 flags |= NTLMSSP_NEGOTIATE_KEY_XCH; 715 626 627 + tmp = *pbuffer + sizeof(NEGOTIATE_MESSAGE); 716 628 sec_blob->NegotiateFlags = cpu_to_le32(flags); 717 629 718 - sec_blob->WorkstationName.BufferOffset = 0; 719 - sec_blob->WorkstationName.Length = 0; 720 - sec_blob->WorkstationName.MaximumLength = 0; 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); 721 636 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 - } 637 + cifs_security_buffer_from_str(&sec_blob->WorkstationName, 638 + NULL, 639 + CIFS_MAX_WORKSTATION_LEN, 640 + *pbuffer, &tmp, 641 + nls_cp); 727 642 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; 643 + *buflen = tmp - *pbuffer; 644 + setup_ntlm_neg_ret: 645 + return rc; 744 646 } 745 647 746 648 int build_ntlmssp_auth_blob(unsigned char **pbuffer, ··· 743 663 AUTHENTICATE_MESSAGE *sec_blob; 744 664 __u32 flags; 745 665 unsigned char *tmp; 666 + int len; 746 667 747 668 rc = setup_ntlmv2_rsp(ses, nls_cp); 748 669 if (rc) { ··· 751 670 *buflen = 0; 752 671 goto setup_ntlmv2_ret; 753 672 } 754 - *pbuffer = kmalloc(size_of_ntlmssp_blob(ses), GFP_KERNEL); 673 + 674 + len = size_of_ntlmssp_blob(ses, sizeof(AUTHENTICATE_MESSAGE)); 675 + *pbuffer = kmalloc(len, GFP_KERNEL); 755 676 if (!*pbuffer) { 756 677 rc = -ENOMEM; 757 678 cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc); ··· 769 686 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | 770 687 NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | 771 688 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC | 772 - NTLMSSP_NEGOTIATE_SEAL; 689 + NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED; 773 690 if (ses->server->sign) 774 691 flags |= NTLMSSP_NEGOTIATE_SIGN; 775 692 if (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess) ··· 802 719 sec_blob->NtChallengeResponse.MaximumLength = 0; 803 720 } 804 721 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 - } 722 + cifs_security_buffer_from_str(&sec_blob->DomainName, 723 + ses->domainName, 724 + CIFS_MAX_DOMAINNAME_LEN, 725 + *pbuffer, &tmp, 726 + nls_cp); 820 727 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 - } 728 + cifs_security_buffer_from_str(&sec_blob->UserName, 729 + ses->user_name, 730 + CIFS_MAX_USERNAME_LEN, 731 + *pbuffer, &tmp, 732 + nls_cp); 836 733 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; 734 + cifs_security_buffer_from_str(&sec_blob->WorkstationName, 735 + ses->workstation_name, 736 + CIFS_MAX_WORKSTATION_LEN, 737 + *pbuffer, &tmp, 738 + nls_cp); 841 739 842 740 if (((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) || 843 741 (ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) ··· 1294 1230 struct cifs_ses *ses = sess_data->ses; 1295 1231 __u16 bytes_remaining; 1296 1232 char *bcc_ptr; 1233 + unsigned char *ntlmsspblob = NULL; 1297 1234 u16 blob_len; 1298 1235 1299 1236 cifs_dbg(FYI, "rawntlmssp session setup negotiate phase\n"); ··· 1318 1253 pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base; 1319 1254 1320 1255 /* 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)); 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); 1325 1265 1326 1266 rc = _sess_auth_rawntlmssp_assemble_req(sess_data); 1327 1267 if (rc)
+17 -5
fs/cifs/smb2inode.c
··· 46 46 struct smb2_file_link_info link_info; 47 47 }; 48 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 + */ 49 53 static int 50 54 smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, 51 55 struct cifs_sb_info *cifs_sb, const char *full_path, ··· 540 536 create_options |= OPEN_REPARSE_POINT; 541 537 542 538 /* Failed on a symbolic link - query a reparse point info */ 539 + cifs_get_readable_path(tcon, full_path, &cfile); 543 540 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 544 541 FILE_READ_ATTRIBUTES, FILE_OPEN, 545 542 create_options, ACL_NO_MODE, 546 - smb2_data, SMB2_OP_QUERY_INFO, NULL); 543 + smb2_data, SMB2_OP_QUERY_INFO, cfile); 547 544 } 548 545 if (rc) 549 546 goto out; ··· 592 587 create_options |= OPEN_REPARSE_POINT; 593 588 594 589 /* Failed on a symbolic link - query a reparse point info */ 590 + cifs_get_readable_path(tcon, full_path, &cfile); 595 591 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 596 592 FILE_READ_ATTRIBUTES, FILE_OPEN, 597 593 create_options, ACL_NO_MODE, 598 - smb2_data, SMB2_OP_POSIX_QUERY_INFO, NULL); 594 + smb2_data, SMB2_OP_POSIX_QUERY_INFO, cfile); 599 595 } 600 596 if (rc) 601 597 goto out; ··· 713 707 struct cifs_sb_info *cifs_sb, bool set_alloc) 714 708 { 715 709 __le64 eof = cpu_to_le64(size); 710 + struct cifsFileInfo *cfile; 716 711 712 + cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); 717 713 return smb2_compound_op(xid, tcon, cifs_sb, full_path, 718 714 FILE_WRITE_DATA, FILE_OPEN, 0, ACL_NO_MODE, 719 - &eof, SMB2_OP_SET_EOF, NULL); 715 + &eof, SMB2_OP_SET_EOF, cfile); 720 716 } 721 717 722 718 int ··· 727 719 { 728 720 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 729 721 struct tcon_link *tlink; 722 + struct cifs_tcon *tcon; 723 + struct cifsFileInfo *cfile; 730 724 int rc; 731 725 732 726 if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) && ··· 739 729 tlink = cifs_sb_tlink(cifs_sb); 740 730 if (IS_ERR(tlink)) 741 731 return PTR_ERR(tlink); 732 + tcon = tlink_tcon(tlink); 742 733 743 - rc = smb2_compound_op(xid, tlink_tcon(tlink), cifs_sb, full_path, 734 + cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); 735 + rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 744 736 FILE_WRITE_ATTRIBUTES, FILE_OPEN, 745 - 0, ACL_NO_MODE, buf, SMB2_OP_SET_INFO, NULL); 737 + 0, ACL_NO_MODE, buf, SMB2_OP_SET_INFO, cfile); 746 738 cifs_put_tlink(tlink); 747 739 return rc; 748 740 }
+7 -3
fs/cifs/smb2ops.c
··· 2844 2844 struct fsctl_get_dfs_referral_req *dfs_req = NULL; 2845 2845 struct get_dfs_referral_rsp *dfs_rsp = NULL; 2846 2846 u32 dfs_req_size = 0, dfs_rsp_size = 0; 2847 + int retry_count = 0; 2847 2848 2848 2849 cifs_dbg(FYI, "%s: path: %s\n", __func__, search_name); 2849 2850 ··· 2896 2895 true /* is_fsctl */, 2897 2896 (char *)dfs_req, dfs_req_size, CIFSMaxBufSize, 2898 2897 (char **)&dfs_rsp, &dfs_rsp_size); 2899 - } while (rc == -EAGAIN); 2898 + if (!is_retryable_error(rc)) 2899 + break; 2900 + usleep_range(512, 2048); 2901 + } while (++retry_count < 5); 2900 2902 2901 2903 if (rc) { 2902 - if ((rc != -ENOENT) && (rc != -EOPNOTSUPP)) 2903 - cifs_tcon_dbg(VFS, "ioctl error in %s rc=%d\n", __func__, rc); 2904 + if (!is_retryable_error(rc) && rc != -ENOENT && rc != -EOPNOTSUPP) 2905 + cifs_tcon_dbg(VFS, "%s: ioctl error: rc=%d\n", __func__, rc); 2904 2906 goto out; 2905 2907 } 2906 2908
+37 -15
fs/cifs/smb2pdu.c
··· 155 155 if (tcon == NULL) 156 156 return 0; 157 157 158 - if (smb2_command == SMB2_TREE_CONNECT) 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) 159 163 return 0; 160 164 161 165 if (tcon->tidStatus == CifsExiting) { ··· 257 253 /* 258 254 * If we are reconnecting an extra channel, bind 259 255 */ 260 - if (server->is_channel) { 256 + if (CIFS_SERVER_IS_CHAN(server)) { 261 257 ses->binding = true; 262 258 ses->binding_chan = cifs_ses_find_chan(ses, server); 263 259 } ··· 1460 1456 int rc; 1461 1457 struct cifs_ses *ses = sess_data->ses; 1462 1458 struct smb2_sess_setup_rsp *rsp = NULL; 1463 - char *ntlmssp_blob = NULL; 1459 + unsigned char *ntlmssp_blob = NULL; 1464 1460 bool use_spnego = false; /* else use raw ntlmssp */ 1465 1461 u16 blob_length = 0; 1466 1462 ··· 1479 1475 if (rc) 1480 1476 goto out_err; 1481 1477 1482 - ntlmssp_blob = kmalloc(sizeof(struct _NEGOTIATE_MESSAGE), 1483 - GFP_KERNEL); 1484 - if (ntlmssp_blob == NULL) { 1485 - rc = -ENOMEM; 1486 - goto out; 1487 - } 1478 + rc = build_ntlmssp_negotiate_blob(&ntlmssp_blob, 1479 + &blob_length, ses, 1480 + sess_data->nls_cp); 1481 + if (rc) 1482 + goto out_err; 1488 1483 1489 - build_ntlmssp_negotiate_blob(ntlmssp_blob, ses); 1490 1484 if (use_spnego) { 1491 1485 /* BB eventually need to add this */ 1492 1486 cifs_dbg(VFS, "spnego not supported for SMB2 yet\n"); 1493 1487 rc = -EOPNOTSUPP; 1494 1488 goto out; 1495 - } else { 1496 - blob_length = sizeof(struct _NEGOTIATE_MESSAGE); 1497 - /* with raw NTLMSSP we don't encapsulate in SPNEGO */ 1498 1489 } 1499 1490 sess_data->iov[1].iov_base = ntlmssp_blob; 1500 1491 sess_data->iov[1].iov_len = blob_length; ··· 1840 1841 cifs_small_buf_release(req); 1841 1842 rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base; 1842 1843 trace_smb3_tcon(xid, tcon->tid, ses->Suid, tree, rc); 1843 - if (rc != 0) { 1844 + if ((rc != 0) || (rsp == NULL)) { 1844 1845 cifs_stats_fail_inc(tcon, SMB2_TREE_CONNECT_HE); 1845 1846 tcon->need_reconnect = true; 1846 1847 goto tcon_error_exit; ··· 2668 2669 goto err_free_rsp_buf; 2669 2670 } 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 + */ 2671 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 + 2672 2684 trace_smb3_posix_mkdir_done(xid, le64_to_cpu(rsp->PersistentFileId), 2673 2685 tcon->tid, 2674 2686 ses->Suid, CREATE_NOT_FILE, ··· 2952 2942 tcon->need_reconnect = true; 2953 2943 } 2954 2944 goto creat_exit; 2955 - } else 2945 + } else if (rsp == NULL) /* unlikely to happen, but safer to check */ 2946 + goto creat_exit; 2947 + else 2956 2948 trace_smb3_open_done(xid, le64_to_cpu(rsp->PersistentFileId), 2957 2949 tcon->tid, 2958 2950 ses->Suid, oparms->create_options, ··· 3174 3162 /* check if caller wants to look at return data or just return rc */ 3175 3163 if ((plen == NULL) || (out_data == NULL)) 3176 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 + } 3177 3175 3178 3176 *plen = le32_to_cpu(rsp->OutputCount); 3179 3177
+3
fs/cifs/transport.c
··· 1044 1044 if (!ses) 1045 1045 return NULL; 1046 1046 1047 + spin_lock(&ses->chan_lock); 1047 1048 if (!ses->binding) { 1048 1049 /* round robin */ 1049 1050 if (ses->chan_count > 1) { 1050 1051 index = (uint)atomic_inc_return(&ses->chan_seq); 1051 1052 index %= ses->chan_count; 1052 1053 } 1054 + spin_unlock(&ses->chan_lock); 1053 1055 return ses->chans[index].server; 1054 1056 } else { 1057 + spin_unlock(&ses->chan_lock); 1055 1058 return cifs_ses_server(ses); 1056 1059 } 1057 1060 }