vfs: spread struct mount - clone_mnt/copy_tree argument
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
692afc312b
commit
87129cc0e3
|
@ -687,17 +687,17 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vfs_kern_mount);
|
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)
|
int flag)
|
||||||
{
|
{
|
||||||
struct super_block *sb = old->mnt_sb;
|
struct super_block *sb = old->mnt.mnt_sb;
|
||||||
struct mount *mnt = alloc_vfsmnt(old->mnt_devname);
|
struct mount *mnt = alloc_vfsmnt(old->mnt.mnt_devname);
|
||||||
|
|
||||||
if (mnt) {
|
if (mnt) {
|
||||||
if (flag & (CL_SLAVE | CL_PRIVATE))
|
if (flag & (CL_SLAVE | CL_PRIVATE))
|
||||||
mnt->mnt.mnt_group_id = 0; /* not a peer of original */
|
mnt->mnt.mnt_group_id = 0; /* not a peer of original */
|
||||||
else
|
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) {
|
if ((flag & CL_MAKE_SHARED) && !mnt->mnt.mnt_group_id) {
|
||||||
int err = mnt_alloc_group_id(mnt);
|
int err = mnt_alloc_group_id(mnt);
|
||||||
|
@ -705,7 +705,7 @@ static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root,
|
||||||
goto out_free;
|
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);
|
atomic_inc(&sb->s_active);
|
||||||
mnt->mnt.mnt_sb = sb;
|
mnt->mnt.mnt_sb = sb;
|
||||||
mnt->mnt.mnt_root = dget(root);
|
mnt->mnt.mnt_root = dget(root);
|
||||||
|
@ -713,15 +713,15 @@ static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root,
|
||||||
mnt->mnt.mnt_parent = &mnt->mnt;
|
mnt->mnt.mnt_parent = &mnt->mnt;
|
||||||
|
|
||||||
if (flag & CL_SLAVE) {
|
if (flag & CL_SLAVE) {
|
||||||
list_add(&mnt->mnt.mnt_slave, &old->mnt_slave_list);
|
list_add(&mnt->mnt.mnt_slave, &old->mnt.mnt_slave_list);
|
||||||
mnt->mnt.mnt_master = old;
|
mnt->mnt.mnt_master = &old->mnt;
|
||||||
CLEAR_MNT_SHARED(&mnt->mnt);
|
CLEAR_MNT_SHARED(&mnt->mnt);
|
||||||
} else if (!(flag & CL_PRIVATE)) {
|
} else if (!(flag & CL_PRIVATE)) {
|
||||||
if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old))
|
if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(&old->mnt))
|
||||||
list_add(&mnt->mnt.mnt_share, &old->mnt_share);
|
list_add(&mnt->mnt.mnt_share, &old->mnt.mnt_share);
|
||||||
if (IS_MNT_SLAVE(old))
|
if (IS_MNT_SLAVE(&old->mnt))
|
||||||
list_add(&mnt->mnt.mnt_slave, &old->mnt_slave);
|
list_add(&mnt->mnt.mnt_slave, &old->mnt.mnt_slave);
|
||||||
mnt->mnt.mnt_master = old->mnt_master;
|
mnt->mnt.mnt_master = old->mnt.mnt_master;
|
||||||
}
|
}
|
||||||
if (flag & CL_MAKE_SHARED)
|
if (flag & CL_MAKE_SHARED)
|
||||||
set_mnt_shared(mnt);
|
set_mnt_shared(mnt);
|
||||||
|
@ -729,8 +729,8 @@ static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root,
|
||||||
/* stick the duplicate mount on the same expiry list
|
/* stick the duplicate mount on the same expiry list
|
||||||
* as the original if that was on one */
|
* as the original if that was on one */
|
||||||
if (flag & CL_EXPIRE) {
|
if (flag & CL_EXPIRE) {
|
||||||
if (!list_empty(&old->mnt_expire))
|
if (!list_empty(&old->mnt.mnt_expire))
|
||||||
list_add(&mnt->mnt.mnt_expire, &old->mnt_expire);
|
list_add(&mnt->mnt.mnt_expire, &old->mnt.mnt_expire);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mnt;
|
return mnt;
|
||||||
|
@ -1408,23 +1408,23 @@ static int mount_is_safe(struct path *path)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
|
struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
|
||||||
int flag)
|
int flag)
|
||||||
{
|
{
|
||||||
struct mount *res, *q;
|
struct mount *res, *p, *q;
|
||||||
struct vfsmount *p, *r;
|
struct vfsmount *r;
|
||||||
struct path path;
|
struct path path;
|
||||||
|
|
||||||
if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt))
|
if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(&mnt->mnt))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
res = q = clone_mnt(mnt, dentry, flag);
|
res = q = clone_mnt(mnt, dentry, flag);
|
||||||
if (!q)
|
if (!q)
|
||||||
goto Enomem;
|
goto Enomem;
|
||||||
q->mnt.mnt_mountpoint = mnt->mnt_mountpoint;
|
q->mnt.mnt_mountpoint = mnt->mnt.mnt_mountpoint;
|
||||||
|
|
||||||
p = mnt;
|
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;
|
struct mount *s;
|
||||||
if (!is_subdir(r->mnt_mountpoint, dentry))
|
if (!is_subdir(r->mnt_mountpoint, dentry))
|
||||||
continue;
|
continue;
|
||||||
|
@ -1434,14 +1434,14 @@ struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
|
||||||
s = skip_mnt_tree(s);
|
s = skip_mnt_tree(s);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
while (p != s->mnt.mnt_parent) {
|
while (p != real_mount(s->mnt.mnt_parent)) {
|
||||||
p = p->mnt_parent;
|
p = real_mount(p->mnt.mnt_parent);
|
||||||
q = real_mount(q->mnt.mnt_parent);
|
q = real_mount(q->mnt.mnt_parent);
|
||||||
}
|
}
|
||||||
p = &s->mnt;
|
p = s;
|
||||||
path.mnt = &q->mnt;
|
path.mnt = &q->mnt;
|
||||||
path.dentry = p->mnt_mountpoint;
|
path.dentry = p->mnt.mnt_mountpoint;
|
||||||
q = clone_mnt(p, p->mnt_root, flag);
|
q = clone_mnt(p, p->mnt.mnt_root, flag);
|
||||||
if (!q)
|
if (!q)
|
||||||
goto Enomem;
|
goto Enomem;
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(vfsmount_lock);
|
||||||
|
@ -1466,7 +1466,8 @@ struct vfsmount *collect_mounts(struct path *path)
|
||||||
{
|
{
|
||||||
struct mount *tree;
|
struct mount *tree;
|
||||||
down_write(&namespace_sem);
|
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);
|
up_write(&namespace_sem);
|
||||||
return tree ? &tree->mnt : NULL;
|
return tree ? &tree->mnt : NULL;
|
||||||
}
|
}
|
||||||
|
@ -1740,7 +1741,7 @@ static int do_loopback(struct path *path, char *old_name,
|
||||||
{
|
{
|
||||||
LIST_HEAD(umount_list);
|
LIST_HEAD(umount_list);
|
||||||
struct path old_path;
|
struct path old_path;
|
||||||
struct mount *mnt = NULL;
|
struct mount *mnt = NULL, *old;
|
||||||
int err = mount_is_safe(path);
|
int err = mount_is_safe(path);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -1754,6 +1755,8 @@ static int do_loopback(struct path *path, char *old_name,
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
old = real_mount(old_path.mnt);
|
||||||
|
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
if (IS_MNT_UNBINDABLE(old_path.mnt))
|
if (IS_MNT_UNBINDABLE(old_path.mnt))
|
||||||
goto out2;
|
goto out2;
|
||||||
|
@ -1763,9 +1766,9 @@ static int do_loopback(struct path *path, char *old_name,
|
||||||
|
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
if (recurse)
|
if (recurse)
|
||||||
mnt = copy_tree(old_path.mnt, old_path.dentry, 0);
|
mnt = copy_tree(old, old_path.dentry, 0);
|
||||||
else
|
else
|
||||||
mnt = clone_mnt(old_path.mnt, old_path.dentry, 0);
|
mnt = clone_mnt(old, old_path.dentry, 0);
|
||||||
|
|
||||||
if (!mnt)
|
if (!mnt)
|
||||||
goto out2;
|
goto out2;
|
||||||
|
@ -2394,7 +2397,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
|
||||||
|
|
||||||
down_write(&namespace_sem);
|
down_write(&namespace_sem);
|
||||||
/* First pass: copy the tree topology */
|
/* 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);
|
CL_COPY_ALL | CL_EXPIRE);
|
||||||
if (!new) {
|
if (!new) {
|
||||||
up_write(&namespace_sem);
|
up_write(&namespace_sem);
|
||||||
|
|
|
@ -239,7 +239,7 @@ int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry,
|
||||||
|
|
||||||
source = get_source(m, prev_dest_mnt, prev_src_mnt, &type);
|
source = get_source(m, prev_dest_mnt, prev_src_mnt, &type);
|
||||||
|
|
||||||
if (!(child = copy_tree(source, source->mnt_root, type))) {
|
if (!(child = copy_tree(real_mount(source), source->mnt_root, type))) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
list_splice(tree_list, tmp_list.prev);
|
list_splice(tree_list, tmp_list.prev);
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -41,7 +41,7 @@ void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
|
||||||
struct vfsmount *);
|
struct vfsmount *);
|
||||||
void release_mounts(struct list_head *);
|
void release_mounts(struct list_head *);
|
||||||
void umount_tree(struct mount *, int, struct list_head *);
|
void umount_tree(struct mount *, int, struct list_head *);
|
||||||
struct mount *copy_tree(struct vfsmount *, struct dentry *, int);
|
struct mount *copy_tree(struct mount *, struct dentry *, int);
|
||||||
bool is_path_reachable(struct vfsmount *, struct dentry *,
|
bool is_path_reachable(struct vfsmount *, struct dentry *,
|
||||||
const struct path *root);
|
const struct path *root);
|
||||||
#endif /* _LINUX_PNODE_H */
|
#endif /* _LINUX_PNODE_H */
|
||||||
|
|
Loading…
Reference in New Issue