@@ -996,10 +996,8 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
996996 */
997997 }
998998
999- #ifdef CONFIG_CIFS_DFS_UPCALL
1000999 kfree (server -> origin_fullpath );
10011000 kfree (server -> leaf_fullpath );
1002- #endif
10031001 kfree (server );
10041002
10051003 length = atomic_dec_return (& tcpSesAllocCount );
@@ -1387,23 +1385,8 @@ match_security(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
13871385 return true;
13881386}
13891387
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-
14041388/* 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 )
14071390{
14081391 struct sockaddr * addr = (struct sockaddr * )& ctx -> dstaddr ;
14091392
@@ -1434,27 +1417,41 @@ static int match_server(struct TCP_Server_Info *server, struct smb3_fs_context *
14341417 (struct sockaddr * )& server -> srcaddr ))
14351418 return 0 ;
14361419 /*
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).
14401427 */
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 ) {
14481434 if (!ctx -> leaf_fullpath ||
1449- strcasecmp (server -> leaf_fullpath , ctx -> leaf_fullpath ))
1435+ strcasecmp (server -> leaf_fullpath ,
1436+ ctx -> leaf_fullpath ))
14501437 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 ) {
14541439 return 0 ;
14551440 }
1441+ } else if (server -> origin_fullpath || server -> leaf_fullpath ) {
1442+ return 0 ;
14561443 }
14571444
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+
14581455 if (!match_security (server , ctx ))
14591456 return 0 ;
14601457
@@ -1485,7 +1482,7 @@ cifs_find_tcp_session(struct smb3_fs_context *ctx)
14851482 * Skip ses channels since they're only handled in lower layers
14861483 * (e.g. cifs_send_recv).
14871484 */
1488- if (CIFS_SERVER_IS_CHAN (server ) || !match_server (server , ctx , false )) {
1485+ if (CIFS_SERVER_IS_CHAN (server ) || !match_server (server , ctx )) {
14891486 spin_unlock (& server -> srv_lock );
14901487 continue ;
14911488 }
@@ -1869,7 +1866,7 @@ cifs_free_ipc(struct cifs_ses *ses)
18691866static struct cifs_ses *
18701867cifs_find_smb_ses (struct TCP_Server_Info * server , struct smb3_fs_context * ctx )
18711868{
1872- struct cifs_ses * ses ;
1869+ struct cifs_ses * ses , * ret = NULL ;
18731870
18741871 spin_lock (& cifs_tcp_ses_lock );
18751872 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)
18791876 continue ;
18801877 }
18811878 spin_lock (& ses -> chan_lock );
1882- if (! match_session (ses , ctx )) {
1879+ if (match_session (ses , ctx )) {
18831880 spin_unlock (& ses -> chan_lock );
18841881 spin_unlock (& ses -> ses_lock );
1885- continue ;
1882+ ret = ses ;
1883+ break ;
18861884 }
18871885 spin_unlock (& ses -> chan_lock );
18881886 spin_unlock (& ses -> ses_lock );
1889-
1890- ++ ses -> ses_count ;
1891- spin_unlock (& cifs_tcp_ses_lock );
1892- return ses ;
18931887 }
1888+ if (ret )
1889+ cifs_smb_ses_inc_refcount (ret );
18941890 spin_unlock (& cifs_tcp_ses_lock );
1895- return NULL ;
1891+ return ret ;
18961892}
18971893
1898- void cifs_put_smb_ses (struct cifs_ses * ses )
1894+ void __cifs_put_smb_ses (struct cifs_ses * ses )
18991895{
19001896 unsigned int rc , xid ;
19011897 unsigned int chan_count ;
@@ -2250,6 +2246,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
22502246 */
22512247 spin_lock (& cifs_tcp_ses_lock );
22522248 ses -> dfs_root_ses = ctx -> dfs_root_ses ;
2249+ if (ses -> dfs_root_ses )
2250+ ses -> dfs_root_ses -> ses_count ++ ;
22532251 list_add (& ses -> smb_ses_list , & server -> smb_ses_list );
22542252 spin_unlock (& cifs_tcp_ses_lock );
22552253
@@ -2266,12 +2264,15 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
22662264}
22672265
22682266/* 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 )
22702268{
2269+ struct TCP_Server_Info * server = tcon -> ses -> server ;
2270+
22712271 if (tcon -> status == TID_EXITING )
22722272 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 ))
22752276 return 0 ;
22762277 if (tcon -> seal != ctx -> seal )
22772278 return 0 ;
@@ -2294,7 +2295,7 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
22942295 spin_lock (& cifs_tcp_ses_lock );
22952296 list_for_each_entry (tcon , & ses -> tcon_list , tcon_list ) {
22962297 spin_lock (& tcon -> tc_lock );
2297- if (!match_tcon (tcon , ctx , false )) {
2298+ if (!match_tcon (tcon , ctx )) {
22982299 spin_unlock (& tcon -> tc_lock );
22992300 continue ;
23002301 }
@@ -2670,16 +2671,22 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
26702671 return 1 ;
26712672}
26722673
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 )
26752677{
2678+ struct smb3_fs_context * ctx = mnt_data -> ctx ;
26762679 struct cifs_sb_info * old = CIFS_SB (sb );
26772680 struct cifs_sb_info * new = mnt_data -> cifs_sb ;
26782681 bool old_set = (old -> mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH ) &&
26792682 old -> prepath ;
26802683 bool new_set = (new -> mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH ) &&
26812684 new -> prepath ;
26822685
2686+ if (server -> origin_fullpath &&
2687+ dfs_src_pathname_equal (server -> origin_fullpath , ctx -> source ))
2688+ return 1 ;
2689+
26832690 if (old_set && new_set && !strcmp (new -> prepath , old -> prepath ))
26842691 return 1 ;
26852692 else if (!old_set && !new_set )
@@ -2698,7 +2705,6 @@ cifs_match_super(struct super_block *sb, void *data)
26982705 struct cifs_ses * ses ;
26992706 struct cifs_tcon * tcon ;
27002707 struct tcon_link * tlink ;
2701- bool dfs_super_cmp ;
27022708 int rc = 0 ;
27032709
27042710 spin_lock (& cifs_tcp_ses_lock );
@@ -2713,18 +2719,16 @@ cifs_match_super(struct super_block *sb, void *data)
27132719 ses = tcon -> ses ;
27142720 tcp_srv = ses -> server ;
27152721
2716- dfs_super_cmp = IS_ENABLED (CONFIG_CIFS_DFS_UPCALL ) && tcp_srv -> origin_fullpath ;
2717-
27182722 ctx = mnt_data -> ctx ;
27192723
27202724 spin_lock (& tcp_srv -> srv_lock );
27212725 spin_lock (& ses -> ses_lock );
27222726 spin_lock (& ses -> chan_lock );
27232727 spin_lock (& tcon -> tc_lock );
2724- if (!match_server (tcp_srv , ctx , dfs_super_cmp ) ||
2728+ if (!match_server (tcp_srv , ctx ) ||
27252729 !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 )) {
27282732 rc = 0 ;
27292733 goto out ;
27302734 }
@@ -3469,8 +3473,6 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
34693473
34703474error :
34713475 dfs_put_root_smb_sessions (& mnt_ctx .dfs_ses_list );
3472- kfree (mnt_ctx .origin_fullpath );
3473- kfree (mnt_ctx .leaf_fullpath );
34743476 cifs_mount_put_conns (& mnt_ctx );
34753477 return rc ;
34763478}
0 commit comments