@@ -996,10 +996,8 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
996
996
*/
997
997
}
998
998
999
- #ifdef CONFIG_CIFS_DFS_UPCALL
1000
999
kfree (server -> origin_fullpath );
1001
1000
kfree (server -> leaf_fullpath );
1002
- #endif
1003
1001
kfree (server );
1004
1002
1005
1003
length = atomic_dec_return (& tcpSesAllocCount );
@@ -1387,23 +1385,8 @@ match_security(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
1387
1385
return true;
1388
1386
}
1389
1387
1390
- static bool dfs_src_pathname_equal (const char * s1 , const char * s2 )
1391
- {
1392
- if (strlen (s1 ) != strlen (s2 ))
1393
- return false;
1394
- for (; * s1 ; s1 ++ , s2 ++ ) {
1395
- if (* s1 == '/' || * s1 == '\\' ) {
1396
- if (* s2 != '/' && * s2 != '\\' )
1397
- return false;
1398
- } else if (tolower (* s1 ) != tolower (* s2 ))
1399
- return false;
1400
- }
1401
- return true;
1402
- }
1403
-
1404
1388
/* this function must be called with srv_lock held */
1405
- static int match_server (struct TCP_Server_Info * server , struct smb3_fs_context * ctx ,
1406
- bool dfs_super_cmp )
1389
+ static int match_server (struct TCP_Server_Info * server , struct smb3_fs_context * ctx )
1407
1390
{
1408
1391
struct sockaddr * addr = (struct sockaddr * )& ctx -> dstaddr ;
1409
1392
@@ -1434,27 +1417,41 @@ static int match_server(struct TCP_Server_Info *server, struct smb3_fs_context *
1434
1417
(struct sockaddr * )& server -> srcaddr ))
1435
1418
return 0 ;
1436
1419
/*
1437
- * When matching DFS superblocks, we only check for original source pathname as the
1438
- * currently connected target might be different than the one parsed earlier in i.e.
1439
- * mount.cifs(8).
1420
+ * - Match for an DFS tcon (@server->origin_fullpath).
1421
+ * - Match for an DFS root server connection (@server->leaf_fullpath).
1422
+ * - If none of the above and @ctx->leaf_fullpath is set, then
1423
+ * it is a new DFS connection.
1424
+ * - If 'nodfs' mount option was passed, then match only connections
1425
+ * that have no DFS referrals set
1426
+ * (e.g. can't failover to other targets).
1440
1427
*/
1441
- if (dfs_super_cmp ) {
1442
- if (!ctx -> source || !server -> origin_fullpath ||
1443
- !dfs_src_pathname_equal (server -> origin_fullpath , ctx -> source ))
1444
- return 0 ;
1445
- } else {
1446
- /* Skip addr, hostname and port matching for DFS connections */
1447
- if (server -> leaf_fullpath ) {
1428
+ if (!ctx -> nodfs ) {
1429
+ if (ctx -> source && server -> origin_fullpath ) {
1430
+ if (!dfs_src_pathname_equal (ctx -> source ,
1431
+ server -> origin_fullpath ))
1432
+ return 0 ;
1433
+ } else if (server -> leaf_fullpath ) {
1448
1434
if (!ctx -> leaf_fullpath ||
1449
- strcasecmp (server -> leaf_fullpath , ctx -> leaf_fullpath ))
1435
+ strcasecmp (server -> leaf_fullpath ,
1436
+ ctx -> leaf_fullpath ))
1450
1437
return 0 ;
1451
- } else if (strcasecmp (server -> hostname , ctx -> server_hostname ) ||
1452
- !match_server_address (server , addr ) ||
1453
- !match_port (server , addr )) {
1438
+ } else if (ctx -> leaf_fullpath ) {
1454
1439
return 0 ;
1455
1440
}
1441
+ } else if (server -> origin_fullpath || server -> leaf_fullpath ) {
1442
+ return 0 ;
1456
1443
}
1457
1444
1445
+ /*
1446
+ * Match for a regular connection (address/hostname/port) which has no
1447
+ * DFS referrals set.
1448
+ */
1449
+ if (!server -> origin_fullpath && !server -> leaf_fullpath &&
1450
+ (strcasecmp (server -> hostname , ctx -> server_hostname ) ||
1451
+ !match_server_address (server , addr ) ||
1452
+ !match_port (server , addr )))
1453
+ return 0 ;
1454
+
1458
1455
if (!match_security (server , ctx ))
1459
1456
return 0 ;
1460
1457
@@ -1485,7 +1482,7 @@ cifs_find_tcp_session(struct smb3_fs_context *ctx)
1485
1482
* Skip ses channels since they're only handled in lower layers
1486
1483
* (e.g. cifs_send_recv).
1487
1484
*/
1488
- if (CIFS_SERVER_IS_CHAN (server ) || !match_server (server , ctx , false )) {
1485
+ if (CIFS_SERVER_IS_CHAN (server ) || !match_server (server , ctx )) {
1489
1486
spin_unlock (& server -> srv_lock );
1490
1487
continue ;
1491
1488
}
@@ -1869,7 +1866,7 @@ cifs_free_ipc(struct cifs_ses *ses)
1869
1866
static struct cifs_ses *
1870
1867
cifs_find_smb_ses (struct TCP_Server_Info * server , struct smb3_fs_context * ctx )
1871
1868
{
1872
- struct cifs_ses * ses ;
1869
+ struct cifs_ses * ses , * ret = NULL ;
1873
1870
1874
1871
spin_lock (& cifs_tcp_ses_lock );
1875
1872
list_for_each_entry (ses , & server -> smb_ses_list , smb_ses_list ) {
@@ -1879,23 +1876,22 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
1879
1876
continue ;
1880
1877
}
1881
1878
spin_lock (& ses -> chan_lock );
1882
- if (! match_session (ses , ctx )) {
1879
+ if (match_session (ses , ctx )) {
1883
1880
spin_unlock (& ses -> chan_lock );
1884
1881
spin_unlock (& ses -> ses_lock );
1885
- continue ;
1882
+ ret = ses ;
1883
+ break ;
1886
1884
}
1887
1885
spin_unlock (& ses -> chan_lock );
1888
1886
spin_unlock (& ses -> ses_lock );
1889
-
1890
- ++ ses -> ses_count ;
1891
- spin_unlock (& cifs_tcp_ses_lock );
1892
- return ses ;
1893
1887
}
1888
+ if (ret )
1889
+ cifs_smb_ses_inc_refcount (ret );
1894
1890
spin_unlock (& cifs_tcp_ses_lock );
1895
- return NULL ;
1891
+ return ret ;
1896
1892
}
1897
1893
1898
- void cifs_put_smb_ses (struct cifs_ses * ses )
1894
+ void __cifs_put_smb_ses (struct cifs_ses * ses )
1899
1895
{
1900
1896
unsigned int rc , xid ;
1901
1897
unsigned int chan_count ;
@@ -2250,6 +2246,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
2250
2246
*/
2251
2247
spin_lock (& cifs_tcp_ses_lock );
2252
2248
ses -> dfs_root_ses = ctx -> dfs_root_ses ;
2249
+ if (ses -> dfs_root_ses )
2250
+ ses -> dfs_root_ses -> ses_count ++ ;
2253
2251
list_add (& ses -> smb_ses_list , & server -> smb_ses_list );
2254
2252
spin_unlock (& cifs_tcp_ses_lock );
2255
2253
@@ -2266,12 +2264,15 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
2266
2264
}
2267
2265
2268
2266
/* this function must be called with tc_lock held */
2269
- static int match_tcon (struct cifs_tcon * tcon , struct smb3_fs_context * ctx , bool dfs_super_cmp )
2267
+ static int match_tcon (struct cifs_tcon * tcon , struct smb3_fs_context * ctx )
2270
2268
{
2269
+ struct TCP_Server_Info * server = tcon -> ses -> server ;
2270
+
2271
2271
if (tcon -> status == TID_EXITING )
2272
2272
return 0 ;
2273
- /* Skip UNC validation when matching DFS superblocks */
2274
- if (!dfs_super_cmp && strncmp (tcon -> tree_name , ctx -> UNC , MAX_TREE_SIZE ))
2273
+ /* Skip UNC validation when matching DFS connections or superblocks */
2274
+ if (!server -> origin_fullpath && !server -> leaf_fullpath &&
2275
+ strncmp (tcon -> tree_name , ctx -> UNC , MAX_TREE_SIZE ))
2275
2276
return 0 ;
2276
2277
if (tcon -> seal != ctx -> seal )
2277
2278
return 0 ;
@@ -2294,7 +2295,7 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
2294
2295
spin_lock (& cifs_tcp_ses_lock );
2295
2296
list_for_each_entry (tcon , & ses -> tcon_list , tcon_list ) {
2296
2297
spin_lock (& tcon -> tc_lock );
2297
- if (!match_tcon (tcon , ctx , false )) {
2298
+ if (!match_tcon (tcon , ctx )) {
2298
2299
spin_unlock (& tcon -> tc_lock );
2299
2300
continue ;
2300
2301
}
@@ -2670,16 +2671,22 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
2670
2671
return 1 ;
2671
2672
}
2672
2673
2673
- static int
2674
- match_prepath (struct super_block * sb , struct cifs_mnt_data * mnt_data )
2674
+ static int match_prepath (struct super_block * sb ,
2675
+ struct TCP_Server_Info * server ,
2676
+ struct cifs_mnt_data * mnt_data )
2675
2677
{
2678
+ struct smb3_fs_context * ctx = mnt_data -> ctx ;
2676
2679
struct cifs_sb_info * old = CIFS_SB (sb );
2677
2680
struct cifs_sb_info * new = mnt_data -> cifs_sb ;
2678
2681
bool old_set = (old -> mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH ) &&
2679
2682
old -> prepath ;
2680
2683
bool new_set = (new -> mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH ) &&
2681
2684
new -> prepath ;
2682
2685
2686
+ if (server -> origin_fullpath &&
2687
+ dfs_src_pathname_equal (server -> origin_fullpath , ctx -> source ))
2688
+ return 1 ;
2689
+
2683
2690
if (old_set && new_set && !strcmp (new -> prepath , old -> prepath ))
2684
2691
return 1 ;
2685
2692
else if (!old_set && !new_set )
@@ -2698,7 +2705,6 @@ cifs_match_super(struct super_block *sb, void *data)
2698
2705
struct cifs_ses * ses ;
2699
2706
struct cifs_tcon * tcon ;
2700
2707
struct tcon_link * tlink ;
2701
- bool dfs_super_cmp ;
2702
2708
int rc = 0 ;
2703
2709
2704
2710
spin_lock (& cifs_tcp_ses_lock );
@@ -2713,18 +2719,16 @@ cifs_match_super(struct super_block *sb, void *data)
2713
2719
ses = tcon -> ses ;
2714
2720
tcp_srv = ses -> server ;
2715
2721
2716
- dfs_super_cmp = IS_ENABLED (CONFIG_CIFS_DFS_UPCALL ) && tcp_srv -> origin_fullpath ;
2717
-
2718
2722
ctx = mnt_data -> ctx ;
2719
2723
2720
2724
spin_lock (& tcp_srv -> srv_lock );
2721
2725
spin_lock (& ses -> ses_lock );
2722
2726
spin_lock (& ses -> chan_lock );
2723
2727
spin_lock (& tcon -> tc_lock );
2724
- if (!match_server (tcp_srv , ctx , dfs_super_cmp ) ||
2728
+ if (!match_server (tcp_srv , ctx ) ||
2725
2729
!match_session (ses , ctx ) ||
2726
- !match_tcon (tcon , ctx , dfs_super_cmp ) ||
2727
- !match_prepath (sb , mnt_data )) {
2730
+ !match_tcon (tcon , ctx ) ||
2731
+ !match_prepath (sb , tcp_srv , mnt_data )) {
2728
2732
rc = 0 ;
2729
2733
goto out ;
2730
2734
}
@@ -3469,8 +3473,6 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
3469
3473
3470
3474
error :
3471
3475
dfs_put_root_smb_sessions (& mnt_ctx .dfs_ses_list );
3472
- kfree (mnt_ctx .origin_fullpath );
3473
- kfree (mnt_ctx .leaf_fullpath );
3474
3476
cifs_mount_put_conns (& mnt_ctx );
3475
3477
return rc ;
3476
3478
}
0 commit comments