53
53
#include "nterr.h"
54
54
#include "rfc1002pdu.h"
55
55
#include "fscache.h"
56
+ #ifdef CONFIG_CIFS_SMB2
57
+ #include "smb2proto.h"
58
+ #endif
56
59
57
60
#define CIFS_PORT 445
58
61
#define RFC1001_PORT 139
@@ -89,13 +92,15 @@ enum {
89
92
Opt_multiuser , Opt_sloppy , Opt_nosharesock ,
90
93
Opt_persistent , Opt_nopersistent ,
91
94
Opt_resilient , Opt_noresilient ,
95
+ Opt_domainauto ,
92
96
93
97
/* Mount options which take numeric value */
94
98
Opt_backupuid , Opt_backupgid , Opt_uid ,
95
99
Opt_cruid , Opt_gid , Opt_file_mode ,
96
100
Opt_dirmode , Opt_port ,
97
101
Opt_rsize , Opt_wsize , Opt_actimeo ,
98
102
Opt_echo_interval , Opt_max_credits ,
103
+ Opt_snapshot ,
99
104
100
105
/* Mount options which take string value */
101
106
Opt_user , Opt_pass , Opt_ip ,
@@ -177,6 +182,7 @@ static const match_table_t cifs_mount_option_tokens = {
177
182
{ Opt_nopersistent , "nopersistenthandles" },
178
183
{ Opt_resilient , "resilienthandles" },
179
184
{ Opt_noresilient , "noresilienthandles" },
185
+ { Opt_domainauto , "domainauto" },
180
186
181
187
{ Opt_backupuid , "backupuid=%s" },
182
188
{ Opt_backupgid , "backupgid=%s" },
@@ -192,6 +198,7 @@ static const match_table_t cifs_mount_option_tokens = {
192
198
{ Opt_actimeo , "actimeo=%s" },
193
199
{ Opt_echo_interval , "echo_interval=%s" },
194
200
{ Opt_max_credits , "max_credits=%s" },
201
+ { Opt_snapshot , "snapshot=%s" },
195
202
196
203
{ Opt_blank_user , "user=" },
197
204
{ Opt_blank_user , "username=" },
@@ -1500,6 +1507,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1500
1507
case Opt_noresilient :
1501
1508
vol -> resilient = false; /* already the default */
1502
1509
break ;
1510
+ case Opt_domainauto :
1511
+ vol -> domainauto = true;
1512
+ break ;
1503
1513
1504
1514
/* Numeric Values */
1505
1515
case Opt_backupuid :
@@ -1602,6 +1612,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
1602
1612
}
1603
1613
vol -> echo_interval = option ;
1604
1614
break ;
1615
+ case Opt_snapshot :
1616
+ if (get_option_ul (args , & option )) {
1617
+ cifs_dbg (VFS , "%s: Invalid snapshot time\n" ,
1618
+ __func__ );
1619
+ goto cifs_parse_mount_err ;
1620
+ }
1621
+ vol -> snapshot_time = option ;
1622
+ break ;
1605
1623
case Opt_max_credits :
1606
1624
if (get_option_ul (args , & option ) || (option < 20 ) ||
1607
1625
(option > 60000 )) {
@@ -2101,8 +2119,8 @@ cifs_find_tcp_session(struct smb_vol *vol)
2101
2119
return NULL ;
2102
2120
}
2103
2121
2104
- static void
2105
- cifs_put_tcp_session (struct TCP_Server_Info * server )
2122
+ void
2123
+ cifs_put_tcp_session (struct TCP_Server_Info * server , int from_reconnect )
2106
2124
{
2107
2125
struct task_struct * task ;
2108
2126
@@ -2119,6 +2137,19 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
2119
2137
2120
2138
cancel_delayed_work_sync (& server -> echo );
2121
2139
2140
+ #ifdef CONFIG_CIFS_SMB2
2141
+ if (from_reconnect )
2142
+ /*
2143
+ * Avoid deadlock here: reconnect work calls
2144
+ * cifs_put_tcp_session() at its end. Need to be sure
2145
+ * that reconnect work does nothing with server pointer after
2146
+ * that step.
2147
+ */
2148
+ cancel_delayed_work (& server -> reconnect );
2149
+ else
2150
+ cancel_delayed_work_sync (& server -> reconnect );
2151
+ #endif
2152
+
2122
2153
spin_lock (& GlobalMid_Lock );
2123
2154
server -> tcpStatus = CifsExiting ;
2124
2155
spin_unlock (& GlobalMid_Lock );
@@ -2183,6 +2214,10 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
2183
2214
INIT_LIST_HEAD (& tcp_ses -> tcp_ses_list );
2184
2215
INIT_LIST_HEAD (& tcp_ses -> smb_ses_list );
2185
2216
INIT_DELAYED_WORK (& tcp_ses -> echo , cifs_echo_request );
2217
+ #ifdef CONFIG_CIFS_SMB2
2218
+ INIT_DELAYED_WORK (& tcp_ses -> reconnect , smb2_reconnect_server );
2219
+ mutex_init (& tcp_ses -> reconnect_mutex );
2220
+ #endif
2186
2221
memcpy (& tcp_ses -> srcaddr , & volume_info -> srcaddr ,
2187
2222
sizeof (tcp_ses -> srcaddr ));
2188
2223
memcpy (& tcp_ses -> dstaddr , & volume_info -> dstaddr ,
@@ -2341,7 +2376,7 @@ cifs_put_smb_ses(struct cifs_ses *ses)
2341
2376
spin_unlock (& cifs_tcp_ses_lock );
2342
2377
2343
2378
sesInfoFree (ses );
2344
- cifs_put_tcp_session (server );
2379
+ cifs_put_tcp_session (server , 0 );
2345
2380
}
2346
2381
2347
2382
#ifdef CONFIG_KEYS
@@ -2515,7 +2550,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2515
2550
mutex_unlock (& ses -> session_mutex );
2516
2551
2517
2552
/* existing SMB ses has a server reference already */
2518
- cifs_put_tcp_session (server );
2553
+ cifs_put_tcp_session (server , 0 );
2519
2554
free_xid (xid );
2520
2555
return ses ;
2521
2556
}
@@ -2549,6 +2584,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
2549
2584
if (!ses -> domainName )
2550
2585
goto get_ses_fail ;
2551
2586
}
2587
+ if (volume_info -> domainauto )
2588
+ ses -> domainAuto = volume_info -> domainauto ;
2552
2589
ses -> cred_uid = volume_info -> cred_uid ;
2553
2590
ses -> linux_uid = volume_info -> linux_uid ;
2554
2591
@@ -2587,16 +2624,22 @@ static int match_tcon(struct cifs_tcon *tcon, const char *unc)
2587
2624
}
2588
2625
2589
2626
static struct cifs_tcon *
2590
- cifs_find_tcon (struct cifs_ses * ses , const char * unc )
2627
+ cifs_find_tcon (struct cifs_ses * ses , struct smb_vol * volume_info )
2591
2628
{
2592
2629
struct list_head * tmp ;
2593
2630
struct cifs_tcon * tcon ;
2594
2631
2595
2632
spin_lock (& cifs_tcp_ses_lock );
2596
2633
list_for_each (tmp , & ses -> tcon_list ) {
2597
2634
tcon = list_entry (tmp , struct cifs_tcon , tcon_list );
2598
- if (!match_tcon (tcon , unc ))
2635
+ if (!match_tcon (tcon , volume_info -> UNC ))
2599
2636
continue ;
2637
+
2638
+ #ifdef CONFIG_CIFS_SMB2
2639
+ if (tcon -> snapshot_time != volume_info -> snapshot_time )
2640
+ continue ;
2641
+ #endif /* CONFIG_CIFS_SMB2 */
2642
+
2600
2643
++ tcon -> tc_count ;
2601
2644
spin_unlock (& cifs_tcp_ses_lock );
2602
2645
return tcon ;
@@ -2605,7 +2648,7 @@ cifs_find_tcon(struct cifs_ses *ses, const char *unc)
2605
2648
return NULL ;
2606
2649
}
2607
2650
2608
- static void
2651
+ void
2609
2652
cifs_put_tcon (struct cifs_tcon * tcon )
2610
2653
{
2611
2654
unsigned int xid ;
@@ -2637,7 +2680,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
2637
2680
int rc , xid ;
2638
2681
struct cifs_tcon * tcon ;
2639
2682
2640
- tcon = cifs_find_tcon (ses , volume_info -> UNC );
2683
+ tcon = cifs_find_tcon (ses , volume_info );
2641
2684
if (tcon ) {
2642
2685
cifs_dbg (FYI , "Found match on UNC path\n" );
2643
2686
/* existing tcon already has a reference */
@@ -2658,6 +2701,22 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
2658
2701
goto out_fail ;
2659
2702
}
2660
2703
2704
+ if (volume_info -> snapshot_time ) {
2705
+ #ifdef CONFIG_CIFS_SMB2
2706
+ if (ses -> server -> vals -> protocol_id == 0 ) {
2707
+ cifs_dbg (VFS ,
2708
+ "Use SMB2 or later for snapshot mount option\n" );
2709
+ rc = - EOPNOTSUPP ;
2710
+ goto out_fail ;
2711
+ } else
2712
+ tcon -> snapshot_time = volume_info -> snapshot_time ;
2713
+ #else
2714
+ cifs_dbg (VFS , "Snapshot mount option requires SMB2 support\n" );
2715
+ rc = - EOPNOTSUPP ;
2716
+ goto out_fail ;
2717
+ #endif /* CONFIG_CIFS_SMB2 */
2718
+ }
2719
+
2661
2720
tcon -> ses = ses ;
2662
2721
if (volume_info -> password ) {
2663
2722
tcon -> password = kstrdup (volume_info -> password , GFP_KERNEL );
@@ -3707,7 +3766,8 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
3707
3766
/*
3708
3767
* cifs_build_path_to_root works only when we have a valid tcon
3709
3768
*/
3710
- full_path = cifs_build_path_to_root (volume_info , cifs_sb , tcon );
3769
+ full_path = cifs_build_path_to_root (volume_info , cifs_sb , tcon ,
3770
+ tcon -> Flags & SMB_SHARE_IS_IN_DFS );
3711
3771
if (full_path == NULL ) {
3712
3772
rc = - ENOMEM ;
3713
3773
goto mount_fail_check ;
@@ -3793,7 +3853,7 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
3793
3853
else if (ses )
3794
3854
cifs_put_smb_ses (ses );
3795
3855
else
3796
- cifs_put_tcp_session (server );
3856
+ cifs_put_tcp_session (server , 0 );
3797
3857
bdi_destroy (& cifs_sb -> bdi );
3798
3858
}
3799
3859
@@ -4104,7 +4164,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
4104
4164
ses = cifs_get_smb_ses (master_tcon -> ses -> server , vol_info );
4105
4165
if (IS_ERR (ses )) {
4106
4166
tcon = (struct cifs_tcon * )ses ;
4107
- cifs_put_tcp_session (master_tcon -> ses -> server );
4167
+ cifs_put_tcp_session (master_tcon -> ses -> server , 0 );
4108
4168
goto out ;
4109
4169
}
4110
4170
0 commit comments