aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/fs/smb/client/dfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/smb/client/dfs.c')
-rw-r--r--fs/smb/client/dfs.c55
1 files changed, 21 insertions, 34 deletions
diff --git a/fs/smb/client/dfs.c b/fs/smb/client/dfs.c
index d741f396c527..dd06b8a0ff7a 100644
--- a/fs/smb/client/dfs.c
+++ b/fs/smb/client/dfs.c
@@ -217,14 +217,12 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx)
server = mnt_ctx->server;
tcon = mnt_ctx->tcon;
- mutex_lock(&server->refpath_lock);
- spin_lock(&server->srv_lock);
- if (!server->origin_fullpath) {
- server->origin_fullpath = origin_fullpath;
+ spin_lock(&tcon->tc_lock);
+ if (!tcon->origin_fullpath) {
+ tcon->origin_fullpath = origin_fullpath;
origin_fullpath = NULL;
}
- spin_unlock(&server->srv_lock);
- mutex_unlock(&server->refpath_lock);
+ spin_unlock(&tcon->tc_lock);
if (list_empty(&tcon->dfs_ses_list)) {
list_replace_init(&mnt_ctx->dfs_ses_list,
@@ -247,18 +245,13 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
{
struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
struct cifs_ses *ses;
- char *source = ctx->source;
bool nodfs = ctx->nodfs;
int rc;
*isdfs = false;
- /* Temporarily set @ctx->source to NULL as we're not matching DFS
- * superblocks yet. See cifs_match_super() and match_server().
- */
- ctx->source = NULL;
rc = get_session(mnt_ctx, NULL);
if (rc)
- goto out;
+ return rc;
ctx->dfs_root_ses = mnt_ctx->ses;
/*
@@ -272,7 +265,7 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
rc = dfs_get_referral(mnt_ctx, ctx->UNC + 1, NULL, NULL);
if (rc) {
if (rc != -ENOENT && rc != -EOPNOTSUPP && rc != -EIO)
- goto out;
+ return rc;
nodfs = true;
}
}
@@ -280,7 +273,7 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
rc = cifs_mount_get_tcon(mnt_ctx);
if (!rc)
rc = cifs_is_path_remote(mnt_ctx);
- goto out;
+ return rc;
}
*isdfs = true;
@@ -296,12 +289,7 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
rc = __dfs_mount_share(mnt_ctx);
if (ses == ctx->dfs_root_ses)
cifs_put_smb_ses(ses);
-out:
- /*
- * Restore previous value of @ctx->source so DFS superblock can be
- * matched in cifs_match_super().
- */
- ctx->source = source;
+
return rc;
}
@@ -535,11 +523,11 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
int rc;
struct TCP_Server_Info *server = tcon->ses->server;
const struct smb_version_operations *ops = server->ops;
- struct super_block *sb = NULL;
- struct cifs_sb_info *cifs_sb;
struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl);
- char *tree;
+ struct cifs_sb_info *cifs_sb = NULL;
+ struct super_block *sb = NULL;
struct dfs_info3_param ref = {0};
+ char *tree;
/* only send once per connect */
spin_lock(&tcon->tc_lock);
@@ -571,19 +559,18 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
goto out;
}
- sb = cifs_get_tcp_super(server);
- if (IS_ERR(sb)) {
- rc = PTR_ERR(sb);
- cifs_dbg(VFS, "%s: could not find superblock: %d\n", __func__, rc);
- goto out;
- }
-
- cifs_sb = CIFS_SB(sb);
+ sb = cifs_get_dfs_tcon_super(tcon);
+ if (!IS_ERR(sb))
+ cifs_sb = CIFS_SB(sb);
- /* If it is not dfs or there was no cached dfs referral, then reconnect to same share */
- if (!server->leaf_fullpath ||
+ /*
+ * Tree connect to last share in @tcon->tree_name whether dfs super or
+ * cached dfs referral was not found.
+ */
+ if (!cifs_sb || !server->leaf_fullpath ||
dfs_cache_noreq_find(server->leaf_fullpath + 1, &ref, &tl)) {
- rc = ops->tree_connect(xid, tcon->ses, tcon->tree_name, tcon, cifs_sb->local_nls);
+ rc = ops->tree_connect(xid, tcon->ses, tcon->tree_name, tcon,
+ cifs_sb ? cifs_sb->local_nls : nlsc);
goto out;
}