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 | |
parent | 5a190ae69766da9a34bf31200c5cea4c0667cf94 (diff) |
[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>
-rw-r--r-- | fs/namespace.c | 22 | ||||
-rw-r--r-- | fs/pnode.h | 1 | ||||
-rw-r--r-- | include/linux/fs.h | 2 |
3 files changed, 24 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, | |||
246 | list_add(&mnt->mnt_slave, &old->mnt_slave_list); | 246 | list_add(&mnt->mnt_slave, &old->mnt_slave_list); |
247 | mnt->mnt_master = old; | 247 | mnt->mnt_master = old; |
248 | CLEAR_MNT_SHARED(mnt); | 248 | CLEAR_MNT_SHARED(mnt); |
249 | } else { | 249 | } else if (!(flag & CL_PRIVATE)) { |
250 | if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old)) | 250 | if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old)) |
251 | list_add(&mnt->mnt_share, &old->mnt_share); | 251 | list_add(&mnt->mnt_share, &old->mnt_share); |
252 | if (IS_MNT_SLAVE(old)) | 252 | if (IS_MNT_SLAVE(old)) |
@@ -746,6 +746,26 @@ Enomem: | |||
746 | return NULL; | 746 | return NULL; |
747 | } | 747 | } |
748 | 748 | ||
749 | struct vfsmount *collect_mounts(struct vfsmount *mnt, struct dentry *dentry) | ||
750 | { | ||
751 | struct vfsmount *tree; | ||
752 | down_read(&namespace_sem); | ||
753 | tree = copy_tree(mnt, dentry, CL_COPY_ALL | CL_PRIVATE); | ||
754 | up_read(&namespace_sem); | ||
755 | return tree; | ||
756 | } | ||
757 | |||
758 | void drop_collected_mounts(struct vfsmount *mnt) | ||
759 | { | ||
760 | LIST_HEAD(umount_list); | ||
761 | down_read(&namespace_sem); | ||
762 | spin_lock(&vfsmount_lock); | ||
763 | umount_tree(mnt, 0, &umount_list); | ||
764 | spin_unlock(&vfsmount_lock); | ||
765 | up_read(&namespace_sem); | ||
766 | release_mounts(&umount_list); | ||
767 | } | ||
768 | |||
749 | /* | 769 | /* |
750 | * @source_mnt : mount tree to be attached | 770 | * @source_mnt : mount tree to be attached |
751 | * @nd : place the mount tree @source_mnt is attached | 771 | * @nd : place the mount tree @source_mnt is attached |
diff --git a/fs/pnode.h b/fs/pnode.h index d45bd8ec36bf..f249be2fee7a 100644 --- a/fs/pnode.h +++ b/fs/pnode.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #define CL_COPY_ALL 0x04 | 22 | #define CL_COPY_ALL 0x04 |
23 | #define CL_MAKE_SHARED 0x08 | 23 | #define CL_MAKE_SHARED 0x08 |
24 | #define CL_PROPAGATION 0x10 | 24 | #define CL_PROPAGATION 0x10 |
25 | #define CL_PRIVATE 0x20 | ||
25 | 26 | ||
26 | static inline void set_mnt_shared(struct vfsmount *mnt) | 27 | static inline void set_mnt_shared(struct vfsmount *mnt) |
27 | { | 28 | { |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 1bcce660cf03..50078bb30a1c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1470,6 +1470,8 @@ extern long do_mount(char *, char *, char *, unsigned long, void *); | |||
1470 | extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); | 1470 | extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); |
1471 | extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *, | 1471 | extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *, |
1472 | struct vfsmount *); | 1472 | struct vfsmount *); |
1473 | extern struct vfsmount *collect_mounts(struct vfsmount *, struct dentry *); | ||
1474 | extern void drop_collected_mounts(struct vfsmount *); | ||
1473 | 1475 | ||
1474 | extern int vfs_statfs(struct dentry *, struct kstatfs *); | 1476 | extern int vfs_statfs(struct dentry *, struct kstatfs *); |
1475 | 1477 | ||