Skip to content

Commit 7d8bb97

Browse files
Paulo Alcantaragregkh
authored andcommitted
cifs: use origin fullpath for automounts
commit 7ad54b98fc1f141cfb70cfe2a3d6def5a85169ff upstream. Use TCP_Server_Info::origin_fullpath instead of cifs_tcon::tree_name when building source paths for automounts as it will be useful for domain-based DFS referrals where the connections and referrals would get either re-used from the cache or re-created when chasing the dfs link. Signed-off-by: Paulo Alcantara (SUSE) <[email protected]> Signed-off-by: Steve French <[email protected]> [apanyaki: backport to v6.1-stable] Signed-off-by: Andrew Paniakin <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent ec28c35 commit 7d8bb97

File tree

3 files changed

+68
-8
lines changed

3 files changed

+68
-8
lines changed

fs/smb/client/cifs_dfs_ref.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,31 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
258258
goto compose_mount_options_out;
259259
}
260260

261+
static int set_dest_addr(struct smb3_fs_context *ctx, const char *full_path)
262+
{
263+
struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr;
264+
char *str_addr = NULL;
265+
int rc;
266+
267+
rc = dns_resolve_server_name_to_ip(full_path, &str_addr, NULL);
268+
if (rc < 0)
269+
goto out;
270+
271+
rc = cifs_convert_address(addr, str_addr, strlen(str_addr));
272+
if (!rc) {
273+
cifs_dbg(FYI, "%s: failed to convert ip address\n", __func__);
274+
rc = -EINVAL;
275+
goto out;
276+
}
277+
278+
cifs_set_port(addr, ctx->port);
279+
rc = 0;
280+
281+
out:
282+
kfree(str_addr);
283+
return rc;
284+
}
285+
261286
/*
262287
* Create a vfsmount that we can automount
263288
*/
@@ -295,8 +320,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path)
295320
ctx = smb3_fc2context(fc);
296321

297322
page = alloc_dentry_path();
298-
/* always use tree name prefix */
299-
full_path = build_path_from_dentry_optional_prefix(mntpt, page, true);
323+
full_path = dfs_get_automount_devname(mntpt, page);
300324
if (IS_ERR(full_path)) {
301325
mnt = ERR_CAST(full_path);
302326
goto out;
@@ -315,6 +339,12 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path)
315339
goto out;
316340
}
317341

342+
rc = set_dest_addr(ctx, full_path);
343+
if (rc) {
344+
mnt = ERR_PTR(rc);
345+
goto out;
346+
}
347+
318348
rc = smb3_parse_devname(full_path, ctx);
319349
if (!rc)
320350
mnt = fc_mount(fc);

fs/smb/client/cifsproto.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,29 @@ extern void exit_cifs_idmap(void);
5757
extern int init_cifs_spnego(void);
5858
extern void exit_cifs_spnego(void);
5959
extern const char *build_path_from_dentry(struct dentry *, void *);
60+
char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
61+
const char *tree, int tree_len,
62+
bool prefix);
6063
extern char *build_path_from_dentry_optional_prefix(struct dentry *direntry,
6164
void *page, bool prefix);
65+
66+
#ifdef CONFIG_CIFS_DFS_UPCALL
67+
static inline char *dfs_get_automount_devname(struct dentry *dentry, void *page)
68+
{
69+
struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
70+
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
71+
struct TCP_Server_Info *server = tcon->ses->server;
72+
73+
if (unlikely(!server->origin_fullpath))
74+
return ERR_PTR(-EREMOTE);
75+
76+
return __build_path_from_dentry_optional_prefix(dentry, page,
77+
server->origin_fullpath,
78+
strlen(server->origin_fullpath),
79+
true);
80+
}
81+
#endif
82+
6283
static inline void *alloc_dentry_path(void)
6384
{
6485
return __getname();

fs/smb/client/dir.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,22 +78,21 @@ build_path_from_dentry(struct dentry *direntry, void *page)
7878
prefix);
7979
}
8080

81-
char *
82-
build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
83-
bool prefix)
81+
char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
82+
const char *tree, int tree_len,
83+
bool prefix)
8484
{
8585
int dfsplen;
8686
int pplen = 0;
8787
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
88-
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
8988
char dirsep = CIFS_DIR_SEP(cifs_sb);
9089
char *s;
9190

9291
if (unlikely(!page))
9392
return ERR_PTR(-ENOMEM);
9493

9594
if (prefix)
96-
dfsplen = strnlen(tcon->tree_name, MAX_TREE_SIZE + 1);
95+
dfsplen = strnlen(tree, tree_len + 1);
9796
else
9897
dfsplen = 0;
9998

@@ -123,7 +122,7 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
123122
}
124123
if (dfsplen) {
125124
s -= dfsplen;
126-
memcpy(s, tcon->tree_name, dfsplen);
125+
memcpy(s, tree, dfsplen);
127126
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
128127
int i;
129128
for (i = 0; i < dfsplen; i++) {
@@ -135,6 +134,16 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
135134
return s;
136135
}
137136

137+
char *build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
138+
bool prefix)
139+
{
140+
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
141+
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
142+
143+
return __build_path_from_dentry_optional_prefix(direntry, page, tcon->tree_name,
144+
MAX_TREE_SIZE, prefix);
145+
}
146+
138147
/*
139148
* Don't allow path components longer than the server max.
140149
* Don't allow the separator character in a path component.

0 commit comments

Comments
 (0)