summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorPaulo Alcantara <pc@manguebit.com>2023-03-15 02:32:53 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-03-22 15:38:01 +0300
commitce82404a832a7a5e131ad743a1c1b5bcac82fa89 (patch)
tree32dec25f100ad0e4c21aa876c988125c4443342e /fs
parentbfa0434497d777b92f8e8af88109adc5d8ada7dd (diff)
downloadlinux-ce82404a832a7a5e131ad743a1c1b5bcac82fa89.tar.xz
cifs: set DFS root session in cifs_get_smb_ses()
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@manguebit.com> Cc: stable@vger.kernel.org # 6.2 Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifs_dfs_ref.c1
-rw-r--r--fs/cifs/cifsglob.h1
-rw-r--r--fs/cifs/connect.c1
-rw-r--r--fs/cifs/dfs.c19
-rw-r--r--fs/cifs/dfs.h3
-rw-r--r--fs/cifs/fs_context.h1
6 files changed, 13 insertions, 13 deletions
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index 2b1a8d55b4ec..cb40074feb3e 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -179,6 +179,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path)
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) {
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index cfdd5bf701a1..f0a88b0ae31b 100644
--- 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;
};
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index af49ae53aaf4..4e7b23af04f4 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2278,6 +2278,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
* 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);
diff --git a/fs/cifs/dfs.c b/fs/cifs/dfs.c
index b64d20374b9c..6505f1b20147 100644
--- a/fs/cifs/dfs.c
+++ b/fs/cifs/dfs.c
@@ -95,25 +95,22 @@ static int get_session(struct cifs_mount_ctx *mnt_ctx, const char *full_path)
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_ctx *mnt_ctx, bool *isdfs)
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.
diff --git a/fs/cifs/dfs.h b/fs/cifs/dfs.h
index 344bea6d8bab..baf16df55d7e 100644
--- a/fs/cifs/dfs.h
+++ b/fs/cifs/dfs.h
@@ -22,9 +22,10 @@ static inline char *dfs_get_path(struct cifs_sb_info *cifs_sb, const char *path)
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);
}
diff --git a/fs/cifs/fs_context.h b/fs/cifs/fs_context.h
index 44cb5639ed3b..1b8d4e27f831 100644
--- 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[];