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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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) {
+0 −1
Original line number Diff line number Diff line
@@ -1749,7 +1749,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;
};
+1 −0
Original line number Diff line number Diff line
@@ -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.
	 */
	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);

+8 −11
Original line number Diff line number Diff line
@@ -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.
+2 −1
Original line number Diff line number Diff line
@@ -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);
}

Loading