cifs: use origin fullpath for automounts
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) <pc@cjr.nz> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
25cf01b7c9
commit
7ad54b98fc
|
@ -21,8 +21,7 @@
|
|||
#include "cifsfs.h"
|
||||
#include "dns_resolve.h"
|
||||
#include "cifs_debug.h"
|
||||
#include "cifs_unicode.h"
|
||||
#include "dfs_cache.h"
|
||||
#include "dfs.h"
|
||||
#include "fs_context.h"
|
||||
|
||||
static LIST_HEAD(cifs_dfs_automount_list);
|
||||
|
@ -119,6 +118,17 @@ cifs_build_devname(char *nodename, const char *prepath)
|
|||
return dev;
|
||||
}
|
||||
|
||||
static int set_dest_addr(struct smb3_fs_context *ctx, const char *full_path)
|
||||
{
|
||||
struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr;
|
||||
int rc;
|
||||
|
||||
rc = dns_resolve_server_name_to_ip(full_path, addr, NULL);
|
||||
if (!rc)
|
||||
cifs_set_port(addr, ctx->port);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a vfsmount that we can automount
|
||||
*/
|
||||
|
@ -156,8 +166,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path)
|
|||
ctx = smb3_fc2context(fc);
|
||||
|
||||
page = alloc_dentry_path();
|
||||
/* always use tree name prefix */
|
||||
full_path = build_path_from_dentry_optional_prefix(mntpt, page, true);
|
||||
full_path = dfs_get_automount_devname(mntpt, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
mnt = ERR_CAST(full_path);
|
||||
goto out;
|
||||
|
@ -168,6 +177,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path)
|
|||
|
||||
tmp = *cur_ctx;
|
||||
tmp.source = full_path;
|
||||
tmp.leaf_fullpath = NULL;
|
||||
tmp.UNC = tmp.prepath = NULL;
|
||||
|
||||
rc = smb3_fs_context_dup(ctx, &tmp);
|
||||
|
@ -176,6 +186,12 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path)
|
|||
goto out;
|
||||
}
|
||||
|
||||
rc = set_dest_addr(ctx, full_path);
|
||||
if (rc) {
|
||||
mnt = ERR_PTR(rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = smb3_parse_devname(full_path, ctx);
|
||||
if (!rc)
|
||||
mnt = fc_mount(fc);
|
||||
|
|
|
@ -57,6 +57,9 @@ extern void exit_cifs_idmap(void);
|
|||
extern int init_cifs_spnego(void);
|
||||
extern void exit_cifs_spnego(void);
|
||||
extern const char *build_path_from_dentry(struct dentry *, void *);
|
||||
char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
|
||||
const char *tree, int tree_len,
|
||||
bool prefix);
|
||||
extern char *build_path_from_dentry_optional_prefix(struct dentry *direntry,
|
||||
void *page, bool prefix);
|
||||
static inline void *alloc_dentry_path(void)
|
||||
|
|
|
@ -28,4 +28,19 @@ static inline int dfs_get_referral(struct cifs_mount_ctx *mnt_ctx, const char *p
|
|||
cifs_remap(cifs_sb), path, ref, tl);
|
||||
}
|
||||
|
||||
static inline char *dfs_get_automount_devname(struct dentry *dentry, void *page)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
struct TCP_Server_Info *server = tcon->ses->server;
|
||||
|
||||
if (unlikely(!server->origin_fullpath))
|
||||
return ERR_PTR(-EREMOTE);
|
||||
|
||||
return __build_path_from_dentry_optional_prefix(dentry, page,
|
||||
server->origin_fullpath,
|
||||
strlen(server->origin_fullpath),
|
||||
true);
|
||||
}
|
||||
|
||||
#endif /* _CIFS_DFS_H */
|
||||
|
|
|
@ -78,14 +78,13 @@ build_path_from_dentry(struct dentry *direntry, void *page)
|
|||
prefix);
|
||||
}
|
||||
|
||||
char *
|
||||
build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
|
||||
bool prefix)
|
||||
char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
|
||||
const char *tree, int tree_len,
|
||||
bool prefix)
|
||||
{
|
||||
int dfsplen;
|
||||
int pplen = 0;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
char dirsep = CIFS_DIR_SEP(cifs_sb);
|
||||
char *s;
|
||||
|
||||
|
@ -93,7 +92,7 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
|
|||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
if (prefix)
|
||||
dfsplen = strnlen(tcon->tree_name, MAX_TREE_SIZE + 1);
|
||||
dfsplen = strnlen(tree, tree_len + 1);
|
||||
else
|
||||
dfsplen = 0;
|
||||
|
||||
|
@ -123,7 +122,7 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
|
|||
}
|
||||
if (dfsplen) {
|
||||
s -= dfsplen;
|
||||
memcpy(s, tcon->tree_name, dfsplen);
|
||||
memcpy(s, tree, dfsplen);
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
|
||||
int i;
|
||||
for (i = 0; i < dfsplen; i++) {
|
||||
|
@ -135,6 +134,16 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
|
|||
return s;
|
||||
}
|
||||
|
||||
char *build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
|
||||
bool prefix)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
|
||||
return __build_path_from_dentry_optional_prefix(direntry, page, tcon->tree_name,
|
||||
MAX_TREE_SIZE, prefix);
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't allow path components longer than the server max.
|
||||
* Don't allow the separator character in a path component.
|
||||
|
|
Loading…
Reference in New Issue