Skip to content

Commit cdc3363

Browse files
Paulo Alcantarasmfrench
authored andcommitted
cifs: do not share tcp sessions of dfs connections
Make sure that we do not share tcp sessions of dfs mounts when mounting regular shares that connect to same server. DFS connections rely on a single instance of tcp in order to do failover properly in cifs_reconnect(). Signed-off-by: Paulo Alcantara (SUSE) <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 4511d7c commit cdc3363

File tree

2 files changed

+38
-3
lines changed

2 files changed

+38
-3
lines changed

fs/cifs/cifsglob.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,9 @@ struct TCP_Server_Info {
693693
bool use_swn_dstaddr;
694694
struct sockaddr_storage swn_dstaddr;
695695
#endif
696+
#ifdef CONFIG_CIFS_DFS_UPCALL
697+
bool is_dfs_conn; /* if a dfs connection */
698+
#endif
696699
};
697700

698701
struct cifs_credits {

fs/cifs/connect.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,16 @@ cifs_find_tcp_session(struct smb3_fs_context *ctx)
12681268

12691269
spin_lock(&cifs_tcp_ses_lock);
12701270
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
12711281
/*
12721282
* Skip ses channels since they're only handled in lower layers
12731283
* (e.g. cifs_send_recv).
@@ -2968,6 +2978,23 @@ static int mount_setup_tlink(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses,
29682978
}
29692979

29702980
#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+
29712998
/*
29722999
* cifs_build_path_to_root returns full path to root when we do not have an
29733000
* existing connection (tcon)
@@ -3163,7 +3190,7 @@ static int do_dfs_failover(const char *path, const char *full_path, struct cifs_
31633190
tmp_ctx.prepath);
31643191

31653192
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);
31673194
if (!rc || (*server && *ses)) {
31683195
/*
31693196
* 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)
34623489
goto error;
34633490
}
34643491

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);
34663498

34673499
/* Get path of DFS root */
34683500
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)
34913523
/* Connect to new DFS target only if we were redirected */
34923524
if (oldmnt != cifs_sb->ctx->mount_options) {
34933525
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);
34953527
}
34963528
if (rc && !server && !ses) {
34973529
/* Failed to connect. Try to connect to other targets in the referral. */

0 commit comments

Comments
 (0)