forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
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,7 +3035,7 @@
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 {
29433041 int rc = -ENOMEM;
....@@ -3018,16 +3116,26 @@
30183116
30193117 ses->sectype = volume_info->sectype;
30203118 ses->sign = volume_info->sign;
3021
-
30223119 mutex_lock(&ses->session_mutex);
3120
+
3121
+ /* add server as first channel */
3122
+ ses->chans[0].server = server;
3123
+ ses->chan_count = 1;
3124
+ ses->chan_max = volume_info->multichannel ? volume_info->max_channels:1;
3125
+
30233126 rc = cifs_negotiate_protocol(xid, ses);
30243127 if (!rc)
30253128 rc = cifs_setup_session(xid, ses, volume_info->local_nls);
3129
+
3130
+ /* each channel uses a different signing key */
3131
+ memcpy(ses->chans[0].signkey, ses->smb3signingkey,
3132
+ sizeof(ses->smb3signingkey));
3133
+
30263134 mutex_unlock(&ses->session_mutex);
30273135 if (rc)
30283136 goto get_ses_fail;
30293137
3030
- /* success, put it on the list */
3138
+ /* success, put it on the list and add it as first channel */
30313139 spin_lock(&cifs_tcp_ses_lock);
30323140 list_add(&ses->smb_ses_list, &server->smb_ses_list);
30333141 spin_unlock(&cifs_tcp_ses_lock);
....@@ -3054,7 +3162,11 @@
30543162 return 0;
30553163 if (tcon->snapshot_time != volume_info->snapshot_time)
30563164 return 0;
3165
+ if (tcon->handle_timeout != volume_info->handle_timeout)
3166
+ return 0;
30573167 if (tcon->no_lease != volume_info->no_lease)
3168
+ return 0;
3169
+ if (tcon->nodelete != volume_info->nodelete)
30583170 return 0;
30593171 return 1;
30603172 }
....@@ -3068,6 +3180,10 @@
30683180 spin_lock(&cifs_tcp_ses_lock);
30693181 list_for_each(tmp, &ses->tcon_list) {
30703182 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
3183
+#ifdef CONFIG_CIFS_DFS_UPCALL
3184
+ if (tcon->dfs_path)
3185
+ continue;
3186
+#endif
30713187 if (!match_tcon(tcon, volume_info))
30723188 continue;
30733189 ++tcon->tc_count;
....@@ -3170,6 +3286,16 @@
31703286 tcon->snapshot_time = volume_info->snapshot_time;
31713287 }
31723288
3289
+ if (volume_info->handle_timeout) {
3290
+ if (ses->server->vals->protocol_id == 0) {
3291
+ cifs_dbg(VFS,
3292
+ "Use SMB2.1 or later for handle timeout option\n");
3293
+ rc = -EOPNOTSUPP;
3294
+ goto out_fail;
3295
+ } else
3296
+ tcon->handle_timeout = volume_info->handle_timeout;
3297
+ }
3298
+
31733299 tcon->ses = ses;
31743300 if (volume_info->password) {
31753301 tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
....@@ -3198,10 +3324,9 @@
31983324 if (volume_info->linux_ext) {
31993325 if (ses->server->posix_ext_supported) {
32003326 tcon->posix_extensions = true;
3201
- printk_once(KERN_WARNING
3202
- "SMB3.11 POSIX Extensions are experimental\n");
3327
+ pr_warn_once("SMB3.11 POSIX Extensions are experimental\n");
32033328 } else {
3204
- cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions.\n");
3329
+ cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions\n");
32053330 rc = -EOPNOTSUPP;
32063331 goto out_fail;
32073332 }
....@@ -3219,10 +3344,6 @@
32193344 if (rc)
32203345 goto out_fail;
32213346
3222
- if (volume_info->nodfs) {
3223
- tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
3224
- cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
3225
- }
32263347 tcon->use_persistent = false;
32273348 /* check if SMB2 or later, CIFS does not support persistent handles */
32283349 if (volume_info->persistent) {
....@@ -3255,6 +3376,24 @@
32553376 tcon->use_resilient = true;
32563377 }
32573378
3379
+ /* If the user really knows what they are doing they can override */
3380
+ if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
3381
+ if (volume_info->cache_ro)
3382
+ cifs_dbg(VFS, "cache=ro requested on mount but NO_CACHING flag set on share\n");
3383
+ else if (volume_info->cache_rw)
3384
+ cifs_dbg(VFS, "cache=singleclient requested on mount but NO_CACHING flag set on share\n");
3385
+ }
3386
+
3387
+ if (volume_info->no_lease) {
3388
+ if (ses->server->vals->protocol_id == 0) {
3389
+ cifs_dbg(VFS,
3390
+ "SMB2 or later required for nolease option\n");
3391
+ rc = -EOPNOTSUPP;
3392
+ goto out_fail;
3393
+ } else
3394
+ tcon->no_lease = volume_info->no_lease;
3395
+ }
3396
+
32583397 /*
32593398 * We can have only one retry value for a connection to a share so for
32603399 * resources mounted more than once to the same server share the last
....@@ -3262,9 +3401,12 @@
32623401 */
32633402 tcon->retry = volume_info->retry;
32643403 tcon->nocase = volume_info->nocase;
3265
- tcon->nohandlecache = volume_info->nohandlecache;
3404
+ if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)
3405
+ tcon->nohandlecache = volume_info->nohandlecache;
3406
+ else
3407
+ tcon->nohandlecache = 1;
3408
+ tcon->nodelete = volume_info->nodelete;
32663409 tcon->local_lease = volume_info->local_lease;
3267
- tcon->no_lease = volume_info->no_lease;
32683410 INIT_LIST_HEAD(&tcon->pending_opens);
32693411
32703412 spin_lock(&cifs_tcp_ses_lock);
....@@ -3400,25 +3542,6 @@
34003542 return rc;
34013543 }
34023544
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
-
34223545 #ifdef CONFIG_DEBUG_LOCK_ALLOC
34233546 static struct lock_class_key cifs_key[2];
34243547 static struct lock_class_key cifs_slock_key[2];
....@@ -3482,10 +3605,10 @@
34823605 saddr4 = (struct sockaddr_in *)&server->srcaddr;
34833606 saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
34843607 if (saddr6->sin6_family == AF_INET6)
3485
- cifs_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
3608
+ cifs_server_dbg(VFS, "Failed to bind to: %pI6c, error: %d\n",
34863609 &saddr6->sin6_addr, rc);
34873610 else
3488
- cifs_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
3611
+ cifs_server_dbg(VFS, "Failed to bind to: %pI4, error: %d\n",
34893612 &saddr4->sin_addr.s_addr, rc);
34903613 }
34913614 }
....@@ -3576,20 +3699,28 @@
35763699 saddr = (struct sockaddr *) &server->dstaddr;
35773700
35783701 if (server->dstaddr.ss_family == AF_INET6) {
3579
- sport = ((struct sockaddr_in6 *) saddr)->sin6_port;
3702
+ struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&server->dstaddr;
3703
+
3704
+ sport = ipv6->sin6_port;
35803705 slen = sizeof(struct sockaddr_in6);
35813706 sfamily = AF_INET6;
3707
+ cifs_dbg(FYI, "%s: connecting to [%pI6]:%d\n", __func__, &ipv6->sin6_addr,
3708
+ ntohs(sport));
35823709 } else {
3583
- sport = ((struct sockaddr_in *) saddr)->sin_port;
3710
+ struct sockaddr_in *ipv4 = (struct sockaddr_in *)&server->dstaddr;
3711
+
3712
+ sport = ipv4->sin_port;
35843713 slen = sizeof(struct sockaddr_in);
35853714 sfamily = AF_INET;
3715
+ cifs_dbg(FYI, "%s: connecting to %pI4:%d\n", __func__, &ipv4->sin_addr,
3716
+ ntohs(sport));
35863717 }
35873718
35883719 if (socket == NULL) {
35893720 rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM,
35903721 IPPROTO_TCP, &socket, 1);
35913722 if (rc < 0) {
3592
- cifs_dbg(VFS, "Error %d creating socket\n", rc);
3723
+ cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
35933724 server->ssocket = NULL;
35943725 return rc;
35953726 }
....@@ -3624,20 +3755,22 @@
36243755 socket->sk->sk_rcvbuf = 140 * 1024;
36253756 }
36263757
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
- }
3758
+ if (server->tcp_nodelay)
3759
+ tcp_sock_set_nodelay(socket->sk);
36353760
36363761 cifs_dbg(FYI, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx\n",
36373762 socket->sk->sk_sndbuf,
36383763 socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo);
36393764
3640
- rc = socket->ops->connect(socket, saddr, slen, 0);
3765
+ rc = socket->ops->connect(socket, saddr, slen,
3766
+ server->noblockcnt ? O_NONBLOCK : 0);
3767
+ /*
3768
+ * When mounting SMB root file systems, we do not want to block in
3769
+ * connect. Otherwise bail out and then let cifs_reconnect() perform
3770
+ * reconnect failover - if possible.
3771
+ */
3772
+ if (server->noblockcnt && rc == -EINPROGRESS)
3773
+ rc = 0;
36413774 if (rc < 0) {
36423775 cifs_dbg(FYI, "Error %d connecting to server\n", rc);
36433776 sock_release(socket);
....@@ -3788,6 +3921,7 @@
37883921 spin_lock_init(&cifs_sb->tlink_tree_lock);
37893922 cifs_sb->tlink_tree = RB_ROOT;
37903923
3924
+ cifs_sb->bsize = pvolume_info->bsize;
37913925 /*
37923926 * Temporarily set r/wsize for matching superblock. If we end up using
37933927 * new sb then client will later negotiate it downward if needed.
....@@ -3805,6 +3939,8 @@
38053939 cifs_sb->actimeo = pvolume_info->actimeo;
38063940 cifs_sb->local_nls = pvolume_info->local_nls;
38073941
3942
+ if (pvolume_info->nodfs)
3943
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
38083944 if (pvolume_info->noperm)
38093945 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
38103946 if (pvolume_info->setuids)
....@@ -3831,6 +3967,8 @@
38313967 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
38323968 if (pvolume_info->rwpidforward)
38333969 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
3970
+ if (pvolume_info->mode_ace)
3971
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
38343972 if (pvolume_info->cifs_acl)
38353973 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
38363974 if (pvolume_info->backupuid_specified) {
....@@ -3858,6 +3996,14 @@
38583996 cifs_dbg(FYI, "mounting share using direct i/o\n");
38593997 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
38603998 }
3999
+ if (pvolume_info->cache_ro) {
4000
+ cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
4001
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
4002
+ } else if (pvolume_info->cache_rw) {
4003
+ cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
4004
+ cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
4005
+ CIFS_MOUNT_RW_CACHE);
4006
+ }
38614007 if (pvolume_info->mfsymlinks) {
38624008 if (pvolume_info->sfu_emul) {
38634009 /*
....@@ -3883,16 +4029,17 @@
38834029 cifs_sb->prepath = kstrdup(pvolume_info->prepath, GFP_KERNEL);
38844030 if (cifs_sb->prepath == NULL)
38854031 return -ENOMEM;
4032
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
38864033 }
38874034
38884035 return 0;
38894036 }
38904037
3891
-static void
3892
-cleanup_volume_info_contents(struct smb_vol *volume_info)
4038
+void
4039
+cifs_cleanup_volume_info_contents(struct smb_vol *volume_info)
38934040 {
38944041 kfree(volume_info->username);
3895
- kzfree(volume_info->password);
4042
+ kfree_sensitive(volume_info->password);
38964043 kfree(volume_info->UNC);
38974044 kfree(volume_info->domainname);
38984045 kfree(volume_info->iocharset);
....@@ -3904,10 +4051,141 @@
39044051 {
39054052 if (!volume_info)
39064053 return;
3907
- cleanup_volume_info_contents(volume_info);
4054
+ cifs_cleanup_volume_info_contents(volume_info);
39084055 kfree(volume_info);
39094056 }
39104057
4058
+/* Release all succeed connections */
4059
+static inline void mount_put_conns(struct cifs_sb_info *cifs_sb,
4060
+ unsigned int xid,
4061
+ struct TCP_Server_Info *server,
4062
+ struct cifs_ses *ses, struct cifs_tcon *tcon)
4063
+{
4064
+ int rc = 0;
4065
+
4066
+ if (tcon)
4067
+ cifs_put_tcon(tcon);
4068
+ else if (ses)
4069
+ cifs_put_smb_ses(ses);
4070
+ else if (server)
4071
+ cifs_put_tcp_session(server, 0);
4072
+ cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
4073
+ free_xid(xid);
4074
+}
4075
+
4076
+/* Get connections for tcp, ses and tcon */
4077
+static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
4078
+ unsigned int *xid,
4079
+ struct TCP_Server_Info **nserver,
4080
+ struct cifs_ses **nses, struct cifs_tcon **ntcon)
4081
+{
4082
+ int rc = 0;
4083
+ struct TCP_Server_Info *server;
4084
+ struct cifs_ses *ses;
4085
+ struct cifs_tcon *tcon;
4086
+
4087
+ *nserver = NULL;
4088
+ *nses = NULL;
4089
+ *ntcon = NULL;
4090
+
4091
+ *xid = get_xid();
4092
+
4093
+ /* get a reference to a tcp session */
4094
+ server = cifs_get_tcp_session(vol);
4095
+ if (IS_ERR(server)) {
4096
+ rc = PTR_ERR(server);
4097
+ return rc;
4098
+ }
4099
+
4100
+ *nserver = server;
4101
+
4102
+ /* get a reference to a SMB session */
4103
+ ses = cifs_get_smb_ses(server, vol);
4104
+ if (IS_ERR(ses)) {
4105
+ rc = PTR_ERR(ses);
4106
+ return rc;
4107
+ }
4108
+
4109
+ *nses = ses;
4110
+
4111
+ if ((vol->persistent == true) && (!(ses->server->capabilities &
4112
+ SMB2_GLOBAL_CAP_PERSISTENT_HANDLES))) {
4113
+ cifs_server_dbg(VFS, "persistent handles not supported by server\n");
4114
+ return -EOPNOTSUPP;
4115
+ }
4116
+
4117
+ /* search for existing tcon to this server share */
4118
+ tcon = cifs_get_tcon(ses, vol);
4119
+ if (IS_ERR(tcon)) {
4120
+ rc = PTR_ERR(tcon);
4121
+ return rc;
4122
+ }
4123
+
4124
+ *ntcon = tcon;
4125
+
4126
+ /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */
4127
+ if (tcon->posix_extensions)
4128
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
4129
+
4130
+ /* tell server which Unix caps we support */
4131
+ if (cap_unix(tcon->ses)) {
4132
+ /*
4133
+ * reset of caps checks mount to see if unix extensions disabled
4134
+ * for just this mount.
4135
+ */
4136
+ reset_cifs_unix_caps(*xid, tcon, cifs_sb, vol);
4137
+ if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
4138
+ (le64_to_cpu(tcon->fsUnixInfo.Capability) &
4139
+ CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP))
4140
+ return -EACCES;
4141
+ } else
4142
+ tcon->unix_ext = 0; /* server does not support them */
4143
+
4144
+ /* do not care if a following call succeed - informational */
4145
+ if (!tcon->pipe && server->ops->qfs_tcon) {
4146
+ server->ops->qfs_tcon(*xid, tcon, cifs_sb);
4147
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
4148
+ if (tcon->fsDevInfo.DeviceCharacteristics &
4149
+ cpu_to_le32(FILE_READ_ONLY_DEVICE))
4150
+ cifs_dbg(VFS, "mounted to read only share\n");
4151
+ else if ((cifs_sb->mnt_cifs_flags &
4152
+ CIFS_MOUNT_RW_CACHE) == 0)
4153
+ cifs_dbg(VFS, "read only mount of RW share\n");
4154
+ /* no need to log a RW mount of a typical RW share */
4155
+ }
4156
+ }
4157
+
4158
+ cifs_sb->wsize = server->ops->negotiate_wsize(tcon, vol);
4159
+ cifs_sb->rsize = server->ops->negotiate_rsize(tcon, vol);
4160
+
4161
+ return 0;
4162
+}
4163
+
4164
+static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4165
+ struct cifs_tcon *tcon)
4166
+{
4167
+ struct tcon_link *tlink;
4168
+
4169
+ /* hang the tcon off of the superblock */
4170
+ tlink = kzalloc(sizeof(*tlink), GFP_KERNEL);
4171
+ if (tlink == NULL)
4172
+ return -ENOMEM;
4173
+
4174
+ tlink->tl_uid = ses->linux_uid;
4175
+ tlink->tl_tcon = tcon;
4176
+ tlink->tl_time = jiffies;
4177
+ set_bit(TCON_LINK_MASTER, &tlink->tl_flags);
4178
+ set_bit(TCON_LINK_IN_TREE, &tlink->tl_flags);
4179
+
4180
+ cifs_sb->master_tlink = tlink;
4181
+ spin_lock(&cifs_sb->tlink_tree_lock);
4182
+ tlink_rb_insert(&cifs_sb->tlink_tree, tlink);
4183
+ spin_unlock(&cifs_sb->tlink_tree_lock);
4184
+
4185
+ queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
4186
+ TLINK_IDLE_EXPIRE);
4187
+ return 0;
4188
+}
39114189
39124190 #ifdef CONFIG_CIFS_DFS_UPCALL
39134191 /*
....@@ -3916,22 +4194,26 @@
39164194 */
39174195 static char *
39184196 build_unc_path_to_root(const struct smb_vol *vol,
3919
- const struct cifs_sb_info *cifs_sb)
4197
+ const struct cifs_sb_info *cifs_sb, bool useppath)
39204198 {
39214199 char *full_path, *pos;
3922
- unsigned int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
4200
+ unsigned int pplen = useppath && vol->prepath ?
4201
+ strlen(vol->prepath) + 1 : 0;
39234202 unsigned int unc_len = strnlen(vol->UNC, MAX_TREE_SIZE + 1);
4203
+
4204
+ if (unc_len > MAX_TREE_SIZE)
4205
+ return ERR_PTR(-EINVAL);
39244206
39254207 full_path = kmalloc(unc_len + pplen + 1, GFP_KERNEL);
39264208 if (full_path == NULL)
39274209 return ERR_PTR(-ENOMEM);
39284210
3929
- strncpy(full_path, vol->UNC, unc_len);
4211
+ memcpy(full_path, vol->UNC, unc_len);
39304212 pos = full_path + unc_len;
39314213
39324214 if (pplen) {
39334215 *pos = CIFS_DIR_SEP(cifs_sb);
3934
- strncpy(pos + 1, vol->prepath, pplen);
4216
+ memcpy(pos + 1, vol->prepath, pplen);
39354217 pos += pplen;
39364218 }
39374219
....@@ -3941,8 +4223,9 @@
39414223 return full_path;
39424224 }
39434225
3944
-/*
3945
- * Perform a dfs referral query for a share and (optionally) prefix
4226
+/**
4227
+ * expand_dfs_referral - Perform a dfs referral query and update the cifs_sb
4228
+ *
39464229 *
39474230 * If a referral is found, cifs_sb->mountdata will be (re-)allocated
39484231 * to a string containing updated options for the submount. Otherwise it
....@@ -3954,39 +4237,36 @@
39544237 static int
39554238 expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
39564239 struct smb_vol *volume_info, struct cifs_sb_info *cifs_sb,
3957
- int check_prefix)
4240
+ char *ref_path)
39584241 {
39594242 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;
4243
+ struct dfs_info3_param referral = {0};
4244
+ char *full_path = NULL, *mdata = NULL;
39634245
3964
- full_path = build_unc_path_to_root(volume_info, cifs_sb);
4246
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4247
+ return -EREMOTE;
4248
+
4249
+ full_path = build_unc_path_to_root(volume_info, cifs_sb, true);
39654250 if (IS_ERR(full_path))
39664251 return PTR_ERR(full_path);
39674252
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) {
4253
+ rc = dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb),
4254
+ ref_path, &referral, NULL);
4255
+ if (!rc) {
39754256 char *fake_devname = NULL;
39764257
39774258 mdata = cifs_compose_mount_options(cifs_sb->mountdata,
3978
- full_path + 1, referrals,
4259
+ full_path + 1, &referral,
39794260 &fake_devname);
3980
-
3981
- free_dfs_info_array(referrals, num_referrals);
4261
+ free_dfs_info_param(&referral);
39824262
39834263 if (IS_ERR(mdata)) {
39844264 rc = PTR_ERR(mdata);
39854265 mdata = NULL;
39864266 } else {
3987
- cleanup_volume_info_contents(volume_info);
4267
+ cifs_cleanup_volume_info_contents(volume_info);
39884268 rc = cifs_setup_volume_info(volume_info, mdata,
3989
- fake_devname, false);
4269
+ fake_devname, false);
39904270 }
39914271 kfree(fake_devname);
39924272 kfree(cifs_sb->mountdata);
....@@ -3995,9 +4275,138 @@
39954275 kfree(full_path);
39964276 return rc;
39974277 }
4278
+
4279
+static inline int get_next_dfs_tgt(const char *path,
4280
+ struct dfs_cache_tgt_list *tgt_list,
4281
+ struct dfs_cache_tgt_iterator **tgt_it)
4282
+{
4283
+ if (!*tgt_it)
4284
+ *tgt_it = dfs_cache_get_tgt_iterator(tgt_list);
4285
+ else
4286
+ *tgt_it = dfs_cache_get_next_tgt(tgt_list, *tgt_it);
4287
+ return !*tgt_it ? -EHOSTDOWN : 0;
4288
+}
4289
+
4290
+static int update_vol_info(const struct dfs_cache_tgt_iterator *tgt_it,
4291
+ struct smb_vol *fake_vol, struct smb_vol *vol)
4292
+{
4293
+ const char *tgt = dfs_cache_get_tgt_name(tgt_it);
4294
+ int len = strlen(tgt) + 2;
4295
+ char *new_unc;
4296
+
4297
+ new_unc = kmalloc(len, GFP_KERNEL);
4298
+ if (!new_unc)
4299
+ return -ENOMEM;
4300
+ scnprintf(new_unc, len, "\\%s", tgt);
4301
+
4302
+ kfree(vol->UNC);
4303
+ vol->UNC = new_unc;
4304
+
4305
+ if (fake_vol->prepath) {
4306
+ kfree(vol->prepath);
4307
+ vol->prepath = fake_vol->prepath;
4308
+ fake_vol->prepath = NULL;
4309
+ }
4310
+ memcpy(&vol->dstaddr, &fake_vol->dstaddr, sizeof(vol->dstaddr));
4311
+
4312
+ return 0;
4313
+}
4314
+
4315
+static int setup_dfs_tgt_conn(const char *path, const char *full_path,
4316
+ const struct dfs_cache_tgt_iterator *tgt_it,
4317
+ struct cifs_sb_info *cifs_sb, struct smb_vol *vol, unsigned int *xid,
4318
+ struct TCP_Server_Info **server, struct cifs_ses **ses,
4319
+ struct cifs_tcon **tcon)
4320
+{
4321
+ int rc;
4322
+ struct dfs_info3_param ref = {0};
4323
+ char *mdata = NULL, *fake_devname = NULL;
4324
+ struct smb_vol fake_vol = {NULL};
4325
+
4326
+ cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);
4327
+
4328
+ rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
4329
+ if (rc)
4330
+ return rc;
4331
+
4332
+ mdata = cifs_compose_mount_options(cifs_sb->mountdata, full_path + 1, &ref, &fake_devname);
4333
+ free_dfs_info_param(&ref);
4334
+
4335
+ if (IS_ERR(mdata)) {
4336
+ rc = PTR_ERR(mdata);
4337
+ mdata = NULL;
4338
+ } else {
4339
+ cifs_dbg(FYI, "%s: fake_devname: %s\n", __func__, fake_devname);
4340
+ rc = cifs_setup_volume_info(&fake_vol, mdata, fake_devname,
4341
+ false);
4342
+ }
4343
+ kfree(mdata);
4344
+ kfree(fake_devname);
4345
+
4346
+ if (!rc) {
4347
+ /*
4348
+ * We use a 'fake_vol' here because we need pass it down to the
4349
+ * mount_{get,put} functions to test connection against new DFS
4350
+ * targets.
4351
+ */
4352
+ mount_put_conns(cifs_sb, *xid, *server, *ses, *tcon);
4353
+ rc = mount_get_conns(&fake_vol, cifs_sb, xid, server, ses,
4354
+ tcon);
4355
+ if (!rc || (*server && *ses)) {
4356
+ /*
4357
+ * We were able to connect to new target server.
4358
+ * Update current volume info with new target server.
4359
+ */
4360
+ rc = update_vol_info(tgt_it, &fake_vol, vol);
4361
+ }
4362
+ }
4363
+ cifs_cleanup_volume_info_contents(&fake_vol);
4364
+ return rc;
4365
+}
4366
+
4367
+static int do_dfs_failover(const char *path, const char *full_path, struct cifs_sb_info *cifs_sb,
4368
+ struct smb_vol *vol, struct cifs_ses *root_ses, unsigned int *xid,
4369
+ struct TCP_Server_Info **server, struct cifs_ses **ses,
4370
+ struct cifs_tcon **tcon)
4371
+{
4372
+ int rc;
4373
+ struct dfs_cache_tgt_list tgt_list;
4374
+ struct dfs_cache_tgt_iterator *tgt_it = NULL;
4375
+
4376
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
4377
+ return -EOPNOTSUPP;
4378
+
4379
+ rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
4380
+ if (rc)
4381
+ return rc;
4382
+
4383
+ for (;;) {
4384
+ /* Get next DFS target server - if any */
4385
+ rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
4386
+ if (rc)
4387
+ break;
4388
+ /* Connect to next DFS target */
4389
+ rc = setup_dfs_tgt_conn(path, full_path, tgt_it, cifs_sb, vol, xid, server, ses,
4390
+ tcon);
4391
+ if (!rc || (*server && *ses))
4392
+ break;
4393
+ }
4394
+ if (!rc) {
4395
+ /*
4396
+ * Update DFS target hint in DFS referral cache with the target
4397
+ * server we successfully reconnected to.
4398
+ */
4399
+ rc = dfs_cache_update_tgthint(*xid, root_ses ? root_ses : *ses,
4400
+ cifs_sb->local_nls,
4401
+ cifs_remap(cifs_sb), path,
4402
+ tgt_it);
4403
+ }
4404
+ dfs_cache_free_tgts(&tgt_list);
4405
+ return rc;
4406
+}
39984407 #endif
39994408
4000
-static int
4409
+int
40014410 cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
40024411 const char *devname, bool is_smb3)
40034412 {
....@@ -4060,11 +4469,13 @@
40604469 unsigned int xid,
40614470 struct cifs_tcon *tcon,
40624471 struct cifs_sb_info *cifs_sb,
4063
- char *full_path)
4472
+ char *full_path,
4473
+ int added_treename)
40644474 {
40654475 int rc;
40664476 char *s;
40674477 char sep, tmp;
4478
+ int skip = added_treename ? 1 : 0;
40684479
40694480 sep = CIFS_DIR_SEP(cifs_sb);
40704481 s = full_path;
....@@ -4079,7 +4490,14 @@
40794490 /* next separator */
40804491 while (*s && *s != sep)
40814492 s++;
4082
-
4493
+ /*
4494
+ * if the treename is added, we then have to skip the first
4495
+ * part within the separators
4496
+ */
4497
+ if (skip) {
4498
+ skip = 0;
4499
+ continue;
4500
+ }
40834501 /*
40844502 * temporarily null-terminate the path at the end of
40854503 * the current component
....@@ -4093,227 +4511,318 @@
40934511 return rc;
40944512 }
40954513
4096
-int
4097
-cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
4514
+/*
4515
+ * Check if path is remote (e.g. a DFS share). Return -EREMOTE if it is,
4516
+ * otherwise 0.
4517
+ */
4518
+static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4519
+ const unsigned int xid,
4520
+ struct TCP_Server_Info *server,
4521
+ struct cifs_tcon *tcon)
40984522 {
40994523 int rc;
4524
+ char *full_path;
4525
+
4526
+ if (!server->ops->is_path_accessible)
4527
+ return -EOPNOTSUPP;
4528
+
4529
+ /*
4530
+ * cifs_build_path_to_root works only when we have a valid tcon
4531
+ */
4532
+ full_path = cifs_build_path_to_root(vol, cifs_sb, tcon,
4533
+ tcon->Flags & SMB_SHARE_IS_IN_DFS);
4534
+ if (full_path == NULL)
4535
+ return -ENOMEM;
4536
+
4537
+ cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
4538
+
4539
+ rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
4540
+ full_path);
4541
+ if (rc != 0 && rc != -EREMOTE) {
4542
+ kfree(full_path);
4543
+ return rc;
4544
+ }
4545
+
4546
+ if (rc != -EREMOTE) {
4547
+ rc = cifs_are_all_path_components_accessible(server, xid, tcon,
4548
+ cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
4549
+ if (rc != 0) {
4550
+ cifs_server_dbg(VFS, "cannot query dirs between root and final path, enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
4551
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4552
+ rc = 0;
4553
+ }
4554
+ }
4555
+
4556
+ kfree(full_path);
4557
+ return rc;
4558
+}
4559
+
4560
+#ifdef CONFIG_CIFS_DFS_UPCALL
4561
+static void set_root_ses(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
4562
+ struct cifs_ses **root_ses)
4563
+{
4564
+ if (ses) {
4565
+ spin_lock(&cifs_tcp_ses_lock);
4566
+ ses->ses_count++;
4567
+ if (ses->tcon_ipc)
4568
+ ses->tcon_ipc->remap = cifs_remap(cifs_sb);
4569
+ spin_unlock(&cifs_tcp_ses_lock);
4570
+ }
4571
+ *root_ses = ses;
4572
+}
4573
+
4574
+static void put_root_ses(struct cifs_ses *ses)
4575
+{
4576
+ if (ses)
4577
+ cifs_put_smb_ses(ses);
4578
+}
4579
+
4580
+/* Check if a path component is remote and then update @dfs_path accordingly */
4581
+static int check_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb_vol *vol,
4582
+ const unsigned int xid, struct TCP_Server_Info *server,
4583
+ struct cifs_tcon *tcon, char **dfs_path)
4584
+{
4585
+ char *path, *s;
4586
+ char sep = CIFS_DIR_SEP(cifs_sb), tmp;
4587
+ char *npath;
4588
+ int rc = 0;
4589
+ int added_treename = tcon->Flags & SMB_SHARE_IS_IN_DFS;
4590
+ int skip = added_treename;
4591
+
4592
+ path = cifs_build_path_to_root(vol, cifs_sb, tcon, added_treename);
4593
+ if (!path)
4594
+ return -ENOMEM;
4595
+
4596
+ /*
4597
+ * Walk through the path components in @path and check if they're accessible. In case any of
4598
+ * the components is -EREMOTE, then update @dfs_path with the next DFS referral request path
4599
+ * (NOT including the remaining components).
4600
+ */
4601
+ s = path;
4602
+ do {
4603
+ /* skip separators */
4604
+ while (*s && *s == sep)
4605
+ s++;
4606
+ if (!*s)
4607
+ break;
4608
+ /* next separator */
4609
+ while (*s && *s != sep)
4610
+ s++;
4611
+ /*
4612
+ * if the treename is added, we then have to skip the first
4613
+ * part within the separators
4614
+ */
4615
+ if (skip) {
4616
+ skip = 0;
4617
+ continue;
4618
+ }
4619
+ tmp = *s;
4620
+ *s = 0;
4621
+ rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, path);
4622
+ if (rc && rc == -EREMOTE) {
4623
+ struct smb_vol v = {NULL};
4624
+ /* if @path contains a tree name, skip it in the prefix path */
4625
+ if (added_treename) {
4626
+ rc = cifs_parse_devname(path, &v);
4627
+ if (rc)
4628
+ break;
4629
+ rc = -EREMOTE;
4630
+ npath = build_unc_path_to_root(&v, cifs_sb, true);
4631
+ cifs_cleanup_volume_info_contents(&v);
4632
+ } else {
4633
+ v.UNC = vol->UNC;
4634
+ v.prepath = path + 1;
4635
+ npath = build_unc_path_to_root(&v, cifs_sb, true);
4636
+ }
4637
+ if (IS_ERR(npath)) {
4638
+ rc = PTR_ERR(npath);
4639
+ break;
4640
+ }
4641
+ kfree(*dfs_path);
4642
+ *dfs_path = npath;
4643
+ }
4644
+ *s = tmp;
4645
+ } while (rc == 0);
4646
+
4647
+ kfree(path);
4648
+ return rc;
4649
+}
4650
+
4651
+int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4652
+{
4653
+ int rc = 0;
4654
+ unsigned int xid;
4655
+ struct TCP_Server_Info *server = NULL;
4656
+ struct cifs_ses *ses = NULL, *root_ses = NULL;
4657
+ struct cifs_tcon *tcon = NULL;
4658
+ int count = 0;
4659
+ char *ref_path = NULL, *full_path = NULL;
4660
+ char *oldmnt = NULL;
4661
+ char *mntdata = NULL;
4662
+
4663
+ rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4664
+ /*
4665
+ * Unconditionally try to get an DFS referral (even cached) to determine whether it is an
4666
+ * DFS mount.
4667
+ *
4668
+ * Skip prefix path to provide support for DFS referrals from w2k8 servers which don't seem
4669
+ * to respond with PATH_NOT_COVERED to requests that include the prefix.
4670
+ */
4671
+ if (dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), vol->UNC + 1, NULL,
4672
+ NULL)) {
4673
+ /* No DFS referral was returned. Looks like a regular share. */
4674
+ if (rc)
4675
+ goto error;
4676
+ /* Check if it is fully accessible and then mount it */
4677
+ rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4678
+ if (!rc)
4679
+ goto out;
4680
+ if (rc != -EREMOTE)
4681
+ goto error;
4682
+ }
4683
+ /* Save mount options */
4684
+ mntdata = kstrndup(cifs_sb->mountdata, strlen(cifs_sb->mountdata), GFP_KERNEL);
4685
+ if (!mntdata) {
4686
+ rc = -ENOMEM;
4687
+ goto error;
4688
+ }
4689
+ /* Get path of DFS root */
4690
+ ref_path = build_unc_path_to_root(vol, cifs_sb, false);
4691
+ if (IS_ERR(ref_path)) {
4692
+ rc = PTR_ERR(ref_path);
4693
+ ref_path = NULL;
4694
+ goto error;
4695
+ }
4696
+
4697
+ set_root_ses(cifs_sb, ses, &root_ses);
4698
+ do {
4699
+ /* Save full path of last DFS path we used to resolve final target server */
4700
+ kfree(full_path);
4701
+ full_path = build_unc_path_to_root(vol, cifs_sb, !!count);
4702
+ if (IS_ERR(full_path)) {
4703
+ rc = PTR_ERR(full_path);
4704
+ full_path = NULL;
4705
+ break;
4706
+ }
4707
+ /* Chase referral */
4708
+ oldmnt = cifs_sb->mountdata;
4709
+ rc = expand_dfs_referral(xid, root_ses, vol, cifs_sb, ref_path + 1);
4710
+ if (rc)
4711
+ break;
4712
+ /* Connect to new DFS target only if we were redirected */
4713
+ if (oldmnt != cifs_sb->mountdata) {
4714
+ mount_put_conns(cifs_sb, xid, server, ses, tcon);
4715
+ rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
4716
+ }
4717
+ if (rc && !server && !ses) {
4718
+ /* Failed to connect. Try to connect to other targets in the referral. */
4719
+ rc = do_dfs_failover(ref_path + 1, full_path, cifs_sb, vol, root_ses, &xid,
4720
+ &server, &ses, &tcon);
4721
+ }
4722
+ if (rc == -EACCES || rc == -EOPNOTSUPP || !server || !ses)
4723
+ break;
4724
+ if (!tcon)
4725
+ continue;
4726
+ /* Make sure that requests go through new root servers */
4727
+ if (is_tcon_dfs(tcon)) {
4728
+ put_root_ses(root_ses);
4729
+ set_root_ses(cifs_sb, ses, &root_ses);
4730
+ }
4731
+ /* Check for remaining path components and then continue chasing them (-EREMOTE) */
4732
+ rc = check_dfs_prepath(cifs_sb, vol, xid, server, tcon, &ref_path);
4733
+ /* Prevent recursion on broken link referrals */
4734
+ if (rc == -EREMOTE && ++count > MAX_NESTED_LINKS)
4735
+ rc = -ELOOP;
4736
+ } while (rc == -EREMOTE);
4737
+
4738
+ if (rc)
4739
+ goto error;
4740
+ put_root_ses(root_ses);
4741
+ root_ses = NULL;
4742
+ kfree(ref_path);
4743
+ ref_path = NULL;
4744
+ /*
4745
+ * Store DFS full path in both superblock and tree connect structures.
4746
+ *
4747
+ * For DFS root mounts, the prefix path (cifs_sb->prepath) is preserved during reconnect so
4748
+ * only the root path is set in cifs_sb->origin_fullpath and tcon->dfs_path. And for DFS
4749
+ * links, the prefix path is included in both and may be changed during reconnect. See
4750
+ * cifs_tree_connect().
4751
+ */
4752
+ cifs_sb->origin_fullpath = kstrndup(full_path, strlen(full_path), GFP_KERNEL);
4753
+ if (!cifs_sb->origin_fullpath) {
4754
+ rc = -ENOMEM;
4755
+ goto error;
4756
+ }
4757
+ spin_lock(&cifs_tcp_ses_lock);
4758
+ tcon->dfs_path = full_path;
4759
+ full_path = NULL;
4760
+ tcon->remap = cifs_remap(cifs_sb);
4761
+ spin_unlock(&cifs_tcp_ses_lock);
4762
+
4763
+ /* Add original volume information for DFS cache to be used when refreshing referrals */
4764
+ rc = dfs_cache_add_vol(mntdata, vol, cifs_sb->origin_fullpath);
4765
+ if (rc)
4766
+ goto error;
4767
+ /*
4768
+ * After reconnecting to a different server, unique ids won't
4769
+ * match anymore, so we disable serverino. This prevents
4770
+ * dentry revalidation to think the dentry are stale (ESTALE).
4771
+ */
4772
+ cifs_autodisable_serverino(cifs_sb);
4773
+ /*
4774
+ * Force the use of prefix path to support failover on DFS paths that
4775
+ * resolve to targets that have different prefix paths.
4776
+ */
4777
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
4778
+ kfree(cifs_sb->prepath);
4779
+ cifs_sb->prepath = vol->prepath;
4780
+ vol->prepath = NULL;
4781
+
4782
+out:
4783
+ free_xid(xid);
4784
+ cifs_try_adding_channels(ses);
4785
+ return mount_setup_tlink(cifs_sb, ses, tcon);
4786
+
4787
+error:
4788
+ kfree(ref_path);
4789
+ kfree(full_path);
4790
+ kfree(mntdata);
4791
+ kfree(cifs_sb->origin_fullpath);
4792
+ put_root_ses(root_ses);
4793
+ mount_put_conns(cifs_sb, xid, server, ses, tcon);
4794
+ return rc;
4795
+}
4796
+#else
4797
+int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol)
4798
+{
4799
+ int rc = 0;
41004800 unsigned int xid;
41014801 struct cifs_ses *ses;
41024802 struct cifs_tcon *tcon;
41034803 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
41094804
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
-
4805
+ rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon);
42764806 if (rc)
4277
- goto mount_fail_check;
4807
+ goto error;
42784808
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;
4809
+ if (tcon) {
4810
+ rc = is_path_remote(cifs_sb, vol, xid, server, tcon);
4811
+ if (rc == -EREMOTE)
4812
+ rc = -EOPNOTSUPP;
4813
+ if (rc)
4814
+ goto error;
42844815 }
42854816
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:
43144817 free_xid(xid);
4818
+
4819
+ return mount_setup_tlink(cifs_sb, ses, tcon);
4820
+
4821
+error:
4822
+ mount_put_conns(cifs_sb, xid, server, ses, tcon);
43154823 return rc;
43164824 }
4825
+#endif
43174826
43184827 /*
43194828 * Issue a TREE_CONNECT request.
....@@ -4416,8 +4925,7 @@
44164925 bcc_ptr += strlen("?????");
44174926 bcc_ptr += 1;
44184927 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);
4928
+ be32_add_cpu(&pSMB->hdr.smb_buf_length, count);
44214929 pSMB->ByteCount = cpu_to_le16(count);
44224930
44234931 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
....@@ -4509,6 +5017,10 @@
45095017
45105018 kfree(cifs_sb->mountdata);
45115019 kfree(cifs_sb->prepath);
5020
+#ifdef CONFIG_CIFS_DFS_UPCALL
5021
+ dfs_cache_del_vol(cifs_sb->origin_fullpath);
5022
+ kfree(cifs_sb->origin_fullpath);
5023
+#endif
45125024 call_rcu(&cifs_sb->rcu, delayed_free);
45135025 }
45145026
....@@ -4516,7 +5028,7 @@
45165028 cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses)
45175029 {
45185030 int rc = 0;
4519
- struct TCP_Server_Info *server = ses->server;
5031
+ struct TCP_Server_Info *server = cifs_ses_server(ses);
45205032
45215033 if (!server->ops->need_neg || !server->ops->negotiate)
45225034 return -ENOSYS;
....@@ -4524,8 +5036,6 @@
45245036 /* only send once per connect */
45255037 if (!server->ops->need_neg(server))
45265038 return 0;
4527
-
4528
- set_credits(server, 1);
45295039
45305040 rc = server->ops->negotiate(xid, ses);
45315041 if (rc == 0) {
....@@ -4545,28 +5055,30 @@
45455055 struct nls_table *nls_info)
45465056 {
45475057 int rc = -ENOSYS;
4548
- struct TCP_Server_Info *server = ses->server;
5058
+ struct TCP_Server_Info *server = cifs_ses_server(ses);
45495059
4550
- ses->capabilities = server->capabilities;
4551
- if (linuxExtEnabled == 0)
4552
- ses->capabilities &= (~server->vals->cap_unix);
5060
+ if (!ses->binding) {
5061
+ ses->capabilities = server->capabilities;
5062
+ if (linuxExtEnabled == 0)
5063
+ ses->capabilities &= (~server->vals->cap_unix);
5064
+
5065
+ if (ses->auth_key.response) {
5066
+ cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
5067
+ ses->auth_key.response);
5068
+ kfree(ses->auth_key.response);
5069
+ ses->auth_key.response = NULL;
5070
+ ses->auth_key.len = 0;
5071
+ }
5072
+ }
45535073
45545074 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
45555075 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
- }
45645076
45655077 if (server->ops->sess_setup)
45665078 rc = server->ops->sess_setup(xid, ses, nls_info);
45675079
45685080 if (rc)
4569
- cifs_dbg(VFS, "Send error in SessSetup = %d\n", rc);
5081
+ cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
45705082
45715083 return rc;
45725084 }
....@@ -4607,6 +5119,7 @@
46075119 vol_info->no_lease = master_tcon->no_lease;
46085120 vol_info->resilient = master_tcon->use_resilient;
46095121 vol_info->persistent = master_tcon->use_persistent;
5122
+ vol_info->handle_timeout = master_tcon->handle_timeout;
46105123 vol_info->no_linux_ext = !master_tcon->unix_ext;
46115124 vol_info->linux_ext = master_tcon->posix_extensions;
46125125 vol_info->sectype = master_tcon->ses->sectype;
....@@ -4642,7 +5155,7 @@
46425155
46435156 out:
46445157 kfree(vol_info->username);
4645
- kzfree(vol_info->password);
5158
+ kfree_sensitive(vol_info->password);
46465159 kfree(vol_info);
46475160
46485161 return tcon;
....@@ -4830,3 +5343,113 @@
48305343 queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks,
48315344 TLINK_IDLE_EXPIRE);
48325345 }
5346
+
5347
+#ifdef CONFIG_CIFS_DFS_UPCALL
5348
+int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
5349
+{
5350
+ int rc;
5351
+ struct TCP_Server_Info *server = tcon->ses->server;
5352
+ const struct smb_version_operations *ops = server->ops;
5353
+ struct dfs_cache_tgt_list tl;
5354
+ struct dfs_cache_tgt_iterator *it = NULL;
5355
+ char *tree;
5356
+ const char *tcp_host;
5357
+ size_t tcp_host_len;
5358
+ const char *dfs_host;
5359
+ size_t dfs_host_len;
5360
+ char *share = NULL, *prefix = NULL;
5361
+ struct dfs_info3_param ref = {0};
5362
+ bool isroot;
5363
+
5364
+ tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
5365
+ if (!tree)
5366
+ return -ENOMEM;
5367
+
5368
+ /* If it is not dfs or there was no cached dfs referral, then reconnect to same share */
5369
+ if (!tcon->dfs_path || dfs_cache_noreq_find(tcon->dfs_path + 1, &ref, &tl)) {
5370
+ if (tcon->ipc) {
5371
+ scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
5372
+ rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
5373
+ } else {
5374
+ rc = ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc);
5375
+ }
5376
+ goto out;
5377
+ }
5378
+
5379
+ isroot = ref.server_type == DFS_TYPE_ROOT;
5380
+ free_dfs_info_param(&ref);
5381
+
5382
+ extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len);
5383
+
5384
+ for (it = dfs_cache_get_tgt_iterator(&tl); it; it = dfs_cache_get_next_tgt(&tl, it)) {
5385
+ bool target_match;
5386
+
5387
+ kfree(share);
5388
+ kfree(prefix);
5389
+ share = NULL;
5390
+ prefix = NULL;
5391
+
5392
+ rc = dfs_cache_get_tgt_share(tcon->dfs_path + 1, it, &share, &prefix);
5393
+ if (rc) {
5394
+ cifs_dbg(VFS, "%s: failed to parse target share %d\n",
5395
+ __func__, rc);
5396
+ continue;
5397
+ }
5398
+
5399
+ extract_unc_hostname(share, &dfs_host, &dfs_host_len);
5400
+
5401
+ if (dfs_host_len != tcp_host_len
5402
+ || strncasecmp(dfs_host, tcp_host, dfs_host_len) != 0) {
5403
+ cifs_dbg(FYI, "%s: %.*s doesn't match %.*s\n", __func__, (int)dfs_host_len,
5404
+ dfs_host, (int)tcp_host_len, tcp_host);
5405
+
5406
+ rc = match_target_ip(server, dfs_host, dfs_host_len, &target_match);
5407
+ if (rc) {
5408
+ cifs_dbg(VFS, "%s: failed to match target ip: %d\n", __func__, rc);
5409
+ break;
5410
+ }
5411
+
5412
+ if (!target_match) {
5413
+ cifs_dbg(FYI, "%s: skipping target\n", __func__);
5414
+ continue;
5415
+ }
5416
+ }
5417
+
5418
+ if (tcon->ipc) {
5419
+ scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", share);
5420
+ rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
5421
+ } else {
5422
+ scnprintf(tree, MAX_TREE_SIZE, "\\%s", share);
5423
+ rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
5424
+ /* Only handle prefix paths of DFS link targets */
5425
+ if (!rc && !isroot) {
5426
+ rc = update_super_prepath(tcon, prefix);
5427
+ break;
5428
+ }
5429
+ }
5430
+ if (rc == -EREMOTE)
5431
+ break;
5432
+ }
5433
+
5434
+ kfree(share);
5435
+ kfree(prefix);
5436
+
5437
+ if (!rc) {
5438
+ if (it)
5439
+ rc = dfs_cache_noreq_update_tgthint(tcon->dfs_path + 1, it);
5440
+ else
5441
+ rc = -ENOENT;
5442
+ }
5443
+ dfs_cache_free_tgts(&tl);
5444
+out:
5445
+ kfree(tree);
5446
+ return rc;
5447
+}
5448
+#else
5449
+int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
5450
+{
5451
+ const struct smb_version_operations *ops = tcon->ses->server->ops;
5452
+
5453
+ return ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc);
5454
+}
5455
+#endif