mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-01 03:54:02 +00:00
vfs: spread struct mount - clone_mnt/copy_tree result
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
0f0afb1dcf
commit
cb338d06e9
3 changed files with 30 additions and 26 deletions
|
@ -687,7 +687,7 @@ 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 vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
|
static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root,
|
||||||
int flag)
|
int flag)
|
||||||
{
|
{
|
||||||
struct super_block *sb = old->mnt_sb;
|
struct super_block *sb = old->mnt_sb;
|
||||||
|
@ -733,7 +733,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
|
||||||
list_add(&mnt->mnt.mnt_expire, &old->mnt_expire);
|
list_add(&mnt->mnt.mnt_expire, &old->mnt_expire);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &mnt->mnt;
|
return mnt;
|
||||||
|
|
||||||
out_free:
|
out_free:
|
||||||
free_vfsmnt(mnt);
|
free_vfsmnt(mnt);
|
||||||
|
@ -1408,10 +1408,11 @@ static int mount_is_safe(struct path *path)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
|
struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
|
||||||
int flag)
|
int flag)
|
||||||
{
|
{
|
||||||
struct vfsmount *res, *p, *q, *r;
|
struct mount *res, *q;
|
||||||
|
struct vfsmount *p, *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))
|
||||||
|
@ -1420,7 +1421,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
|
||||||
res = q = clone_mnt(mnt, dentry, flag);
|
res = q = clone_mnt(mnt, dentry, flag);
|
||||||
if (!q)
|
if (!q)
|
||||||
goto Enomem;
|
goto Enomem;
|
||||||
q->mnt_mountpoint = mnt->mnt_mountpoint;
|
q->mnt.mnt_mountpoint = mnt->mnt_mountpoint;
|
||||||
|
|
||||||
p = mnt;
|
p = mnt;
|
||||||
list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) {
|
list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) {
|
||||||
|
@ -1435,17 +1436,17 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
|
||||||
}
|
}
|
||||||
while (p != s->mnt.mnt_parent) {
|
while (p != s->mnt.mnt_parent) {
|
||||||
p = p->mnt_parent;
|
p = p->mnt_parent;
|
||||||
q = q->mnt_parent;
|
q = real_mount(q->mnt.mnt_parent);
|
||||||
}
|
}
|
||||||
p = &s->mnt;
|
p = &s->mnt;
|
||||||
path.mnt = q;
|
path.mnt = &q->mnt;
|
||||||
path.dentry = p->mnt_mountpoint;
|
path.dentry = p->mnt_mountpoint;
|
||||||
q = clone_mnt(p, p->mnt_root, flag);
|
q = clone_mnt(p, p->mnt_root, flag);
|
||||||
if (!q)
|
if (!q)
|
||||||
goto Enomem;
|
goto Enomem;
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(vfsmount_lock);
|
||||||
list_add_tail(&q->mnt_list, &res->mnt_list);
|
list_add_tail(&q->mnt.mnt_list, &res->mnt.mnt_list);
|
||||||
attach_mnt(real_mount(q), &path);
|
attach_mnt(q, &path);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(vfsmount_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1454,7 +1455,7 @@ Enomem:
|
||||||
if (res) {
|
if (res) {
|
||||||
LIST_HEAD(umount_list);
|
LIST_HEAD(umount_list);
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(vfsmount_lock);
|
||||||
umount_tree(res, 0, &umount_list);
|
umount_tree(&res->mnt, 0, &umount_list);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(vfsmount_lock);
|
||||||
release_mounts(&umount_list);
|
release_mounts(&umount_list);
|
||||||
}
|
}
|
||||||
|
@ -1463,11 +1464,11 @@ Enomem:
|
||||||
|
|
||||||
struct vfsmount *collect_mounts(struct path *path)
|
struct vfsmount *collect_mounts(struct path *path)
|
||||||
{
|
{
|
||||||
struct vfsmount *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(path->mnt, path->dentry, CL_COPY_ALL | CL_PRIVATE);
|
||||||
up_write(&namespace_sem);
|
up_write(&namespace_sem);
|
||||||
return tree;
|
return tree ? &tree->mnt : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void drop_collected_mounts(struct vfsmount *mnt)
|
void drop_collected_mounts(struct vfsmount *mnt)
|
||||||
|
@ -1739,7 +1740,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 vfsmount *mnt = NULL;
|
struct mount *mnt = NULL;
|
||||||
int err = mount_is_safe(path);
|
int err = mount_is_safe(path);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -1769,10 +1770,10 @@ static int do_loopback(struct path *path, char *old_name,
|
||||||
if (!mnt)
|
if (!mnt)
|
||||||
goto out2;
|
goto out2;
|
||||||
|
|
||||||
err = graft_tree(mnt, path);
|
err = graft_tree(&mnt->mnt, path);
|
||||||
if (err) {
|
if (err) {
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(vfsmount_lock);
|
||||||
umount_tree(mnt, 0, &umount_list);
|
umount_tree(&mnt->mnt, 0, &umount_list);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(vfsmount_lock);
|
||||||
}
|
}
|
||||||
out2:
|
out2:
|
||||||
|
@ -2385,6 +2386,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
|
||||||
struct mnt_namespace *new_ns;
|
struct mnt_namespace *new_ns;
|
||||||
struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
|
struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
|
||||||
struct mount *p, *q;
|
struct mount *p, *q;
|
||||||
|
struct mount *new;
|
||||||
|
|
||||||
new_ns = alloc_mnt_ns();
|
new_ns = alloc_mnt_ns();
|
||||||
if (IS_ERR(new_ns))
|
if (IS_ERR(new_ns))
|
||||||
|
@ -2392,13 +2394,14 @@ 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_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);
|
CL_COPY_ALL | CL_EXPIRE);
|
||||||
if (!new_ns->root) {
|
if (!new) {
|
||||||
up_write(&namespace_sem);
|
up_write(&namespace_sem);
|
||||||
kfree(new_ns);
|
kfree(new_ns);
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
|
new_ns->root = &new->mnt;
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(vfsmount_lock);
|
||||||
list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
|
list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(vfsmount_lock);
|
||||||
|
@ -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.
|
* fs_struct, so tsk->fs->lock is not needed.
|
||||||
*/
|
*/
|
||||||
p = real_mount(mnt_ns->root);
|
p = real_mount(mnt_ns->root);
|
||||||
q = real_mount(new_ns->root);
|
q = new;
|
||||||
while (p) {
|
while (p) {
|
||||||
q->mnt.mnt_ns = new_ns;
|
q->mnt.mnt_ns = new_ns;
|
||||||
__mnt_make_longterm(&q->mnt);
|
__mnt_make_longterm(&q->mnt);
|
||||||
|
|
15
fs/pnode.c
15
fs/pnode.c
|
@ -221,7 +221,8 @@ static struct vfsmount *get_source(struct vfsmount *dest,
|
||||||
int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry,
|
int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry,
|
||||||
struct vfsmount *source_mnt, struct list_head *tree_list)
|
struct vfsmount *source_mnt, struct list_head *tree_list)
|
||||||
{
|
{
|
||||||
struct vfsmount *m, *child;
|
struct vfsmount *m;
|
||||||
|
struct mount *child;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct vfsmount *prev_dest_mnt = dest_mnt;
|
struct vfsmount *prev_dest_mnt = dest_mnt;
|
||||||
struct vfsmount *prev_src_mnt = source_mnt;
|
struct vfsmount *prev_src_mnt = source_mnt;
|
||||||
|
@ -245,23 +246,23 @@ int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_subdir(dest_dentry, m->mnt_root)) {
|
if (is_subdir(dest_dentry, m->mnt_root)) {
|
||||||
mnt_set_mountpoint(m, dest_dentry, child);
|
mnt_set_mountpoint(m, dest_dentry, &child->mnt);
|
||||||
list_add_tail(&child->mnt_hash, tree_list);
|
list_add_tail(&child->mnt.mnt_hash, tree_list);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* This can happen if the parent mount was bind mounted
|
* This can happen if the parent mount was bind mounted
|
||||||
* on some subdirectory of a shared/slave mount.
|
* 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_dest_mnt = m;
|
||||||
prev_src_mnt = child;
|
prev_src_mnt = &child->mnt;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(vfsmount_lock);
|
||||||
while (!list_empty(&tmp_list)) {
|
while (!list_empty(&tmp_list)) {
|
||||||
child = list_first_entry(&tmp_list, struct vfsmount, mnt_hash);
|
child = list_first_entry(&tmp_list, struct mount, mnt.mnt_hash);
|
||||||
umount_tree(child, 0, &umount_list);
|
umount_tree(&child->mnt, 0, &umount_list);
|
||||||
}
|
}
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(vfsmount_lock);
|
||||||
release_mounts(&umount_list);
|
release_mounts(&umount_list);
|
||||||
|
|
|
@ -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 vfsmount *, int, 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 *,
|
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…
Add table
Reference in a new issue