From: Al Viro <viro@zeniv.linux.org.uk>
Date: Fri, 8 Jun 2012 19:59:33 +0000 (-0400)
Subject: __d_unalias() should refuse to move mountpoints
X-Git-Tag: v3.6-rc1~152^2~60
X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=ee3efa91e240f513898050ef305a49a653c8ed90;p=users%2Fwilly%2Flinux.git

__d_unalias() should refuse to move mountpoints

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---

diff --git a/fs/dcache.c b/fs/dcache.c
index 015586f1ffc6..8086636bf796 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -2387,14 +2387,13 @@ static struct dentry *__d_unalias(struct inode *inode,
 		struct dentry *dentry, struct dentry *alias)
 {
 	struct mutex *m1 = NULL, *m2 = NULL;
-	struct dentry *ret;
+	struct dentry *ret = ERR_PTR(-EBUSY);
 
 	/* If alias and dentry share a parent, then no extra locks required */
 	if (alias->d_parent == dentry->d_parent)
 		goto out_unalias;
 
 	/* See lock_rename() */
-	ret = ERR_PTR(-EBUSY);
 	if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex))
 		goto out_err;
 	m1 = &dentry->d_sb->s_vfs_rename_mutex;
@@ -2402,8 +2401,10 @@ static struct dentry *__d_unalias(struct inode *inode,
 		goto out_err;
 	m2 = &alias->d_parent->d_inode->i_mutex;
 out_unalias:
-	__d_move(alias, dentry);
-	ret = alias;
+	if (likely(!d_mountpoint(alias))) {
+		__d_move(alias, dentry);
+		ret = alias;
+	}
 out_err:
 	spin_unlock(&inode->i_lock);
 	if (m2)