hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/fs/cifs/connect.c
....@@ -21,6 +21,7 @@
2121 #include <linux/fs.h>
2222 #include <linux/net.h>
2323 #include <linux/string.h>
24
+#include <linux/sched/mm.h>
2425 #include <linux/sched/signal.h>
2526 #include <linux/list.h>
2627 #include <linux/wait.h>
....@@ -50,13 +51,17 @@
5051 #include "cifs_unicode.h"
5152 #include "cifs_debug.h"
5253 #include "cifs_fs_sb.h"
53
-#include "dns_resolve.h"
5454 #include "ntlmssp.h"
5555 #include "nterr.h"
5656 #include "rfc1002pdu.h"
5757 #include "fscache.h"
5858 #include "smb2proto.h"
5959 #include "smbdirect.h"
60
+#include "dns_resolve.h"
61
+#ifdef CONFIG_CIFS_DFS_UPCALL
62
+#include "dfs_cache.h"
63
+#endif
64
+#include "fs_context.h"
6065
6166 extern mempool_t *cifs_req_poolp;
6267 extern bool disable_legacy_dialects;
....@@ -65,13 +70,16 @@
6570 #define TLINK_ERROR_EXPIRE (1 * HZ)
6671 #define TLINK_IDLE_EXPIRE (600 * HZ)
6772
73
+/* Drop the connection to not overload the server */
74
+#define NUM_STATUS_IO_TIMEOUT 5
75
+
6876 enum {
6977 /* Mount options that take no arguments */
7078 Opt_user_xattr, Opt_nouser_xattr,
7179 Opt_forceuid, Opt_noforceuid,
7280 Opt_forcegid, Opt_noforcegid,
7381 Opt_noblocksend, Opt_noautotune, Opt_nolease,
74
- Opt_hard, Opt_soft, Opt_perm, Opt_noperm,
82
+ Opt_hard, Opt_soft, Opt_perm, Opt_noperm, Opt_nodelete,
7583 Opt_mapposix, Opt_nomapposix,
7684 Opt_mapchars, Opt_nomapchars, Opt_sfu,
7785 Opt_nosfu, Opt_nodfs, Opt_posixpaths,
....@@ -87,20 +95,23 @@
8795 Opt_serverino, Opt_noserverino,
8896 Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl,
8997 Opt_acl, Opt_noacl, Opt_locallease,
90
- Opt_sign, Opt_seal, Opt_noac,
98
+ Opt_sign, Opt_ignore_signature, Opt_seal, Opt_noac,
9199 Opt_fsc, Opt_mfsymlinks,
92100 Opt_multiuser, Opt_sloppy, Opt_nosharesock,
93101 Opt_persistent, Opt_nopersistent,
94102 Opt_resilient, Opt_noresilient,
95
- Opt_domainauto, Opt_rdma,
103
+ Opt_domainauto, Opt_rdma, Opt_modesid, Opt_rootfs,
104
+ Opt_multichannel, Opt_nomultichannel,
105
+ Opt_compress,
96106
97107 /* Mount options which take numeric value */
98108 Opt_backupuid, Opt_backupgid, Opt_uid,
99109 Opt_cruid, Opt_gid, Opt_file_mode,
100110 Opt_dirmode, Opt_port,
101
- Opt_rsize, Opt_wsize, Opt_actimeo,
102
- Opt_echo_interval, Opt_max_credits,
103
- Opt_snapshot,
111
+ Opt_min_enc_offload,
112
+ Opt_blocksize, Opt_rsize, Opt_wsize, Opt_actimeo,
113
+ Opt_echo_interval, Opt_max_credits, Opt_handletimeout,
114
+ Opt_snapshot, Opt_max_channels,
104115
105116 /* Mount options which take string value */
106117 Opt_user, Opt_pass, Opt_ip,
....@@ -134,6 +145,7 @@
134145 { Opt_soft, "soft" },
135146 { Opt_perm, "perm" },
136147 { Opt_noperm, "noperm" },
148
+ { Opt_nodelete, "nodelete" },
137149 { Opt_mapchars, "mapchars" }, /* SFU style */
138150 { Opt_nomapchars, "nomapchars" },
139151 { Opt_mapposix, "mapposix" }, /* SFM style */
....@@ -172,12 +184,14 @@
172184 { Opt_serverino, "serverino" },
173185 { Opt_noserverino, "noserverino" },
174186 { Opt_rwpidforward, "rwpidforward" },
187
+ { Opt_modesid, "modefromsid" },
175188 { Opt_cifsacl, "cifsacl" },
176189 { Opt_nocifsacl, "nocifsacl" },
177190 { Opt_acl, "acl" },
178191 { Opt_noacl, "noacl" },
179192 { Opt_locallease, "locallease" },
180193 { Opt_sign, "sign" },
194
+ { Opt_ignore_signature, "signloosely" },
181195 { Opt_seal, "seal" },
182196 { Opt_noac, "noac" },
183197 { Opt_fsc, "fsc" },
....@@ -191,6 +205,8 @@
191205 { Opt_noresilient, "noresilienthandles"},
192206 { Opt_domainauto, "domainauto"},
193207 { Opt_rdma, "rdma"},
208
+ { Opt_multichannel, "multichannel" },
209
+ { Opt_nomultichannel, "nomultichannel" },
194210
195211 { Opt_backupuid, "backupuid=%s" },
196212 { Opt_backupgid, "backupgid=%s" },
....@@ -201,12 +217,17 @@
201217 { Opt_dirmode, "dirmode=%s" },
202218 { Opt_dirmode, "dir_mode=%s" },
203219 { Opt_port, "port=%s" },
220
+ { Opt_min_enc_offload, "esize=%s" },
221
+ { Opt_blocksize, "bsize=%s" },
204222 { Opt_rsize, "rsize=%s" },
205223 { Opt_wsize, "wsize=%s" },
206224 { Opt_actimeo, "actimeo=%s" },
225
+ { Opt_handletimeout, "handletimeout=%s" },
207226 { Opt_echo_interval, "echo_interval=%s" },
208227 { Opt_max_credits, "max_credits=%s" },
209228 { Opt_snapshot, "snapshot=%s" },
229
+ { Opt_max_channels, "max_channels=%s" },
230
+ { Opt_compress, "compress=%s" },
210231
211232 { Opt_blank_user, "user=" },
212233 { Opt_blank_user, "username=" },
....@@ -252,72 +273,18 @@
252273 { Opt_ignore, "dev" },
253274 { Opt_ignore, "mand" },
254275 { Opt_ignore, "nomand" },
276
+ { Opt_ignore, "relatime" },
255277 { Opt_ignore, "_netdev" },
278
+ { Opt_rootfs, "rootfs" },
256279
257280 { Opt_err, NULL }
258
-};
259
-
260
-enum {
261
- Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
262
- Opt_sec_ntlmsspi, Opt_sec_ntlmssp,
263
- Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2,
264
- Opt_sec_ntlmv2i, Opt_sec_lanman,
265
- Opt_sec_none,
266
-
267
- Opt_sec_err
268
-};
269
-
270
-static const match_table_t cifs_secflavor_tokens = {
271
- { Opt_sec_krb5, "krb5" },
272
- { Opt_sec_krb5i, "krb5i" },
273
- { Opt_sec_krb5p, "krb5p" },
274
- { Opt_sec_ntlmsspi, "ntlmsspi" },
275
- { Opt_sec_ntlmssp, "ntlmssp" },
276
- { Opt_ntlm, "ntlm" },
277
- { Opt_sec_ntlmi, "ntlmi" },
278
- { Opt_sec_ntlmv2, "nontlm" },
279
- { Opt_sec_ntlmv2, "ntlmv2" },
280
- { Opt_sec_ntlmv2i, "ntlmv2i" },
281
- { Opt_sec_lanman, "lanman" },
282
- { Opt_sec_none, "none" },
283
-
284
- { Opt_sec_err, NULL }
285
-};
286
-
287
-/* cache flavors */
288
-enum {
289
- Opt_cache_loose,
290
- Opt_cache_strict,
291
- Opt_cache_none,
292
- Opt_cache_err
293
-};
294
-
295
-static const match_table_t cifs_cacheflavor_tokens = {
296
- { Opt_cache_loose, "loose" },
297
- { Opt_cache_strict, "strict" },
298
- { Opt_cache_none, "none" },
299
- { Opt_cache_err, NULL }
300
-};
301
-
302
-static const match_table_t cifs_smb_version_tokens = {
303
- { Smb_1, SMB1_VERSION_STRING },
304
- { Smb_20, SMB20_VERSION_STRING},
305
- { Smb_21, SMB21_VERSION_STRING },
306
- { Smb_30, SMB30_VERSION_STRING },
307
- { Smb_302, SMB302_VERSION_STRING },
308
- { Smb_311, SMB311_VERSION_STRING },
309
- { Smb_311, ALT_SMB311_VERSION_STRING },
310
- { Smb_3any, SMB3ANY_VERSION_STRING },
311
- { Smb_default, SMBDEFAULT_VERSION_STRING },
312
- { Smb_version_err, NULL }
313281 };
314282
315283 static int ip_connect(struct TCP_Server_Info *server);
316284 static int generic_ip_connect(struct TCP_Server_Info *server);
317285 static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
318286 static void cifs_prune_tlinks(struct work_struct *work);
319
-static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
320
- const char *devname, bool is_smb3);
287
+static char *extract_hostname(const char *unc);
321288
322289 /*
323290 * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
....@@ -342,7 +309,7 @@
342309 cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
343310 return -ENOMEM;
344311 }
345
- snprintf(unc, len, "\\\\%s", server->hostname);
312
+ scnprintf(unc, len, "\\\\%s", server->hostname);
346313
347314 rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
348315 kfree(unc);
....@@ -368,6 +335,49 @@
368335 }
369336 #endif
370337
338
+#ifdef CONFIG_CIFS_DFS_UPCALL
339
+/* These functions must be called with server->srv_mutex held */
340
+static void reconn_set_next_dfs_target(struct TCP_Server_Info *server,
341
+ struct cifs_sb_info *cifs_sb,
342
+ struct dfs_cache_tgt_list *tgt_list,
343
+ struct dfs_cache_tgt_iterator **tgt_it)
344
+{
345
+ const char *name;
346
+
347
+ if (!cifs_sb || !cifs_sb->origin_fullpath)
348
+ return;
349
+
350
+ if (!*tgt_it) {
351
+ *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
352
+ } else {
353
+ *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
354
+ if (!*tgt_it)
355
+ *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
356
+ }
357
+
358
+ cifs_dbg(FYI, "%s: UNC: %s\n", __func__, cifs_sb->origin_fullpath);
359
+
360
+ name = dfs_cache_get_tgt_name(*tgt_it);
361
+
362
+ kfree(server->hostname);
363
+
364
+ server->hostname = extract_hostname(name);
365
+ if (IS_ERR(server->hostname)) {
366
+ cifs_dbg(FYI,
367
+ "%s: failed to extract hostname from target: %ld\n",
368
+ __func__, PTR_ERR(server->hostname));
369
+ }
370
+}
371
+
372
+static inline int reconn_setup_dfs_targets(struct cifs_sb_info *cifs_sb,
373
+ struct dfs_cache_tgt_list *tl)
374
+{
375
+ if (!cifs_sb->origin_fullpath)
376
+ return -EOPNOTSUPP;
377
+ return dfs_cache_noreq_find(cifs_sb->origin_fullpath + 1, NULL, tl);
378
+}
379
+#endif
380
+
371381 /*
372382 * cifs tcp session reconnection
373383 *
....@@ -385,12 +395,49 @@
385395 struct cifs_tcon *tcon;
386396 struct mid_q_entry *mid_entry;
387397 struct list_head retry_list;
398
+#ifdef CONFIG_CIFS_DFS_UPCALL
399
+ struct super_block *sb = NULL;
400
+ struct cifs_sb_info *cifs_sb = NULL;
401
+ struct dfs_cache_tgt_list tgt_list = {0};
402
+ struct dfs_cache_tgt_iterator *tgt_it = NULL;
403
+#endif
388404
389405 spin_lock(&GlobalMid_Lock);
406
+ server->nr_targets = 1;
407
+#ifdef CONFIG_CIFS_DFS_UPCALL
408
+ spin_unlock(&GlobalMid_Lock);
409
+ sb = cifs_get_tcp_super(server);
410
+ if (IS_ERR(sb)) {
411
+ rc = PTR_ERR(sb);
412
+ cifs_dbg(FYI, "%s: will not do DFS failover: rc = %d\n",
413
+ __func__, rc);
414
+ sb = NULL;
415
+ } else {
416
+ cifs_sb = CIFS_SB(sb);
417
+ rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list);
418
+ if (rc) {
419
+ cifs_sb = NULL;
420
+ if (rc != -EOPNOTSUPP) {
421
+ cifs_server_dbg(VFS, "%s: no target servers for DFS failover\n",
422
+ __func__);
423
+ }
424
+ } else {
425
+ server->nr_targets = dfs_cache_get_nr_tgts(&tgt_list);
426
+ }
427
+ }
428
+ cifs_dbg(FYI, "%s: will retry %d target(s)\n", __func__,
429
+ server->nr_targets);
430
+ spin_lock(&GlobalMid_Lock);
431
+#endif
390432 if (server->tcpStatus == CifsExiting) {
391433 /* the demux thread will exit normally
392434 next time through the loop */
393435 spin_unlock(&GlobalMid_Lock);
436
+#ifdef CONFIG_CIFS_DFS_UPCALL
437
+ dfs_cache_free_tgts(&tgt_list);
438
+ cifs_put_tcp_super(sb);
439
+#endif
440
+ wake_up(&server->response_q);
394441 return rc;
395442 } else
396443 server->tcpStatus = CifsNeedReconnect;
....@@ -398,7 +445,7 @@
398445 server->maxBuf = 0;
399446 server->max_read = 0;
400447
401
- cifs_dbg(FYI, "Reconnecting tcp session\n");
448
+ cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
402449 trace_smb3_reconnect(server->CurrentMid, server->hostname);
403450
404451 /* before reconnecting the tcp session, mark the smb session (uid)
....@@ -443,9 +490,11 @@
443490 spin_lock(&GlobalMid_Lock);
444491 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
445492 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
493
+ kref_get(&mid_entry->refcount);
446494 if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
447495 mid_entry->mid_state = MID_RETRY_NEEDED;
448496 list_move(&mid_entry->qhead, &retry_list);
497
+ mid_entry->mid_flags |= MID_DELETED;
449498 }
450499 spin_unlock(&GlobalMid_Lock);
451500 mutex_unlock(&server->srv_mutex);
....@@ -455,28 +504,44 @@
455504 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
456505 list_del_init(&mid_entry->qhead);
457506 mid_entry->callback(mid_entry);
507
+ cifs_mid_q_entry_release(mid_entry);
508
+ }
509
+
510
+ if (cifs_rdma_enabled(server)) {
511
+ mutex_lock(&server->srv_mutex);
512
+ smbd_destroy(server);
513
+ mutex_unlock(&server->srv_mutex);
458514 }
459515
460516 do {
461517 try_to_freeze();
462518
463
- /* we should try only the port we connected to before */
464519 mutex_lock(&server->srv_mutex);
520
+#ifdef CONFIG_CIFS_DFS_UPCALL
521
+ /*
522
+ * Set up next DFS target server (if any) for reconnect. If DFS
523
+ * feature is disabled, then we will retry last server we
524
+ * connected to before.
525
+ */
526
+ reconn_set_next_dfs_target(server, cifs_sb, &tgt_list, &tgt_it);
527
+#endif
528
+ rc = reconn_set_ipaddr(server);
529
+ if (rc) {
530
+ cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
531
+ __func__, rc);
532
+ }
533
+
465534 if (cifs_rdma_enabled(server))
466535 rc = smbd_reconnect(server);
467536 else
468537 rc = generic_ip_connect(server);
469538 if (rc) {
470539 cifs_dbg(FYI, "reconnect error %d\n", rc);
471
- rc = reconn_set_ipaddr(server);
472
- if (rc) {
473
- cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n",
474
- __func__, rc);
475
- }
476540 mutex_unlock(&server->srv_mutex);
477541 msleep(3000);
478542 } else {
479543 atomic_inc(&tcpSesReconnectCount);
544
+ set_credits(server, 1);
480545 spin_lock(&GlobalMid_Lock);
481546 if (server->tcpStatus != CifsExiting)
482547 server->tcpStatus = CifsNeedNegotiate;
....@@ -485,9 +550,29 @@
485550 }
486551 } while (server->tcpStatus == CifsNeedReconnect);
487552
553
+#ifdef CONFIG_CIFS_DFS_UPCALL
554
+ if (tgt_it) {
555
+ rc = dfs_cache_noreq_update_tgthint(cifs_sb->origin_fullpath + 1,
556
+ tgt_it);
557
+ if (rc) {
558
+ cifs_server_dbg(VFS, "%s: failed to update DFS target hint: rc = %d\n",
559
+ __func__, rc);
560
+ }
561
+ rc = dfs_cache_update_vol(cifs_sb->origin_fullpath, server);
562
+ if (rc) {
563
+ cifs_server_dbg(VFS, "%s: failed to update vol info in DFS cache: rc = %d\n",
564
+ __func__, rc);
565
+ }
566
+ dfs_cache_free_tgts(&tgt_list);
567
+
568
+ }
569
+
570
+ cifs_put_tcp_super(sb);
571
+#endif
488572 if (server->tcpStatus == CifsNeedNegotiate)
489573 mod_delayed_work(cifsiod_wq, &server->echo, 0);
490574
575
+ wake_up(&server->response_q);
491576 return rc;
492577 }
493578
....@@ -535,7 +620,7 @@
535620 if (!server->bigbuf) {
536621 server->bigbuf = (char *)cifs_buf_get();
537622 if (!server->bigbuf) {
538
- cifs_dbg(VFS, "No memory for large SMB response\n");
623
+ cifs_server_dbg(VFS, "No memory for large SMB response\n");
539624 msleep(3000);
540625 /* retry will check if exiting */
541626 return false;
....@@ -548,7 +633,7 @@
548633 if (!server->smallbuf) {
549634 server->smallbuf = (char *)cifs_small_buf_get();
550635 if (!server->smallbuf) {
551
- cifs_dbg(VFS, "No memory for SMB response\n");
636
+ cifs_server_dbg(VFS, "No memory for SMB response\n");
552637 msleep(1000);
553638 /* retry will check if exiting */
554639 return false;
....@@ -569,7 +654,7 @@
569654 * We need to wait 3 echo intervals to make sure we handle such
570655 * situations right:
571656 * 1s client sends a normal SMB request
572
- * 3s client gets a response
657
+ * 2s client gets a response
573658 * 30s echo workqueue job pops, and decides we got a response recently
574659 * and don't need to send another
575660 * ...
....@@ -578,11 +663,11 @@
578663 */
579664 if ((server->tcpStatus == CifsGood ||
580665 server->tcpStatus == CifsNeedNegotiate) &&
666
+ (!server->ops->can_echo || server->ops->can_echo(server)) &&
581667 time_after(jiffies, server->lstrp + 3 * server->echo_interval)) {
582
- cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n",
583
- server->hostname, (3 * server->echo_interval) / HZ);
668
+ cifs_server_dbg(VFS, "has not responded in %lu seconds. Reconnecting...\n",
669
+ (3 * server->echo_interval) / HZ);
584670 cifs_reconnect(server);
585
- wake_up(&server->response_q);
586671 return true;
587672 }
588673
....@@ -609,9 +694,6 @@
609694 {
610695 int length = 0;
611696 int total_read;
612
-
613
- smb_msg->msg_control = NULL;
614
- smb_msg->msg_controllen = 0;
615697
616698 for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
617699 try_to_freeze();
....@@ -663,9 +745,24 @@
663745 cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
664746 unsigned int to_read)
665747 {
666
- struct msghdr smb_msg;
748
+ struct msghdr smb_msg = {};
667749 struct kvec iov = {.iov_base = buf, .iov_len = to_read};
668
- iov_iter_kvec(&smb_msg.msg_iter, READ | ITER_KVEC, &iov, 1, to_read);
750
+ iov_iter_kvec(&smb_msg.msg_iter, READ, &iov, 1, to_read);
751
+
752
+ return cifs_readv_from_socket(server, &smb_msg);
753
+}
754
+
755
+ssize_t
756
+cifs_discard_from_socket(struct TCP_Server_Info *server, size_t to_read)
757
+{
758
+ struct msghdr smb_msg = {};
759
+
760
+ /*
761
+ * iov_iter_discard already sets smb_msg.type and count and iov_offset
762
+ * and cifs_readv_from_socket sets msg_control and msg_controllen
763
+ * so little to initialize in struct msghdr
764
+ */
765
+ iov_iter_discard(&smb_msg.msg_iter, READ, to_read);
669766
670767 return cifs_readv_from_socket(server, &smb_msg);
671768 }
....@@ -674,10 +771,10 @@
674771 cifs_read_page_from_socket(struct TCP_Server_Info *server, struct page *page,
675772 unsigned int page_offset, unsigned int to_read)
676773 {
677
- struct msghdr smb_msg;
774
+ struct msghdr smb_msg = {};
678775 struct bio_vec bv = {
679776 .bv_page = page, .bv_len = to_read, .bv_offset = page_offset};
680
- iov_iter_bvec(&smb_msg.msg_iter, READ | ITER_BVEC, &bv, 1, to_read);
777
+ iov_iter_bvec(&smb_msg.msg_iter, READ, &bv, 1, to_read);
681778 return cifs_readv_from_socket(server, &smb_msg);
682779 }
683780
....@@ -715,10 +812,9 @@
715812 */
716813 cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT);
717814 cifs_reconnect(server);
718
- wake_up(&server->response_q);
719815 break;
720816 default:
721
- cifs_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
817
+ cifs_server_dbg(VFS, "RFC 1002 unknown response type 0x%x\n", type);
722818 cifs_reconnect(server);
723819 }
724820
....@@ -741,11 +837,26 @@
741837 * function has finished processing it is a bug.
742838 */
743839 if (mid->mid_flags & MID_DELETED)
744
- printk_once(KERN_WARNING
745
- "trying to dequeue a deleted mid\n");
746
- else
840
+ pr_warn_once("trying to dequeue a deleted mid\n");
841
+ else {
747842 list_del_init(&mid->qhead);
843
+ mid->mid_flags |= MID_DELETED;
844
+ }
748845 spin_unlock(&GlobalMid_Lock);
846
+}
847
+
848
+static unsigned int
849
+smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
850
+{
851
+ struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
852
+
853
+ /*
854
+ * SMB1 does not use credits.
855
+ */
856
+ if (server->vals->header_preamble_size)
857
+ return 0;
858
+
859
+ return le16_to_cpu(shdr->CreditRequest);
749860 }
750861
751862 static void
....@@ -755,6 +866,7 @@
755866 if (server->ops->check_trans2 &&
756867 server->ops->check_trans2(mid, server, buf, malformed))
757868 return;
869
+ mid->credits_received = smb2_get_credits_from_hdr(buf, server);
758870 mid->resp_buf = buf;
759871 mid->large_buf = server->large_buf;
760872 /* Was previous buf put in mpx struct for multi-rsp? */
....@@ -799,10 +911,8 @@
799911 wake_up_all(&server->request_q);
800912 /* give those requests time to exit */
801913 msleep(125);
802
- if (cifs_rdma_enabled(server) && server->smbd_conn) {
803
- smbd_destroy(server->smbd_conn);
804
- server->smbd_conn = NULL;
805
- }
914
+ if (cifs_rdma_enabled(server))
915
+ smbd_destroy(server);
806916 if (server->ssocket) {
807917 sock_release(server->ssocket);
808918 server->ssocket = NULL;
....@@ -818,8 +928,10 @@
818928 list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
819929 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
820930 cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
931
+ kref_get(&mid_entry->refcount);
821932 mid_entry->mid_state = MID_SHUTDOWN;
822933 list_move(&mid_entry->qhead, &dispose_list);
934
+ mid_entry->mid_flags |= MID_DELETED;
823935 }
824936 spin_unlock(&GlobalMid_Lock);
825937
....@@ -829,6 +941,7 @@
829941 cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
830942 list_del_init(&mid_entry->qhead);
831943 mid_entry->callback(mid_entry);
944
+ cifs_mid_q_entry_release(mid_entry);
832945 }
833946 /* 1/8th of sec is more than enough time for them to exit */
834947 msleep(125);
....@@ -869,9 +982,8 @@
869982 /* make sure this will fit in a large buffer */
870983 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
871984 server->vals->header_preamble_size) {
872
- cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
985
+ cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
873986 cifs_reconnect(server);
874
- wake_up(&server->response_q);
875987 return -ECONNABORTED;
876988 }
877989
....@@ -919,12 +1031,11 @@
9191031 if (server->ops->is_session_expired &&
9201032 server->ops->is_session_expired(buf)) {
9211033 cifs_reconnect(server);
922
- wake_up(&server->response_q);
9231034 return -1;
9241035 }
9251036
9261037 if (server->ops->is_status_pending &&
927
- server->ops->is_status_pending(buf, server, length))
1038
+ server->ops->is_status_pending(buf, server))
9281039 return -1;
9291040
9301041 if (!mid)
....@@ -965,8 +1076,9 @@
9651076 struct task_struct *task_to_wake = NULL;
9661077 struct mid_q_entry *mids[MAX_COMPOUND];
9671078 char *bufs[MAX_COMPOUND];
1079
+ unsigned int noreclaim_flag, num_io_timeout = 0;
9681080
969
- current->flags |= PF_MEMALLOC;
1081
+ noreclaim_flag = memalloc_noreclaim_save();
9701082 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
9711083
9721084 length = atomic_inc_return(&tcpSesAllocCount);
....@@ -1010,10 +1122,9 @@
10101122 /* make sure we have enough to get to the MID */
10111123 if (server->pdu_size < HEADER_SIZE(server) - 1 -
10121124 server->vals->header_preamble_size) {
1013
- cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
1125
+ cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
10141126 server->pdu_size);
10151127 cifs_reconnect(server);
1016
- wake_up(&server->response_q);
10171128 continue;
10181129 }
10191130
....@@ -1061,21 +1172,21 @@
10611172 continue;
10621173 }
10631174
1064
- if (server->large_buf)
1065
- buf = server->bigbuf;
1066
-
1175
+ if (server->ops->is_status_io_timeout &&
1176
+ server->ops->is_status_io_timeout(buf)) {
1177
+ num_io_timeout++;
1178
+ if (num_io_timeout > NUM_STATUS_IO_TIMEOUT) {
1179
+ cifs_reconnect(server);
1180
+ num_io_timeout = 0;
1181
+ continue;
1182
+ }
1183
+ }
10671184
10681185 server->lstrp = jiffies;
10691186
10701187 for (i = 0; i < num_mids; i++) {
10711188 if (mids[i] != NULL) {
10721189 mids[i]->resp_buf_size = server->pdu_size;
1073
- if ((mids[i]->mid_flags & MID_WAIT_CANCELLED) &&
1074
- mids[i]->mid_state == MID_RESPONSE_RECEIVED &&
1075
- server->ops->handle_cancelled_mid)
1076
- server->ops->handle_cancelled_mid(
1077
- mids[i]->resp_buf,
1078
- server);
10791190
10801191 if (!mids[i]->multiRsp || mids[i]->multiEnd)
10811192 mids[i]->callback(mids[i]);
....@@ -1087,16 +1198,15 @@
10871198 smb2_add_credits_from_hdr(bufs[i], server);
10881199 cifs_dbg(FYI, "Received oplock break\n");
10891200 } else {
1090
- cifs_dbg(VFS, "No task to wake, unknown frame "
1091
- "received! NumMids %d\n",
1092
- atomic_read(&midCount));
1201
+ cifs_server_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
1202
+ atomic_read(&midCount));
10931203 cifs_dump_mem("Received Data is: ", bufs[i],
10941204 HEADER_SIZE(server));
1205
+ smb2_add_credits_from_hdr(bufs[i], server);
10951206 #ifdef CONFIG_CIFS_DEBUG2
10961207 if (server->ops->dump_detail)
10971208 server->ops->dump_detail(bufs[i],
10981209 server);
1099
- smb2_add_credits_from_hdr(bufs[i], server);
11001210 cifs_dump_mids(server);
11011211 #endif /* CIFS_DEBUG2 */
11021212 }
....@@ -1131,6 +1241,7 @@
11311241 set_current_state(TASK_RUNNING);
11321242 }
11331243
1244
+ memalloc_noreclaim_restore(noreclaim_flag);
11341245 module_put_and_exit(0);
11351246 }
11361247
....@@ -1144,7 +1255,12 @@
11441255
11451256 /* skip double chars at beginning of string */
11461257 /* BB: check validity of these bytes? */
1147
- src = unc + 2;
1258
+ if (strlen(unc) < 3)
1259
+ return ERR_PTR(-EINVAL);
1260
+ for (src = unc; *src && *src == '\\'; src++)
1261
+ ;
1262
+ if (!*src)
1263
+ return ERR_PTR(-EINVAL);
11481264
11491265 /* delimiter between hostname and sharename is always '\\' now */
11501266 delim = strchr(src, '\\');
....@@ -1212,158 +1328,6 @@
12121328 return 0;
12131329 }
12141330
1215
-static int cifs_parse_security_flavors(char *value,
1216
- struct smb_vol *vol)
1217
-{
1218
-
1219
- substring_t args[MAX_OPT_ARGS];
1220
-
1221
- /*
1222
- * With mount options, the last one should win. Reset any existing
1223
- * settings back to default.
1224
- */
1225
- vol->sectype = Unspecified;
1226
- vol->sign = false;
1227
-
1228
- switch (match_token(value, cifs_secflavor_tokens, args)) {
1229
- case Opt_sec_krb5p:
1230
- cifs_dbg(VFS, "sec=krb5p is not supported!\n");
1231
- return 1;
1232
- case Opt_sec_krb5i:
1233
- vol->sign = true;
1234
- /* Fallthrough */
1235
- case Opt_sec_krb5:
1236
- vol->sectype = Kerberos;
1237
- break;
1238
- case Opt_sec_ntlmsspi:
1239
- vol->sign = true;
1240
- /* Fallthrough */
1241
- case Opt_sec_ntlmssp:
1242
- vol->sectype = RawNTLMSSP;
1243
- break;
1244
- case Opt_sec_ntlmi:
1245
- vol->sign = true;
1246
- /* Fallthrough */
1247
- case Opt_ntlm:
1248
- vol->sectype = NTLM;
1249
- break;
1250
- case Opt_sec_ntlmv2i:
1251
- vol->sign = true;
1252
- /* Fallthrough */
1253
- case Opt_sec_ntlmv2:
1254
- vol->sectype = NTLMv2;
1255
- break;
1256
-#ifdef CONFIG_CIFS_WEAK_PW_HASH
1257
- case Opt_sec_lanman:
1258
- vol->sectype = LANMAN;
1259
- break;
1260
-#endif
1261
- case Opt_sec_none:
1262
- vol->nullauth = 1;
1263
- break;
1264
- default:
1265
- cifs_dbg(VFS, "bad security option: %s\n", value);
1266
- return 1;
1267
- }
1268
-
1269
- return 0;
1270
-}
1271
-
1272
-static int
1273
-cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
1274
-{
1275
- substring_t args[MAX_OPT_ARGS];
1276
-
1277
- switch (match_token(value, cifs_cacheflavor_tokens, args)) {
1278
- case Opt_cache_loose:
1279
- vol->direct_io = false;
1280
- vol->strict_io = false;
1281
- break;
1282
- case Opt_cache_strict:
1283
- vol->direct_io = false;
1284
- vol->strict_io = true;
1285
- break;
1286
- case Opt_cache_none:
1287
- vol->direct_io = true;
1288
- vol->strict_io = false;
1289
- break;
1290
- default:
1291
- cifs_dbg(VFS, "bad cache= option: %s\n", value);
1292
- return 1;
1293
- }
1294
- return 0;
1295
-}
1296
-
1297
-static int
1298
-cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
1299
-{
1300
- substring_t args[MAX_OPT_ARGS];
1301
-
1302
- switch (match_token(value, cifs_smb_version_tokens, args)) {
1303
-#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
1304
- case Smb_1:
1305
- if (disable_legacy_dialects) {
1306
- cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1307
- return 1;
1308
- }
1309
- if (is_smb3) {
1310
- cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1311
- return 1;
1312
- }
1313
- vol->ops = &smb1_operations;
1314
- vol->vals = &smb1_values;
1315
- break;
1316
- case Smb_20:
1317
- if (disable_legacy_dialects) {
1318
- cifs_dbg(VFS, "mount with legacy dialect disabled\n");
1319
- return 1;
1320
- }
1321
- if (is_smb3) {
1322
- cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1323
- return 1;
1324
- }
1325
- vol->ops = &smb20_operations;
1326
- vol->vals = &smb20_values;
1327
- break;
1328
-#else
1329
- case Smb_1:
1330
- cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
1331
- return 1;
1332
- case Smb_20:
1333
- cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
1334
- return 1;
1335
-#endif /* CIFS_ALLOW_INSECURE_LEGACY */
1336
- case Smb_21:
1337
- vol->ops = &smb21_operations;
1338
- vol->vals = &smb21_values;
1339
- break;
1340
- case Smb_30:
1341
- vol->ops = &smb30_operations;
1342
- vol->vals = &smb30_values;
1343
- break;
1344
- case Smb_302:
1345
- vol->ops = &smb30_operations; /* currently identical with 3.0 */
1346
- vol->vals = &smb302_values;
1347
- break;
1348
- case Smb_311:
1349
- vol->ops = &smb311_operations;
1350
- vol->vals = &smb311_values;
1351
- break;
1352
- case Smb_3any:
1353
- vol->ops = &smb30_operations; /* currently identical with 3.0 */
1354
- vol->vals = &smb3any_values;
1355
- break;
1356
- case Smb_default:
1357
- vol->ops = &smb30_operations; /* currently identical with 3.0 */
1358
- vol->vals = &smbdefault_values;
1359
- break;
1360
- default:
1361
- cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
1362
- return 1;
1363
- }
1364
- return 0;
1365
-}
1366
-
13671331 /*
13681332 * Parse a devname into substrings and populate the vol->UNC and vol->prepath
13691333 * fields with the result. Returns 0 on success and an error otherwise.
....@@ -1376,7 +1340,7 @@
13761340 size_t len;
13771341
13781342 if (unlikely(!devname || !*devname)) {
1379
- cifs_dbg(VFS, "Device name not specified.\n");
1343
+ cifs_dbg(VFS, "Device name not specified\n");
13801344 return -EINVAL;
13811345 }
13821346
....@@ -1465,7 +1429,7 @@
14651429 vol->cred_uid = current_uid();
14661430 vol->linux_uid = current_uid();
14671431 vol->linux_gid = current_gid();
1468
-
1432
+ vol->bsize = 1024 * 1024; /* can improve cp performance significantly */
14691433 /*
14701434 * default to SFM style remapping of seven reserved characters
14711435 * unless user overrides it or we negotiate CIFS POSIX where
....@@ -1488,11 +1452,18 @@
14881452
14891453 vol->actimeo = CIFS_DEF_ACTIMEO;
14901454
1455
+ /* Most clients set timeout to 0, allows server to use its default */
1456
+ vol->handle_timeout = 0; /* See MS-SMB2 spec section 2.2.14.2.12 */
1457
+
14911458 /* offer SMB2.1 and later (SMB3 etc). Secure and widely accepted */
14921459 vol->ops = &smb30_operations;
14931460 vol->vals = &smbdefault_values;
14941461
14951462 vol->echo_interval = SMB_ECHO_INTERVAL_DEFAULT;
1463
+
1464
+ /* default to no multichannel (single server connection) */
1465
+ vol->multichannel = false;
1466
+ vol->max_channels = 1;
14961467
14971468 if (!mountdata)
14981469 goto cifs_parse_mount_err;
....@@ -1519,13 +1490,13 @@
15191490 case 0:
15201491 break;
15211492 case -ENOMEM:
1522
- cifs_dbg(VFS, "Unable to allocate memory for devname.\n");
1493
+ cifs_dbg(VFS, "Unable to allocate memory for devname\n");
15231494 goto cifs_parse_mount_err;
15241495 case -EINVAL:
1525
- cifs_dbg(VFS, "Malformed UNC in devname.\n");
1496
+ cifs_dbg(VFS, "Malformed UNC in devname\n");
15261497 goto cifs_parse_mount_err;
15271498 default:
1528
- cifs_dbg(VFS, "Unknown error parsing devname.\n");
1499
+ cifs_dbg(VFS, "Unknown error parsing devname\n");
15291500 goto cifs_parse_mount_err;
15301501 }
15311502
....@@ -1585,6 +1556,9 @@
15851556 case Opt_noperm:
15861557 vol->noperm = 1;
15871558 break;
1559
+ case Opt_nodelete:
1560
+ vol->nodelete = 1;
1561
+ break;
15881562 case Opt_mapchars:
15891563 vol->sfu_remap = true;
15901564 vol->remap = false; /* disable SFM mapping */
....@@ -1607,6 +1581,11 @@
16071581 break;
16081582 case Opt_nodfs:
16091583 vol->nodfs = 1;
1584
+ break;
1585
+ case Opt_rootfs:
1586
+#ifdef CONFIG_CIFS_ROOT
1587
+ vol->rootfs = true;
1588
+#endif
16101589 break;
16111590 case Opt_posixpaths:
16121591 vol->posix_paths = 1;
....@@ -1694,6 +1673,9 @@
16941673 case Opt_rwpidforward:
16951674 vol->rwpidforward = 1;
16961675 break;
1676
+ case Opt_modesid:
1677
+ vol->mode_ace = 1;
1678
+ break;
16971679 case Opt_cifsacl:
16981680 vol->cifs_acl = 1;
16991681 break;
....@@ -1712,6 +1694,10 @@
17121694 case Opt_sign:
17131695 vol->sign = true;
17141696 break;
1697
+ case Opt_ignore_signature:
1698
+ vol->sign = true;
1699
+ vol->ignore_signature = true;
1700
+ break;
17151701 case Opt_seal:
17161702 /* we do not do the following in secFlags because seal
17171703 * is a per tree connection (mount) not a per socket
....@@ -1721,7 +1707,7 @@
17211707 vol->seal = 1;
17221708 break;
17231709 case Opt_noac:
1724
- pr_warn("CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1710
+ pr_warn("Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
17251711 break;
17261712 case Opt_fsc:
17271713 #ifndef CONFIG_CIFS_FSCACHE
....@@ -1774,6 +1760,21 @@
17741760 break;
17751761 case Opt_rdma:
17761762 vol->rdma = true;
1763
+ break;
1764
+ case Opt_multichannel:
1765
+ vol->multichannel = true;
1766
+ /* if number of channels not specified, default to 2 */
1767
+ if (vol->max_channels < 2)
1768
+ vol->max_channels = 2;
1769
+ break;
1770
+ case Opt_nomultichannel:
1771
+ vol->multichannel = false;
1772
+ vol->max_channels = 1;
1773
+ break;
1774
+ case Opt_compress:
1775
+ vol->compression = UNKNOWN_TYPE;
1776
+ cifs_dbg(VFS,
1777
+ "SMB3 compression support is experimental\n");
17771778 break;
17781779
17791780 /* Numeric Values */
....@@ -1841,6 +1842,33 @@
18411842 }
18421843 port = (unsigned short)option;
18431844 break;
1845
+ case Opt_min_enc_offload:
1846
+ if (get_option_ul(args, &option)) {
1847
+ cifs_dbg(VFS, "Invalid minimum encrypted read offload size (esize)\n");
1848
+ goto cifs_parse_mount_err;
1849
+ }
1850
+ vol->min_offload = option;
1851
+ break;
1852
+ case Opt_blocksize:
1853
+ if (get_option_ul(args, &option)) {
1854
+ cifs_dbg(VFS, "%s: Invalid blocksize value\n",
1855
+ __func__);
1856
+ goto cifs_parse_mount_err;
1857
+ }
1858
+ /*
1859
+ * inode blocksize realistically should never need to be
1860
+ * less than 16K or greater than 16M and default is 1MB.
1861
+ * Note that small inode block sizes (e.g. 64K) can lead
1862
+ * to very poor performance of common tools like cp and scp
1863
+ */
1864
+ if ((option < CIFS_MAX_MSGSIZE) ||
1865
+ (option > (4 * SMB3_DEFAULT_IOSIZE))) {
1866
+ cifs_dbg(VFS, "%s: Invalid blocksize\n",
1867
+ __func__);
1868
+ goto cifs_parse_mount_err;
1869
+ }
1870
+ vol->bsize = option;
1871
+ break;
18441872 case Opt_rsize:
18451873 if (get_option_ul(args, &option)) {
18461874 cifs_dbg(VFS, "%s: Invalid rsize value\n",
....@@ -1869,6 +1897,18 @@
18691897 goto cifs_parse_mount_err;
18701898 }
18711899 break;
1900
+ case Opt_handletimeout:
1901
+ if (get_option_ul(args, &option)) {
1902
+ cifs_dbg(VFS, "%s: Invalid handletimeout value\n",
1903
+ __func__);
1904
+ goto cifs_parse_mount_err;
1905
+ }
1906
+ vol->handle_timeout = option;
1907
+ if (vol->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
1908
+ cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
1909
+ goto cifs_parse_mount_err;
1910
+ }
1911
+ break;
18721912 case Opt_echo_interval:
18731913 if (get_option_ul(args, &option)) {
18741914 cifs_dbg(VFS, "%s: Invalid echo interval value\n",
....@@ -1894,6 +1934,15 @@
18941934 }
18951935 vol->max_credits = option;
18961936 break;
1937
+ case Opt_max_channels:
1938
+ if (get_option_ul(args, &option) || option < 1 ||
1939
+ option > CIFS_MAX_CHANNELS) {
1940
+ cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n",
1941
+ __func__, CIFS_MAX_CHANNELS);
1942
+ goto cifs_parse_mount_err;
1943
+ }
1944
+ vol->max_channels = option;
1945
+ break;
18971946
18981947 /* String Arguments */
18991948
....@@ -1909,7 +1958,7 @@
19091958
19101959 if (strnlen(string, CIFS_MAX_USERNAME_LEN) >
19111960 CIFS_MAX_USERNAME_LEN) {
1912
- pr_warn("CIFS: username too long\n");
1961
+ pr_warn("username too long\n");
19131962 goto cifs_parse_mount_err;
19141963 }
19151964
....@@ -1932,11 +1981,11 @@
19321981 tmp_end++;
19331982 if (!(tmp_end < end && tmp_end[1] == delim)) {
19341983 /* No it is not. Set the password to NULL */
1935
- kzfree(vol->password);
1984
+ kfree_sensitive(vol->password);
19361985 vol->password = NULL;
19371986 break;
19381987 }
1939
- /* Yes it is. Drop down to Opt_pass below.*/
1988
+ fallthrough; /* to Opt_pass below */
19401989 case Opt_pass:
19411990 /* Obtain the value string */
19421991 value = strchr(data, '=');
....@@ -1970,12 +2019,12 @@
19702019 options = end;
19712020 }
19722021
1973
- kzfree(vol->password);
2022
+ kfree_sensitive(vol->password);
19742023 /* Now build new password string */
19752024 temp_len = strlen(value);
19762025 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
19772026 if (vol->password == NULL) {
1978
- pr_warn("CIFS: no memory for password\n");
2027
+ pr_warn("no memory for password\n");
19792028 goto cifs_parse_mount_err;
19802029 }
19812030
....@@ -1999,7 +2048,7 @@
19992048
20002049 if (!cifs_convert_address(dstaddr, string,
20012050 strlen(string))) {
2002
- pr_err("CIFS: bad ip= option (%s).\n", string);
2051
+ pr_err("bad ip= option (%s)\n", string);
20032052 goto cifs_parse_mount_err;
20042053 }
20052054 got_ip = true;
....@@ -2011,14 +2060,14 @@
20112060
20122061 if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN)
20132062 == CIFS_MAX_DOMAINNAME_LEN) {
2014
- pr_warn("CIFS: domain name too long\n");
2063
+ pr_warn("domain name too long\n");
20152064 goto cifs_parse_mount_err;
20162065 }
20172066
20182067 kfree(vol->domainname);
20192068 vol->domainname = kstrdup(string, GFP_KERNEL);
20202069 if (!vol->domainname) {
2021
- pr_warn("CIFS: no memory for domainname\n");
2070
+ pr_warn("no memory for domainname\n");
20222071 goto cifs_parse_mount_err;
20232072 }
20242073 cifs_dbg(FYI, "Domain name set\n");
....@@ -2031,7 +2080,7 @@
20312080 if (!cifs_convert_address(
20322081 (struct sockaddr *)&vol->srcaddr,
20332082 string, strlen(string))) {
2034
- pr_warn("CIFS: Could not parse srcaddr: %s\n",
2083
+ pr_warn("Could not parse srcaddr: %s\n",
20352084 string);
20362085 goto cifs_parse_mount_err;
20372086 }
....@@ -2042,7 +2091,7 @@
20422091 goto out_nomem;
20432092
20442093 if (strnlen(string, 1024) >= 65) {
2045
- pr_warn("CIFS: iocharset name too long.\n");
2094
+ pr_warn("iocharset name too long\n");
20462095 goto cifs_parse_mount_err;
20472096 }
20482097
....@@ -2051,7 +2100,7 @@
20512100 vol->iocharset = kstrdup(string,
20522101 GFP_KERNEL);
20532102 if (!vol->iocharset) {
2054
- pr_warn("CIFS: no memory for charset\n");
2103
+ pr_warn("no memory for charset\n");
20552104 goto cifs_parse_mount_err;
20562105 }
20572106 }
....@@ -2082,7 +2131,7 @@
20822131 * set at top of the function
20832132 */
20842133 if (i == RFC1001_NAME_LEN && string[i] != 0)
2085
- pr_warn("CIFS: netbiosname longer than 15 truncated.\n");
2134
+ pr_warn("netbiosname longer than 15 truncated\n");
20862135 break;
20872136 case Opt_servern:
20882137 /* servernetbiosname specified override *SMBSERVER */
....@@ -2108,7 +2157,7 @@
21082157 /* The string has 16th byte zero still from
21092158 set at top of the function */
21102159 if (i == RFC1001_NAME_LEN && string[i] != 0)
2111
- pr_warn("CIFS: server netbiosname longer than 15 truncated.\n");
2160
+ pr_warn("server netbiosname longer than 15 truncated\n");
21122161 break;
21132162 case Opt_ver:
21142163 /* version of mount userspace tools, not dialect */
....@@ -2119,17 +2168,15 @@
21192168 /* If interface changes in mount.cifs bump to new ver */
21202169 if (strncasecmp(string, "1", 1) == 0) {
21212170 if (strlen(string) > 1) {
2122
- pr_warn("Bad mount helper ver=%s. Did "
2123
- "you want SMB1 (CIFS) dialect "
2124
- "and mean to type vers=1.0 "
2125
- "instead?\n", string);
2171
+ pr_warn("Bad mount helper ver=%s. Did you want SMB1 (CIFS) dialect and mean to type vers=1.0 instead?\n",
2172
+ string);
21262173 goto cifs_parse_mount_err;
21272174 }
21282175 /* This is the default */
21292176 break;
21302177 }
21312178 /* For all other value, error */
2132
- pr_warn("CIFS: Invalid mount helper version specified\n");
2179
+ pr_warn("Invalid mount helper version specified\n");
21332180 goto cifs_parse_mount_err;
21342181 case Opt_vers:
21352182 /* protocol version (dialect) */
....@@ -2172,7 +2219,7 @@
21722219 }
21732220
21742221 if (!sloppy && invalid) {
2175
- pr_err("CIFS: Unknown mount option \"%s\"\n", invalid);
2222
+ pr_err("Unknown mount option \"%s\"\n", invalid);
21762223 goto cifs_parse_mount_err;
21772224 }
21782225
....@@ -2208,7 +2255,7 @@
22082255 slash = strchr(&vol->UNC[2], '\\');
22092256 len = slash - &vol->UNC[2];
22102257 if (!cifs_convert_address(dstaddr, &vol->UNC[2], len)) {
2211
- pr_err("Unable to determine destination address.\n");
2258
+ pr_err("Unable to determine destination address\n");
22122259 goto cifs_parse_mount_err;
22132260 }
22142261 }
....@@ -2219,19 +2266,15 @@
22192266 if (uid_specified)
22202267 vol->override_uid = override_uid;
22212268 else if (override_uid == 1)
2222
- pr_notice("CIFS: ignoring forceuid mount option specified with no uid= option.\n");
2269
+ pr_notice("ignoring forceuid mount option specified with no uid= option\n");
22232270
22242271 if (gid_specified)
22252272 vol->override_gid = override_gid;
22262273 else if (override_gid == 1)
2227
- pr_notice("CIFS: ignoring forcegid mount option specified with no gid= option.\n");
2274
+ pr_notice("ignoring forcegid mount option specified with no gid= option\n");
22282275
22292276 if (got_version == false)
2230
- pr_warn("No dialect specified on mount. Default has changed to "
2231
- "a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS "
2232
- "(SMB1). To use the less secure SMB1 dialect to access "
2233
- "old servers which do not support SMB3 (or SMB2.1) specify vers=1.0"
2234
- " on mount.\n");
2277
+ pr_warn_once("No dialect specified on mount. Default has changed to a more secure dialect, SMB2.1 or later (e.g. SMB3.1.1), from CIFS (SMB1). To use the less secure SMB1 dialect to access old servers which do not support SMB3.1.1 (or even SMB3 or SMB2.1) specify vers=1.0 on mount.\n");
22352278
22362279 kfree(mountdata_copy);
22372280 return 0;
....@@ -2248,8 +2291,8 @@
22482291 * specified, or if srcaddr is specified and
22492292 * matches the IP address of the rhs argument.
22502293 */
2251
-static bool
2252
-srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
2294
+bool
2295
+cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs)
22532296 {
22542297 switch (srcaddr->sa_family) {
22552298 case AF_UNSPEC:
....@@ -2279,6 +2322,10 @@
22792322 match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
22802323 {
22812324 __be16 port, *sport;
2325
+
2326
+ /* SMBDirect manages its own ports, don't match it here */
2327
+ if (server->rdma)
2328
+ return true;
22822329
22832330 switch (addr->sa_family) {
22842331 case AF_INET:
....@@ -2336,7 +2383,7 @@
23362383 return false; /* don't expect to be here */
23372384 }
23382385
2339
- if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr))
2386
+ if (!cifs_match_ipaddr(srcaddr, (struct sockaddr *)&server->srcaddr))
23402387 return false;
23412388
23422389 return true;
....@@ -2372,8 +2419,15 @@
23722419 if (vol->nosharesock)
23732420 return 0;
23742421
2375
- /* BB update this for smb3any and default case */
2376
- if ((server->vals != vol->vals) || (server->ops != vol->ops))
2422
+ /* If multidialect negotiation see if existing sessions match one */
2423
+ if (strcmp(vol->vals->version_string, SMB3ANY_VERSION_STRING) == 0) {
2424
+ if (server->vals->protocol_id < SMB30_PROT_ID)
2425
+ return 0;
2426
+ } else if (strcmp(vol->vals->version_string,
2427
+ SMBDEFAULT_VERSION_STRING) == 0) {
2428
+ if (server->vals->protocol_id < SMB21_PROT_ID)
2429
+ return 0;
2430
+ } else if ((server->vals != vol->vals) || (server->ops != vol->ops))
23772431 return 0;
23782432
23792433 if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
....@@ -2395,17 +2449,27 @@
23952449 if (server->rdma != vol->rdma)
23962450 return 0;
23972451
2452
+ if (server->ignore_signature != vol->ignore_signature)
2453
+ return 0;
2454
+
2455
+ if (server->min_offload != vol->min_offload)
2456
+ return 0;
2457
+
23982458 return 1;
23992459 }
24002460
2401
-static struct TCP_Server_Info *
2461
+struct TCP_Server_Info *
24022462 cifs_find_tcp_session(struct smb_vol *vol)
24032463 {
24042464 struct TCP_Server_Info *server;
24052465
24062466 spin_lock(&cifs_tcp_ses_lock);
24072467 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
2408
- if (!match_server(server, vol))
2468
+ /*
2469
+ * Skip ses channels since they're only handled in lower layers
2470
+ * (e.g. cifs_send_recv).
2471
+ */
2472
+ if (server->is_channel || !match_server(server, vol))
24092473 continue;
24102474
24112475 ++server->srv_count;
....@@ -2462,7 +2526,7 @@
24622526 send_sig(SIGKILL, task, 1);
24632527 }
24642528
2465
-static struct TCP_Server_Info *
2529
+struct TCP_Server_Info *
24662530 cifs_get_tcp_session(struct smb_vol *volume_info)
24672531 {
24682532 struct TCP_Server_Info *tcp_ses = NULL;
....@@ -2490,11 +2554,13 @@
24902554 goto out_err_crypto_release;
24912555 }
24922556
2493
- tcp_ses->noblocksnd = volume_info->noblocksnd;
2557
+ tcp_ses->noblockcnt = volume_info->rootfs;
2558
+ tcp_ses->noblocksnd = volume_info->noblocksnd || volume_info->rootfs;
24942559 tcp_ses->noautotune = volume_info->noautotune;
24952560 tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay;
24962561 tcp_ses->rdma = volume_info->rdma;
24972562 tcp_ses->in_flight = 0;
2563
+ tcp_ses->max_in_flight = 0;
24982564 tcp_ses->credits = 1;
24992565 init_waitqueue_head(&tcp_ses->response_q);
25002566 init_waitqueue_head(&tcp_ses->request_q);
....@@ -2506,7 +2572,9 @@
25062572 volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL);
25072573 tcp_ses->session_estab = false;
25082574 tcp_ses->sequence_number = 0;
2575
+ tcp_ses->reconnect_instance = 1;
25092576 tcp_ses->lstrp = jiffies;
2577
+ tcp_ses->compress_algorithm = cpu_to_le16(volume_info->compression);
25102578 spin_lock_init(&tcp_ses->req_lock);
25112579 INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
25122580 INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
....@@ -2517,7 +2585,11 @@
25172585 sizeof(tcp_ses->srcaddr));
25182586 memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
25192587 sizeof(tcp_ses->dstaddr));
2520
- generate_random_uuid(tcp_ses->client_guid);
2588
+ if (volume_info->use_client_guid)
2589
+ memcpy(tcp_ses->client_guid, volume_info->client_guid,
2590
+ SMB2_CLIENT_GUID_SIZE);
2591
+ else
2592
+ generate_random_uuid(tcp_ses->client_guid);
25212593 /*
25222594 * at this point we are the only ones with the pointer
25232595 * to the struct since the kernel thread not created yet
....@@ -2567,8 +2639,16 @@
25672639 module_put(THIS_MODULE);
25682640 goto out_err_crypto_release;
25692641 }
2642
+ tcp_ses->min_offload = volume_info->min_offload;
25702643 tcp_ses->tcpStatus = CifsNeedNegotiate;
25712644
2645
+ if ((volume_info->max_credits < 20) || (volume_info->max_credits > 60000))
2646
+ tcp_ses->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
2647
+ else
2648
+ tcp_ses->max_credits = volume_info->max_credits;
2649
+
2650
+ tcp_ses->nr_targets = 1;
2651
+ tcp_ses->ignore_signature = volume_info->ignore_signature;
25722652 /* thread spawned, put it on the list */
25732653 spin_lock(&cifs_tcp_ses_lock);
25742654 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
....@@ -2601,6 +2681,13 @@
26012681 {
26022682 if (vol->sectype != Unspecified &&
26032683 vol->sectype != ses->sectype)
2684
+ return 0;
2685
+
2686
+ /*
2687
+ * If an existing session is limited to less channels than
2688
+ * requested, it should not be reused
2689
+ */
2690
+ if (ses->chan_max < vol->max_channels)
26042691 return 0;
26052692
26062693 switch (ses->sectype) {
....@@ -2645,16 +2732,17 @@
26452732 struct nls_table *nls_codepage;
26462733 char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
26472734 bool seal = false;
2735
+ struct TCP_Server_Info *server = ses->server;
26482736
26492737 /*
26502738 * If the mount request that resulted in the creation of the
26512739 * session requires encryption, force IPC to be encrypted too.
26522740 */
26532741 if (volume_info->seal) {
2654
- if (ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
2742
+ if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
26552743 seal = true;
26562744 else {
2657
- cifs_dbg(VFS,
2745
+ cifs_server_dbg(VFS,
26582746 "IPC: server doesn't support encryption\n");
26592747 return -EOPNOTSUPP;
26602748 }
....@@ -2664,7 +2752,7 @@
26642752 if (tcon == NULL)
26652753 return -ENOMEM;
26662754
2667
- snprintf(unc, sizeof(unc), "\\\\%s\\IPC$", ses->server->hostname);
2755
+ scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
26682756
26692757 /* cannot fail */
26702758 nls_codepage = load_nls_default();
....@@ -2673,11 +2761,11 @@
26732761 tcon->ses = ses;
26742762 tcon->ipc = true;
26752763 tcon->seal = seal;
2676
- rc = ses->server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
2764
+ rc = server->ops->tree_connect(xid, ses, unc, tcon, nls_codepage);
26772765 free_xid(xid);
26782766
26792767 if (rc) {
2680
- cifs_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
2768
+ cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
26812769 tconInfoFree(tcon);
26822770 goto out;
26832771 }
....@@ -2737,8 +2825,7 @@
27372825 return NULL;
27382826 }
27392827
2740
-static void
2741
-cifs_put_smb_ses(struct cifs_ses *ses)
2828
+void cifs_put_smb_ses(struct cifs_ses *ses)
27422829 {
27432830 unsigned int rc, xid;
27442831 struct TCP_Server_Info *server = ses->server;
....@@ -2754,9 +2841,12 @@
27542841 spin_unlock(&cifs_tcp_ses_lock);
27552842 return;
27562843 }
2844
+ spin_unlock(&cifs_tcp_ses_lock);
2845
+
2846
+ spin_lock(&GlobalMid_Lock);
27572847 if (ses->status == CifsGood)
27582848 ses->status = CifsExiting;
2759
- spin_unlock(&cifs_tcp_ses_lock);
2849
+ spin_unlock(&GlobalMid_Lock);
27602850
27612851 cifs_free_ipc(ses);
27622852
....@@ -2764,7 +2854,7 @@
27642854 xid = get_xid();
27652855 rc = server->ops->logoff(xid, ses);
27662856 if (rc)
2767
- cifs_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
2857
+ cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
27682858 __func__, rc);
27692859 _free_xid(xid);
27702860 }
....@@ -2772,6 +2862,14 @@
27722862 spin_lock(&cifs_tcp_ses_lock);
27732863 list_del_init(&ses->smb_ses_list);
27742864 spin_unlock(&cifs_tcp_ses_lock);
2865
+
2866
+ /* close any extra channels */
2867
+ if (ses->chan_count > 1) {
2868
+ int i;
2869
+
2870
+ for (i = 1; i < ses->chan_count; i++)
2871
+ cifs_put_tcp_session(ses->chans[i].server, 0);
2872
+ }
27752873
27762874 sesInfoFree(ses);
27772875 cifs_put_tcp_session(server, 0);
....@@ -2902,12 +3000,12 @@
29023000 strlen(ses->domainName),
29033001 GFP_KERNEL);
29043002 if (!vol->domainname) {
2905
- cifs_dbg(FYI, "Unable to allocate %zd bytes for "
2906
- "domain\n", len);
3003
+ cifs_dbg(FYI, "Unable to allocate %zd bytes for domain\n",
3004
+ len);
29073005 rc = -ENOMEM;
29083006 kfree(vol->username);
29093007 vol->username = NULL;
2910
- kzfree(vol->password);
3008
+ kfree_sensitive(vol->password);
29113009 vol->password = NULL;
29123010 goto out_key_put;
29133011 }
....@@ -2937,10 +3035,10 @@
29373035 * already got a server reference (server refcount +1). See
29383036 * cifs_get_tcon() for refcount explanations.
29393037 */
2940
-static struct cifs_ses *
3038
+struct cifs_ses *
29413039 cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
29423040 {
2943
- int rc = -ENOMEM;
3041
+ int rc = 0;
29443042 unsigned int xid;
29453043 struct cifs_ses *ses;
29463044 struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
....@@ -2982,6 +3080,8 @@
29823080 return ses;
29833081 }
29843082
3083
+ rc = -ENOMEM;
3084
+
29853085 cifs_dbg(FYI, "Existing smb sess not found\n");
29863086 ses = sesInfoAlloc();
29873087 if (ses == NULL)
....@@ -3018,16 +3118,26 @@
30183118
30193119 ses->sectype = volume_info->sectype;
30203120 ses->sign = volume_info->sign;
3021
-
30223121 mutex_lock(&ses->session_mutex);
3122
+
3123
+ /* add server as first channel */
3124
+ ses->chans[0].server = server;
3125
+ ses->chan_count = 1;
3126
+ ses->chan_max = volume_info->multichannel ? volume_info->max_channels:1;
3127
+
30233128 rc = cifs_negotiate_protocol(xid, ses);
30243129 if (!rc)
30253130 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
3131
+
3132
+ /* each channel uses a different signing key */
3133
+ memcpy(ses->chans[0].signkey, ses->smb3signingkey,
3134
+ sizeof(ses->smb3signingkey));
3135
+
30263136 mutex_unlock(&ses->session_mutex);
30273137 if (rc)
30283138 goto get_ses_fail;
30293139
3030
- /* success, put it on the list */
3140
+ /* success, put it on the list and add it as first channel */
30313141 spin_lock(&cifs_tcp_ses_lock);
30323142 list_add(&ses->smb_ses_list, &server->smb_ses_list);
30333143 spin_unlock(&cifs_tcp_ses_lock);
....@@ -3054,7 +3164,11 @@
30543164 return 0;
30553165 if (tcon->snapshot_time != volume_info->snapshot_time)
30563166 return 0;
3167
+ if (tcon->handle_timeout != volume_info->handle_timeout)
3168
+ return 0;
30573169 if (tcon->no_lease != volume_info->no_lease)
3170
+ return 0;
3171
+ if (tcon->nodelete != volume_info->nodelete)
30583172 return 0;
30593173 return 1;
30603174 }
....@@ -3068,6 +3182,10 @@
30683182 spin_lock(&cifs_tcp_ses_lock);
30693183 list_for_each(tmp, &ses->tcon_list) {
30703184 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
3185
+#ifdef CONFIG_CIFS_DFS_UPCALL
3186
+ if (tcon->dfs_path)
3187
+ continue;
3188
+#endif
30713189 if (!match_tcon(tcon, volume_info))
30723190 continue;
30733191 ++tcon->tc_count;
....@@ -3170,6 +3288,16 @@
31703288 tcon->snapshot_time = volume_info->snapshot_time;
31713289 }
31723290
3291
+ if (volume_info->handle_timeout) {
3292
+ if (ses->server->vals->protocol_id == 0) {
3293
+ cifs_dbg(VFS,
3294
+ "Use SMB2.1 or later for handle timeout option\n");
3295
+ rc = -EOPNOTSUPP;
3296
+ goto out_fail;
3297
+ } else
3298
+ tcon->handle_timeout = volume_info->handle_timeout;
3299
+ }
3300
+
31733301 tcon->ses = ses;
31743302 if (volume_info->password) {
31753303 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
....@@ -3198,10 +3326,9 @@
31983326 if (volume_info->linux_ext) {
31993327 if (ses->server->posix_ext_supported) {
32003328 tcon->posix_extensions = true;
3201
- printk_once(KERN_WARNING
3202
- "SMB3.11 POSIX Extensions are experimental\n");
3329
+ pr_warn_once("SMB3.11 POSIX Extensions are experimental\n");
32033330 } else {
3204
- cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n");
3331
+ cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions\n");
32053332 rc = -EOPNOTSUPP;
32063333 goto out_fail;
32073334 }
....@@ -3219,10 +3346,6 @@
32193346 if (rc)
32203347 goto out_fail;
32213348
3222
- if (volume_info->nodfs) {
3223
- tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
3224
- cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
3225
- }
32263349 tcon->use_persistent = false;
32273350 /* check if SMB2 or later, CIFS does not support persistent handles */
32283351 if (volume_info->persistent) {
....@@ -3255,6 +3378,24 @@
32553378 tcon->use_resilient = true;
32563379 }
32573380
3381
+ /* If the user really knows what they are doing they can override */
3382
+ if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
3383
+ if (volume_info->cache_ro)
3384
+ cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
3385
+ else if (volume_info->cache_rw)
3386
+ cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
3387
+ }
3388
+
3389
+ if (volume_info->no_lease) {
3390
+ if (ses->server->vals->protocol_id == 0) {
3391
+ cifs_dbg(VFS,
3392
+ "SMB2 or later required for nolease option\n");
3393
+ rc = -EOPNOTSUPP;
3394
+ goto out_fail;
3395
+ } else
3396
+ tcon->no_lease = volume_info->no_lease;
3397
+ }
3398
+
32583399 /*
32593400 * We can have only one retry value for a connection to a share so for
32603401 * resources mounted more than once to the same server share the last
....@@ -3262,9 +3403,12 @@
32623403 */
32633404 tcon->retry = volume_info->retry;
32643405 tcon->nocase = volume_info->nocase;
3265
- tcon->nohandlecache = volume_info->nohandlecache;
3406
+ if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)
3407
+ tcon->nohandlecache = volume_info->nohandlecache;
3408
+ else
3409
+ tcon->nohandlecache = 1;
3410
+ tcon->nodelete = volume_info->nodelete;
32663411 tcon->local_lease = volume_info->local_lease;
3267
- tcon->no_lease = volume_info->no_lease;
32683412 INIT_LIST_HEAD(&tcon->pending_opens);
32693413
32703414 spin_lock(&cifs_tcp_ses_lock);
....@@ -3400,25 +3544,6 @@
34003544 return rc;
34013545 }
34023546
3403
-int
3404
-get_dfs_path(const unsigned int xid, struct cifs_ses *ses, const char *old_path,
3405
- const struct nls_table *nls_codepage, unsigned int *num_referrals,
3406
- struct dfs_info3_param **referrals, int remap)
3407
-{
3408
- int rc = 0;
3409
-
3410
- if (!ses->server->ops->get_dfs_refer)
3411
- return -ENOSYS;
3412
-
3413
- *num_referrals = 0;
3414
- *referrals = NULL;
3415
-
3416
- rc = ses->server->ops->get_dfs_refer(xid, ses, old_path,
3417
- referrals, num_referrals,
3418
- nls_codepage, remap);
3419
- return rc;
3420
-}
3421
-
34223547 #ifdef CONFIG_DEBUG_LOCK_ALLOC
34233548 static struct lock_class_key cifs_key[2];
34243549 static struct lock_class_key cifs_slock_key[2];
....@@ -3482,10 +3607,10 @@
34823607 saddr4 = (struct sockaddr_in *)&server->srcaddr;
34833608 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
34843609 if (saddr6->sin6_family == AF_INET6)
3485
- cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
3610
+ cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
34863611 &saddr6->sin6_addr, rc);
34873612 else
3488
- cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
3613
+ cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
34893614 &saddr4->sin_addr.s_addr, rc);
34903615 }
34913616 }
....@@ -3576,20 +3701,28 @@
35763701 saddr = (struct sockaddr *) &server->dstaddr;
35773702
35783703 if (server->dstaddr.ss_family == AF_INET6) {
3579
- sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3704
+ struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&server->dstaddr;
3705
+
3706
+ sport = ipv6->sin6_port;
35803707 slen = sizeof(struct sockaddr_in6);
35813708 sfamily = AF_INET6;
3709
+ cifs_dbg(FYI, "%s: connecting to [%pI6]:%d\n", __func__, &ipv6->sin6_addr,
3710
+ ntohs(sport));
35823711 } else {
3583
- sport = ((struct sockaddr_in *) saddr)->sin_port;
3712
+ struct sockaddr_in *ipv4 = (struct sockaddr_in *)&server->dstaddr;
3713
+
3714
+ sport = ipv4->sin_port;
35843715 slen = sizeof(struct sockaddr_in);
35853716 sfamily = AF_INET;
3717
+ cifs_dbg(FYI, "%s: connecting to %pI4:%d\n", __func__, &ipv4->sin_addr,
3718
+ ntohs(sport));
35863719 }
35873720
35883721 if (socket == NULL) {
35893722 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
35903723 IPPROTO_TCP, &socket, 1);
35913724 if (rc < 0) {
3592
- cifs_dbg(VFS, "Error %d creating socket\n", rc);
3725
+ cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
35933726 server->ssocket = NULL;
35943727 return rc;
35953728 }
....@@ -3624,20 +3757,22 @@
36243757 socket->sk->sk_rcvbuf = 140 * 1024;
36253758 }
36263759
3627
- if (server->tcp_nodelay) {
3628
- int val = 1;
3629
- rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY,
3630
- (char *)&val, sizeof(val));
3631
- if (rc)
3632
- cifs_dbg(FYI, "set TCP_NODELAY socket option error %d\n",
3633
- rc);
3634
- }
3760
+ if (server->tcp_nodelay)
3761
+ tcp_sock_set_nodelay(socket->sk);
36353762
36363763 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
36373764 socket->sk->sk_sndbuf,
36383765 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
36393766
3640
- rc = socket->ops->connect(socket, saddr, slen, 0);
3767
+ rc = socket->ops->connect(socket, saddr, slen,
3768
+ server->noblockcnt ? O_NONBLOCK : 0);
3769
+ /*
3770
+ * When mounting SMB root file systems, we do not want to block in
3771
+ * connect. Otherwise bail out and then let cifs_reconnect() perform
3772
+ * reconnect failover - if possible.
3773
+ */
3774
+ if (server->noblockcnt && rc == -EINPROGRESS)
3775
+ rc = 0;
36413776 if (rc < 0) {
36423777 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
36433778 sock_release(socket);
....@@ -3788,6 +3923,7 @@
37883923 spin_lock_init(&cifs_sb->tlink_tree_lock);
37893924 cifs_sb->tlink_tree = RB_ROOT;
37903925
3926
+ cifs_sb->bsize = pvolume_info->bsize;
37913927 /*
37923928 * Temporarily set r/wsize for matching superblock. If we end up using
37933929 * new sb then client will later negotiate it downward if needed.
....@@ -3805,6 +3941,8 @@
38053941 cifs_sb->actimeo = pvolume_info->actimeo;
38063942 cifs_sb->local_nls = pvolume_info->local_nls;
38073943
3944
+ if (pvolume_info->nodfs)
3945
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
38083946 if (pvolume_info->noperm)
38093947 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
38103948 if (pvolume_info->setuids)
....@@ -3831,6 +3969,8 @@
38313969 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
38323970 if (pvolume_info->rwpidforward)
38333971 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
3972
+ if (pvolume_info->mode_ace)
3973
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
38343974 if (pvolume_info->cifs_acl)
38353975 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
38363976 if (pvolume_info->backupuid_specified) {
....@@ -3858,6 +3998,14 @@
38583998 cifs_dbg(FYI, "mounting share using direct i/o\n");
38593999 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
38604000 }
4001
+ if (pvolume_info->cache_ro) {
4002
+ cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
4003
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
4004
+ } else if (pvolume_info->cache_rw) {
4005
+ cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
4006
+ cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
4007
+ CIFS_MOUNT_RW_CACHE);
4008
+ }
38614009 if (pvolume_info->mfsymlinks) {
38624010 if (pvolume_info->sfu_emul) {
38634011 /*
....@@ -3883,16 +4031,17 @@
38834031 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
38844032 if (cifs_sb->prepath == NULL)
38854033 return -ENOMEM;
4034
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
38864035 }
38874036
38884037 return 0;
38894038 }
38904039
3891
-static void
3892
-cleanup_volume_info_contents(struct smb_vol *volume_info)
4040
+void
4041
+cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
38934042 {
38944043 kfree(volume_info->username);
3895
- kzfree(volume_info->password);
4044
+ kfree_sensitive(volume_info->password);
38964045 kfree(volume_info->UNC);
38974046 kfree(volume_info->domainname);
38984047 kfree(volume_info->iocharset);
....@@ -3904,10 +4053,141 @@
39044053 {
39054054 if (!volume_info)
39064055 return;
3907
- cleanup_volume_info_contents(volume_info);
4056
+ cifs_cleanup_volume_info_contents(volume_info);
39084057 kfree(volume_info);
39094058 }
39104059
4060
+/* Release all succeed connections */
4061
+static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
4062
+ unsigned int xid,
4063
+ struct TCP_Server_Info *server,
4064
+ struct cifs_ses *ses, struct cifs_tcon *tcon)
4065
+{
4066
+ int rc = 0;
4067
+
4068
+ if (tcon)
4069
+ cifs_put_tcon(tcon);
4070
+ else if (ses)
4071
+ cifs_put_smb_ses(ses);
4072
+ else if (server)
4073
+ cifs_put_tcp_session(server, 0);
4074
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
4075
+ free_xid(xid);
4076
+}
4077
+
4078
+/* Get connections for tcp, ses and tcon */
4079
+static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
4080
+ unsigned int *xid,
4081
+ struct TCP_Server_Info **nserver,
4082
+ struct cifs_ses **nses, struct cifs_tcon **ntcon)
4083
+{
4084
+ int rc = 0;
4085
+ struct TCP_Server_Info *server;
4086
+ struct cifs_ses *ses;
4087
+ struct cifs_tcon *tcon;
4088
+
4089
+ *nserver = NULL;
4090
+ *nses = NULL;
4091
+ *ntcon = NULL;
4092
+
4093
+ *xid = get_xid();
4094
+
4095
+ /* get a reference to a tcp session */
4096
+ server = cifs_get_tcp_session(vol);
4097
+ if (IS_ERR(server)) {
4098
+ rc = PTR_ERR(server);
4099
+ return rc;
4100
+ }
4101
+
4102
+ *nserver = server;
4103
+
4104
+ /* get a reference to a SMB session */
4105
+ ses = cifs_get_smb_ses(server, vol);
4106
+ if (IS_ERR(ses)) {
4107
+ rc = PTR_ERR(ses);
4108
+ return rc;
4109
+ }
4110
+
4111
+ *nses = ses;
4112
+
4113
+ if ((vol->persistent == true) && (!(ses->server->capabilities &
4114
+ SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
4115
+ cifs_server_dbg(VFS, "persistent handles not supported by server\n");
4116
+ return -EOPNOTSUPP;
4117
+ }
4118
+
4119
+ /* search for existing tcon to this server share */
4120
+ tcon = cifs_get_tcon(ses, vol);
4121
+ if (IS_ERR(tcon)) {
4122
+ rc = PTR_ERR(tcon);
4123
+ return rc;
4124
+ }
4125
+
4126
+ *ntcon = tcon;
4127
+
4128
+ /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4129
+ if (tcon->posix_extensions)
4130
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
4131
+
4132
+ /* tell server which Unix caps we support */
4133
+ if (cap_unix(tcon->ses)) {
4134
+ /*
4135
+ * reset of caps checks mount to see if unix extensions disabled
4136
+ * for just this mount.
4137
+ */
4138
+ reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol);
4139
+ if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4140
+ (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4141
+ CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
4142
+ return -EACCES;
4143
+ } else
4144
+ tcon->unix_ext = 0; /* server does not support them */
4145
+
4146
+ /* do not care if a following call succeed - informational */
4147
+ if (!tcon->pipe && server->ops->qfs_tcon) {
4148
+ server->ops->qfs_tcon(*xid, tcon, cifs_sb);
4149
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
4150
+ if (tcon->fsDevInfo.DeviceCharacteristics &
4151
+ cpu_to_le32(FILE_READ_ONLY_DEVICE))
4152
+ cifs_dbg(VFS, "mounted to read only share\n");
4153
+ else if ((cifs_sb->mnt_cifs_flags &
4154
+ CIFS_MOUNT_RW_CACHE) == 0)
4155
+ cifs_dbg(VFS, "read only mount of RW share\n");
4156
+ /* no need to log a RW mount of a typical RW share */
4157
+ }
4158
+ }
4159
+
4160
+ cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol);
4161
+ cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol);
4162
+
4163
+ return 0;
4164
+}
4165
+
4166
+static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4167
+ struct cifs_tcon *tcon)
4168
+{
4169
+ struct tcon_link *tlink;
4170
+
4171
+ /* hang the tcon off of the superblock */
4172
+ tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4173
+ if (tlink == NULL)
4174
+ return -ENOMEM;
4175
+
4176
+ tlink->tl_uid = ses->linux_uid;
4177
+ tlink->tl_tcon = tcon;
4178
+ tlink->tl_time = jiffies;
4179
+ set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4180
+ set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4181
+
4182
+ cifs_sb->master_tlink = tlink;
4183
+ spin_lock(&cifs_sb->tlink_tree_lock);
4184
+ tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4185
+ spin_unlock(&cifs_sb->tlink_tree_lock);
4186
+
4187
+ queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4188
+ TLINK_IDLE_EXPIRE);
4189
+ return 0;
4190
+}
39114191
39124192 #ifdef CONFIG_CIFS_DFS_UPCALL
39134193 /*
....@@ -3916,22 +4196,26 @@
39164196 */
39174197 static char *
39184198 build_unc_path_to_root(const struct smb_vol *vol,
3919
- const struct cifs_sb_info *cifs_sb)
4199
+ const struct cifs_sb_info *cifs_sb, bool useppath)
39204200 {
39214201 char *full_path, *pos;
3922
- unsigned int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
4202
+ unsigned int pplen = useppath && vol->prepath ?
4203
+ strlen(vol->prepath) + 1 : 0;
39234204 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
4205
+
4206
+ if (unc_len > MAX_TREE_SIZE)
4207
+ return ERR_PTR(-EINVAL);
39244208
39254209 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
39264210 if (full_path == NULL)
39274211 return ERR_PTR(-ENOMEM);
39284212
3929
- strncpy(full_path, vol->UNC, unc_len);
4213
+ memcpy(full_path, vol->UNC, unc_len);
39304214 pos = full_path + unc_len;
39314215
39324216 if (pplen) {
39334217 *pos = CIFS_DIR_SEP(cifs_sb);
3934
- strncpy(pos + 1, vol->prepath, pplen);
4218
+ memcpy(pos + 1, vol->prepath, pplen);
39354219 pos += pplen;
39364220 }
39374221
....@@ -3941,8 +4225,9 @@
39414225 return full_path;
39424226 }
39434227
3944
-/*
3945
- * Perform a dfs referral query for a share and (optionally) prefix
4228
+/**
4229
+ * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
4230
+ *
39464231 *
39474232 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
39484233 * to a string containing updated options for the submount. Otherwise it
....@@ -3954,39 +4239,36 @@
39544239 static int
39554240 expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
39564241 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
3957
- int check_prefix)
4242
+ char *ref_path)
39584243 {
39594244 int rc;
3960
- unsigned int num_referrals = 0;
3961
- struct dfs_info3_param *referrals = NULL;
3962
- char *full_path = NULL, *ref_path = NULL, *mdata = NULL;
4245
+ struct dfs_info3_param referral = {0};
4246
+ char *full_path = NULL, *mdata = NULL;
39634247
3964
- full_path = build_unc_path_to_root(volume_info, cifs_sb);
4248
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4249
+ return -EREMOTE;
4250
+
4251
+ full_path = build_unc_path_to_root(volume_info, cifs_sb, true);
39654252 if (IS_ERR(full_path))
39664253 return PTR_ERR(full_path);
39674254
3968
- /* For DFS paths, skip the first '\' of the UNC */
3969
- ref_path = check_prefix ? full_path + 1 : volume_info->UNC + 1;
3970
-
3971
- rc = get_dfs_path(xid, ses, ref_path, cifs_sb->local_nls,
3972
- &num_referrals, &referrals, cifs_remap(cifs_sb));
3973
-
3974
- if (!rc && num_referrals > 0) {
4255
+ rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4256
+ ref_path, &referral, NULL);
4257
+ if (!rc) {
39754258 char *fake_devname = NULL;
39764259
39774260 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3978
- full_path + 1, referrals,
4261
+ full_path + 1, &referral,
39794262 &fake_devname);
3980
-
3981
- free_dfs_info_array(referrals, num_referrals);
4263
+ free_dfs_info_param(&referral);
39824264
39834265 if (IS_ERR(mdata)) {
39844266 rc = PTR_ERR(mdata);
39854267 mdata = NULL;
39864268 } else {
3987
- cleanup_volume_info_contents(volume_info);
4269
+ cifs_cleanup_volume_info_contents(volume_info);
39884270 rc = cifs_setup_volume_info(volume_info, mdata,
3989
- fake_devname, false);
4271
+ fake_devname, false);
39904272 }
39914273 kfree(fake_devname);
39924274 kfree(cifs_sb->mountdata);
....@@ -3995,9 +4277,138 @@
39954277 kfree(full_path);
39964278 return rc;
39974279 }
4280
+
4281
+static inline int get_next_dfs_tgt(const char *path,
4282
+ struct dfs_cache_tgt_list *tgt_list,
4283
+ struct dfs_cache_tgt_iterator **tgt_it)
4284
+{
4285
+ if (!*tgt_it)
4286
+ *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
4287
+ else
4288
+ *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
4289
+ return !*tgt_it ? -EHOSTDOWN : 0;
4290
+}
4291
+
4292
+static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
4293
+ struct smb_vol *fake_vol, struct smb_vol *vol)
4294
+{
4295
+ const char *tgt = dfs_cache_get_tgt_name(tgt_it);
4296
+ int len = strlen(tgt) + 2;
4297
+ char *new_unc;
4298
+
4299
+ new_unc = kmalloc(len, GFP_KERNEL);
4300
+ if (!new_unc)
4301
+ return -ENOMEM;
4302
+ scnprintf(new_unc, len, "\\%s", tgt);
4303
+
4304
+ kfree(vol->UNC);
4305
+ vol->UNC = new_unc;
4306
+
4307
+ if (fake_vol->prepath) {
4308
+ kfree(vol->prepath);
4309
+ vol->prepath = fake_vol->prepath;
4310
+ fake_vol->prepath = NULL;
4311
+ }
4312
+ memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr));
4313
+
4314
+ return 0;
4315
+}
4316
+
4317
+static int setup_dfs_tgt_conn(const char *path, const char *full_path,
4318
+ const struct dfs_cache_tgt_iterator *tgt_it,
4319
+ struct cifs_sb_info *cifs_sb, struct smb_vol *vol, unsigned int *xid,
4320
+ struct TCP_Server_Info **server, struct cifs_ses **ses,
4321
+ struct cifs_tcon **tcon)
4322
+{
4323
+ int rc;
4324
+ struct dfs_info3_param ref = {0};
4325
+ char *mdata = NULL, *fake_devname = NULL;
4326
+ struct smb_vol fake_vol = {NULL};
4327
+
4328
+ cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);
4329
+
4330
+ rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
4331
+ if (rc)
4332
+ return rc;
4333
+
4334
+ mdata = cifs_compose_mount_options(cifs_sb->mountdata, full_path + 1, &ref, &fake_devname);
4335
+ free_dfs_info_param(&ref);
4336
+
4337
+ if (IS_ERR(mdata)) {
4338
+ rc = PTR_ERR(mdata);
4339
+ mdata = NULL;
4340
+ } else {
4341
+ cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname);
4342
+ rc = cifs_setup_volume_info(&fake_vol, mdata, fake_devname,
4343
+ false);
4344
+ }
4345
+ kfree(mdata);
4346
+ kfree(fake_devname);
4347
+
4348
+ if (!rc) {
4349
+ /*
4350
+ * We use a 'fake_vol' here because we need pass it down to the
4351
+ * mount_{get,put} functions to test connection against new DFS
4352
+ * targets.
4353
+ */
4354
+ mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
4355
+ rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses,
4356
+ tcon);
4357
+ if (!rc || (*server && *ses)) {
4358
+ /*
4359
+ * We were able to connect to new target server.
4360
+ * Update current volume info with new target server.
4361
+ */
4362
+ rc = update_vol_info(tgt_it, &fake_vol, vol);
4363
+ }
4364
+ }
4365
+ cifs_cleanup_volume_info_contents(&fake_vol);
4366
+ return rc;
4367
+}
4368
+
4369
+static int do_dfs_failover(const char *path, const char *full_path, struct cifs_sb_info *cifs_sb,
4370
+ struct smb_vol *vol, struct cifs_ses *root_ses, unsigned int *xid,
4371
+ struct TCP_Server_Info **server, struct cifs_ses **ses,
4372
+ struct cifs_tcon **tcon)
4373
+{
4374
+ int rc;
4375
+ struct dfs_cache_tgt_list tgt_list;
4376
+ struct dfs_cache_tgt_iterator *tgt_it = NULL;
4377
+
4378
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4379
+ return -EOPNOTSUPP;
4380
+
4381
+ rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
4382
+ if (rc)
4383
+ return rc;
4384
+
4385
+ for (;;) {
4386
+ /* Get next DFS target server - if any */
4387
+ rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
4388
+ if (rc)
4389
+ break;
4390
+ /* Connect to next DFS target */
4391
+ rc = setup_dfs_tgt_conn(path, full_path, tgt_it, cifs_sb, vol, xid, server, ses,
4392
+ tcon);
4393
+ if (!rc || (*server && *ses))
4394
+ break;
4395
+ }
4396
+ if (!rc) {
4397
+ /*
4398
+ * Update DFS target hint in DFS referral cache with the target
4399
+ * server we successfully reconnected to.
4400
+ */
4401
+ rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
4402
+ cifs_sb->local_nls,
4403
+ cifs_remap(cifs_sb), path,
4404
+ tgt_it);
4405
+ }
4406
+ dfs_cache_free_tgts(&tgt_list);
4407
+ return rc;
4408
+}
39984409 #endif
39994410
4000
-static int
4411
+int
40014412 cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
40024413 const char *devname, bool is_smb3)
40034414 {
....@@ -4060,11 +4471,13 @@
40604471 unsigned int xid,
40614472 struct cifs_tcon *tcon,
40624473 struct cifs_sb_info *cifs_sb,
4063
- char *full_path)
4474
+ char *full_path,
4475
+ int added_treename)
40644476 {
40654477 int rc;
40664478 char *s;
40674479 char sep, tmp;
4480
+ int skip = added_treename ? 1 : 0;
40684481
40694482 sep = CIFS_DIR_SEP(cifs_sb);
40704483 s = full_path;
....@@ -4079,7 +4492,14 @@
40794492 /* next separator */
40804493 while (*s && *s != sep)
40814494 s++;
4082
-
4495
+ /*
4496
+ * if the treename is added, we then have to skip the first
4497
+ * part within the separators
4498
+ */
4499
+ if (skip) {
4500
+ skip = 0;
4501
+ continue;
4502
+ }
40834503 /*
40844504 * temporarily null-terminate the path at the end of
40854505 * the current component
....@@ -4093,227 +4513,318 @@
40934513 return rc;
40944514 }
40954515
4096
-int
4097
-cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
4516
+/*
4517
+ * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
4518
+ * otherwise 0.
4519
+ */
4520
+static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4521
+ const unsigned int xid,
4522
+ struct TCP_Server_Info *server,
4523
+ struct cifs_tcon *tcon)
40984524 {
40994525 int rc;
4526
+ char *full_path;
4527
+
4528
+ if (!server->ops->is_path_accessible)
4529
+ return -EOPNOTSUPP;
4530
+
4531
+ /*
4532
+ * cifs_build_path_to_root works only when we have a valid tcon
4533
+ */
4534
+ full_path = cifs_build_path_to_root(vol, cifs_sb, tcon,
4535
+ tcon->Flags & SMB_SHARE_IS_IN_DFS);
4536
+ if (full_path == NULL)
4537
+ return -ENOMEM;
4538
+
4539
+ cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
4540
+
4541
+ rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4542
+ full_path);
4543
+ if (rc != 0 && rc != -EREMOTE) {
4544
+ kfree(full_path);
4545
+ return rc;
4546
+ }
4547
+
4548
+ if (rc != -EREMOTE) {
4549
+ rc = cifs_are_all_path_components_accessible(server, xid, tcon,
4550
+ cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
4551
+ if (rc != 0) {
4552
+ cifs_server_dbg(VFS, "cannot query dirs between root and final path, enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
4553
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4554
+ rc = 0;
4555
+ }
4556
+ }
4557
+
4558
+ kfree(full_path);
4559
+ return rc;
4560
+}
4561
+
4562
+#ifdef CONFIG_CIFS_DFS_UPCALL
4563
+static void set_root_ses(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4564
+ struct cifs_ses **root_ses)
4565
+{
4566
+ if (ses) {
4567
+ spin_lock(&cifs_tcp_ses_lock);
4568
+ ses->ses_count++;
4569
+ if (ses->tcon_ipc)
4570
+ ses->tcon_ipc->remap = cifs_remap(cifs_sb);
4571
+ spin_unlock(&cifs_tcp_ses_lock);
4572
+ }
4573
+ *root_ses = ses;
4574
+}
4575
+
4576
+static void put_root_ses(struct cifs_ses *ses)
4577
+{
4578
+ if (ses)
4579
+ cifs_put_smb_ses(ses);
4580
+}
4581
+
4582
+/* Check if a path component is remote and then update @dfs_path accordingly */
4583
+static int check_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4584
+ const unsigned int xid, struct TCP_Server_Info *server,
4585
+ struct cifs_tcon *tcon, char **dfs_path)
4586
+{
4587
+ char *path, *s;
4588
+ char sep = CIFS_DIR_SEP(cifs_sb), tmp;
4589
+ char *npath;
4590
+ int rc = 0;
4591
+ int added_treename = tcon->Flags & SMB_SHARE_IS_IN_DFS;
4592
+ int skip = added_treename;
4593
+
4594
+ path = cifs_build_path_to_root(vol, cifs_sb, tcon, added_treename);
4595
+ if (!path)
4596
+ return -ENOMEM;
4597
+
4598
+ /*
4599
+ * Walk through the path components in @path and check if they're accessible. In case any of
4600
+ * the components is -EREMOTE, then update @dfs_path with the next DFS referral request path
4601
+ * (NOT including the remaining components).
4602
+ */
4603
+ s = path;
4604
+ do {
4605
+ /* skip separators */
4606
+ while (*s && *s == sep)
4607
+ s++;
4608
+ if (!*s)
4609
+ break;
4610
+ /* next separator */
4611
+ while (*s && *s != sep)
4612
+ s++;
4613
+ /*
4614
+ * if the treename is added, we then have to skip the first
4615
+ * part within the separators
4616
+ */
4617
+ if (skip) {
4618
+ skip = 0;
4619
+ continue;
4620
+ }
4621
+ tmp = *s;
4622
+ *s = 0;
4623
+ rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, path);
4624
+ if (rc && rc == -EREMOTE) {
4625
+ struct smb_vol v = {NULL};
4626
+ /* if @path contains a tree name, skip it in the prefix path */
4627
+ if (added_treename) {
4628
+ rc = cifs_parse_devname(path, &v);
4629
+ if (rc)
4630
+ break;
4631
+ rc = -EREMOTE;
4632
+ npath = build_unc_path_to_root(&v, cifs_sb, true);
4633
+ cifs_cleanup_volume_info_contents(&v);
4634
+ } else {
4635
+ v.UNC = vol->UNC;
4636
+ v.prepath = path + 1;
4637
+ npath = build_unc_path_to_root(&v, cifs_sb, true);
4638
+ }
4639
+ if (IS_ERR(npath)) {
4640
+ rc = PTR_ERR(npath);
4641
+ break;
4642
+ }
4643
+ kfree(*dfs_path);
4644
+ *dfs_path = npath;
4645
+ }
4646
+ *s = tmp;
4647
+ } while (rc == 0);
4648
+
4649
+ kfree(path);
4650
+ return rc;
4651
+}
4652
+
4653
+int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4654
+{
4655
+ int rc = 0;
4656
+ unsigned int xid;
4657
+ struct TCP_Server_Info *server = NULL;
4658
+ struct cifs_ses *ses = NULL, *root_ses = NULL;
4659
+ struct cifs_tcon *tcon = NULL;
4660
+ int count = 0;
4661
+ char *ref_path = NULL, *full_path = NULL;
4662
+ char *oldmnt = NULL;
4663
+ char *mntdata = NULL;
4664
+
4665
+ rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4666
+ /*
4667
+ * Unconditionally try to get an DFS referral (even cached) to determine whether it is an
4668
+ * DFS mount.
4669
+ *
4670
+ * Skip prefix path to provide support for DFS referrals from w2k8 servers which don't seem
4671
+ * to respond with PATH_NOT_COVERED to requests that include the prefix.
4672
+ */
4673
+ if (dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), vol->UNC + 1, NULL,
4674
+ NULL)) {
4675
+ /* No DFS referral was returned. Looks like a regular share. */
4676
+ if (rc)
4677
+ goto error;
4678
+ /* Check if it is fully accessible and then mount it */
4679
+ rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4680
+ if (!rc)
4681
+ goto out;
4682
+ if (rc != -EREMOTE)
4683
+ goto error;
4684
+ }
4685
+ /* Save mount options */
4686
+ mntdata = kstrndup(cifs_sb->mountdata, strlen(cifs_sb->mountdata), GFP_KERNEL);
4687
+ if (!mntdata) {
4688
+ rc = -ENOMEM;
4689
+ goto error;
4690
+ }
4691
+ /* Get path of DFS root */
4692
+ ref_path = build_unc_path_to_root(vol, cifs_sb, false);
4693
+ if (IS_ERR(ref_path)) {
4694
+ rc = PTR_ERR(ref_path);
4695
+ ref_path = NULL;
4696
+ goto error;
4697
+ }
4698
+
4699
+ set_root_ses(cifs_sb, ses, &root_ses);
4700
+ do {
4701
+ /* Save full path of last DFS path we used to resolve final target server */
4702
+ kfree(full_path);
4703
+ full_path = build_unc_path_to_root(vol, cifs_sb, !!count);
4704
+ if (IS_ERR(full_path)) {
4705
+ rc = PTR_ERR(full_path);
4706
+ full_path = NULL;
4707
+ break;
4708
+ }
4709
+ /* Chase referral */
4710
+ oldmnt = cifs_sb->mountdata;
4711
+ rc = expand_dfs_referral(xid, root_ses, vol, cifs_sb, ref_path + 1);
4712
+ if (rc)
4713
+ break;
4714
+ /* Connect to new DFS target only if we were redirected */
4715
+ if (oldmnt != cifs_sb->mountdata) {
4716
+ mount_put_conns(cifs_sb, xid, server, ses, tcon);
4717
+ rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4718
+ }
4719
+ if (rc && !server && !ses) {
4720
+ /* Failed to connect. Try to connect to other targets in the referral. */
4721
+ rc = do_dfs_failover(ref_path + 1, full_path, cifs_sb, vol, root_ses, &xid,
4722
+ &server, &ses, &tcon);
4723
+ }
4724
+ if (rc == -EACCES || rc == -EOPNOTSUPP || !server || !ses)
4725
+ break;
4726
+ if (!tcon)
4727
+ continue;
4728
+ /* Make sure that requests go through new root servers */
4729
+ if (is_tcon_dfs(tcon)) {
4730
+ put_root_ses(root_ses);
4731
+ set_root_ses(cifs_sb, ses, &root_ses);
4732
+ }
4733
+ /* Check for remaining path components and then continue chasing them (-EREMOTE) */
4734
+ rc = check_dfs_prepath(cifs_sb, vol, xid, server, tcon, &ref_path);
4735
+ /* Prevent recursion on broken link referrals */
4736
+ if (rc == -EREMOTE && ++count > MAX_NESTED_LINKS)
4737
+ rc = -ELOOP;
4738
+ } while (rc == -EREMOTE);
4739
+
4740
+ if (rc)
4741
+ goto error;
4742
+ put_root_ses(root_ses);
4743
+ root_ses = NULL;
4744
+ kfree(ref_path);
4745
+ ref_path = NULL;
4746
+ /*
4747
+ * Store DFS full path in both superblock and tree connect structures.
4748
+ *
4749
+ * For DFS root mounts, the prefix path (cifs_sb->prepath) is preserved during reconnect so
4750
+ * only the root path is set in cifs_sb->origin_fullpath and tcon->dfs_path. And for DFS
4751
+ * links, the prefix path is included in both and may be changed during reconnect. See
4752
+ * cifs_tree_connect().
4753
+ */
4754
+ cifs_sb->origin_fullpath = kstrndup(full_path, strlen(full_path), GFP_KERNEL);
4755
+ if (!cifs_sb->origin_fullpath) {
4756
+ rc = -ENOMEM;
4757
+ goto error;
4758
+ }
4759
+ spin_lock(&cifs_tcp_ses_lock);
4760
+ tcon->dfs_path = full_path;
4761
+ full_path = NULL;
4762
+ tcon->remap = cifs_remap(cifs_sb);
4763
+ spin_unlock(&cifs_tcp_ses_lock);
4764
+
4765
+ /* Add original volume information for DFS cache to be used when refreshing referrals */
4766
+ rc = dfs_cache_add_vol(mntdata, vol, cifs_sb->origin_fullpath);
4767
+ if (rc)
4768
+ goto error;
4769
+ /*
4770
+ * After reconnecting to a different server, unique ids won't
4771
+ * match anymore, so we disable serverino. This prevents
4772
+ * dentry revalidation to think the dentry are stale (ESTALE).
4773
+ */
4774
+ cifs_autodisable_serverino(cifs_sb);
4775
+ /*
4776
+ * Force the use of prefix path to support failover on DFS paths that
4777
+ * resolve to targets that have different prefix paths.
4778
+ */
4779
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4780
+ kfree(cifs_sb->prepath);
4781
+ cifs_sb->prepath = vol->prepath;
4782
+ vol->prepath = NULL;
4783
+
4784
+out:
4785
+ free_xid(xid);
4786
+ cifs_try_adding_channels(ses);
4787
+ return mount_setup_tlink(cifs_sb, ses, tcon);
4788
+
4789
+error:
4790
+ kfree(ref_path);
4791
+ kfree(full_path);
4792
+ kfree(mntdata);
4793
+ kfree(cifs_sb->origin_fullpath);
4794
+ put_root_ses(root_ses);
4795
+ mount_put_conns(cifs_sb, xid, server, ses, tcon);
4796
+ return rc;
4797
+}
4798
+#else
4799
+int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4800
+{
4801
+ int rc = 0;
41004802 unsigned int xid;
41014803 struct cifs_ses *ses;
41024804 struct cifs_tcon *tcon;
41034805 struct TCP_Server_Info *server;
4104
- char *full_path;
4105
- struct tcon_link *tlink;
4106
-#ifdef CONFIG_CIFS_DFS_UPCALL
4107
- int referral_walks_count = 0;
4108
-#endif
41094806
4110
-#ifdef CONFIG_CIFS_DFS_UPCALL
4111
-try_mount_again:
4112
- /* cleanup activities if we're chasing a referral */
4113
- if (referral_walks_count) {
4114
- if (tcon)
4115
- cifs_put_tcon(tcon);
4116
- else if (ses)
4117
- cifs_put_smb_ses(ses);
4118
-
4119
- cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
4120
-
4121
- free_xid(xid);
4122
- }
4123
-#endif
4124
- rc = 0;
4125
- tcon = NULL;
4126
- ses = NULL;
4127
- server = NULL;
4128
- full_path = NULL;
4129
- tlink = NULL;
4130
-
4131
- xid = get_xid();
4132
-
4133
- /* get a reference to a tcp session */
4134
- server = cifs_get_tcp_session(volume_info);
4135
- if (IS_ERR(server)) {
4136
- rc = PTR_ERR(server);
4137
- goto out;
4138
- }
4139
- if ((volume_info->max_credits < 20) ||
4140
- (volume_info->max_credits > 60000))
4141
- server->max_credits = SMB2_MAX_CREDITS_AVAILABLE;
4142
- else
4143
- server->max_credits = volume_info->max_credits;
4144
- /* get a reference to a SMB session */
4145
- ses = cifs_get_smb_ses(server, volume_info);
4146
- if (IS_ERR(ses)) {
4147
- rc = PTR_ERR(ses);
4148
- ses = NULL;
4149
- goto mount_fail_check;
4150
- }
4151
-
4152
- if ((volume_info->persistent == true) && ((ses->server->capabilities &
4153
- SMB2_GLOBAL_CAP_PERSISTENT_HANDLES) == 0)) {
4154
- cifs_dbg(VFS, "persistent handles not supported by server\n");
4155
- rc = -EOPNOTSUPP;
4156
- goto mount_fail_check;
4157
- }
4158
-
4159
- /* search for existing tcon to this server share */
4160
- tcon = cifs_get_tcon(ses, volume_info);
4161
- if (IS_ERR(tcon)) {
4162
- rc = PTR_ERR(tcon);
4163
- tcon = NULL;
4164
- if (rc == -EACCES)
4165
- goto mount_fail_check;
4166
-
4167
- goto remote_path_check;
4168
- }
4169
-
4170
- /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4171
- if (tcon->posix_extensions)
4172
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
4173
-
4174
- /* tell server which Unix caps we support */
4175
- if (cap_unix(tcon->ses)) {
4176
- /* reset of caps checks mount to see if unix extensions
4177
- disabled for just this mount */
4178
- reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
4179
- if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4180
- (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4181
- CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
4182
- rc = -EACCES;
4183
- goto mount_fail_check;
4184
- }
4185
- } else
4186
- tcon->unix_ext = 0; /* server does not support them */
4187
-
4188
- /* do not care if a following call succeed - informational */
4189
- if (!tcon->pipe && server->ops->qfs_tcon)
4190
- server->ops->qfs_tcon(xid, tcon);
4191
-
4192
- cifs_sb->wsize = server->ops->negotiate_wsize(tcon, volume_info);
4193
- cifs_sb->rsize = server->ops->negotiate_rsize(tcon, volume_info);
4194
-
4195
-remote_path_check:
4196
-#ifdef CONFIG_CIFS_DFS_UPCALL
4197
- /*
4198
- * Perform an unconditional check for whether there are DFS
4199
- * referrals for this path without prefix, to provide support
4200
- * for DFS referrals from w2k8 servers which don't seem to respond
4201
- * with PATH_NOT_COVERED to requests that include the prefix.
4202
- * Chase the referral if found, otherwise continue normally.
4203
- */
4204
- if (referral_walks_count == 0) {
4205
- int refrc = expand_dfs_referral(xid, ses, volume_info, cifs_sb,
4206
- false);
4207
- if (!refrc) {
4208
- referral_walks_count++;
4209
- goto try_mount_again;
4210
- }
4211
- }
4212
-#endif
4213
-
4214
- /* check if a whole path is not remote */
4215
- if (!rc && tcon) {
4216
- if (!server->ops->is_path_accessible) {
4217
- rc = -ENOSYS;
4218
- goto mount_fail_check;
4219
- }
4220
- /*
4221
- * cifs_build_path_to_root works only when we have a valid tcon
4222
- */
4223
- full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon,
4224
- tcon->Flags & SMB_SHARE_IS_IN_DFS);
4225
- if (full_path == NULL) {
4226
- rc = -ENOMEM;
4227
- goto mount_fail_check;
4228
- }
4229
- rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4230
- full_path);
4231
- if (rc != 0 && rc != -EREMOTE) {
4232
- kfree(full_path);
4233
- goto mount_fail_check;
4234
- }
4235
-
4236
- if (rc != -EREMOTE) {
4237
- rc = cifs_are_all_path_components_accessible(server,
4238
- xid, tcon, cifs_sb,
4239
- full_path);
4240
- if (rc != 0) {
4241
- cifs_dbg(VFS, "cannot query dirs between root and final path, "
4242
- "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
4243
- cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4244
- rc = 0;
4245
- }
4246
- }
4247
- kfree(full_path);
4248
- }
4249
-
4250
- /* get referral if needed */
4251
- if (rc == -EREMOTE) {
4252
-#ifdef CONFIG_CIFS_DFS_UPCALL
4253
- if (referral_walks_count > MAX_NESTED_LINKS) {
4254
- /*
4255
- * BB: when we implement proper loop detection,
4256
- * we will remove this check. But now we need it
4257
- * to prevent an indefinite loop if 'DFS tree' is
4258
- * misconfigured (i.e. has loops).
4259
- */
4260
- rc = -ELOOP;
4261
- goto mount_fail_check;
4262
- }
4263
-
4264
- rc = expand_dfs_referral(xid, ses, volume_info, cifs_sb, true);
4265
-
4266
- if (!rc) {
4267
- referral_walks_count++;
4268
- goto try_mount_again;
4269
- }
4270
- goto mount_fail_check;
4271
-#else /* No DFS support, return error on mount */
4272
- rc = -EOPNOTSUPP;
4273
-#endif
4274
- }
4275
-
4807
+ rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
42764808 if (rc)
4277
- goto mount_fail_check;
4809
+ goto error;
42784810
4279
- /* now, hang the tcon off of the superblock */
4280
- tlink = kzalloc(sizeof *tlink, GFP_KERNEL);
4281
- if (tlink == NULL) {
4282
- rc = -ENOMEM;
4283
- goto mount_fail_check;
4811
+ if (tcon) {
4812
+ rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4813
+ if (rc == -EREMOTE)
4814
+ rc = -EOPNOTSUPP;
4815
+ if (rc)
4816
+ goto error;
42844817 }
42854818
4286
- tlink->tl_uid = ses->linux_uid;
4287
- tlink->tl_tcon = tcon;
4288
- tlink->tl_time = jiffies;
4289
- set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4290
- set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4291
-
4292
- cifs_sb->master_tlink = tlink;
4293
- spin_lock(&cifs_sb->tlink_tree_lock);
4294
- tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4295
- spin_unlock(&cifs_sb->tlink_tree_lock);
4296
-
4297
- queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4298
- TLINK_IDLE_EXPIRE);
4299
-
4300
-mount_fail_check:
4301
- /* on error free sesinfo and tcon struct if needed */
4302
- if (rc) {
4303
- /* If find_unc succeeded then rc == 0 so we can not end */
4304
- /* up accidentally freeing someone elses tcon struct */
4305
- if (tcon)
4306
- cifs_put_tcon(tcon);
4307
- else if (ses)
4308
- cifs_put_smb_ses(ses);
4309
- else
4310
- cifs_put_tcp_session(server, 0);
4311
- }
4312
-
4313
-out:
43144819 free_xid(xid);
4820
+
4821
+ return mount_setup_tlink(cifs_sb, ses, tcon);
4822
+
4823
+error:
4824
+ mount_put_conns(cifs_sb, xid, server, ses, tcon);
43154825 return rc;
43164826 }
4827
+#endif
43174828
43184829 /*
43194830 * Issue a TREE_CONNECT request.
....@@ -4416,8 +4927,7 @@
44164927 bcc_ptr += strlen("?????");
44174928 bcc_ptr += 1;
44184929 count = bcc_ptr - &pSMB->Password[0];
4419
- pSMB->hdr.smb_buf_length = cpu_to_be32(be32_to_cpu(
4420
- pSMB->hdr.smb_buf_length) + count);
4930
+ be32_add_cpu(&pSMB->hdr.smb_buf_length, count);
44214931 pSMB->ByteCount = cpu_to_le16(count);
44224932
44234933 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
....@@ -4509,6 +5019,10 @@
45095019
45105020 kfree(cifs_sb->mountdata);
45115021 kfree(cifs_sb->prepath);
5022
+#ifdef CONFIG_CIFS_DFS_UPCALL
5023
+ dfs_cache_del_vol(cifs_sb->origin_fullpath);
5024
+ kfree(cifs_sb->origin_fullpath);
5025
+#endif
45125026 call_rcu(&cifs_sb->rcu, delayed_free);
45135027 }
45145028
....@@ -4516,7 +5030,7 @@
45165030 cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
45175031 {
45185032 int rc = 0;
4519
- struct TCP_Server_Info *server = ses->server;
5033
+ struct TCP_Server_Info *server = cifs_ses_server(ses);
45205034
45215035 if (!server->ops->need_neg || !server->ops->negotiate)
45225036 return -ENOSYS;
....@@ -4524,8 +5038,6 @@
45245038 /* only send once per connect */
45255039 if (!server->ops->need_neg(server))
45265040 return 0;
4527
-
4528
- set_credits(server, 1);
45295041
45305042 rc = server->ops->negotiate(xid, ses);
45315043 if (rc == 0) {
....@@ -4545,28 +5057,30 @@
45455057 struct nls_table *nls_info)
45465058 {
45475059 int rc = -ENOSYS;
4548
- struct TCP_Server_Info *server = ses->server;
5060
+ struct TCP_Server_Info *server = cifs_ses_server(ses);
45495061
4550
- ses->capabilities = server->capabilities;
4551
- if (linuxExtEnabled == 0)
4552
- ses->capabilities &= (~server->vals->cap_unix);
5062
+ if (!ses->binding) {
5063
+ ses->capabilities = server->capabilities;
5064
+ if (linuxExtEnabled == 0)
5065
+ ses->capabilities &= (~server->vals->cap_unix);
5066
+
5067
+ if (ses->auth_key.response) {
5068
+ cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
5069
+ ses->auth_key.response);
5070
+ kfree(ses->auth_key.response);
5071
+ ses->auth_key.response = NULL;
5072
+ ses->auth_key.len = 0;
5073
+ }
5074
+ }
45535075
45545076 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
45555077 server->sec_mode, server->capabilities, server->timeAdj);
4556
-
4557
- if (ses->auth_key.response) {
4558
- cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
4559
- ses->auth_key.response);
4560
- kfree(ses->auth_key.response);
4561
- ses->auth_key.response = NULL;
4562
- ses->auth_key.len = 0;
4563
- }
45645078
45655079 if (server->ops->sess_setup)
45665080 rc = server->ops->sess_setup(xid, ses, nls_info);
45675081
45685082 if (rc)
4569
- cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
5083
+ cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
45705084
45715085 return rc;
45725086 }
....@@ -4607,6 +5121,7 @@
46075121 vol_info->no_lease = master_tcon->no_lease;
46085122 vol_info->resilient = master_tcon->use_resilient;
46095123 vol_info->persistent = master_tcon->use_persistent;
5124
+ vol_info->handle_timeout = master_tcon->handle_timeout;
46105125 vol_info->no_linux_ext = !master_tcon->unix_ext;
46115126 vol_info->linux_ext = master_tcon->posix_extensions;
46125127 vol_info->sectype = master_tcon->ses->sectype;
....@@ -4642,7 +5157,7 @@
46425157
46435158 out:
46445159 kfree(vol_info->username);
4645
- kzfree(vol_info->password);
5160
+ kfree_sensitive(vol_info->password);
46465161 kfree(vol_info);
46475162
46485163 return tcon;
....@@ -4830,3 +5345,113 @@
48305345 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
48315346 TLINK_IDLE_EXPIRE);
48325347 }
5348
+
5349
+#ifdef CONFIG_CIFS_DFS_UPCALL
5350
+int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
5351
+{
5352
+ int rc;
5353
+ struct TCP_Server_Info *server = tcon->ses->server;
5354
+ const struct smb_version_operations *ops = server->ops;
5355
+ struct dfs_cache_tgt_list tl;
5356
+ struct dfs_cache_tgt_iterator *it = NULL;
5357
+ char *tree;
5358
+ const char *tcp_host;
5359
+ size_t tcp_host_len;
5360
+ const char *dfs_host;
5361
+ size_t dfs_host_len;
5362
+ char *share = NULL, *prefix = NULL;
5363
+ struct dfs_info3_param ref = {0};
5364
+ bool isroot;
5365
+
5366
+ tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
5367
+ if (!tree)
5368
+ return -ENOMEM;
5369
+
5370
+ /* If it is not dfs or there was no cached dfs referral, then reconnect to same share */
5371
+ if (!tcon->dfs_path || dfs_cache_noreq_find(tcon->dfs_path + 1, &ref, &tl)) {
5372
+ if (tcon->ipc) {
5373
+ scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
5374
+ rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
5375
+ } else {
5376
+ rc = ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc);
5377
+ }
5378
+ goto out;
5379
+ }
5380
+
5381
+ isroot = ref.server_type == DFS_TYPE_ROOT;
5382
+ free_dfs_info_param(&ref);
5383
+
5384
+ extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len);
5385
+
5386
+ for (it = dfs_cache_get_tgt_iterator(&tl); it; it = dfs_cache_get_next_tgt(&tl, it)) {
5387
+ bool target_match;
5388
+
5389
+ kfree(share);
5390
+ kfree(prefix);
5391
+ share = NULL;
5392
+ prefix = NULL;
5393
+
5394
+ rc = dfs_cache_get_tgt_share(tcon->dfs_path + 1, it, &share, &prefix);
5395
+ if (rc) {
5396
+ cifs_dbg(VFS, "%s: failed to parse target share %d\n",
5397
+ __func__, rc);
5398
+ continue;
5399
+ }
5400
+
5401
+ extract_unc_hostname(share, &dfs_host, &dfs_host_len);
5402
+
5403
+ if (dfs_host_len != tcp_host_len
5404
+ || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) {
5405
+ cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len,
5406
+ dfs_host, (int)tcp_host_len, tcp_host);
5407
+
5408
+ rc = match_target_ip(server, dfs_host, dfs_host_len, &target_match);
5409
+ if (rc) {
5410
+ cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc);
5411
+ break;
5412
+ }
5413
+
5414
+ if (!target_match) {
5415
+ cifs_dbg(FYI, "%s: skipping target\n", __func__);
5416
+ continue;
5417
+ }
5418
+ }
5419
+
5420
+ if (tcon->ipc) {
5421
+ scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", share);
5422
+ rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
5423
+ } else {
5424
+ scnprintf(tree, MAX_TREE_SIZE, "\\%s", share);
5425
+ rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
5426
+ /* Only handle prefix paths of DFS link targets */
5427
+ if (!rc && !isroot) {
5428
+ rc = update_super_prepath(tcon, prefix);
5429
+ break;
5430
+ }
5431
+ }
5432
+ if (rc == -EREMOTE)
5433
+ break;
5434
+ }
5435
+
5436
+ kfree(share);
5437
+ kfree(prefix);
5438
+
5439
+ if (!rc) {
5440
+ if (it)
5441
+ rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1, it);
5442
+ else
5443
+ rc = -ENOENT;
5444
+ }
5445
+ dfs_cache_free_tgts(&tl);
5446
+out:
5447
+ kfree(tree);
5448
+ return rc;
5449
+}
5450
+#else
5451
+int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
5452
+{
5453
+ const struct smb_version_operations *ops = tcon->ses->server->ops;
5454
+
5455
+ return ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc);
5456
+}
5457
+#endif