Loading fs/namespace.c +33 −30 Original line number Diff line number Diff line Loading @@ -687,17 +687,17 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void } 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); Loading @@ -705,7 +705,7 @@ static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root, 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); Loading @@ -713,15 +713,15 @@ static struct mount *clone_mnt(struct vfsmount *old, struct dentry *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); Loading @@ -729,8 +729,8 @@ static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root, /* 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; Loading Loading @@ -1408,23 +1408,23 @@ static int mount_is_safe(struct path *path) #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; Loading @@ -1434,14 +1434,14 @@ struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, 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); Loading @@ -1466,7 +1466,8 @@ struct vfsmount *collect_mounts(struct path *path) { 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; } Loading Loading @@ -1740,7 +1741,7 @@ static int do_loopback(struct path *path, char *old_name, { 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; Loading @@ -1754,6 +1755,8 @@ static int do_loopback(struct path *path, char *old_name, if (err) goto out; old = real_mount(old_path.mnt); err = -EINVAL; if (IS_MNT_UNBINDABLE(old_path.mnt)) goto out2; Loading @@ -1763,9 +1766,9 @@ static int do_loopback(struct path *path, char *old_name, 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; Loading Loading @@ -2394,7 +2397,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, 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); Loading fs/pnode.c +1 −1 Original line number Diff line number Diff line Loading @@ -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); if (!(child = copy_tree(source, source->mnt_root, type))) { if (!(child = copy_tree(real_mount(source), source->mnt_root, type))) { ret = -ENOMEM; list_splice(tree_list, tmp_list.prev); goto out; Loading fs/pnode.h +1 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,7 @@ void mnt_set_mountpoint(struct vfsmount *, struct dentry *, struct vfsmount *); void release_mounts(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 *, const struct path *root); #endif /* _LINUX_PNODE_H */ Loading
fs/namespace.c +33 −30 Original line number Diff line number Diff line Loading @@ -687,17 +687,17 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void } 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); Loading @@ -705,7 +705,7 @@ static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root, 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); Loading @@ -713,15 +713,15 @@ static struct mount *clone_mnt(struct vfsmount *old, struct dentry *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); Loading @@ -729,8 +729,8 @@ static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root, /* 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; Loading Loading @@ -1408,23 +1408,23 @@ static int mount_is_safe(struct path *path) #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; Loading @@ -1434,14 +1434,14 @@ struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, 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); Loading @@ -1466,7 +1466,8 @@ struct vfsmount *collect_mounts(struct path *path) { 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; } Loading Loading @@ -1740,7 +1741,7 @@ static int do_loopback(struct path *path, char *old_name, { 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; Loading @@ -1754,6 +1755,8 @@ static int do_loopback(struct path *path, char *old_name, if (err) goto out; old = real_mount(old_path.mnt); err = -EINVAL; if (IS_MNT_UNBINDABLE(old_path.mnt)) goto out2; Loading @@ -1763,9 +1766,9 @@ static int do_loopback(struct path *path, char *old_name, 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; Loading Loading @@ -2394,7 +2397,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, 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); Loading
fs/pnode.c +1 −1 Original line number Diff line number Diff line Loading @@ -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); if (!(child = copy_tree(source, source->mnt_root, type))) { if (!(child = copy_tree(real_mount(source), source->mnt_root, type))) { ret = -ENOMEM; list_splice(tree_list, tmp_list.prev); goto out; Loading
fs/pnode.h +1 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,7 @@ void mnt_set_mountpoint(struct vfsmount *, struct dentry *, struct vfsmount *); void release_mounts(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 *, const struct path *root); #endif /* _LINUX_PNODE_H */