aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c19
1 files changed, 3 insertions, 16 deletions
diff --git a/fs/namei.c b/fs/namei.c
index b20f83d1e065..3df2ed50ab57 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -689,33 +689,20 @@ static __always_inline void follow_dotdot(struct nameidata *nd)
689 set_root(nd); 689 set_root(nd);
690 690
691 while(1) { 691 while(1) {
692 struct vfsmount *parent;
693 struct dentry *old = nd->path.dentry; 692 struct dentry *old = nd->path.dentry;
694 693
695 if (nd->path.dentry == nd->root.dentry && 694 if (nd->path.dentry == nd->root.dentry &&
696 nd->path.mnt == nd->root.mnt) { 695 nd->path.mnt == nd->root.mnt) {
697 break; 696 break;
698 } 697 }
699 spin_lock(&dcache_lock);
700 if (nd->path.dentry != nd->path.mnt->mnt_root) { 698 if (nd->path.dentry != nd->path.mnt->mnt_root) {
701 nd->path.dentry = dget(nd->path.dentry->d_parent); 699 /* rare case of legitimate dget_parent()... */
702 spin_unlock(&dcache_lock); 700 nd->path.dentry = dget_parent(nd->path.dentry);
703 dput(old); 701 dput(old);
704 break; 702 break;
705 } 703 }
706 spin_unlock(&dcache_lock); 704 if (!follow_up(&nd->path))
707 spin_lock(&vfsmount_lock);
708 parent = nd->path.mnt->mnt_parent;
709 if (parent == nd->path.mnt) {
710 spin_unlock(&vfsmount_lock);
711 break; 705 break;
712 }
713 mntget(parent);
714 nd->path.dentry = dget(nd->path.mnt->mnt_mountpoint);
715 spin_unlock(&vfsmount_lock);
716 dput(old);
717 mntput(nd->path.mnt);
718 nd->path.mnt = parent;
719 } 706 }
720 follow_mount(&nd->path); 707 follow_mount(&nd->path);
721} 708}