Skip to content

Commit 9fd29a5

Browse files
Paulo Alcantarasmfrench
authored andcommitted
cifs: use fs_context for automounts
Use filesystem context support to handle dfs links. Signed-off-by: Paulo Alcantara (SUSE) <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent c877ce4 commit 9fd29a5

File tree

1 file changed

+40
-60
lines changed

1 file changed

+40
-60
lines changed

fs/cifs/cifs_dfs_ref.c

Lines changed: 40 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -258,61 +258,23 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
258258
goto compose_mount_options_out;
259259
}
260260

261-
/**
262-
* cifs_dfs_do_mount - mounts specified path using DFS full path
263-
*
264-
* Always pass down @fullpath to smb3_do_mount() so we can use the root server
265-
* to perform failover in case we failed to connect to the first target in the
266-
* referral.
267-
*
268-
* @mntpt: directory entry for the path we are trying to automount
269-
* @cifs_sb: parent/root superblock
270-
* @fullpath: full path in UNC format
271-
*/
272-
static struct vfsmount *cifs_dfs_do_mount(struct dentry *mntpt,
273-
struct cifs_sb_info *cifs_sb,
274-
const char *fullpath)
275-
{
276-
struct vfsmount *mnt;
277-
char *mountdata;
278-
char *devname;
279-
280-
devname = kstrdup(fullpath, GFP_KERNEL);
281-
if (!devname)
282-
return ERR_PTR(-ENOMEM);
283-
284-
convert_delimiter(devname, '/');
285-
286-
/* TODO: change to call fs_context_for_mount(), fill in context directly, call fc_mount */
287-
288-
/* See afs_mntpt_do_automount in fs/afs/mntpt.c for an example */
289-
290-
/* strip first '\' from fullpath */
291-
mountdata = cifs_compose_mount_options(cifs_sb->ctx->mount_options,
292-
fullpath + 1, NULL, NULL);
293-
if (IS_ERR(mountdata)) {
294-
kfree(devname);
295-
return (struct vfsmount *)mountdata;
296-
}
297-
298-
mnt = vfs_submount(mntpt, &cifs_fs_type, devname, mountdata);
299-
kfree(mountdata);
300-
kfree(devname);
301-
return mnt;
302-
}
303-
304261
/*
305262
* Create a vfsmount that we can automount
306263
*/
307-
static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
264+
static struct vfsmount *cifs_dfs_do_automount(struct path *path)
308265
{
266+
int rc;
267+
struct dentry *mntpt = path->dentry;
268+
struct fs_context *fc;
309269
struct cifs_sb_info *cifs_sb;
310-
void *page;
270+
void *page = NULL;
271+
struct smb3_fs_context *ctx, *cur_ctx;
272+
struct smb3_fs_context tmp;
311273
char *full_path;
312274
struct vfsmount *mnt;
313275

314-
cifs_dbg(FYI, "in %s\n", __func__);
315-
BUG_ON(IS_ROOT(mntpt));
276+
if (IS_ROOT(mntpt))
277+
return ERR_PTR(-ESTALE);
316278

317279
/*
318280
* 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)
321283
* gives us the latter, so we must adjust the result.
322284
*/
323285
cifs_sb = CIFS_SB(mntpt->d_sb);
324-
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) {
325-
mnt = ERR_PTR(-EREMOTE);
326-
goto cdda_exit;
327-
}
286+
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
287+
return ERR_PTR(-EREMOTE);
288+
289+
cur_ctx = cifs_sb->ctx;
290+
291+
fc = fs_context_for_submount(path->mnt->mnt_sb->s_type, mntpt);
292+
if (IS_ERR(fc))
293+
return ERR_CAST(fc);
294+
295+
ctx = smb3_fc2context(fc);
328296

329297
page = alloc_dentry_path();
330298
/* always use tree name prefix */
331299
full_path = build_path_from_dentry_optional_prefix(mntpt, page, true);
332300
if (IS_ERR(full_path)) {
333301
mnt = ERR_CAST(full_path);
334-
goto free_full_path;
302+
goto out;
335303
}
336304

337-
convert_delimiter(full_path, '\\');
305+
convert_delimiter(full_path, '/');
338306
cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
339307

340-
mnt = cifs_dfs_do_mount(mntpt, cifs_sb, full_path);
341-
cifs_dbg(FYI, "%s: cifs_dfs_do_mount:%s , mnt:%p\n", __func__, full_path + 1, mnt);
308+
tmp = *cur_ctx;
309+
tmp.source = full_path;
310+
tmp.UNC = tmp.prepath = NULL;
311+
312+
rc = smb3_fs_context_dup(ctx, &tmp);
313+
if (rc) {
314+
mnt = ERR_PTR(rc);
315+
goto out;
316+
}
317+
318+
rc = smb3_parse_devname(full_path, ctx);
319+
if (!rc)
320+
mnt = fc_mount(fc);
321+
else
322+
mnt = ERR_PTR(rc);
342323

343-
free_full_path:
324+
out:
325+
put_fs_context(fc);
344326
free_dentry_path(page);
345-
cdda_exit:
346-
cifs_dbg(FYI, "leaving %s\n" , __func__);
347327
return mnt;
348328
}
349329

@@ -354,9 +334,9 @@ struct vfsmount *cifs_dfs_d_automount(struct path *path)
354334
{
355335
struct vfsmount *newmnt;
356336

357-
cifs_dbg(FYI, "in %s\n", __func__);
337+
cifs_dbg(FYI, "%s: %pd\n", __func__, path->dentry);
358338

359-
newmnt = cifs_dfs_do_automount(path->dentry);
339+
newmnt = cifs_dfs_do_automount(path);
360340
if (IS_ERR(newmnt)) {
361341
cifs_dbg(FYI, "leaving %s [automount failed]\n" , __func__);
362342
return newmnt;

0 commit comments

Comments
 (0)