summary refs log tree commit diff
path: root/fs/namespace.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-03-16 14:35:16 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2013-04-09 14:12:52 -0400
commite3197d83d6f5b9bd0e57a05592437ffa459ee106 (patch)
treead0a4f5f256f55ed8115c30823c0c967cbedba13 /fs/namespace.c
parent84d17192d2afd52aeba88c71ae4959a015f56a38 (diff)
downloadlinux-e3197d83d6f5b9bd0e57a05592437ffa459ee106.tar.gz
saner umount_tree()/release_mounts(), part 1
global list of release_mounts() fodder, protected by namespace_sem;
eventually, all umount_tree() callers will use it as kill list.
Helper picking the contents of that list, releasing namespace_sem
and doing release_mounts() on what it got.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index d7bb5a55cf36..0d91711a3160 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1119,6 +1119,8 @@ int may_umount(struct vfsmount *mnt)
 
 EXPORT_SYMBOL(may_umount);
 
+static LIST_HEAD(unmounted);	/* protected by namespace_sem */
+
 void release_mounts(struct list_head *head)
 {
 	struct mount *mnt;
@@ -1143,6 +1145,14 @@ void release_mounts(struct list_head *head)
 	}
 }
 
+static void namespace_unlock(void)
+{
+	LIST_HEAD(head);
+	list_splice_init(&unmounted, &head);
+	up_write(&namespace_sem);
+	release_mounts(&head);
+}
+
 /*
  * vfsmount lock must be held for write
  * namespace_sem must be held for write
@@ -1252,17 +1262,16 @@ static int do_umount(struct mount *mnt, int flags)
 	event++;
 
 	if (!(flags & MNT_DETACH))
-		shrink_submounts(mnt, &umount_list);
+		shrink_submounts(mnt, &unmounted);
 
 	retval = -EBUSY;
 	if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) {
 		if (!list_empty(&mnt->mnt_list))
-			umount_tree(mnt, 1, &umount_list);
+			umount_tree(mnt, 1, &unmounted);
 		retval = 0;
 	}
 	br_write_unlock(&vfsmount_lock);
-	up_write(&namespace_sem);
-	release_mounts(&umount_list);
+	namespace_unlock();
 	return retval;
 }