[PATCH] do shrink_submounts() for all fs types

... and take it out of ->umount_begin() instances.  Call with all locks
already taken (by do_umount()) and leave calling release_mounts() to
caller (it will do release_mounts() anyway, so we can just put into
the same list).

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro
2008-03-22 00:46:23 -04:00
parent bcc5c7d2b6
commit c35038beca
7 changed files with 10 additions and 27 deletions

View File

@@ -581,6 +581,8 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill)
}
}
static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts);
static int do_umount(struct vfsmount *mnt, int flags)
{
struct super_block *sb = mnt->mnt_sb;
@@ -653,6 +655,9 @@ static int do_umount(struct vfsmount *mnt, int flags)
spin_lock(&vfsmount_lock);
event++;
if (!(flags & MNT_DETACH))
shrink_submounts(mnt, &umount_list);
retval = -EBUSY;
if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) {
if (!list_empty(&mnt->mnt_list))
@@ -1302,30 +1307,22 @@ resume:
* process a list of expirable mountpoints with the intent of discarding any
* submounts of a specific parent mountpoint
*/
void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts)
static void shrink_submounts(struct vfsmount *mnt, struct list_head *umounts)
{
LIST_HEAD(graveyard);
LIST_HEAD(umounts);
struct vfsmount *mnt;
struct vfsmount *m;
down_write(&namespace_sem);
spin_lock(&vfsmount_lock);
/* extract submounts of 'mountpoint' from the expiration list */
while (select_submounts(mountpoint, &graveyard)) {
while (select_submounts(mnt, &graveyard)) {
while (!list_empty(&graveyard)) {
mnt = list_first_entry(&graveyard, struct vfsmount,
m = list_first_entry(&graveyard, struct vfsmount,
mnt_expire);
touch_mnt_namespace(mnt->mnt_ns);
umount_tree(mnt, 1, &umounts);
umount_tree(mnt, 1, umounts);
}
}
spin_unlock(&vfsmount_lock);
up_write(&namespace_sem);
release_mounts(&umounts);
}
EXPORT_SYMBOL_GPL(shrink_submounts);
/*
* Some copy_from_user() implementations do not return the exact number of
* bytes remaining to copy on a fault. But copy_mount_options() requires that.