smb: client: get rid of dfs code dep in namespace.c
Make namespace.c being built without requiring CONFIG_CIFS_DFS_UPCALL=y by moving set_dest_addr() to dfs.c and call it at the beginning of dfs_mount_share() so it can chase the DFS link starting from the correct server in @ctx->dstaddr. Signed-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
0a049935e4
commit
348a04a8d1
|
@ -11,7 +11,8 @@ cifs-y := trace.o cifsfs.o cifs_debug.o connect.o dir.o file.o \
|
|||
readdir.o ioctl.o sess.o export.o unc.o winucase.o \
|
||||
smb2ops.o smb2maperror.o smb2transport.o \
|
||||
smb2misc.o smb2pdu.o smb2inode.o smb2file.o cifsacl.o fs_context.o \
|
||||
dns_resolve.o cifs_spnego_negtokeninit.asn1.o asn1.o
|
||||
dns_resolve.o cifs_spnego_negtokeninit.asn1.o asn1.o \
|
||||
namespace.o
|
||||
|
||||
$(obj)/asn1.o: $(obj)/cifs_spnego_negtokeninit.asn1.h
|
||||
|
||||
|
@ -21,7 +22,7 @@ cifs-$(CONFIG_CIFS_XATTR) += xattr.o
|
|||
|
||||
cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
|
||||
|
||||
cifs-$(CONFIG_CIFS_DFS_UPCALL) += namespace.o dfs_cache.o dfs.o
|
||||
cifs-$(CONFIG_CIFS_DFS_UPCALL) += dfs_cache.o dfs.o
|
||||
|
||||
cifs-$(CONFIG_CIFS_SWN_UPCALL) += netlink.o cifs_swn.o
|
||||
|
||||
|
|
|
@ -118,14 +118,7 @@ extern void cifs_pages_write_redirty(struct inode *inode, loff_t start, unsigned
|
|||
extern const struct dentry_operations cifs_dentry_ops;
|
||||
extern const struct dentry_operations cifs_ci_dentry_ops;
|
||||
|
||||
#ifdef CONFIG_CIFS_DFS_UPCALL
|
||||
extern struct vfsmount *cifs_d_automount(struct path *path);
|
||||
#else
|
||||
static inline struct vfsmount *cifs_d_automount(struct path *path)
|
||||
{
|
||||
return ERR_PTR(-EREMOTE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Functions related to symlinks */
|
||||
extern const char *cifs_get_link(struct dentry *, struct inode *,
|
||||
|
|
|
@ -295,11 +295,7 @@ extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
|
|||
int from_reconnect);
|
||||
extern void cifs_put_tcon(struct cifs_tcon *tcon);
|
||||
|
||||
#if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)
|
||||
extern void cifs_release_automount_timer(void);
|
||||
#else /* ! IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) */
|
||||
#define cifs_release_automount_timer() do { } while (0)
|
||||
#endif /* ! IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) */
|
||||
|
||||
void cifs_proc_init(void);
|
||||
void cifs_proc_clean(void);
|
||||
|
|
|
@ -263,12 +263,28 @@ out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
/* Resolve UNC hostname in @ctx->source and set ip addr in @ctx->dstaddr */
|
||||
static int update_fs_context_dstaddr(struct smb3_fs_context *ctx)
|
||||
{
|
||||
struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr;
|
||||
int rc;
|
||||
|
||||
rc = dns_resolve_server_name_to_ip(ctx->source, addr, NULL);
|
||||
if (!rc)
|
||||
cifs_set_port(addr, ctx->port);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
|
||||
{
|
||||
struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
|
||||
bool nodfs = ctx->nodfs;
|
||||
int rc;
|
||||
|
||||
rc = update_fs_context_dstaddr(ctx);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
*isdfs = false;
|
||||
rc = get_session(mnt_ctx, NULL);
|
||||
if (rc)
|
||||
|
|
|
@ -138,43 +138,6 @@ static inline int dfs_get_referral(struct cifs_mount_ctx *mnt_ctx, const char *p
|
|||
cifs_remap(cifs_sb), path, ref, tl);
|
||||
}
|
||||
|
||||
/* Return DFS full path out of a dentry set for automount */
|
||||
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);
|
||||
size_t len;
|
||||
char *s;
|
||||
|
||||
spin_lock(&tcon->tc_lock);
|
||||
if (unlikely(!tcon->origin_fullpath)) {
|
||||
spin_unlock(&tcon->tc_lock);
|
||||
return ERR_PTR(-EREMOTE);
|
||||
}
|
||||
spin_unlock(&tcon->tc_lock);
|
||||
|
||||
s = dentry_path_raw(dentry, page, PATH_MAX);
|
||||
if (IS_ERR(s))
|
||||
return s;
|
||||
/* for root, we want "" */
|
||||
if (!s[1])
|
||||
s++;
|
||||
|
||||
spin_lock(&tcon->tc_lock);
|
||||
len = strlen(tcon->origin_fullpath);
|
||||
if (s < (char *)page + len) {
|
||||
spin_unlock(&tcon->tc_lock);
|
||||
return ERR_PTR(-ENAMETOOLONG);
|
||||
}
|
||||
|
||||
s -= len;
|
||||
memcpy(s, tcon->origin_fullpath, len);
|
||||
spin_unlock(&tcon->tc_lock);
|
||||
convert_delimiter(s, '/');
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline void dfs_put_root_smb_sessions(struct list_head *head)
|
||||
{
|
||||
struct dfs_root_ses *root, *tmp;
|
||||
|
|
|
@ -58,13 +58,9 @@ static void cifs_set_ops(struct inode *inode)
|
|||
inode->i_data.a_ops = &cifs_addr_ops;
|
||||
break;
|
||||
case S_IFDIR:
|
||||
#ifdef CONFIG_CIFS_DFS_UPCALL
|
||||
if (IS_AUTOMOUNT(inode)) {
|
||||
inode->i_op = &cifs_namespace_inode_operations;
|
||||
} else {
|
||||
#else /* NO DFS support, treat as a directory */
|
||||
{
|
||||
#endif
|
||||
inode->i_op = &cifs_dir_inode_ops;
|
||||
inode->i_fop = &cifs_dir_ops;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Copyright (C) International Business Machines Corp., 2008
|
||||
* Author(s): Igor Mammedov (niallain@gmail.com)
|
||||
* Steve French (sfrench@us.ibm.com)
|
||||
* Copyright (c) 2023 Paulo Alcantara <palcantara@suse.de>
|
||||
*/
|
||||
|
||||
#include <linux/dcache.h>
|
||||
|
@ -18,9 +19,7 @@
|
|||
#include "cifsglob.h"
|
||||
#include "cifsproto.h"
|
||||
#include "cifsfs.h"
|
||||
#include "dns_resolve.h"
|
||||
#include "cifs_debug.h"
|
||||
#include "dfs.h"
|
||||
#include "fs_context.h"
|
||||
|
||||
static LIST_HEAD(cifs_automount_list);
|
||||
|
@ -118,15 +117,41 @@ cifs_build_devname(char *nodename, const char *prepath)
|
|||
return dev;
|
||||
}
|
||||
|
||||
static int set_dest_addr(struct smb3_fs_context *ctx)
|
||||
/* Return full path out of a dentry set for automount */
|
||||
static char *automount_fullpath(struct dentry *dentry, void *page)
|
||||
{
|
||||
struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr;
|
||||
int rc;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
size_t len;
|
||||
char *s;
|
||||
|
||||
rc = dns_resolve_server_name_to_ip(ctx->source, addr, NULL);
|
||||
if (!rc)
|
||||
cifs_set_port(addr, ctx->port);
|
||||
return rc;
|
||||
spin_lock(&tcon->tc_lock);
|
||||
if (unlikely(!tcon->origin_fullpath)) {
|
||||
spin_unlock(&tcon->tc_lock);
|
||||
return ERR_PTR(-EREMOTE);
|
||||
}
|
||||
spin_unlock(&tcon->tc_lock);
|
||||
|
||||
s = dentry_path_raw(dentry, page, PATH_MAX);
|
||||
if (IS_ERR(s))
|
||||
return s;
|
||||
/* for root, we want "" */
|
||||
if (!s[1])
|
||||
s++;
|
||||
|
||||
spin_lock(&tcon->tc_lock);
|
||||
len = strlen(tcon->origin_fullpath);
|
||||
if (s < (char *)page + len) {
|
||||
spin_unlock(&tcon->tc_lock);
|
||||
return ERR_PTR(-ENAMETOOLONG);
|
||||
}
|
||||
|
||||
s -= len;
|
||||
memcpy(s, tcon->origin_fullpath, len);
|
||||
spin_unlock(&tcon->tc_lock);
|
||||
convert_delimiter(s, '/');
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -166,7 +191,7 @@ static struct vfsmount *cifs_do_automount(struct path *path)
|
|||
ctx = smb3_fc2context(fc);
|
||||
|
||||
page = alloc_dentry_path();
|
||||
full_path = dfs_get_automount_devname(mntpt, page);
|
||||
full_path = automount_fullpath(mntpt, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
mnt = ERR_CAST(full_path);
|
||||
goto out;
|
||||
|
@ -196,15 +221,10 @@ static struct vfsmount *cifs_do_automount(struct path *path)
|
|||
ctx->source = NULL;
|
||||
goto out;
|
||||
}
|
||||
cifs_dbg(FYI, "%s: ctx: source=%s UNC=%s prepath=%s dstaddr=%pISpc\n",
|
||||
__func__, ctx->source, ctx->UNC, ctx->prepath, &ctx->dstaddr);
|
||||
cifs_dbg(FYI, "%s: ctx: source=%s UNC=%s prepath=%s\n",
|
||||
__func__, ctx->source, ctx->UNC, ctx->prepath);
|
||||
|
||||
rc = set_dest_addr(ctx);
|
||||
if (!rc)
|
||||
mnt = fc_mount(fc);
|
||||
else
|
||||
mnt = ERR_PTR(rc);
|
||||
|
||||
out:
|
||||
put_fs_context(fc);
|
||||
free_dentry_path(page);
|
||||
|
|
Loading…
Reference in New Issue