Loading fs/namespace.c +21 −18 Original line number Diff line number Diff line Loading @@ -687,7 +687,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void } EXPORT_SYMBOL_GPL(vfs_kern_mount); static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root, int flag) { struct super_block *sb = old->mnt_sb; Loading Loading @@ -733,7 +733,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, list_add(&mnt->mnt.mnt_expire, &old->mnt_expire); } } return &mnt->mnt; return mnt; out_free: free_vfsmnt(mnt); Loading Loading @@ -1408,10 +1408,11 @@ static int mount_is_safe(struct path *path) #endif } struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, int flag) { struct vfsmount *res, *p, *q, *r; struct mount *res, *q; struct vfsmount *p, *r; struct path path; if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) Loading @@ -1420,7 +1421,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, res = q = clone_mnt(mnt, dentry, flag); if (!q) goto Enomem; q->mnt_mountpoint = mnt->mnt_mountpoint; q->mnt.mnt_mountpoint = mnt->mnt_mountpoint; p = mnt; list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) { Loading @@ -1435,17 +1436,17 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, } while (p != s->mnt.mnt_parent) { p = p->mnt_parent; q = q->mnt_parent; q = real_mount(q->mnt.mnt_parent); } p = &s->mnt; path.mnt = q; path.mnt = &q->mnt; path.dentry = p->mnt_mountpoint; q = clone_mnt(p, p->mnt_root, flag); if (!q) goto Enomem; br_write_lock(vfsmount_lock); list_add_tail(&q->mnt_list, &res->mnt_list); attach_mnt(real_mount(q), &path); list_add_tail(&q->mnt.mnt_list, &res->mnt.mnt_list); attach_mnt(q, &path); br_write_unlock(vfsmount_lock); } } Loading @@ -1454,7 +1455,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, if (res) { LIST_HEAD(umount_list); br_write_lock(vfsmount_lock); umount_tree(res, 0, &umount_list); umount_tree(&res->mnt, 0, &umount_list); br_write_unlock(vfsmount_lock); release_mounts(&umount_list); } Loading @@ -1463,11 +1464,11 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, struct vfsmount *collect_mounts(struct path *path) { struct vfsmount *tree; struct mount *tree; down_write(&namespace_sem); tree = copy_tree(path->mnt, path->dentry, CL_COPY_ALL | CL_PRIVATE); up_write(&namespace_sem); return tree; return tree ? &tree->mnt : NULL; } void drop_collected_mounts(struct vfsmount *mnt) Loading Loading @@ -1739,7 +1740,7 @@ static int do_loopback(struct path *path, char *old_name, { LIST_HEAD(umount_list); struct path old_path; struct vfsmount *mnt = NULL; struct mount *mnt = NULL; int err = mount_is_safe(path); if (err) return err; Loading Loading @@ -1769,10 +1770,10 @@ static int do_loopback(struct path *path, char *old_name, if (!mnt) goto out2; err = graft_tree(mnt, path); err = graft_tree(&mnt->mnt, path); if (err) { br_write_lock(vfsmount_lock); umount_tree(mnt, 0, &umount_list); umount_tree(&mnt->mnt, 0, &umount_list); br_write_unlock(vfsmount_lock); } out2: Loading Loading @@ -2385,6 +2386,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, struct mnt_namespace *new_ns; struct vfsmount *rootmnt = NULL, *pwdmnt = NULL; struct mount *p, *q; struct mount *new; new_ns = alloc_mnt_ns(); if (IS_ERR(new_ns)) Loading @@ -2392,13 +2394,14 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, down_write(&namespace_sem); /* First pass: copy the tree topology */ new_ns->root = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root, new = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root, CL_COPY_ALL | CL_EXPIRE); if (!new_ns->root) { if (!new) { up_write(&namespace_sem); kfree(new_ns); return ERR_PTR(-ENOMEM); } new_ns->root = &new->mnt; br_write_lock(vfsmount_lock); list_add_tail(&new_ns->list, &new_ns->root->mnt_list); br_write_unlock(vfsmount_lock); Loading @@ -2409,7 +2412,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, * fs_struct, so tsk->fs->lock is not needed. */ p = real_mount(mnt_ns->root); q = real_mount(new_ns->root); q = new; while (p) { q->mnt.mnt_ns = new_ns; __mnt_make_longterm(&q->mnt); Loading fs/pnode.c +8 −7 Original line number Diff line number Diff line Loading @@ -221,7 +221,8 @@ static struct vfsmount *get_source(struct vfsmount *dest, int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, struct vfsmount *source_mnt, struct list_head *tree_list) { struct vfsmount *m, *child; struct vfsmount *m; struct mount *child; int ret = 0; struct vfsmount *prev_dest_mnt = dest_mnt; struct vfsmount *prev_src_mnt = source_mnt; Loading @@ -245,23 +246,23 @@ int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, } if (is_subdir(dest_dentry, m->mnt_root)) { mnt_set_mountpoint(m, dest_dentry, child); list_add_tail(&child->mnt_hash, tree_list); mnt_set_mountpoint(m, dest_dentry, &child->mnt); list_add_tail(&child->mnt.mnt_hash, tree_list); } else { /* * This can happen if the parent mount was bind mounted * on some subdirectory of a shared/slave mount. */ list_add_tail(&child->mnt_hash, &tmp_list); list_add_tail(&child->mnt.mnt_hash, &tmp_list); } prev_dest_mnt = m; prev_src_mnt = child; prev_src_mnt = &child->mnt; } out: br_write_lock(vfsmount_lock); while (!list_empty(&tmp_list)) { child = list_first_entry(&tmp_list, struct vfsmount, mnt_hash); umount_tree(child, 0, &umount_list); child = list_first_entry(&tmp_list, struct mount, mnt.mnt_hash); umount_tree(&child->mnt, 0, &umount_list); } br_write_unlock(vfsmount_lock); release_mounts(&umount_list); 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 vfsmount *, int, struct list_head *); struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); struct mount *copy_tree(struct vfsmount *, struct dentry *, int); bool is_path_reachable(struct vfsmount *, struct dentry *, const struct path *root); #endif /* _LINUX_PNODE_H */ Loading
fs/namespace.c +21 −18 Original line number Diff line number Diff line Loading @@ -687,7 +687,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void } EXPORT_SYMBOL_GPL(vfs_kern_mount); static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root, int flag) { struct super_block *sb = old->mnt_sb; Loading Loading @@ -733,7 +733,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, list_add(&mnt->mnt.mnt_expire, &old->mnt_expire); } } return &mnt->mnt; return mnt; out_free: free_vfsmnt(mnt); Loading Loading @@ -1408,10 +1408,11 @@ static int mount_is_safe(struct path *path) #endif } struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, int flag) { struct vfsmount *res, *p, *q, *r; struct mount *res, *q; struct vfsmount *p, *r; struct path path; if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) Loading @@ -1420,7 +1421,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, res = q = clone_mnt(mnt, dentry, flag); if (!q) goto Enomem; q->mnt_mountpoint = mnt->mnt_mountpoint; q->mnt.mnt_mountpoint = mnt->mnt_mountpoint; p = mnt; list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) { Loading @@ -1435,17 +1436,17 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, } while (p != s->mnt.mnt_parent) { p = p->mnt_parent; q = q->mnt_parent; q = real_mount(q->mnt.mnt_parent); } p = &s->mnt; path.mnt = q; path.mnt = &q->mnt; path.dentry = p->mnt_mountpoint; q = clone_mnt(p, p->mnt_root, flag); if (!q) goto Enomem; br_write_lock(vfsmount_lock); list_add_tail(&q->mnt_list, &res->mnt_list); attach_mnt(real_mount(q), &path); list_add_tail(&q->mnt.mnt_list, &res->mnt.mnt_list); attach_mnt(q, &path); br_write_unlock(vfsmount_lock); } } Loading @@ -1454,7 +1455,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, if (res) { LIST_HEAD(umount_list); br_write_lock(vfsmount_lock); umount_tree(res, 0, &umount_list); umount_tree(&res->mnt, 0, &umount_list); br_write_unlock(vfsmount_lock); release_mounts(&umount_list); } Loading @@ -1463,11 +1464,11 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, struct vfsmount *collect_mounts(struct path *path) { struct vfsmount *tree; struct mount *tree; down_write(&namespace_sem); tree = copy_tree(path->mnt, path->dentry, CL_COPY_ALL | CL_PRIVATE); up_write(&namespace_sem); return tree; return tree ? &tree->mnt : NULL; } void drop_collected_mounts(struct vfsmount *mnt) Loading Loading @@ -1739,7 +1740,7 @@ static int do_loopback(struct path *path, char *old_name, { LIST_HEAD(umount_list); struct path old_path; struct vfsmount *mnt = NULL; struct mount *mnt = NULL; int err = mount_is_safe(path); if (err) return err; Loading Loading @@ -1769,10 +1770,10 @@ static int do_loopback(struct path *path, char *old_name, if (!mnt) goto out2; err = graft_tree(mnt, path); err = graft_tree(&mnt->mnt, path); if (err) { br_write_lock(vfsmount_lock); umount_tree(mnt, 0, &umount_list); umount_tree(&mnt->mnt, 0, &umount_list); br_write_unlock(vfsmount_lock); } out2: Loading Loading @@ -2385,6 +2386,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, struct mnt_namespace *new_ns; struct vfsmount *rootmnt = NULL, *pwdmnt = NULL; struct mount *p, *q; struct mount *new; new_ns = alloc_mnt_ns(); if (IS_ERR(new_ns)) Loading @@ -2392,13 +2394,14 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, down_write(&namespace_sem); /* First pass: copy the tree topology */ new_ns->root = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root, new = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root, CL_COPY_ALL | CL_EXPIRE); if (!new_ns->root) { if (!new) { up_write(&namespace_sem); kfree(new_ns); return ERR_PTR(-ENOMEM); } new_ns->root = &new->mnt; br_write_lock(vfsmount_lock); list_add_tail(&new_ns->list, &new_ns->root->mnt_list); br_write_unlock(vfsmount_lock); Loading @@ -2409,7 +2412,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, * fs_struct, so tsk->fs->lock is not needed. */ p = real_mount(mnt_ns->root); q = real_mount(new_ns->root); q = new; while (p) { q->mnt.mnt_ns = new_ns; __mnt_make_longterm(&q->mnt); Loading
fs/pnode.c +8 −7 Original line number Diff line number Diff line Loading @@ -221,7 +221,8 @@ static struct vfsmount *get_source(struct vfsmount *dest, int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, struct vfsmount *source_mnt, struct list_head *tree_list) { struct vfsmount *m, *child; struct vfsmount *m; struct mount *child; int ret = 0; struct vfsmount *prev_dest_mnt = dest_mnt; struct vfsmount *prev_src_mnt = source_mnt; Loading @@ -245,23 +246,23 @@ int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, } if (is_subdir(dest_dentry, m->mnt_root)) { mnt_set_mountpoint(m, dest_dentry, child); list_add_tail(&child->mnt_hash, tree_list); mnt_set_mountpoint(m, dest_dentry, &child->mnt); list_add_tail(&child->mnt.mnt_hash, tree_list); } else { /* * This can happen if the parent mount was bind mounted * on some subdirectory of a shared/slave mount. */ list_add_tail(&child->mnt_hash, &tmp_list); list_add_tail(&child->mnt.mnt_hash, &tmp_list); } prev_dest_mnt = m; prev_src_mnt = child; prev_src_mnt = &child->mnt; } out: br_write_lock(vfsmount_lock); while (!list_empty(&tmp_list)) { child = list_first_entry(&tmp_list, struct vfsmount, mnt_hash); umount_tree(child, 0, &umount_list); child = list_first_entry(&tmp_list, struct mount, mnt.mnt_hash); umount_tree(&child->mnt, 0, &umount_list); } br_write_unlock(vfsmount_lock); release_mounts(&umount_list); 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 vfsmount *, int, struct list_head *); struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); struct mount *copy_tree(struct vfsmount *, struct dentry *, int); bool is_path_reachable(struct vfsmount *, struct dentry *, const struct path *root); #endif /* _LINUX_PNODE_H */