aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/namei.c35
1 files changed, 16 insertions, 19 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 444086d441e1..36925ff307b3 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -596,20 +596,17 @@ static int __follow_mount(struct path *path)
596 return res; 596 return res;
597} 597}
598 598
599static int follow_mount(struct vfsmount **mnt, struct dentry **dentry) 599static void follow_mount(struct vfsmount **mnt, struct dentry **dentry)
600{ 600{
601 int res = 0;
602 while (d_mountpoint(*dentry)) { 601 while (d_mountpoint(*dentry)) {
603 struct vfsmount *mounted = lookup_mnt(*mnt, *dentry); 602 struct vfsmount *mounted = lookup_mnt(*mnt, *dentry);
604 if (!mounted) 603 if (!mounted)
605 break; 604 break;
605 dput(*dentry);
606 mntput(*mnt); 606 mntput(*mnt);
607 *mnt = mounted; 607 *mnt = mounted;
608 dput(*dentry);
609 *dentry = dget(mounted->mnt_root); 608 *dentry = dget(mounted->mnt_root);
610 res = 1;
611 } 609 }
612 return res;
613} 610}
614 611
615/* no need for dcache_lock, as serialization is taken care in 612/* no need for dcache_lock, as serialization is taken care in
@@ -630,41 +627,41 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry)
630 return 0; 627 return 0;
631} 628}
632 629
633static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry) 630static inline void follow_dotdot(struct nameidata *nd)
634{ 631{
635 while(1) { 632 while(1) {
636 struct vfsmount *parent; 633 struct vfsmount *parent;
637 struct dentry *old = *dentry; 634 struct dentry *old = nd->dentry;
638 635
639 read_lock(&current->fs->lock); 636 read_lock(&current->fs->lock);
640 if (*dentry == current->fs->root && 637 if (nd->dentry == current->fs->root &&
641 *mnt == current->fs->rootmnt) { 638 nd->mnt == current->fs->rootmnt) {
642 read_unlock(&current->fs->lock); 639 read_unlock(&current->fs->lock);
643 break; 640 break;
644 } 641 }
645 read_unlock(&current->fs->lock); 642 read_unlock(&current->fs->lock);
646 spin_lock(&dcache_lock); 643 spin_lock(&dcache_lock);
647 if (*dentry != (*mnt)->mnt_root) { 644 if (nd->dentry != nd->mnt->mnt_root) {
648 *dentry = dget((*dentry)->d_parent); 645 nd->dentry = dget(nd->dentry->d_parent);
649 spin_unlock(&dcache_lock); 646 spin_unlock(&dcache_lock);
650 dput(old); 647 dput(old);
651 break; 648 break;
652 } 649 }
653 spin_unlock(&dcache_lock); 650 spin_unlock(&dcache_lock);
654 spin_lock(&vfsmount_lock); 651 spin_lock(&vfsmount_lock);
655 parent = (*mnt)->mnt_parent; 652 parent = nd->mnt->mnt_parent;
656 if (parent == *mnt) { 653 if (parent == nd->mnt) {
657 spin_unlock(&vfsmount_lock); 654 spin_unlock(&vfsmount_lock);
658 break; 655 break;
659 } 656 }
660 mntget(parent); 657 mntget(parent);
661 *dentry = dget((*mnt)->mnt_mountpoint); 658 nd->dentry = dget(nd->mnt->mnt_mountpoint);
662 spin_unlock(&vfsmount_lock); 659 spin_unlock(&vfsmount_lock);
663 dput(old); 660 dput(old);
664 mntput(*mnt); 661 mntput(nd->mnt);
665 *mnt = parent; 662 nd->mnt = parent;
666 } 663 }
667 follow_mount(mnt, dentry); 664 follow_mount(&nd->mnt, &nd->dentry);
668} 665}
669 666
670/* 667/*
@@ -772,7 +769,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
772 case 2: 769 case 2:
773 if (this.name[1] != '.') 770 if (this.name[1] != '.')
774 break; 771 break;
775 follow_dotdot(&nd->mnt, &nd->dentry); 772 follow_dotdot(nd);
776 inode = nd->dentry->d_inode; 773 inode = nd->dentry->d_inode;
777 /* fallthrough */ 774 /* fallthrough */
778 case 1: 775 case 1:
@@ -839,7 +836,7 @@ last_component:
839 case 2: 836 case 2:
840 if (this.name[1] != '.') 837 if (this.name[1] != '.')
841 break; 838 break;
842 follow_dotdot(&nd->mnt, &nd->dentry); 839 follow_dotdot(nd);
843 inode = nd->dentry->d_inode; 840 inode = nd->dentry->d_inode;
844 /* fallthrough */ 841 /* fallthrough */
845 case 1: 842 case 1: