@@ -1268,6 +1268,16 @@ cifs_find_tcp_session(struct smb3_fs_context *ctx)
1268
1268
1269
1269
spin_lock (& cifs_tcp_ses_lock );
1270
1270
list_for_each_entry (server , & cifs_tcp_ses_list , tcp_ses_list ) {
1271
+ #ifdef CONFIG_CIFS_DFS_UPCALL
1272
+ /*
1273
+ * DFS failover implementation in cifs_reconnect() requires unique tcp sessions for
1274
+ * DFS connections to do failover properly, so avoid sharing them with regular
1275
+ * shares or even links that may connect to same server but having completely
1276
+ * different failover targets.
1277
+ */
1278
+ if (server -> is_dfs_conn )
1279
+ continue ;
1280
+ #endif
1271
1281
/*
1272
1282
* Skip ses channels since they're only handled in lower layers
1273
1283
* (e.g. cifs_send_recv).
@@ -2968,6 +2978,23 @@ static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
2968
2978
}
2969
2979
2970
2980
#ifdef CONFIG_CIFS_DFS_UPCALL
2981
+ static int mount_get_dfs_conns (struct smb3_fs_context * ctx , struct cifs_sb_info * cifs_sb ,
2982
+ unsigned int * xid , struct TCP_Server_Info * * nserver ,
2983
+ struct cifs_ses * * nses , struct cifs_tcon * * ntcon )
2984
+ {
2985
+ int rc ;
2986
+
2987
+ ctx -> nosharesock = true;
2988
+ rc = mount_get_conns (ctx , cifs_sb , xid , nserver , nses , ntcon );
2989
+ if (* nserver ) {
2990
+ cifs_dbg (FYI , "%s: marking tcp session as a dfs connection\n" , __func__ );
2991
+ spin_lock (& cifs_tcp_ses_lock );
2992
+ (* nserver )-> is_dfs_conn = true;
2993
+ spin_unlock (& cifs_tcp_ses_lock );
2994
+ }
2995
+ return rc ;
2996
+ }
2997
+
2971
2998
/*
2972
2999
* cifs_build_path_to_root returns full path to root when we do not have an
2973
3000
* existing connection (tcon)
@@ -3163,7 +3190,7 @@ static int do_dfs_failover(const char *path, const char *full_path, struct cifs_
3163
3190
tmp_ctx .prepath );
3164
3191
3165
3192
mount_put_conns (cifs_sb , * xid , * server , * ses , * tcon );
3166
- rc = mount_get_conns (& tmp_ctx , cifs_sb , xid , server , ses , tcon );
3193
+ rc = mount_get_dfs_conns (& tmp_ctx , cifs_sb , xid , server , ses , tcon );
3167
3194
if (!rc || (* server && * ses )) {
3168
3195
/*
3169
3196
* We were able to connect to new target server. Update current context with
@@ -3462,7 +3489,12 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
3462
3489
goto error ;
3463
3490
}
3464
3491
3465
- ctx -> nosharesock = true;
3492
+ mount_put_conns (cifs_sb , xid , server , ses , tcon );
3493
+ /*
3494
+ * Ignore error check here because we may failover to other targets from cached a
3495
+ * referral.
3496
+ */
3497
+ (void )mount_get_dfs_conns (ctx , cifs_sb , & xid , & server , & ses , & tcon );
3466
3498
3467
3499
/* Get path of DFS root */
3468
3500
ref_path = build_unc_path_to_root (ctx , cifs_sb , false);
@@ -3491,7 +3523,7 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
3491
3523
/* Connect to new DFS target only if we were redirected */
3492
3524
if (oldmnt != cifs_sb -> ctx -> mount_options ) {
3493
3525
mount_put_conns (cifs_sb , xid , server , ses , tcon );
3494
- rc = mount_get_conns (ctx , cifs_sb , & xid , & server , & ses , & tcon );
3526
+ rc = mount_get_dfs_conns (ctx , cifs_sb , & xid , & server , & ses , & tcon );
3495
3527
}
3496
3528
if (rc && !server && !ses ) {
3497
3529
/* Failed to connect. Try to connect to other targets in the referral. */
0 commit comments