/* no need for dcache_lock, as serialization is taken care in
  * namespace.c
  */
-static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry)
+int follow_down(struct vfsmount **mnt, struct dentry **dentry)
 {
        struct vfsmount *mounted;
 
        mounted = lookup_mnt(*mnt, *dentry);
        if (mounted) {
+               dput(*dentry);
                mntput(*mnt);
                *mnt = mounted;
-               dput(*dentry);
                *dentry = dget(mounted->mnt_root);
                return 1;
        }
        return 0;
 }
 
-int follow_down(struct vfsmount **mnt, struct dentry **dentry)
-{
-       return __follow_down(mnt,dentry);
-}
- 
 static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry)
 {
        while(1) {
        if (flag & O_EXCL)
                goto exit_dput;
 
-       if (d_mountpoint(path.dentry)) {
+       if (__follow_mount(&path)) {
                error = -ELOOP;
-               if (flag & O_NOFOLLOW)
-                       goto exit_dput;
-               while (__follow_down(&path.mnt,&path.dentry) && d_mountpoint(path.dentry));
+               if (flag & O_NOFOLLOW) {
+                       dput(path.dentry);
+                       mntput(path.mnt);
+                       goto exit;
+               }
+               mntput(nd->mnt);
                nd->mnt = path.mnt;
        }
        error = -ENOENT;