aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
parent84d17192d2afd52aeba88c71ae4959a015f56a38 (diff)
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')
-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)
1119 1119
1120EXPORT_SYMBOL(may_umount); 1120EXPORT_SYMBOL(may_umount);
1121 1121
1122static LIST_HEAD(unmounted); /* protected by namespace_sem */
1123
1122void release_mounts(struct list_head *head) 1124void release_mounts(struct list_head *head)
1123{ 1125{
1124 struct mount *mnt; 1126 struct mount *mnt;
@@ -1143,6 +1145,14 @@ void release_mounts(struct list_head *head)
1143 } 1145 }
1144} 1146}
1145 1147
1148static void namespace_unlock(void)
1149{
1150 LIST_HEAD(head);
1151 list_splice_init(&unmounted, &head);
1152 up_write(&namespace_sem);
1153 release_mounts(&head);
1154}
1155
1146/* 1156/*
1147 * vfsmount lock must be held for write 1157 * vfsmount lock must be held for write
1148 * namespace_sem must be held for write 1158 * namespace_sem must be held for write
@@ -1252,17 +1262,16 @@ static int do_umount(struct mount *mnt, int flags)
1252 event++; 1262 event++;
1253 1263
1254 if (!(flags & MNT_DETACH)) 1264 if (!(flags & MNT_DETACH))
1255 shrink_submounts(mnt, &umount_list); 1265 shrink_submounts(mnt, &unmounted);
1256 1266
1257 retval = -EBUSY; 1267 retval = -EBUSY;
1258 if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) { 1268 if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) {
1259 if (!list_empty(&mnt->mnt_list)) 1269 if (!list_empty(&mnt->mnt_list))
1260 umount_tree(mnt, 1, &umount_list); 1270 umount_tree(mnt, 1, &unmounted);
1261 retval = 0; 1271 retval = 0;
1262 } 1272 }
1263 br_write_unlock(&vfsmount_lock); 1273 br_write_unlock(&vfsmount_lock);
1264 up_write(&namespace_sem); 1274 namespace_unlock();
1265 release_mounts(&umount_list);
1266 return retval; 1275 return retval;
1267} 1276}
1268 1277