}
EXPORT_SYMBOL_GPL(vfs_kern_mount);
-static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root,
+static struct mount *clone_mnt(struct mount *old, struct dentry *root,
int flag)
{
- struct super_block *sb = old->mnt_sb;
- struct mount *mnt = alloc_vfsmnt(old->mnt_devname);
+ struct super_block *sb = old->mnt.mnt_sb;
+ struct mount *mnt = alloc_vfsmnt(old->mnt.mnt_devname);
if (mnt) {
if (flag & (CL_SLAVE | CL_PRIVATE))
mnt->mnt.mnt_group_id = 0; /* not a peer of original */
else
- mnt->mnt.mnt_group_id = old->mnt_group_id;
+ mnt->mnt.mnt_group_id = old->mnt.mnt_group_id;
if ((flag & CL_MAKE_SHARED) && !mnt->mnt.mnt_group_id) {
int err = mnt_alloc_group_id(mnt);
goto out_free;
}
- mnt->mnt.mnt_flags = old->mnt_flags & ~MNT_WRITE_HOLD;
+ mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~MNT_WRITE_HOLD;
atomic_inc(&sb->s_active);
mnt->mnt.mnt_sb = sb;
mnt->mnt.mnt_root = dget(root);
mnt->mnt.mnt_parent = &mnt->mnt;
if (flag & CL_SLAVE) {
- list_add(&mnt->mnt.mnt_slave, &old->mnt_slave_list);
- mnt->mnt.mnt_master = old;
+ list_add(&mnt->mnt.mnt_slave, &old->mnt.mnt_slave_list);
+ mnt->mnt.mnt_master = &old->mnt;
CLEAR_MNT_SHARED(&mnt->mnt);
} else if (!(flag & CL_PRIVATE)) {
- if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old))
- list_add(&mnt->mnt.mnt_share, &old->mnt_share);
- if (IS_MNT_SLAVE(old))
- list_add(&mnt->mnt.mnt_slave, &old->mnt_slave);
- mnt->mnt.mnt_master = old->mnt_master;
+ if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(&old->mnt))
+ list_add(&mnt->mnt.mnt_share, &old->mnt.mnt_share);
+ if (IS_MNT_SLAVE(&old->mnt))
+ list_add(&mnt->mnt.mnt_slave, &old->mnt.mnt_slave);
+ mnt->mnt.mnt_master = old->mnt.mnt_master;
}
if (flag & CL_MAKE_SHARED)
set_mnt_shared(mnt);
/* stick the duplicate mount on the same expiry list
* as the original if that was on one */
if (flag & CL_EXPIRE) {
- if (!list_empty(&old->mnt_expire))
- list_add(&mnt->mnt.mnt_expire, &old->mnt_expire);
+ if (!list_empty(&old->mnt.mnt_expire))
+ list_add(&mnt->mnt.mnt_expire, &old->mnt.mnt_expire);
}
}
return mnt;
#endif
}
-struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
+struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
int flag)
{
- struct mount *res, *q;
- struct vfsmount *p, *r;
+ struct mount *res, *p, *q;
+ struct vfsmount *r;
struct path path;
- if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt))
+ if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(&mnt->mnt))
return NULL;
res = q = clone_mnt(mnt, dentry, flag);
if (!q)
goto Enomem;
- q->mnt.mnt_mountpoint = mnt->mnt_mountpoint;
+ q->mnt.mnt_mountpoint = mnt->mnt.mnt_mountpoint;
p = mnt;
- list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) {
+ list_for_each_entry(r, &mnt->mnt.mnt_mounts, mnt_child) {
struct mount *s;
if (!is_subdir(r->mnt_mountpoint, dentry))
continue;
s = skip_mnt_tree(s);
continue;
}
- while (p != s->mnt.mnt_parent) {
- p = p->mnt_parent;
+ while (p != real_mount(s->mnt.mnt_parent)) {
+ p = real_mount(p->mnt.mnt_parent);
q = real_mount(q->mnt.mnt_parent);
}
- p = &s->mnt;
+ p = s;
path.mnt = &q->mnt;
- path.dentry = p->mnt_mountpoint;
- q = clone_mnt(p, p->mnt_root, flag);
+ path.dentry = p->mnt.mnt_mountpoint;
+ q = clone_mnt(p, p->mnt.mnt_root, flag);
if (!q)
goto Enomem;
br_write_lock(vfsmount_lock);
{
struct mount *tree;
down_write(&namespace_sem);
- tree = copy_tree(path->mnt, path->dentry, CL_COPY_ALL | CL_PRIVATE);
+ tree = copy_tree(real_mount(path->mnt), path->dentry,
+ CL_COPY_ALL | CL_PRIVATE);
up_write(&namespace_sem);
return tree ? &tree->mnt : NULL;
}
{
LIST_HEAD(umount_list);
struct path old_path;
- struct mount *mnt = NULL;
+ struct mount *mnt = NULL, *old;
int err = mount_is_safe(path);
if (err)
return err;
if (err)
goto out;
+ old = real_mount(old_path.mnt);
+
err = -EINVAL;
if (IS_MNT_UNBINDABLE(old_path.mnt))
goto out2;
err = -ENOMEM;
if (recurse)
- mnt = copy_tree(old_path.mnt, old_path.dentry, 0);
+ mnt = copy_tree(old, old_path.dentry, 0);
else
- mnt = clone_mnt(old_path.mnt, old_path.dentry, 0);
+ mnt = clone_mnt(old, old_path.dentry, 0);
if (!mnt)
goto out2;
down_write(&namespace_sem);
/* First pass: copy the tree topology */
- new = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root,
+ new = copy_tree(real_mount(mnt_ns->root), mnt_ns->root->mnt_root,
CL_COPY_ALL | CL_EXPIRE);
if (!new) {
up_write(&namespace_sem);