Commit b56bce50 authored by Paulo Alcantara's avatar Paulo Alcantara Committed by Steve French

cifs: set DFS root session in cifs_get_smb_ses()

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: default avatarPaulo Alcantara (SUSE) <pc@manguebit.com>
Cc: stable@vger.kernel.org # 6.2
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 05ce0448
...@@ -179,6 +179,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path) ...@@ -179,6 +179,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path)
tmp.source = full_path; tmp.source = full_path;
tmp.leaf_fullpath = NULL; tmp.leaf_fullpath = NULL;
tmp.UNC = tmp.prepath = NULL; tmp.UNC = tmp.prepath = NULL;
tmp.dfs_root_ses = NULL;
rc = smb3_fs_context_dup(ctx, &tmp); rc = smb3_fs_context_dup(ctx, &tmp);
if (rc) { if (rc) {
......
...@@ -1749,7 +1749,6 @@ struct cifs_mount_ctx { ...@@ -1749,7 +1749,6 @@ struct cifs_mount_ctx {
struct TCP_Server_Info *server; struct TCP_Server_Info *server;
struct cifs_ses *ses; struct cifs_ses *ses;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
struct cifs_ses *root_ses;
uuid_t mount_id; uuid_t mount_id;
char *origin_fullpath, *leaf_fullpath; char *origin_fullpath, *leaf_fullpath;
}; };
......
...@@ -2229,6 +2229,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) ...@@ -2229,6 +2229,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
* need to lock before changing something in the session. * need to lock before changing something in the session.
*/ */
spin_lock(&cifs_tcp_ses_lock); spin_lock(&cifs_tcp_ses_lock);
ses->dfs_root_ses = ctx->dfs_root_ses;
list_add(&ses->smb_ses_list, &server->smb_ses_list); list_add(&ses->smb_ses_list, &server->smb_ses_list);
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
......
...@@ -95,25 +95,22 @@ static int get_session(struct cifs_mount_ctx *mnt_ctx, const char *full_path) ...@@ -95,25 +95,22 @@ static int get_session(struct cifs_mount_ctx *mnt_ctx, const char *full_path)
ctx->leaf_fullpath = (char *)full_path; ctx->leaf_fullpath = (char *)full_path;
rc = cifs_mount_get_session(mnt_ctx); rc = cifs_mount_get_session(mnt_ctx);
ctx->leaf_fullpath = NULL; 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; return rc;
} }
static void set_root_ses(struct cifs_mount_ctx *mnt_ctx) 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); spin_lock(&cifs_tcp_ses_lock);
mnt_ctx->ses->ses_count++; ses->ses_count++;
spin_unlock(&cifs_tcp_ses_lock); 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, 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) ...@@ -260,7 +257,7 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
rc = get_session(mnt_ctx, NULL); rc = get_session(mnt_ctx, NULL);
if (rc) if (rc)
return 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 * 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. * try to get an DFS referral (even cached) to determine whether it is an DFS mount.
......
...@@ -22,9 +22,10 @@ static inline char *dfs_get_path(struct cifs_sb_info *cifs_sb, const char *path) ...@@ -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, 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 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; 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); cifs_remap(cifs_sb), path, ref, tl);
} }
......
...@@ -265,6 +265,7 @@ struct smb3_fs_context { ...@@ -265,6 +265,7 @@ struct smb3_fs_context {
bool rootfs:1; /* if it's a SMB root file system */ bool rootfs:1; /* if it's a SMB root file system */
bool witness:1; /* use witness protocol */ bool witness:1; /* use witness protocol */
char *leaf_fullpath; char *leaf_fullpath;
struct cifs_ses *dfs_root_ses;
}; };
extern const struct fs_parameter_spec smb3_fs_parameters[]; extern const struct fs_parameter_spec smb3_fs_parameters[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment