From: Paulo Alcantara <pc@xxxxxxxxxxxxx> commit b56bce502f55505a97e381d546ee881928183126 upstream. Set the DFS root session pointer earlier when creating a new SMB session to prevent racing with smb2_reconnect(), cifs_reconnect_tcon() and DFS cache refresher. Signed-off-by: Paulo Alcantara (SUSE) <pc@xxxxxxxxxxxxx> Cc: stable@xxxxxxxxxxxxxxx # 6.2 Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- fs/cifs/cifs_dfs_ref.c | 1 + fs/cifs/cifsglob.h | 1 - fs/cifs/connect.c | 1 + fs/cifs/dfs.c | 19 ++++++++----------- fs/cifs/dfs.h | 3 ++- fs/cifs/fs_context.h | 1 + 6 files changed, 13 insertions(+), 13 deletions(-) --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -179,6 +179,7 @@ static struct vfsmount *cifs_dfs_do_auto tmp.source = full_path; tmp.leaf_fullpath = NULL; tmp.UNC = tmp.prepath = NULL; + tmp.dfs_root_ses = NULL; rc = smb3_fs_context_dup(ctx, &tmp); if (rc) { --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1767,7 +1767,6 @@ struct cifs_mount_ctx { struct TCP_Server_Info *server; struct cifs_ses *ses; struct cifs_tcon *tcon; - struct cifs_ses *root_ses; uuid_t mount_id; char *origin_fullpath, *leaf_fullpath; }; --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2278,6 +2278,7 @@ cifs_get_smb_ses(struct TCP_Server_Info * need to lock before changing something in the session. */ spin_lock(&cifs_tcp_ses_lock); + ses->dfs_root_ses = ctx->dfs_root_ses; list_add(&ses->smb_ses_list, &server->smb_ses_list); spin_unlock(&cifs_tcp_ses_lock); --- a/fs/cifs/dfs.c +++ b/fs/cifs/dfs.c @@ -95,25 +95,22 @@ static int get_session(struct cifs_mount ctx->leaf_fullpath = (char *)full_path; rc = cifs_mount_get_session(mnt_ctx); ctx->leaf_fullpath = NULL; - if (!rc) { - struct cifs_ses *ses = mnt_ctx->ses; - mutex_lock(&ses->session_mutex); - ses->dfs_root_ses = mnt_ctx->root_ses; - mutex_unlock(&ses->session_mutex); - } return rc; } static void set_root_ses(struct cifs_mount_ctx *mnt_ctx) { - if (mnt_ctx->ses) { + struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; + struct cifs_ses *ses = mnt_ctx->ses; + + if (ses) { spin_lock(&cifs_tcp_ses_lock); - mnt_ctx->ses->ses_count++; + ses->ses_count++; spin_unlock(&cifs_tcp_ses_lock); - dfs_cache_add_refsrv_session(&mnt_ctx->mount_id, mnt_ctx->ses); + dfs_cache_add_refsrv_session(&mnt_ctx->mount_id, ses); } - mnt_ctx->root_ses = mnt_ctx->ses; + ctx->dfs_root_ses = mnt_ctx->ses; } static int get_dfs_conn(struct cifs_mount_ctx *mnt_ctx, const char *ref_path, const char *full_path, @@ -260,7 +257,7 @@ int dfs_mount_share(struct cifs_mount_ct rc = get_session(mnt_ctx, NULL); if (rc) return rc; - mnt_ctx->root_ses = mnt_ctx->ses; + ctx->dfs_root_ses = mnt_ctx->ses; /* * If called with 'nodfs' mount option, then skip DFS resolving. Otherwise unconditionally * try to get an DFS referral (even cached) to determine whether it is an DFS mount. --- a/fs/cifs/dfs.h +++ b/fs/cifs/dfs.h @@ -22,9 +22,10 @@ static inline char *dfs_get_path(struct static inline int dfs_get_referral(struct cifs_mount_ctx *mnt_ctx, const char *path, struct dfs_info3_param *ref, struct dfs_cache_tgt_list *tl) { + struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb; - return dfs_cache_find(mnt_ctx->xid, mnt_ctx->root_ses, cifs_sb->local_nls, + return dfs_cache_find(mnt_ctx->xid, ctx->dfs_root_ses, cifs_sb->local_nls, cifs_remap(cifs_sb), path, ref, tl); } --- a/fs/cifs/fs_context.h +++ b/fs/cifs/fs_context.h @@ -265,6 +265,7 @@ struct smb3_fs_context { bool rootfs:1; /* if it's a SMB root file system */ bool witness:1; /* use witness protocol */ char *leaf_fullpath; + struct cifs_ses *dfs_root_ses; }; extern const struct fs_parameter_spec smb3_fs_parameters[];