Commit 1ab59738 authored by Al Viro's avatar Al Viro
Browse files

vfs: spread struct mount - do_umount/propagate_mount_busy



Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 44d964d6
Loading
Loading
Loading
Loading
+14 −14
Original line number Diff line number Diff line
@@ -1180,7 +1180,7 @@ int may_umount(struct vfsmount *mnt)
	int ret = 1;
	down_read(&namespace_sem);
	br_write_lock(vfsmount_lock);
	if (propagate_mount_busy(mnt, 2))
	if (propagate_mount_busy(real_mount(mnt), 2))
		ret = 0;
	br_write_unlock(vfsmount_lock);
	up_read(&namespace_sem);
@@ -1246,13 +1246,13 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill)

static void shrink_submounts(struct mount *mnt, struct list_head *umounts);

static int do_umount(struct vfsmount *mnt, int flags)
static int do_umount(struct mount *mnt, int flags)
{
	struct super_block *sb = mnt->mnt_sb;
	struct super_block *sb = mnt->mnt.mnt_sb;
	int retval;
	LIST_HEAD(umount_list);

	retval = security_sb_umount(mnt, flags);
	retval = security_sb_umount(&mnt->mnt, flags);
	if (retval)
		return retval;

@@ -1263,7 +1263,7 @@ static int do_umount(struct vfsmount *mnt, int flags)
	 *  (2) the usage count == 1 [parent vfsmount] + 1 [sys_umount]
	 */
	if (flags & MNT_EXPIRE) {
		if (mnt == current->fs->root.mnt ||
		if (&mnt->mnt == current->fs->root.mnt ||
		    flags & (MNT_FORCE | MNT_DETACH))
			return -EINVAL;

@@ -1272,13 +1272,13 @@ static int do_umount(struct vfsmount *mnt, int flags)
		 * all race cases, but it's a slowpath.
		 */
		br_write_lock(vfsmount_lock);
		if (mnt_get_count(mnt) != 2) {
		if (mnt_get_count(&mnt->mnt) != 2) {
			br_write_unlock(vfsmount_lock);
			return -EBUSY;
		}
		br_write_unlock(vfsmount_lock);

		if (!xchg(&mnt->mnt_expiry_mark, 1))
		if (!xchg(&mnt->mnt.mnt_expiry_mark, 1))
			return -EAGAIN;
	}

@@ -1305,7 +1305,7 @@ static int do_umount(struct vfsmount *mnt, int flags)
	 * /reboot - static binary that would close all descriptors and
	 * call reboot(9). Then init(8) could umount root and exec /reboot.
	 */
	if (mnt == current->fs->root.mnt && !(flags & MNT_DETACH)) {
	if (&mnt->mnt == current->fs->root.mnt && !(flags & MNT_DETACH)) {
		/*
		 * Special case for "unmounting" root ...
		 * we just try to remount it readonly.
@@ -1322,12 +1322,12 @@ static int do_umount(struct vfsmount *mnt, int flags)
	event++;

	if (!(flags & MNT_DETACH))
		shrink_submounts(real_mount(mnt), &umount_list);
		shrink_submounts(mnt, &umount_list);

	retval = -EBUSY;
	if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) {
		if (!list_empty(&mnt->mnt_list))
			umount_tree(real_mount(mnt), 1, &umount_list);
		if (!list_empty(&mnt->mnt.mnt_list))
			umount_tree(mnt, 1, &umount_list);
		retval = 0;
	}
	br_write_unlock(vfsmount_lock);
@@ -1369,7 +1369,7 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
	if (!capable(CAP_SYS_ADMIN))
		goto dput_and_out;

	retval = do_umount(path.mnt, flags);
	retval = do_umount(real_mount(path.mnt), flags);
dput_and_out:
	/* we mustn't call path_put() as that would clear mnt_expiry_mark */
	dput(path.dentry);
@@ -2101,7 +2101,7 @@ void mark_mounts_for_expiry(struct list_head *mounts)
	 */
	list_for_each_entry_safe(mnt, next, mounts, mnt.mnt_expire) {
		if (!xchg(&mnt->mnt.mnt_expiry_mark, 1) ||
			propagate_mount_busy(&mnt->mnt, 1))
			propagate_mount_busy(mnt, 1))
			continue;
		list_move(&mnt->mnt.mnt_expire, &graveyard);
	}
@@ -2148,7 +2148,7 @@ resume:
			goto repeat;
		}

		if (!propagate_mount_busy(&mnt->mnt, 1)) {
		if (!propagate_mount_busy(mnt, 1)) {
			list_move_tail(&mnt->mnt.mnt_expire, graveyard);
			found++;
		}
+8 −8
Original line number Diff line number Diff line
@@ -272,9 +272,9 @@ out:
/*
 * return true if the refcount is greater than count
 */
static inline int do_refcount_check(struct vfsmount *mnt, int count)
static inline int do_refcount_check(struct mount *mnt, int count)
{
	int mycount = mnt_get_count(mnt) - mnt->mnt_ghosts;
	int mycount = mnt_get_count(&mnt->mnt) - mnt->mnt.mnt_ghosts;
	return (mycount > count);
}

@@ -288,14 +288,14 @@ static inline int do_refcount_check(struct vfsmount *mnt, int count)
 *
 * vfsmount lock must be held for write
 */
int propagate_mount_busy(struct vfsmount *mnt, int refcnt)
int propagate_mount_busy(struct mount *mnt, int refcnt)
{
	struct vfsmount *m;
	struct mount *child;
	struct vfsmount *parent = mnt->mnt_parent;
	struct vfsmount *parent = mnt->mnt.mnt_parent;
	int ret = 0;

	if (mnt == parent)
	if (&mnt->mnt == parent)
		return do_refcount_check(mnt, refcnt);

	/*
@@ -303,14 +303,14 @@ int propagate_mount_busy(struct vfsmount *mnt, int refcnt)
	 * If not, we don't have to go checking for all other
	 * mounts
	 */
	if (!list_empty(&mnt->mnt_mounts) || do_refcount_check(mnt, refcnt))
	if (!list_empty(&mnt->mnt.mnt_mounts) || do_refcount_check(mnt, refcnt))
		return 1;

	for (m = propagation_next(parent, parent); m;
	     		m = propagation_next(m, parent)) {
		child = __lookup_mnt(m, mnt->mnt_mountpoint, 0);
		child = __lookup_mnt(m, mnt->mnt.mnt_mountpoint, 0);
		if (child && list_empty(&child->mnt.mnt_mounts) &&
		    (ret = do_refcount_check(&child->mnt, 1)))
		    (ret = do_refcount_check(child, 1)))
			break;
	}
	return ret;
+1 −1
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ void change_mnt_propagation(struct mount *, int);
int propagate_mnt(struct vfsmount *, struct dentry *, struct vfsmount *,
		struct list_head *);
int propagate_umount(struct list_head *);
int propagate_mount_busy(struct vfsmount *, int);
int propagate_mount_busy(struct mount *, int);
void mnt_release_group_id(struct mount *);
int get_dominating_id(struct vfsmount *mnt, const struct path *root);
unsigned int mnt_get_count(struct vfsmount *mnt);