Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e3197d83 authored by Al Viro's avatar Al Viro
Browse files

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 84d17192
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -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;
}