aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c23
1 files changed, 10 insertions, 13 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 1c78917ec930..7bd74b25930c 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -581,6 +581,8 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill)
581 } 581 }
582} 582}
583 583
584static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts);
585
584static int do_umount(struct vfsmount *mnt, int flags) 586static int do_umount(struct vfsmount *mnt, int flags)
585{ 587{
586 struct super_block *sb = mnt->mnt_sb; 588 struct super_block *sb = mnt->mnt_sb;
@@ -653,6 +655,9 @@ static int do_umount(struct vfsmount *mnt, int flags)
653 spin_lock(&vfsmount_lock); 655 spin_lock(&vfsmount_lock);
654 event++; 656 event++;
655 657
658 if (!(flags & MNT_DETACH))
659 shrink_submounts(mnt, &umount_list);
660
656 retval = -EBUSY; 661 retval = -EBUSY;
657 if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) { 662 if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) {
658 if (!list_empty(&mnt->mnt_list)) 663 if (!list_empty(&mnt->mnt_list))
@@ -1302,30 +1307,22 @@ resume:
1302 * process a list of expirable mountpoints with the intent of discarding any 1307 * process a list of expirable mountpoints with the intent of discarding any
1303 * submounts of a specific parent mountpoint 1308 * submounts of a specific parent mountpoint
1304 */ 1309 */
1305void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts) 1310static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts)
1306{ 1311{
1307 LIST_HEAD(graveyard); 1312 LIST_HEAD(graveyard);
1308 LIST_HEAD(umounts); 1313 struct vfsmount *m;
1309 struct vfsmount *mnt;
1310 1314
1311 down_write(&namespace_sem);
1312 spin_lock(&vfsmount_lock);
1313 /* extract submounts of 'mountpoint' from the expiration list */ 1315 /* extract submounts of 'mountpoint' from the expiration list */
1314 while (select_submounts(mountpoint, &graveyard)) { 1316 while (select_submounts(mnt, &graveyard)) {
1315 while (!list_empty(&graveyard)) { 1317 while (!list_empty(&graveyard)) {
1316 mnt = list_first_entry(&graveyard, struct vfsmount, 1318 m = list_first_entry(&graveyard, struct vfsmount,
1317 mnt_expire); 1319 mnt_expire);
1318 touch_mnt_namespace(mnt->mnt_ns); 1320 touch_mnt_namespace(mnt->mnt_ns);
1319 umount_tree(mnt, 1, &umounts); 1321 umount_tree(mnt, 1, umounts);
1320 } 1322 }
1321 } 1323 }
1322 spin_unlock(&vfsmount_lock);
1323 up_write(&namespace_sem);
1324 release_mounts(&umounts);
1325} 1324}
1326 1325
1327EXPORT_SYMBOL_GPL(shrink_submounts);
1328
1329/* 1326/*
1330 * Some copy_from_user() implementations do not return the exact number of 1327 * Some copy_from_user() implementations do not return the exact number of
1331 * bytes remaining to copy on a fault. But copy_mount_options() requires that. 1328 * bytes remaining to copy on a fault. But copy_mount_options() requires that.