diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 158 |
1 files changed, 66 insertions, 92 deletions
diff --git a/fs/namei.c b/fs/namei.c index 868d0cb9d473..f7dbc06857ab 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -282,8 +282,7 @@ int inode_permission(struct inode *inode, int mask) | |||
282 | if (retval) | 282 | if (retval) |
283 | return retval; | 283 | return retval; |
284 | 284 | ||
285 | return security_inode_permission(inode, | 285 | return security_inode_permission(inode, mask); |
286 | mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND)); | ||
287 | } | 286 | } |
288 | 287 | ||
289 | /** | 288 | /** |
@@ -484,13 +483,8 @@ ok: | |||
484 | 483 | ||
485 | static __always_inline void set_root(struct nameidata *nd) | 484 | static __always_inline void set_root(struct nameidata *nd) |
486 | { | 485 | { |
487 | if (!nd->root.mnt) { | 486 | if (!nd->root.mnt) |
488 | struct fs_struct *fs = current->fs; | 487 | get_fs_root(current->fs, &nd->root); |
489 | read_lock(&fs->lock); | ||
490 | nd->root = fs->root; | ||
491 | path_get(&nd->root); | ||
492 | read_unlock(&fs->lock); | ||
493 | } | ||
494 | } | 488 | } |
495 | 489 | ||
496 | static int link_path_walk(const char *, struct nameidata *); | 490 | static int link_path_walk(const char *, struct nameidata *); |
@@ -601,15 +595,16 @@ int follow_up(struct path *path) | |||
601 | { | 595 | { |
602 | struct vfsmount *parent; | 596 | struct vfsmount *parent; |
603 | struct dentry *mountpoint; | 597 | struct dentry *mountpoint; |
604 | spin_lock(&vfsmount_lock); | 598 | |
599 | br_read_lock(vfsmount_lock); | ||
605 | parent = path->mnt->mnt_parent; | 600 | parent = path->mnt->mnt_parent; |
606 | if (parent == path->mnt) { | 601 | if (parent == path->mnt) { |
607 | spin_unlock(&vfsmount_lock); | 602 | br_read_unlock(vfsmount_lock); |
608 | return 0; | 603 | return 0; |
609 | } | 604 | } |
610 | mntget(parent); | 605 | mntget(parent); |
611 | mountpoint = dget(path->mnt->mnt_mountpoint); | 606 | mountpoint = dget(path->mnt->mnt_mountpoint); |
612 | spin_unlock(&vfsmount_lock); | 607 | br_read_unlock(vfsmount_lock); |
613 | dput(path->dentry); | 608 | dput(path->dentry); |
614 | path->dentry = mountpoint; | 609 | path->dentry = mountpoint; |
615 | mntput(path->mnt); | 610 | mntput(path->mnt); |
@@ -692,6 +687,35 @@ static __always_inline void follow_dotdot(struct nameidata *nd) | |||
692 | } | 687 | } |
693 | 688 | ||
694 | /* | 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 | /* | ||
695 | * 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 |
696 | * 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. |
697 | * It _is_ time-critical. | 721 | * It _is_ time-critical. |
@@ -712,9 +736,15 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, | |||
712 | return err; | 736 | return err; |
713 | } | 737 | } |
714 | 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 | */ | ||
715 | dentry = __d_lookup(nd->path.dentry, name); | 744 | dentry = __d_lookup(nd->path.dentry, name); |
716 | if (!dentry) | 745 | if (!dentry) |
717 | goto need_lookup; | 746 | goto need_lookup; |
747 | found: | ||
718 | if (dentry->d_op && dentry->d_op->d_revalidate) | 748 | if (dentry->d_op && dentry->d_op->d_revalidate) |
719 | goto need_revalidate; | 749 | goto need_revalidate; |
720 | done: | 750 | done: |
@@ -730,56 +760,28 @@ need_lookup: | |||
730 | mutex_lock(&dir->i_mutex); | 760 | mutex_lock(&dir->i_mutex); |
731 | /* | 761 | /* |
732 | * 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 |
733 | * while we waited for the directory semaphore.. | 763 | * while we waited for the directory semaphore, or the first |
734 | * | 764 | * lookup failed due to an unrelated rename. |
735 | * FIXME! This could use version numbering or similar to | ||
736 | * avoid unnecessary cache lookups. | ||
737 | * | ||
738 | * The "dcache_lock" is purely to protect the RCU list walker | ||
739 | * from concurrent renames at this point (we mustn't get false | ||
740 | * negatives from the RCU list walk here, unlike the optimistic | ||
741 | * fast walk). | ||
742 | * | 765 | * |
743 | * so doing d_lookup() (with seqlock), instead of lockfree __d_lookup | 766 | * This could use version numbering or similar to avoid unnecessary |
767 | * cache lookups, but then we'd have to do the first lookup in the | ||
768 | * non-racy way. However in the common case here, everything should | ||
769 | * be hot in cache, so would it be a big win? | ||
744 | */ | 770 | */ |
745 | dentry = d_lookup(parent, name); | 771 | dentry = d_lookup(parent, name); |
746 | if (!dentry) { | 772 | if (likely(!dentry)) { |
747 | struct dentry *new; | 773 | dentry = d_alloc_and_lookup(parent, name, nd); |
748 | |||
749 | /* Don't create child dentry for a dead directory. */ | ||
750 | dentry = ERR_PTR(-ENOENT); | ||
751 | if (IS_DEADDIR(dir)) | ||
752 | goto out_unlock; | ||
753 | |||
754 | new = d_alloc(parent, name); | ||
755 | dentry = ERR_PTR(-ENOMEM); | ||
756 | if (new) { | ||
757 | dentry = dir->i_op->lookup(dir, new, nd); | ||
758 | if (dentry) | ||
759 | dput(new); | ||
760 | else | ||
761 | dentry = new; | ||
762 | } | ||
763 | out_unlock: | ||
764 | mutex_unlock(&dir->i_mutex); | 774 | mutex_unlock(&dir->i_mutex); |
765 | if (IS_ERR(dentry)) | 775 | if (IS_ERR(dentry)) |
766 | goto fail; | 776 | goto fail; |
767 | goto done; | 777 | goto done; |
768 | } | 778 | } |
769 | |||
770 | /* | 779 | /* |
771 | * Uhhuh! Nasty case: the cache was re-populated while | 780 | * Uhhuh! Nasty case: the cache was re-populated while |
772 | * we waited on the semaphore. Need to revalidate. | 781 | * we waited on the semaphore. Need to revalidate. |
773 | */ | 782 | */ |
774 | mutex_unlock(&dir->i_mutex); | 783 | mutex_unlock(&dir->i_mutex); |
775 | if (dentry->d_op && dentry->d_op->d_revalidate) { | 784 | goto found; |
776 | dentry = do_revalidate(dentry, nd); | ||
777 | if (!dentry) | ||
778 | dentry = ERR_PTR(-ENOENT); | ||
779 | } | ||
780 | if (IS_ERR(dentry)) | ||
781 | goto fail; | ||
782 | goto done; | ||
783 | 785 | ||
784 | need_revalidate: | 786 | need_revalidate: |
785 | dentry = do_revalidate(dentry, nd); | 787 | dentry = do_revalidate(dentry, nd); |
@@ -1016,11 +1018,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, struct namei | |||
1016 | nd->path = nd->root; | 1018 | nd->path = nd->root; |
1017 | path_get(&nd->root); | 1019 | path_get(&nd->root); |
1018 | } else if (dfd == AT_FDCWD) { | 1020 | } else if (dfd == AT_FDCWD) { |
1019 | struct fs_struct *fs = current->fs; | 1021 | get_fs_pwd(current->fs, &nd->path); |
1020 | read_lock(&fs->lock); | ||
1021 | nd->path = fs->pwd; | ||
1022 | path_get(&fs->pwd); | ||
1023 | read_unlock(&fs->lock); | ||
1024 | } else { | 1022 | } else { |
1025 | struct dentry *dentry; | 1023 | struct dentry *dentry; |
1026 | 1024 | ||
@@ -1123,11 +1121,13 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, | |||
1123 | static struct dentry *__lookup_hash(struct qstr *name, | 1121 | static struct dentry *__lookup_hash(struct qstr *name, |
1124 | struct dentry *base, struct nameidata *nd) | 1122 | struct dentry *base, struct nameidata *nd) |
1125 | { | 1123 | { |
1124 | struct inode *inode = base->d_inode; | ||
1126 | struct dentry *dentry; | 1125 | struct dentry *dentry; |
1127 | struct inode *inode; | ||
1128 | int err; | 1126 | int err; |
1129 | 1127 | ||
1130 | inode = base->d_inode; | 1128 | err = exec_permission(inode); |
1129 | if (err) | ||
1130 | return ERR_PTR(err); | ||
1131 | 1131 | ||
1132 | /* | 1132 | /* |
1133 | * See if the low-level filesystem might want | 1133 | * See if the low-level filesystem might want |
@@ -1140,35 +1140,18 @@ static struct dentry *__lookup_hash(struct qstr *name, | |||
1140 | goto out; | 1140 | goto out; |
1141 | } | 1141 | } |
1142 | 1142 | ||
1143 | dentry = __d_lookup(base, name); | 1143 | /* |
1144 | 1144 | * Don't bother with __d_lookup: callers are for creat as | |
1145 | /* lockess __d_lookup may fail due to concurrent d_move() | 1145 | * well as unlink, so a lot of the time it would cost |
1146 | * in some unrelated directory, so try with d_lookup | 1146 | * a double lookup. |
1147 | */ | 1147 | */ |
1148 | if (!dentry) | 1148 | dentry = d_lookup(base, name); |
1149 | dentry = d_lookup(base, name); | ||
1150 | 1149 | ||
1151 | if (dentry && dentry->d_op && dentry->d_op->d_revalidate) | 1150 | if (dentry && dentry->d_op && dentry->d_op->d_revalidate) |
1152 | dentry = do_revalidate(dentry, nd); | 1151 | dentry = do_revalidate(dentry, nd); |
1153 | 1152 | ||
1154 | if (!dentry) { | 1153 | if (!dentry) |
1155 | struct dentry *new; | 1154 | dentry = d_alloc_and_lookup(base, name, nd); |
1156 | |||
1157 | /* Don't create child dentry for a dead directory. */ | ||
1158 | dentry = ERR_PTR(-ENOENT); | ||
1159 | if (IS_DEADDIR(inode)) | ||
1160 | goto out; | ||
1161 | |||
1162 | new = d_alloc(base, name); | ||
1163 | dentry = ERR_PTR(-ENOMEM); | ||
1164 | if (!new) | ||
1165 | goto out; | ||
1166 | dentry = inode->i_op->lookup(inode, new, nd); | ||
1167 | if (!dentry) | ||
1168 | dentry = new; | ||
1169 | else | ||
1170 | dput(new); | ||
1171 | } | ||
1172 | out: | 1155 | out: |
1173 | return dentry; | 1156 | return dentry; |
1174 | } | 1157 | } |
@@ -1180,11 +1163,6 @@ out: | |||
1180 | */ | 1163 | */ |
1181 | static struct dentry *lookup_hash(struct nameidata *nd) | 1164 | static struct dentry *lookup_hash(struct nameidata *nd) |
1182 | { | 1165 | { |
1183 | int err; | ||
1184 | |||
1185 | err = exec_permission(nd->path.dentry->d_inode); | ||
1186 | if (err) | ||
1187 | return ERR_PTR(err); | ||
1188 | return __lookup_hash(&nd->last, nd->path.dentry, nd); | 1166 | return __lookup_hash(&nd->last, nd->path.dentry, nd); |
1189 | } | 1167 | } |
1190 | 1168 | ||
@@ -1232,9 +1210,6 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) | |||
1232 | if (err) | 1210 | if (err) |
1233 | return ERR_PTR(err); | 1211 | return ERR_PTR(err); |
1234 | 1212 | ||
1235 | err = exec_permission(base->d_inode); | ||
1236 | if (err) | ||
1237 | return ERR_PTR(err); | ||
1238 | return __lookup_hash(&this, base, NULL); | 1213 | return __lookup_hash(&this, base, NULL); |
1239 | } | 1214 | } |
1240 | 1215 | ||
@@ -1484,8 +1459,7 @@ static int handle_truncate(struct path *path) | |||
1484 | */ | 1459 | */ |
1485 | error = locks_verify_locked(inode); | 1460 | error = locks_verify_locked(inode); |
1486 | if (!error) | 1461 | if (!error) |
1487 | error = security_path_truncate(path, 0, | 1462 | error = security_path_truncate(path); |
1488 | ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); | ||
1489 | if (!error) { | 1463 | if (!error) { |
1490 | error = do_truncate(path->dentry, 0, | 1464 | error = do_truncate(path->dentry, 0, |
1491 | ATTR_MTIME|ATTR_CTIME|ATTR_OPEN, | 1465 | ATTR_MTIME|ATTR_CTIME|ATTR_OPEN, |
@@ -2311,7 +2285,7 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
2311 | goto slashes; | 2285 | goto slashes; |
2312 | inode = dentry->d_inode; | 2286 | inode = dentry->d_inode; |
2313 | if (inode) | 2287 | if (inode) |
2314 | atomic_inc(&inode->i_count); | 2288 | ihold(inode); |
2315 | error = mnt_want_write(nd.path.mnt); | 2289 | error = mnt_want_write(nd.path.mnt); |
2316 | if (error) | 2290 | if (error) |
2317 | goto exit2; | 2291 | goto exit2; |
@@ -2635,7 +2609,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2635 | { | 2609 | { |
2636 | int error; | 2610 | int error; |
2637 | int is_dir = S_ISDIR(old_dentry->d_inode->i_mode); | 2611 | int is_dir = S_ISDIR(old_dentry->d_inode->i_mode); |
2638 | const char *old_name; | 2612 | const unsigned char *old_name; |
2639 | 2613 | ||
2640 | if (old_dentry->d_inode == new_dentry->d_inode) | 2614 | if (old_dentry->d_inode == new_dentry->d_inode) |
2641 | return 0; | 2615 | return 0; |