Commit 0ddfb62f authored by Al Viro's avatar Al Viro
Browse files

fix the softlockups in attach_recursive_mnt()



In case when we mounting something on top of a large stack of overmounts,
all of them being peers of each other, we get quadratic time by the
depth of overmount stack.  Easily fixed by doing commit_tree() before
reparenting the overmount; simplifies commit_tree() as well - it doesn't
need to skip the already mounted stuff that had been reparented on top
of the new mounts.

Since we are holding mount_lock through both reparenting and call of
commit_tree(), the order does not matter from the mount hash point
of view.

Reported-by: default avatar"Lai, Yi" <yi1.lai@linux.intel.com>
Tested-by: default avatar"Lai, Yi" <yi1.lai@linux.intel.com>
Reviewed-by: default avatarChristian Brauner <brauner@kernel.org>
Fixes: 66320685 "copy_tree(): don't link the mounts via mnt_list"
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 8742b2d8
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -1197,9 +1197,6 @@ static void commit_tree(struct mount *mnt)

	if (!mnt_ns_attached(mnt)) {
		for (struct mount *m = mnt; m; m = next_mnt(m, mnt))
			if (unlikely(mnt_ns_attached(m)))
				m = skip_mnt_tree(m);
			else
			mnt_add_to_ns(n, m);
		n->nr_mounts += n->pending_mounts;
		n->pending_mounts = 0;
@@ -2704,6 +2701,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
			lock_mnt_tree(child);
		q = __lookup_mnt(&child->mnt_parent->mnt,
				 child->mnt_mountpoint);
		commit_tree(child);
		if (q) {
			struct mountpoint *mp = root.mp;
			struct mount *r = child;
@@ -2713,7 +2711,6 @@ static int attach_recursive_mnt(struct mount *source_mnt,
				mp = shorter;
			mnt_change_mountpoint(r, mp, q);
		}
		commit_tree(child);
	}
	unpin_mountpoint(&root);
	unlock_mount_hash();