diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 134 |
1 files changed, 58 insertions, 76 deletions
diff --git a/fs/namei.c b/fs/namei.c index 13ff4abdbdca..24896e833565 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -483,13 +483,8 @@ ok: | |||
483 | 483 | ||
484 | static __always_inline void set_root(struct nameidata *nd) | 484 | static __always_inline void set_root(struct nameidata *nd) |
485 | { | 485 | { |
486 | if (!nd->root.mnt) { | 486 | if (!nd->root.mnt) |
487 | struct fs_struct *fs = current->fs; | 487 | get_fs_root(current->fs, &nd->root); |
488 | read_lock(&fs->lock); | ||
489 | nd->root = fs->root; | ||
490 | path_get(&nd->root); | ||
491 | read_unlock(&fs->lock); | ||
492 | } | ||
493 | } | 488 | } |
494 | 489 | ||
495 | static int link_path_walk(const char *, struct nameidata *); | 490 | static int link_path_walk(const char *, struct nameidata *); |
@@ -600,15 +595,16 @@ int follow_up(struct path *path) | |||
600 | { | 595 | { |
601 | struct vfsmount *parent; | 596 | struct vfsmount *parent; |
602 | struct dentry *mountpoint; | 597 | struct dentry *mountpoint; |
603 | spin_lock(&vfsmount_lock); | 598 | |
599 | br_read_lock(vfsmount_lock); | ||
604 | parent = path->mnt->mnt_parent; | 600 | parent = path->mnt->mnt_parent; |
605 | if (parent == path->mnt) { | 601 | if (parent == path->mnt) { |
606 | spin_unlock(&vfsmount_lock); | 602 | br_read_unlock(vfsmount_lock); |
607 | return 0; | 603 | return 0; |
608 | } | 604 | } |
609 | mntget(parent); | 605 | mntget(parent); |
610 | mountpoint = dget(path->mnt->mnt_mountpoint); | 606 | mountpoint = dget(path->mnt->mnt_mountpoint); |
611 | spin_unlock(&vfsmount_lock); | 607 | br_read_unlock(vfsmount_lock); |
612 | dput(path->dentry); | 608 | dput(path->dentry); |
613 | path->dentry = mountpoint; | 609 | path->dentry = mountpoint; |
614 | mntput(path->mnt); | 610 | mntput(path->mnt); |
@@ -691,6 +687,35 @@ static __always_inline void follow_dotdot(struct nameidata *nd) | |||
691 | } | 687 | } |
692 | 688 | ||
693 | /* | 689 | /* |
690 | * Allocate a dentry with name and parent, and perform a parent | ||
691 | * directory ->lookup on it. Returns the new dentry, or ERR_PTR | ||
692 | * on error. parent->d_inode->i_mutex must be held. d_lookup must | ||
693 | * have verified that no child exists while under i_mutex. | ||
694 | */ | ||
695 | static struct dentry *d_alloc_and_lookup(struct dentry *parent, | ||
696 | struct qstr *name, struct nameidata *nd) | ||
697 | { | ||
698 | struct inode *inode = parent->d_inode; | ||
699 | struct dentry *dentry; | ||
700 | struct dentry *old; | ||
701 | |||
702 | /* Don't create child dentry for a dead directory. */ | ||
703 | if (unlikely(IS_DEADDIR(inode))) | ||
704 | return ERR_PTR(-ENOENT); | ||
705 | |||
706 | dentry = d_alloc(parent, name); | ||
707 | if (unlikely(!dentry)) | ||
708 | return ERR_PTR(-ENOMEM); | ||
709 | |||
710 | old = inode->i_op->lookup(inode, dentry, nd); | ||
711 | if (unlikely(old)) { | ||
712 | dput(dentry); | ||
713 | dentry = old; | ||
714 | } | ||
715 | return dentry; | ||
716 | } | ||
717 | |||
718 | /* | ||
694 | * It's more convoluted than I'd like it to be, but... it's still fairly | 719 | * It's more convoluted than I'd like it to be, but... it's still fairly |
695 | * small and for now I'd prefer to have fast path as straight as possible. | 720 | * small and for now I'd prefer to have fast path as straight as possible. |
696 | * It _is_ time-critical. | 721 | * It _is_ time-critical. |
@@ -711,9 +736,15 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, | |||
711 | return err; | 736 | return err; |
712 | } | 737 | } |
713 | 738 | ||
739 | /* | ||
740 | * Rename seqlock is not required here because in the off chance | ||
741 | * of a false negative due to a concurrent rename, we're going to | ||
742 | * do the non-racy lookup, below. | ||
743 | */ | ||
714 | dentry = __d_lookup(nd->path.dentry, name); | 744 | dentry = __d_lookup(nd->path.dentry, name); |
715 | if (!dentry) | 745 | if (!dentry) |
716 | goto need_lookup; | 746 | goto need_lookup; |
747 | found: | ||
717 | if (dentry->d_op && dentry->d_op->d_revalidate) | 748 | if (dentry->d_op && dentry->d_op->d_revalidate) |
718 | goto need_revalidate; | 749 | goto need_revalidate; |
719 | done: | 750 | done: |
@@ -729,56 +760,28 @@ need_lookup: | |||
729 | mutex_lock(&dir->i_mutex); | 760 | mutex_lock(&dir->i_mutex); |
730 | /* | 761 | /* |
731 | * First re-do the cached lookup just in case it was created | 762 | * First re-do the cached lookup just in case it was created |
732 | * while we waited for the directory semaphore.. | 763 | * while we waited for the directory semaphore, or the first |
733 | * | 764 | * lookup failed due to an unrelated rename. |
734 | * FIXME! This could use version numbering or similar to | ||
735 | * avoid unnecessary cache lookups. | ||
736 | * | 765 | * |
737 | * The "dcache_lock" is purely to protect the RCU list walker | 766 | * This could use version numbering or similar to avoid unnecessary |
738 | * from concurrent renames at this point (we mustn't get false | 767 | * cache lookups, but then we'd have to do the first lookup in the |
739 | * negatives from the RCU list walk here, unlike the optimistic | 768 | * non-racy way. However in the common case here, everything should |
740 | * fast walk). | 769 | * be hot in cache, so would it be a big win? |
741 | * | ||
742 | * so doing d_lookup() (with seqlock), instead of lockfree __d_lookup | ||
743 | */ | 770 | */ |
744 | dentry = d_lookup(parent, name); | 771 | dentry = d_lookup(parent, name); |
745 | if (!dentry) { | 772 | if (likely(!dentry)) { |
746 | struct dentry *new; | 773 | dentry = d_alloc_and_lookup(parent, name, nd); |
747 | |||
748 | /* Don't create child dentry for a dead directory. */ | ||
749 | dentry = ERR_PTR(-ENOENT); | ||
750 | if (IS_DEADDIR(dir)) | ||
751 | goto out_unlock; | ||
752 | |||
753 | new = d_alloc(parent, name); | ||
754 | dentry = ERR_PTR(-ENOMEM); | ||
755 | if (new) { | ||
756 | dentry = dir->i_op->lookup(dir, new, nd); | ||
757 | if (dentry) | ||
758 | dput(new); | ||
759 | else | ||
760 | dentry = new; | ||
761 | } | ||
762 | out_unlock: | ||
763 | mutex_unlock(&dir->i_mutex); | 774 | mutex_unlock(&dir->i_mutex); |
764 | if (IS_ERR(dentry)) | 775 | if (IS_ERR(dentry)) |
765 | goto fail; | 776 | goto fail; |
766 | goto done; | 777 | goto done; |
767 | } | 778 | } |
768 | |||
769 | /* | 779 | /* |
770 | * Uhhuh! Nasty case: the cache was re-populated while | 780 | * Uhhuh! Nasty case: the cache was re-populated while |
771 | * we waited on the semaphore. Need to revalidate. | 781 | * we waited on the semaphore. Need to revalidate. |
772 | */ | 782 | */ |
773 | mutex_unlock(&dir->i_mutex); | 783 | mutex_unlock(&dir->i_mutex); |
774 | if (dentry->d_op && dentry->d_op->d_revalidate) { | 784 | goto found; |
775 | dentry = do_revalidate(dentry, nd); | ||
776 | if (!dentry) | ||
777 | dentry = ERR_PTR(-ENOENT); | ||
778 | } | ||
779 | if (IS_ERR(dentry)) | ||
780 | goto fail; | ||
781 | goto done; | ||
782 | 785 | ||
783 | need_revalidate: | 786 | need_revalidate: |
784 | dentry = do_revalidate(dentry, nd); | 787 | dentry = do_revalidate(dentry, nd); |
@@ -1015,11 +1018,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, struct namei | |||
1015 | nd->path = nd->root; | 1018 | nd->path = nd->root; |
1016 | path_get(&nd->root); | 1019 | path_get(&nd->root); |
1017 | } else if (dfd == AT_FDCWD) { | 1020 | } else if (dfd == AT_FDCWD) { |
1018 | struct fs_struct *fs = current->fs; | 1021 | get_fs_pwd(current->fs, &nd->path); |
1019 | read_lock(&fs->lock); | ||
1020 | nd->path = fs->pwd; | ||
1021 | path_get(&fs->pwd); | ||
1022 | read_unlock(&fs->lock); | ||
1023 | } else { | 1022 | } else { |
1024 | struct dentry *dentry; | 1023 | struct dentry *dentry; |
1025 | 1024 | ||
@@ -1139,35 +1138,18 @@ static struct dentry *__lookup_hash(struct qstr *name, | |||
1139 | goto out; | 1138 | goto out; |
1140 | } | 1139 | } |
1141 | 1140 | ||
1142 | dentry = __d_lookup(base, name); | 1141 | /* |
1143 | 1142 | * Don't bother with __d_lookup: callers are for creat as | |
1144 | /* lockess __d_lookup may fail due to concurrent d_move() | 1143 | * well as unlink, so a lot of the time it would cost |
1145 | * in some unrelated directory, so try with d_lookup | 1144 | * a double lookup. |
1146 | */ | 1145 | */ |
1147 | if (!dentry) | 1146 | dentry = d_lookup(base, name); |
1148 | dentry = d_lookup(base, name); | ||
1149 | 1147 | ||
1150 | if (dentry && dentry->d_op && dentry->d_op->d_revalidate) | 1148 | if (dentry && dentry->d_op && dentry->d_op->d_revalidate) |
1151 | dentry = do_revalidate(dentry, nd); | 1149 | dentry = do_revalidate(dentry, nd); |
1152 | 1150 | ||
1153 | if (!dentry) { | 1151 | if (!dentry) |
1154 | struct dentry *new; | 1152 | dentry = d_alloc_and_lookup(base, name, nd); |
1155 | |||
1156 | /* Don't create child dentry for a dead directory. */ | ||
1157 | dentry = ERR_PTR(-ENOENT); | ||
1158 | if (IS_DEADDIR(inode)) | ||
1159 | goto out; | ||
1160 | |||
1161 | new = d_alloc(base, name); | ||
1162 | dentry = ERR_PTR(-ENOMEM); | ||
1163 | if (!new) | ||
1164 | goto out; | ||
1165 | dentry = inode->i_op->lookup(inode, new, nd); | ||
1166 | if (!dentry) | ||
1167 | dentry = new; | ||
1168 | else | ||
1169 | dput(new); | ||
1170 | } | ||
1171 | out: | 1153 | out: |
1172 | return dentry; | 1154 | return dentry; |
1173 | } | 1155 | } |