diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2007-06-07 12:20:32 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2007-10-21 02:37:25 -0400 |
commit | 8aec08094570562bc305df33b088926d983c3540 (patch) | |
tree | 399f4590f81428d1f72d754d336da13c449120f9 /fs/namespace.c | |
parent | 5a190ae69766da9a34bf31200c5cea4c0667cf94 (diff) | |
download | lwn-8aec08094570562bc305df33b088926d983c3540.tar.gz lwn-8aec08094570562bc305df33b088926d983c3540.zip |
[PATCH] new helpers - collect_mounts() and release_collected_mounts()
Get a snapshot of a subtree, creating private clones of vfsmounts
for all its components and release such snapshot resp.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 860752998fb3..06083885b21e 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -246,7 +246,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, list_add(&mnt->mnt_slave, &old->mnt_slave_list); mnt->mnt_master = old; CLEAR_MNT_SHARED(mnt); - } else { + } else if (!(flag & CL_PRIVATE)) { if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old)) list_add(&mnt->mnt_share, &old->mnt_share); if (IS_MNT_SLAVE(old)) @@ -746,6 +746,26 @@ Enomem: return NULL; } +struct vfsmount *collect_mounts(struct vfsmount *mnt, struct dentry *dentry) +{ + struct vfsmount *tree; + down_read(&namespace_sem); + tree = copy_tree(mnt, dentry, CL_COPY_ALL | CL_PRIVATE); + up_read(&namespace_sem); + return tree; +} + +void drop_collected_mounts(struct vfsmount *mnt) +{ + LIST_HEAD(umount_list); + down_read(&namespace_sem); + spin_lock(&vfsmount_lock); + umount_tree(mnt, 0, &umount_list); + spin_unlock(&vfsmount_lock); + up_read(&namespace_sem); + release_mounts(&umount_list); +} + /* * @source_mnt : mount tree to be attached * @nd : place the mount tree @source_mnt is attached |