Commit 9fd29a5b authored by Paulo Alcantara's avatar Paulo Alcantara Committed by Steve French

cifs: use fs_context for automounts

Use filesystem context support to handle dfs links.
Signed-off-by: default avatarPaulo Alcantara (SUSE) <pc@cjr.nz>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent c877ce47
...@@ -258,61 +258,23 @@ char *cifs_compose_mount_options(const char *sb_mountdata, ...@@ -258,61 +258,23 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
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) ...@@ -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;
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);
free_full_path: 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) ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment