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))
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
#define CL_COPY_ALL 0x04
#define CL_MAKE_SHARED 0x08
#define CL_PROPAGATION 0x10
+#define CL_PRIVATE 0x20
static inline void set_mnt_shared(struct vfsmount *mnt)
{
extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
struct vfsmount *);
+extern struct vfsmount *collect_mounts(struct vfsmount *, struct dentry *);
+extern void drop_collected_mounts(struct vfsmount *);
extern int vfs_statfs(struct dentry *, struct kstatfs *);