cifs: set DFS root session in cifs_get_smb_ses()
authorPaulo Alcantara <pc@manguebit.com>
Tue, 14 Mar 2023 23:32:53 +0000 (20:32 -0300)
committerSteve French <stfrench@microsoft.com>
Thu, 1 Jun 2023 04:22:31 +0000 (23:22 -0500)
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>
fs/cifs/cifs_dfs_ref.c
fs/cifs/cifsglob.h
fs/cifs/connect.c
fs/cifs/dfs.c
fs/cifs/dfs.h
fs/cifs/fs_context.h

index 2b1a8d55b4ec427dcd25ddad2439bd9a65f79c93..cb40074feb3e99bb5a86723fb17d00da744e5f41 100644 (file)
@@ -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) {
index 48ea6c6a8f36f4b824bbe3eb02a6ce78f22dd3c3..358872e432eecbbe29410b93413165931a640d0f 100644 (file)
@@ -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;
 };
index ef5ed23659eed8bdb92463021ddf27ed42c781eb..52c2ff3ad345786acf57dea969bfe2cc1536c551 100644 (file)
@@ -2240,6 +2240,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);
 
index b64d20374b9c853d4402ef3f8617dbfa57921d94..6505f1b20147e5b08c3707ce1e587a7633629739 100644 (file)
@@ -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.
index 344bea6d8bab1e471444131b1841c4442e5ca657..baf16df55d7e7826960c32f58da0b0bcacaba10e 100644 (file)
@@ -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);
 }
 
index 44cb5639ed3ba3502db464c887526c3c0b0ec58a..1b8d4e27f831c1fc7fa9c2c14843d0eb9fc735a5 100644 (file)
@@ -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[];