cifs: use fs_context for automounts
Use filesystem context support to handle dfs links. Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
c877ce47e1
commit
9fd29a5bae
1 changed files with 40 additions and 60 deletions
|
@ -258,61 +258,23 @@ compose_mount_options_err:
|
||||||
goto compose_mount_options_out;
|
goto compose_mount_options_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* cifs_dfs_do_mount - mounts specified path using DFS full path
|
|
||||||
*
|
|
||||||
* Always pass down @fullpath to smb3_do_mount() so we can use the root server
|
|
||||||
* to perform failover in case we failed to connect to the first target in the
|
|
||||||
* referral.
|
|
||||||
*
|
|
||||||
* @mntpt: directory entry for the path we are trying to automount
|
|
||||||
* @cifs_sb: parent/root superblock
|
|
||||||
* @fullpath: full path in UNC format
|
|
||||||
*/
|
|
||||||
static struct vfsmount *cifs_dfs_do_mount(struct dentry *mntpt,
|
|
||||||
struct cifs_sb_info *cifs_sb,
|
|
||||||
const char *fullpath)
|
|
||||||
{
|
|
||||||
struct vfsmount *mnt;
|
|
||||||
char *mountdata;
|
|
||||||
char *devname;
|
|
||||||
|
|
||||||
devname = kstrdup(fullpath, GFP_KERNEL);
|
|
||||||
if (!devname)
|
|
||||||
return ERR_PTR(-ENOMEM);
|
|
||||||
|
|
||||||
convert_delimiter(devname, '/');
|
|
||||||
|
|
||||||
/* TODO: change to call fs_context_for_mount(), fill in context directly, call fc_mount */
|
|
||||||
|
|
||||||
/* See afs_mntpt_do_automount in fs/afs/mntpt.c for an example */
|
|
||||||
|
|
||||||
/* strip first '\' from fullpath */
|
|
||||||
mountdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options,
|
|
||||||
fullpath + 1, NULL, NULL);
|
|
||||||
if (IS_ERR(mountdata)) {
|
|
||||||
kfree(devname);
|
|
||||||
return (struct vfsmount *)mountdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
mnt = vfs_submount(mntpt, &cifs_fs_type, devname, mountdata);
|
|
||||||
kfree(mountdata);
|
|
||||||
kfree(devname);
|
|
||||||
return mnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a vfsmount that we can automount
|
* Create a vfsmount that we can automount
|
||||||
*/
|
*/
|
||||||
static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
|
static struct vfsmount *cifs_dfs_do_automount(struct path *path)
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
struct dentry *mntpt = path->dentry;
|
||||||
|
struct fs_context *fc;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
void *page;
|
void *page = NULL;
|
||||||
|
struct smb3_fs_context *ctx, *cur_ctx;
|
||||||
|
struct smb3_fs_context tmp;
|
||||||
char *full_path;
|
char *full_path;
|
||||||
struct vfsmount *mnt;
|
struct vfsmount *mnt;
|
||||||
|
|
||||||
cifs_dbg(FYI, "in %s\n", __func__);
|
if (IS_ROOT(mntpt))
|
||||||
BUG_ON(IS_ROOT(mntpt));
|
return ERR_PTR(-ESTALE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The MSDFS spec states that paths in DFS referral requests and
|
* The MSDFS spec states that paths in DFS referral requests and
|
||||||
|
@ -321,29 +283,47 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
|
||||||
* gives us the latter, so we must adjust the result.
|
* gives us the latter, so we must adjust the result.
|
||||||
*/
|
*/
|
||||||
cifs_sb = CIFS_SB(mntpt->d_sb);
|
cifs_sb = CIFS_SB(mntpt->d_sb);
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) {
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
|
||||||
mnt = ERR_PTR(-EREMOTE);
|
return ERR_PTR(-EREMOTE);
|
||||||
goto cdda_exit;
|
|
||||||
}
|
cur_ctx = cifs_sb->ctx;
|
||||||
|
|
||||||
|
fc = fs_context_for_submount(path->mnt->mnt_sb->s_type, mntpt);
|
||||||
|
if (IS_ERR(fc))
|
||||||
|
return ERR_CAST(fc);
|
||||||
|
|
||||||
|
ctx = smb3_fc2context(fc);
|
||||||
|
|
||||||
page = alloc_dentry_path();
|
page = alloc_dentry_path();
|
||||||
/* always use tree name prefix */
|
/* always use tree name prefix */
|
||||||
full_path = build_path_from_dentry_optional_prefix(mntpt, page, true);
|
full_path = build_path_from_dentry_optional_prefix(mntpt, page, true);
|
||||||
if (IS_ERR(full_path)) {
|
if (IS_ERR(full_path)) {
|
||||||
mnt = ERR_CAST(full_path);
|
mnt = ERR_CAST(full_path);
|
||||||
goto free_full_path;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
convert_delimiter(full_path, '\\');
|
convert_delimiter(full_path, '/');
|
||||||
cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
|
cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
|
||||||
|
|
||||||
mnt = cifs_dfs_do_mount(mntpt, cifs_sb, full_path);
|
tmp = *cur_ctx;
|
||||||
cifs_dbg(FYI, "%s: cifs_dfs_do_mount:%s , mnt:%p\n", __func__, full_path + 1, mnt);
|
tmp.source = full_path;
|
||||||
|
tmp.UNC = tmp.prepath = NULL;
|
||||||
|
|
||||||
free_full_path:
|
rc = smb3_fs_context_dup(ctx, &tmp);
|
||||||
|
if (rc) {
|
||||||
|
mnt = ERR_PTR(rc);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = smb3_parse_devname(full_path, ctx);
|
||||||
|
if (!rc)
|
||||||
|
mnt = fc_mount(fc);
|
||||||
|
else
|
||||||
|
mnt = ERR_PTR(rc);
|
||||||
|
|
||||||
|
out:
|
||||||
|
put_fs_context(fc);
|
||||||
free_dentry_path(page);
|
free_dentry_path(page);
|
||||||
cdda_exit:
|
|
||||||
cifs_dbg(FYI, "leaving %s\n" , __func__);
|
|
||||||
return mnt;
|
return mnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,9 +334,9 @@ struct vfsmount *cifs_dfs_d_automount(struct path *path)
|
||||||
{
|
{
|
||||||
struct vfsmount *newmnt;
|
struct vfsmount *newmnt;
|
||||||
|
|
||||||
cifs_dbg(FYI, "in %s\n", __func__);
|
cifs_dbg(FYI, "%s: %pd\n", __func__, path->dentry);
|
||||||
|
|
||||||
newmnt = cifs_dfs_do_automount(path->dentry);
|
newmnt = cifs_dfs_do_automount(path);
|
||||||
if (IS_ERR(newmnt)) {
|
if (IS_ERR(newmnt)) {
|
||||||
cifs_dbg(FYI, "leaving %s [automount failed]\n" , __func__);
|
cifs_dbg(FYI, "leaving %s [automount failed]\n" , __func__);
|
||||||
return newmnt;
|
return newmnt;
|
||||||
|
|
Loading…
Add table
Reference in a new issue