diff options
author | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-02-17 21:51:42 -0500 |
---|---|---|
committer | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-02-17 21:51:42 -0500 |
commit | c58310bf4933986513020fa90b4190c7492995ae (patch) | |
tree | 143f2c7578d02ebef5db8fc57ae69e951ae0e2ee /fs/namei.c | |
parent | 269cdfaf769f5cd831284cc831790c7c5038040f (diff) | |
parent | 1309d4e68497184d2fd87e892ddf14076c2bda98 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-linus
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 330 |
1 files changed, 166 insertions, 164 deletions
diff --git a/fs/namei.c b/fs/namei.c index 73e2e665817a..941c8e8228c0 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -106,7 +106,7 @@ | |||
106 | * any extra contention... | 106 | * any extra contention... |
107 | */ | 107 | */ |
108 | 108 | ||
109 | static int fastcall link_path_walk(const char *name, struct nameidata *nd); | 109 | static int link_path_walk(const char *name, struct nameidata *nd); |
110 | 110 | ||
111 | /* In order to reduce some races, while at the same time doing additional | 111 | /* In order to reduce some races, while at the same time doing additional |
112 | * checking and hopefully speeding things up, we copy filenames to the | 112 | * checking and hopefully speeding things up, we copy filenames to the |
@@ -231,7 +231,7 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) | |||
231 | struct vfsmount *mnt = NULL; | 231 | struct vfsmount *mnt = NULL; |
232 | 232 | ||
233 | if (nd) | 233 | if (nd) |
234 | mnt = nd->mnt; | 234 | mnt = nd->path.mnt; |
235 | 235 | ||
236 | if (mask & MAY_WRITE) { | 236 | if (mask & MAY_WRITE) { |
237 | umode_t mode = inode->i_mode; | 237 | umode_t mode = inode->i_mode; |
@@ -296,7 +296,7 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) | |||
296 | */ | 296 | */ |
297 | int vfs_permission(struct nameidata *nd, int mask) | 297 | int vfs_permission(struct nameidata *nd, int mask) |
298 | { | 298 | { |
299 | return permission(nd->dentry->d_inode, mask, nd); | 299 | return permission(nd->path.dentry->d_inode, mask, nd); |
300 | } | 300 | } |
301 | 301 | ||
302 | /** | 302 | /** |
@@ -362,21 +362,31 @@ int deny_write_access(struct file * file) | |||
362 | return 0; | 362 | return 0; |
363 | } | 363 | } |
364 | 364 | ||
365 | void path_release(struct nameidata *nd) | 365 | /** |
366 | * path_get - get a reference to a path | ||
367 | * @path: path to get the reference to | ||
368 | * | ||
369 | * Given a path increment the reference count to the dentry and the vfsmount. | ||
370 | */ | ||
371 | void path_get(struct path *path) | ||
366 | { | 372 | { |
367 | dput(nd->dentry); | 373 | mntget(path->mnt); |
368 | mntput(nd->mnt); | 374 | dget(path->dentry); |
369 | } | 375 | } |
376 | EXPORT_SYMBOL(path_get); | ||
370 | 377 | ||
371 | /* | 378 | /** |
372 | * umount() mustn't call path_release()/mntput() as that would clear | 379 | * path_put - put a reference to a path |
373 | * mnt_expiry_mark | 380 | * @path: path to put the reference to |
381 | * | ||
382 | * Given a path decrement the reference count to the dentry and the vfsmount. | ||
374 | */ | 383 | */ |
375 | void path_release_on_umount(struct nameidata *nd) | 384 | void path_put(struct path *path) |
376 | { | 385 | { |
377 | dput(nd->dentry); | 386 | dput(path->dentry); |
378 | mntput_no_expire(nd->mnt); | 387 | mntput(path->mnt); |
379 | } | 388 | } |
389 | EXPORT_SYMBOL(path_put); | ||
380 | 390 | ||
381 | /** | 391 | /** |
382 | * release_open_intent - free up open intent resources | 392 | * release_open_intent - free up open intent resources |
@@ -539,16 +549,16 @@ walk_init_root(const char *name, struct nameidata *nd) | |||
539 | struct fs_struct *fs = current->fs; | 549 | struct fs_struct *fs = current->fs; |
540 | 550 | ||
541 | read_lock(&fs->lock); | 551 | read_lock(&fs->lock); |
542 | if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) { | 552 | if (fs->altroot.dentry && !(nd->flags & LOOKUP_NOALT)) { |
543 | nd->mnt = mntget(fs->altrootmnt); | 553 | nd->path = fs->altroot; |
544 | nd->dentry = dget(fs->altroot); | 554 | path_get(&fs->altroot); |
545 | read_unlock(&fs->lock); | 555 | read_unlock(&fs->lock); |
546 | if (__emul_lookup_dentry(name,nd)) | 556 | if (__emul_lookup_dentry(name,nd)) |
547 | return 0; | 557 | return 0; |
548 | read_lock(&fs->lock); | 558 | read_lock(&fs->lock); |
549 | } | 559 | } |
550 | nd->mnt = mntget(fs->rootmnt); | 560 | nd->path = fs->root; |
551 | nd->dentry = dget(fs->root); | 561 | path_get(&fs->root); |
552 | read_unlock(&fs->lock); | 562 | read_unlock(&fs->lock); |
553 | return 1; | 563 | return 1; |
554 | } | 564 | } |
@@ -561,7 +571,7 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l | |||
561 | goto fail; | 571 | goto fail; |
562 | 572 | ||
563 | if (*link == '/') { | 573 | if (*link == '/') { |
564 | path_release(nd); | 574 | path_put(&nd->path); |
565 | if (!walk_init_root(link, nd)) | 575 | if (!walk_init_root(link, nd)) |
566 | /* weird __emul_prefix() stuff did it */ | 576 | /* weird __emul_prefix() stuff did it */ |
567 | goto out; | 577 | goto out; |
@@ -577,31 +587,31 @@ out: | |||
577 | */ | 587 | */ |
578 | name = __getname(); | 588 | name = __getname(); |
579 | if (unlikely(!name)) { | 589 | if (unlikely(!name)) { |
580 | path_release(nd); | 590 | path_put(&nd->path); |
581 | return -ENOMEM; | 591 | return -ENOMEM; |
582 | } | 592 | } |
583 | strcpy(name, nd->last.name); | 593 | strcpy(name, nd->last.name); |
584 | nd->last.name = name; | 594 | nd->last.name = name; |
585 | return 0; | 595 | return 0; |
586 | fail: | 596 | fail: |
587 | path_release(nd); | 597 | path_put(&nd->path); |
588 | return PTR_ERR(link); | 598 | return PTR_ERR(link); |
589 | } | 599 | } |
590 | 600 | ||
591 | static inline void dput_path(struct path *path, struct nameidata *nd) | 601 | static void path_put_conditional(struct path *path, struct nameidata *nd) |
592 | { | 602 | { |
593 | dput(path->dentry); | 603 | dput(path->dentry); |
594 | if (path->mnt != nd->mnt) | 604 | if (path->mnt != nd->path.mnt) |
595 | mntput(path->mnt); | 605 | mntput(path->mnt); |
596 | } | 606 | } |
597 | 607 | ||
598 | static inline void path_to_nameidata(struct path *path, struct nameidata *nd) | 608 | static inline void path_to_nameidata(struct path *path, struct nameidata *nd) |
599 | { | 609 | { |
600 | dput(nd->dentry); | 610 | dput(nd->path.dentry); |
601 | if (nd->mnt != path->mnt) | 611 | if (nd->path.mnt != path->mnt) |
602 | mntput(nd->mnt); | 612 | mntput(nd->path.mnt); |
603 | nd->mnt = path->mnt; | 613 | nd->path.mnt = path->mnt; |
604 | nd->dentry = path->dentry; | 614 | nd->path.dentry = path->dentry; |
605 | } | 615 | } |
606 | 616 | ||
607 | static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) | 617 | static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) |
@@ -613,7 +623,7 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata | |||
613 | touch_atime(path->mnt, dentry); | 623 | touch_atime(path->mnt, dentry); |
614 | nd_set_link(nd, NULL); | 624 | nd_set_link(nd, NULL); |
615 | 625 | ||
616 | if (path->mnt != nd->mnt) { | 626 | if (path->mnt != nd->path.mnt) { |
617 | path_to_nameidata(path, nd); | 627 | path_to_nameidata(path, nd); |
618 | dget(dentry); | 628 | dget(dentry); |
619 | } | 629 | } |
@@ -628,8 +638,7 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata | |||
628 | if (dentry->d_inode->i_op->put_link) | 638 | if (dentry->d_inode->i_op->put_link) |
629 | dentry->d_inode->i_op->put_link(dentry, nd, cookie); | 639 | dentry->d_inode->i_op->put_link(dentry, nd, cookie); |
630 | } | 640 | } |
631 | dput(dentry); | 641 | path_put(path); |
632 | mntput(path->mnt); | ||
633 | 642 | ||
634 | return error; | 643 | return error; |
635 | } | 644 | } |
@@ -661,8 +670,8 @@ static inline int do_follow_link(struct path *path, struct nameidata *nd) | |||
661 | nd->depth--; | 670 | nd->depth--; |
662 | return err; | 671 | return err; |
663 | loop: | 672 | loop: |
664 | dput_path(path, nd); | 673 | path_put_conditional(path, nd); |
665 | path_release(nd); | 674 | path_put(&nd->path); |
666 | return err; | 675 | return err; |
667 | } | 676 | } |
668 | 677 | ||
@@ -743,37 +752,37 @@ static __always_inline void follow_dotdot(struct nameidata *nd) | |||
743 | 752 | ||
744 | while(1) { | 753 | while(1) { |
745 | struct vfsmount *parent; | 754 | struct vfsmount *parent; |
746 | struct dentry *old = nd->dentry; | 755 | struct dentry *old = nd->path.dentry; |
747 | 756 | ||
748 | read_lock(&fs->lock); | 757 | read_lock(&fs->lock); |
749 | if (nd->dentry == fs->root && | 758 | if (nd->path.dentry == fs->root.dentry && |
750 | nd->mnt == fs->rootmnt) { | 759 | nd->path.mnt == fs->root.mnt) { |
751 | read_unlock(&fs->lock); | 760 | read_unlock(&fs->lock); |
752 | break; | 761 | break; |
753 | } | 762 | } |
754 | read_unlock(&fs->lock); | 763 | read_unlock(&fs->lock); |
755 | spin_lock(&dcache_lock); | 764 | spin_lock(&dcache_lock); |
756 | if (nd->dentry != nd->mnt->mnt_root) { | 765 | if (nd->path.dentry != nd->path.mnt->mnt_root) { |
757 | nd->dentry = dget(nd->dentry->d_parent); | 766 | nd->path.dentry = dget(nd->path.dentry->d_parent); |
758 | spin_unlock(&dcache_lock); | 767 | spin_unlock(&dcache_lock); |
759 | dput(old); | 768 | dput(old); |
760 | break; | 769 | break; |
761 | } | 770 | } |
762 | spin_unlock(&dcache_lock); | 771 | spin_unlock(&dcache_lock); |
763 | spin_lock(&vfsmount_lock); | 772 | spin_lock(&vfsmount_lock); |
764 | parent = nd->mnt->mnt_parent; | 773 | parent = nd->path.mnt->mnt_parent; |
765 | if (parent == nd->mnt) { | 774 | if (parent == nd->path.mnt) { |
766 | spin_unlock(&vfsmount_lock); | 775 | spin_unlock(&vfsmount_lock); |
767 | break; | 776 | break; |
768 | } | 777 | } |
769 | mntget(parent); | 778 | mntget(parent); |
770 | nd->dentry = dget(nd->mnt->mnt_mountpoint); | 779 | nd->path.dentry = dget(nd->path.mnt->mnt_mountpoint); |
771 | spin_unlock(&vfsmount_lock); | 780 | spin_unlock(&vfsmount_lock); |
772 | dput(old); | 781 | dput(old); |
773 | mntput(nd->mnt); | 782 | mntput(nd->path.mnt); |
774 | nd->mnt = parent; | 783 | nd->path.mnt = parent; |
775 | } | 784 | } |
776 | follow_mount(&nd->mnt, &nd->dentry); | 785 | follow_mount(&nd->path.mnt, &nd->path.dentry); |
777 | } | 786 | } |
778 | 787 | ||
779 | /* | 788 | /* |
@@ -784,8 +793,8 @@ static __always_inline void follow_dotdot(struct nameidata *nd) | |||
784 | static int do_lookup(struct nameidata *nd, struct qstr *name, | 793 | static int do_lookup(struct nameidata *nd, struct qstr *name, |
785 | struct path *path) | 794 | struct path *path) |
786 | { | 795 | { |
787 | struct vfsmount *mnt = nd->mnt; | 796 | struct vfsmount *mnt = nd->path.mnt; |
788 | struct dentry *dentry = __d_lookup(nd->dentry, name); | 797 | struct dentry *dentry = __d_lookup(nd->path.dentry, name); |
789 | 798 | ||
790 | if (!dentry) | 799 | if (!dentry) |
791 | goto need_lookup; | 800 | goto need_lookup; |
@@ -798,7 +807,7 @@ done: | |||
798 | return 0; | 807 | return 0; |
799 | 808 | ||
800 | need_lookup: | 809 | need_lookup: |
801 | dentry = real_lookup(nd->dentry, name, nd); | 810 | dentry = real_lookup(nd->path.dentry, name, nd); |
802 | if (IS_ERR(dentry)) | 811 | if (IS_ERR(dentry)) |
803 | goto fail; | 812 | goto fail; |
804 | goto done; | 813 | goto done; |
@@ -823,7 +832,7 @@ fail: | |||
823 | * Returns 0 and nd will have valid dentry and mnt on success. | 832 | * Returns 0 and nd will have valid dentry and mnt on success. |
824 | * Returns error and drops reference to input namei data on failure. | 833 | * Returns error and drops reference to input namei data on failure. |
825 | */ | 834 | */ |
826 | static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | 835 | static int __link_path_walk(const char *name, struct nameidata *nd) |
827 | { | 836 | { |
828 | struct path next; | 837 | struct path next; |
829 | struct inode *inode; | 838 | struct inode *inode; |
@@ -835,7 +844,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
835 | if (!*name) | 844 | if (!*name) |
836 | goto return_reval; | 845 | goto return_reval; |
837 | 846 | ||
838 | inode = nd->dentry->d_inode; | 847 | inode = nd->path.dentry->d_inode; |
839 | if (nd->depth) | 848 | if (nd->depth) |
840 | lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE); | 849 | lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE); |
841 | 850 | ||
@@ -883,7 +892,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
883 | if (this.name[1] != '.') | 892 | if (this.name[1] != '.') |
884 | break; | 893 | break; |
885 | follow_dotdot(nd); | 894 | follow_dotdot(nd); |
886 | inode = nd->dentry->d_inode; | 895 | inode = nd->path.dentry->d_inode; |
887 | /* fallthrough */ | 896 | /* fallthrough */ |
888 | case 1: | 897 | case 1: |
889 | continue; | 898 | continue; |
@@ -892,8 +901,9 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
892 | * See if the low-level filesystem might want | 901 | * See if the low-level filesystem might want |
893 | * to use its own hash.. | 902 | * to use its own hash.. |
894 | */ | 903 | */ |
895 | if (nd->dentry->d_op && nd->dentry->d_op->d_hash) { | 904 | if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) { |
896 | err = nd->dentry->d_op->d_hash(nd->dentry, &this); | 905 | err = nd->path.dentry->d_op->d_hash(nd->path.dentry, |
906 | &this); | ||
897 | if (err < 0) | 907 | if (err < 0) |
898 | break; | 908 | break; |
899 | } | 909 | } |
@@ -915,7 +925,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) | |||
915 | if (err) | 925 | if (err) |
916 | goto return_err; | 926 | goto return_err; |
917 | err = -ENOENT; | 927 | err = -ENOENT; |
918 | inode = nd->dentry->d_inode; | 928 | inode = nd->path.dentry->d_inode; |
919 | if (!inode) | 929 | if (!inode) |
920 | break; | 930 | break; |
921 | err = -ENOTDIR; | 931 | err = -ENOTDIR; |
@@ -943,13 +953,14 @@ last_component: | |||
943 | if (this.name[1] != '.') | 953 | if (this.name[1] != '.') |
944 | break; | 954 | break; |
945 | follow_dotdot(nd); | 955 | follow_dotdot(nd); |
946 | inode = nd->dentry->d_inode; | 956 | inode = nd->path.dentry->d_inode; |
947 | /* fallthrough */ | 957 | /* fallthrough */ |
948 | case 1: | 958 | case 1: |
949 | goto return_reval; | 959 | goto return_reval; |
950 | } | 960 | } |
951 | if (nd->dentry->d_op && nd->dentry->d_op->d_hash) { | 961 | if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) { |
952 | err = nd->dentry->d_op->d_hash(nd->dentry, &this); | 962 | err = nd->path.dentry->d_op->d_hash(nd->path.dentry, |
963 | &this); | ||
953 | if (err < 0) | 964 | if (err < 0) |
954 | break; | 965 | break; |
955 | } | 966 | } |
@@ -962,7 +973,7 @@ last_component: | |||
962 | err = do_follow_link(&next, nd); | 973 | err = do_follow_link(&next, nd); |
963 | if (err) | 974 | if (err) |
964 | goto return_err; | 975 | goto return_err; |
965 | inode = nd->dentry->d_inode; | 976 | inode = nd->path.dentry->d_inode; |
966 | } else | 977 | } else |
967 | path_to_nameidata(&next, nd); | 978 | path_to_nameidata(&next, nd); |
968 | err = -ENOENT; | 979 | err = -ENOENT; |
@@ -990,20 +1001,21 @@ return_reval: | |||
990 | * We bypassed the ordinary revalidation routines. | 1001 | * We bypassed the ordinary revalidation routines. |
991 | * We may need to check the cached dentry for staleness. | 1002 | * We may need to check the cached dentry for staleness. |
992 | */ | 1003 | */ |
993 | if (nd->dentry && nd->dentry->d_sb && | 1004 | if (nd->path.dentry && nd->path.dentry->d_sb && |
994 | (nd->dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)) { | 1005 | (nd->path.dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)) { |
995 | err = -ESTALE; | 1006 | err = -ESTALE; |
996 | /* Note: we do not d_invalidate() */ | 1007 | /* Note: we do not d_invalidate() */ |
997 | if (!nd->dentry->d_op->d_revalidate(nd->dentry, nd)) | 1008 | if (!nd->path.dentry->d_op->d_revalidate( |
1009 | nd->path.dentry, nd)) | ||
998 | break; | 1010 | break; |
999 | } | 1011 | } |
1000 | return_base: | 1012 | return_base: |
1001 | return 0; | 1013 | return 0; |
1002 | out_dput: | 1014 | out_dput: |
1003 | dput_path(&next, nd); | 1015 | path_put_conditional(&next, nd); |
1004 | break; | 1016 | break; |
1005 | } | 1017 | } |
1006 | path_release(nd); | 1018 | path_put(&nd->path); |
1007 | return_err: | 1019 | return_err: |
1008 | return err; | 1020 | return err; |
1009 | } | 1021 | } |
@@ -1015,31 +1027,30 @@ return_err: | |||
1015 | * Retry the whole path once, forcing real lookup requests | 1027 | * Retry the whole path once, forcing real lookup requests |
1016 | * instead of relying on the dcache. | 1028 | * instead of relying on the dcache. |
1017 | */ | 1029 | */ |
1018 | static int fastcall link_path_walk(const char *name, struct nameidata *nd) | 1030 | static int link_path_walk(const char *name, struct nameidata *nd) |
1019 | { | 1031 | { |
1020 | struct nameidata save = *nd; | 1032 | struct nameidata save = *nd; |
1021 | int result; | 1033 | int result; |
1022 | 1034 | ||
1023 | /* make sure the stuff we saved doesn't go away */ | 1035 | /* make sure the stuff we saved doesn't go away */ |
1024 | dget(save.dentry); | 1036 | dget(save.path.dentry); |
1025 | mntget(save.mnt); | 1037 | mntget(save.path.mnt); |
1026 | 1038 | ||
1027 | result = __link_path_walk(name, nd); | 1039 | result = __link_path_walk(name, nd); |
1028 | if (result == -ESTALE) { | 1040 | if (result == -ESTALE) { |
1029 | *nd = save; | 1041 | *nd = save; |
1030 | dget(nd->dentry); | 1042 | dget(nd->path.dentry); |
1031 | mntget(nd->mnt); | 1043 | mntget(nd->path.mnt); |
1032 | nd->flags |= LOOKUP_REVAL; | 1044 | nd->flags |= LOOKUP_REVAL; |
1033 | result = __link_path_walk(name, nd); | 1045 | result = __link_path_walk(name, nd); |
1034 | } | 1046 | } |
1035 | 1047 | ||
1036 | dput(save.dentry); | 1048 | path_put(&save.path); |
1037 | mntput(save.mnt); | ||
1038 | 1049 | ||
1039 | return result; | 1050 | return result; |
1040 | } | 1051 | } |
1041 | 1052 | ||
1042 | static int fastcall path_walk(const char * name, struct nameidata *nd) | 1053 | static int path_walk(const char *name, struct nameidata *nd) |
1043 | { | 1054 | { |
1044 | current->total_link_count = 0; | 1055 | current->total_link_count = 0; |
1045 | return link_path_walk(name, nd); | 1056 | return link_path_walk(name, nd); |
@@ -1054,9 +1065,9 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd) | |||
1054 | if (path_walk(name, nd)) | 1065 | if (path_walk(name, nd)) |
1055 | return 0; /* something went wrong... */ | 1066 | return 0; /* something went wrong... */ |
1056 | 1067 | ||
1057 | if (!nd->dentry->d_inode || S_ISDIR(nd->dentry->d_inode->i_mode)) { | 1068 | if (!nd->path.dentry->d_inode || |
1058 | struct dentry *old_dentry = nd->dentry; | 1069 | S_ISDIR(nd->path.dentry->d_inode->i_mode)) { |
1059 | struct vfsmount *old_mnt = nd->mnt; | 1070 | struct path old_path = nd->path; |
1060 | struct qstr last = nd->last; | 1071 | struct qstr last = nd->last; |
1061 | int last_type = nd->last_type; | 1072 | int last_type = nd->last_type; |
1062 | struct fs_struct *fs = current->fs; | 1073 | struct fs_struct *fs = current->fs; |
@@ -1067,19 +1078,17 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd) | |||
1067 | */ | 1078 | */ |
1068 | nd->last_type = LAST_ROOT; | 1079 | nd->last_type = LAST_ROOT; |
1069 | read_lock(&fs->lock); | 1080 | read_lock(&fs->lock); |
1070 | nd->mnt = mntget(fs->rootmnt); | 1081 | nd->path = fs->root; |
1071 | nd->dentry = dget(fs->root); | 1082 | path_get(&fs->root); |
1072 | read_unlock(&fs->lock); | 1083 | read_unlock(&fs->lock); |
1073 | if (path_walk(name, nd) == 0) { | 1084 | if (path_walk(name, nd) == 0) { |
1074 | if (nd->dentry->d_inode) { | 1085 | if (nd->path.dentry->d_inode) { |
1075 | dput(old_dentry); | 1086 | path_put(&old_path); |
1076 | mntput(old_mnt); | ||
1077 | return 1; | 1087 | return 1; |
1078 | } | 1088 | } |
1079 | path_release(nd); | 1089 | path_put(&nd->path); |
1080 | } | 1090 | } |
1081 | nd->dentry = old_dentry; | 1091 | nd->path = old_path; |
1082 | nd->mnt = old_mnt; | ||
1083 | nd->last = last; | 1092 | nd->last = last; |
1084 | nd->last_type = last_type; | 1093 | nd->last_type = last_type; |
1085 | } | 1094 | } |
@@ -1090,33 +1099,26 @@ void set_fs_altroot(void) | |||
1090 | { | 1099 | { |
1091 | char *emul = __emul_prefix(); | 1100 | char *emul = __emul_prefix(); |
1092 | struct nameidata nd; | 1101 | struct nameidata nd; |
1093 | struct vfsmount *mnt = NULL, *oldmnt; | 1102 | struct path path = {}, old_path; |
1094 | struct dentry *dentry = NULL, *olddentry; | ||
1095 | int err; | 1103 | int err; |
1096 | struct fs_struct *fs = current->fs; | 1104 | struct fs_struct *fs = current->fs; |
1097 | 1105 | ||
1098 | if (!emul) | 1106 | if (!emul) |
1099 | goto set_it; | 1107 | goto set_it; |
1100 | err = path_lookup(emul, LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_NOALT, &nd); | 1108 | err = path_lookup(emul, LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_NOALT, &nd); |
1101 | if (!err) { | 1109 | if (!err) |
1102 | mnt = nd.mnt; | 1110 | path = nd.path; |
1103 | dentry = nd.dentry; | ||
1104 | } | ||
1105 | set_it: | 1111 | set_it: |
1106 | write_lock(&fs->lock); | 1112 | write_lock(&fs->lock); |
1107 | oldmnt = fs->altrootmnt; | 1113 | old_path = fs->altroot; |
1108 | olddentry = fs->altroot; | 1114 | fs->altroot = path; |
1109 | fs->altrootmnt = mnt; | ||
1110 | fs->altroot = dentry; | ||
1111 | write_unlock(&fs->lock); | 1115 | write_unlock(&fs->lock); |
1112 | if (olddentry) { | 1116 | if (old_path.dentry) |
1113 | dput(olddentry); | 1117 | path_put(&old_path); |
1114 | mntput(oldmnt); | ||
1115 | } | ||
1116 | } | 1118 | } |
1117 | 1119 | ||
1118 | /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ | 1120 | /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ |
1119 | static int fastcall do_path_lookup(int dfd, const char *name, | 1121 | static int do_path_lookup(int dfd, const char *name, |
1120 | unsigned int flags, struct nameidata *nd) | 1122 | unsigned int flags, struct nameidata *nd) |
1121 | { | 1123 | { |
1122 | int retval = 0; | 1124 | int retval = 0; |
@@ -1130,21 +1132,21 @@ static int fastcall do_path_lookup(int dfd, const char *name, | |||
1130 | 1132 | ||
1131 | if (*name=='/') { | 1133 | if (*name=='/') { |
1132 | read_lock(&fs->lock); | 1134 | read_lock(&fs->lock); |
1133 | if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) { | 1135 | if (fs->altroot.dentry && !(nd->flags & LOOKUP_NOALT)) { |
1134 | nd->mnt = mntget(fs->altrootmnt); | 1136 | nd->path = fs->altroot; |
1135 | nd->dentry = dget(fs->altroot); | 1137 | path_get(&fs->altroot); |
1136 | read_unlock(&fs->lock); | 1138 | read_unlock(&fs->lock); |
1137 | if (__emul_lookup_dentry(name,nd)) | 1139 | if (__emul_lookup_dentry(name,nd)) |
1138 | goto out; /* found in altroot */ | 1140 | goto out; /* found in altroot */ |
1139 | read_lock(&fs->lock); | 1141 | read_lock(&fs->lock); |
1140 | } | 1142 | } |
1141 | nd->mnt = mntget(fs->rootmnt); | 1143 | nd->path = fs->root; |
1142 | nd->dentry = dget(fs->root); | 1144 | path_get(&fs->root); |
1143 | read_unlock(&fs->lock); | 1145 | read_unlock(&fs->lock); |
1144 | } else if (dfd == AT_FDCWD) { | 1146 | } else if (dfd == AT_FDCWD) { |
1145 | read_lock(&fs->lock); | 1147 | read_lock(&fs->lock); |
1146 | nd->mnt = mntget(fs->pwdmnt); | 1148 | nd->path = fs->pwd; |
1147 | nd->dentry = dget(fs->pwd); | 1149 | path_get(&fs->pwd); |
1148 | read_unlock(&fs->lock); | 1150 | read_unlock(&fs->lock); |
1149 | } else { | 1151 | } else { |
1150 | struct dentry *dentry; | 1152 | struct dentry *dentry; |
@@ -1164,17 +1166,17 @@ static int fastcall do_path_lookup(int dfd, const char *name, | |||
1164 | if (retval) | 1166 | if (retval) |
1165 | goto fput_fail; | 1167 | goto fput_fail; |
1166 | 1168 | ||
1167 | nd->mnt = mntget(file->f_path.mnt); | 1169 | nd->path = file->f_path; |
1168 | nd->dentry = dget(dentry); | 1170 | path_get(&file->f_path); |
1169 | 1171 | ||
1170 | fput_light(file, fput_needed); | 1172 | fput_light(file, fput_needed); |
1171 | } | 1173 | } |
1172 | 1174 | ||
1173 | retval = path_walk(name, nd); | 1175 | retval = path_walk(name, nd); |
1174 | out: | 1176 | out: |
1175 | if (unlikely(!retval && !audit_dummy_context() && nd->dentry && | 1177 | if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry && |
1176 | nd->dentry->d_inode)) | 1178 | nd->path.dentry->d_inode)) |
1177 | audit_inode(name, nd->dentry); | 1179 | audit_inode(name, nd->path.dentry); |
1178 | out_fail: | 1180 | out_fail: |
1179 | return retval; | 1181 | return retval; |
1180 | 1182 | ||
@@ -1183,7 +1185,7 @@ fput_fail: | |||
1183 | goto out_fail; | 1185 | goto out_fail; |
1184 | } | 1186 | } |
1185 | 1187 | ||
1186 | int fastcall path_lookup(const char *name, unsigned int flags, | 1188 | int path_lookup(const char *name, unsigned int flags, |
1187 | struct nameidata *nd) | 1189 | struct nameidata *nd) |
1188 | { | 1190 | { |
1189 | return do_path_lookup(AT_FDCWD, name, flags, nd); | 1191 | return do_path_lookup(AT_FDCWD, name, flags, nd); |
@@ -1208,13 +1210,13 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, | |||
1208 | nd->flags = flags; | 1210 | nd->flags = flags; |
1209 | nd->depth = 0; | 1211 | nd->depth = 0; |
1210 | 1212 | ||
1211 | nd->mnt = mntget(mnt); | 1213 | nd->path.mnt = mntget(mnt); |
1212 | nd->dentry = dget(dentry); | 1214 | nd->path.dentry = dget(dentry); |
1213 | 1215 | ||
1214 | retval = path_walk(name, nd); | 1216 | retval = path_walk(name, nd); |
1215 | if (unlikely(!retval && !audit_dummy_context() && nd->dentry && | 1217 | if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry && |
1216 | nd->dentry->d_inode)) | 1218 | nd->path.dentry->d_inode)) |
1217 | audit_inode(name, nd->dentry); | 1219 | audit_inode(name, nd->path.dentry); |
1218 | 1220 | ||
1219 | return retval; | 1221 | return retval; |
1220 | 1222 | ||
@@ -1236,7 +1238,7 @@ static int __path_lookup_intent_open(int dfd, const char *name, | |||
1236 | if (IS_ERR(nd->intent.open.file)) { | 1238 | if (IS_ERR(nd->intent.open.file)) { |
1237 | if (err == 0) { | 1239 | if (err == 0) { |
1238 | err = PTR_ERR(nd->intent.open.file); | 1240 | err = PTR_ERR(nd->intent.open.file); |
1239 | path_release(nd); | 1241 | path_put(&nd->path); |
1240 | } | 1242 | } |
1241 | } else if (err != 0) | 1243 | } else if (err != 0) |
1242 | release_open_intent(nd); | 1244 | release_open_intent(nd); |
@@ -1333,10 +1335,10 @@ static struct dentry *lookup_hash(struct nameidata *nd) | |||
1333 | { | 1335 | { |
1334 | int err; | 1336 | int err; |
1335 | 1337 | ||
1336 | err = permission(nd->dentry->d_inode, MAY_EXEC, nd); | 1338 | err = permission(nd->path.dentry->d_inode, MAY_EXEC, nd); |
1337 | if (err) | 1339 | if (err) |
1338 | return ERR_PTR(err); | 1340 | return ERR_PTR(err); |
1339 | return __lookup_hash(&nd->last, nd->dentry, nd); | 1341 | return __lookup_hash(&nd->last, nd->path.dentry, nd); |
1340 | } | 1342 | } |
1341 | 1343 | ||
1342 | static int __lookup_one_len(const char *name, struct qstr *this, | 1344 | static int __lookup_one_len(const char *name, struct qstr *this, |
@@ -1409,7 +1411,7 @@ struct dentry *lookup_one_noperm(const char *name, struct dentry *base) | |||
1409 | return __lookup_hash(&this, base, NULL); | 1411 | return __lookup_hash(&this, base, NULL); |
1410 | } | 1412 | } |
1411 | 1413 | ||
1412 | int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags, | 1414 | int __user_walk_fd(int dfd, const char __user *name, unsigned flags, |
1413 | struct nameidata *nd) | 1415 | struct nameidata *nd) |
1414 | { | 1416 | { |
1415 | char *tmp = getname(name); | 1417 | char *tmp = getname(name); |
@@ -1422,7 +1424,7 @@ int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags, | |||
1422 | return err; | 1424 | return err; |
1423 | } | 1425 | } |
1424 | 1426 | ||
1425 | int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd) | 1427 | int __user_walk(const char __user *name, unsigned flags, struct nameidata *nd) |
1426 | { | 1428 | { |
1427 | return __user_walk_fd(AT_FDCWD, name, flags, nd); | 1429 | return __user_walk_fd(AT_FDCWD, name, flags, nd); |
1428 | } | 1430 | } |
@@ -1595,7 +1597,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
1595 | 1597 | ||
1596 | int may_open(struct nameidata *nd, int acc_mode, int flag) | 1598 | int may_open(struct nameidata *nd, int acc_mode, int flag) |
1597 | { | 1599 | { |
1598 | struct dentry *dentry = nd->dentry; | 1600 | struct dentry *dentry = nd->path.dentry; |
1599 | struct inode *inode = dentry->d_inode; | 1601 | struct inode *inode = dentry->d_inode; |
1600 | int error; | 1602 | int error; |
1601 | 1603 | ||
@@ -1616,7 +1618,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) | |||
1616 | if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { | 1618 | if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { |
1617 | flag &= ~O_TRUNC; | 1619 | flag &= ~O_TRUNC; |
1618 | } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { | 1620 | } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { |
1619 | if (nd->mnt->mnt_flags & MNT_NODEV) | 1621 | if (nd->path.mnt->mnt_flags & MNT_NODEV) |
1620 | return -EACCES; | 1622 | return -EACCES; |
1621 | 1623 | ||
1622 | flag &= ~O_TRUNC; | 1624 | flag &= ~O_TRUNC; |
@@ -1678,14 +1680,14 @@ static int open_namei_create(struct nameidata *nd, struct path *path, | |||
1678 | int flag, int mode) | 1680 | int flag, int mode) |
1679 | { | 1681 | { |
1680 | int error; | 1682 | int error; |
1681 | struct dentry *dir = nd->dentry; | 1683 | struct dentry *dir = nd->path.dentry; |
1682 | 1684 | ||
1683 | if (!IS_POSIXACL(dir->d_inode)) | 1685 | if (!IS_POSIXACL(dir->d_inode)) |
1684 | mode &= ~current->fs->umask; | 1686 | mode &= ~current->fs->umask; |
1685 | error = vfs_create(dir->d_inode, path->dentry, mode, nd); | 1687 | error = vfs_create(dir->d_inode, path->dentry, mode, nd); |
1686 | mutex_unlock(&dir->d_inode->i_mutex); | 1688 | mutex_unlock(&dir->d_inode->i_mutex); |
1687 | dput(nd->dentry); | 1689 | dput(nd->path.dentry); |
1688 | nd->dentry = path->dentry; | 1690 | nd->path.dentry = path->dentry; |
1689 | if (error) | 1691 | if (error) |
1690 | return error; | 1692 | return error; |
1691 | /* Don't check for write permission, don't truncate */ | 1693 | /* Don't check for write permission, don't truncate */ |
@@ -1752,11 +1754,11 @@ int open_namei(int dfd, const char *pathname, int flag, | |||
1752 | if (nd->last_type != LAST_NORM || nd->last.name[nd->last.len]) | 1754 | if (nd->last_type != LAST_NORM || nd->last.name[nd->last.len]) |
1753 | goto exit; | 1755 | goto exit; |
1754 | 1756 | ||
1755 | dir = nd->dentry; | 1757 | dir = nd->path.dentry; |
1756 | nd->flags &= ~LOOKUP_PARENT; | 1758 | nd->flags &= ~LOOKUP_PARENT; |
1757 | mutex_lock(&dir->d_inode->i_mutex); | 1759 | mutex_lock(&dir->d_inode->i_mutex); |
1758 | path.dentry = lookup_hash(nd); | 1760 | path.dentry = lookup_hash(nd); |
1759 | path.mnt = nd->mnt; | 1761 | path.mnt = nd->path.mnt; |
1760 | 1762 | ||
1761 | do_last: | 1763 | do_last: |
1762 | error = PTR_ERR(path.dentry); | 1764 | error = PTR_ERR(path.dentry); |
@@ -1812,11 +1814,11 @@ ok: | |||
1812 | return 0; | 1814 | return 0; |
1813 | 1815 | ||
1814 | exit_dput: | 1816 | exit_dput: |
1815 | dput_path(&path, nd); | 1817 | path_put_conditional(&path, nd); |
1816 | exit: | 1818 | exit: |
1817 | if (!IS_ERR(nd->intent.open.file)) | 1819 | if (!IS_ERR(nd->intent.open.file)) |
1818 | release_open_intent(nd); | 1820 | release_open_intent(nd); |
1819 | path_release(nd); | 1821 | path_put(&nd->path); |
1820 | return error; | 1822 | return error; |
1821 | 1823 | ||
1822 | do_link: | 1824 | do_link: |
@@ -1861,10 +1863,10 @@ do_link: | |||
1861 | __putname(nd->last.name); | 1863 | __putname(nd->last.name); |
1862 | goto exit; | 1864 | goto exit; |
1863 | } | 1865 | } |
1864 | dir = nd->dentry; | 1866 | dir = nd->path.dentry; |
1865 | mutex_lock(&dir->d_inode->i_mutex); | 1867 | mutex_lock(&dir->d_inode->i_mutex); |
1866 | path.dentry = lookup_hash(nd); | 1868 | path.dentry = lookup_hash(nd); |
1867 | path.mnt = nd->mnt; | 1869 | path.mnt = nd->path.mnt; |
1868 | __putname(nd->last.name); | 1870 | __putname(nd->last.name); |
1869 | goto do_last; | 1871 | goto do_last; |
1870 | } | 1872 | } |
@@ -1877,13 +1879,13 @@ do_link: | |||
1877 | * Simple function to lookup and return a dentry and create it | 1879 | * Simple function to lookup and return a dentry and create it |
1878 | * if it doesn't exist. Is SMP-safe. | 1880 | * if it doesn't exist. Is SMP-safe. |
1879 | * | 1881 | * |
1880 | * Returns with nd->dentry->d_inode->i_mutex locked. | 1882 | * Returns with nd->path.dentry->d_inode->i_mutex locked. |
1881 | */ | 1883 | */ |
1882 | struct dentry *lookup_create(struct nameidata *nd, int is_dir) | 1884 | struct dentry *lookup_create(struct nameidata *nd, int is_dir) |
1883 | { | 1885 | { |
1884 | struct dentry *dentry = ERR_PTR(-EEXIST); | 1886 | struct dentry *dentry = ERR_PTR(-EEXIST); |
1885 | 1887 | ||
1886 | mutex_lock_nested(&nd->dentry->d_inode->i_mutex, I_MUTEX_PARENT); | 1888 | mutex_lock_nested(&nd->path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); |
1887 | /* | 1889 | /* |
1888 | * Yucky last component or no last component at all? | 1890 | * Yucky last component or no last component at all? |
1889 | * (foo/., foo/.., /////) | 1891 | * (foo/., foo/.., /////) |
@@ -1962,19 +1964,19 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
1962 | dentry = lookup_create(&nd, 0); | 1964 | dentry = lookup_create(&nd, 0); |
1963 | error = PTR_ERR(dentry); | 1965 | error = PTR_ERR(dentry); |
1964 | 1966 | ||
1965 | if (!IS_POSIXACL(nd.dentry->d_inode)) | 1967 | if (!IS_POSIXACL(nd.path.dentry->d_inode)) |
1966 | mode &= ~current->fs->umask; | 1968 | mode &= ~current->fs->umask; |
1967 | if (!IS_ERR(dentry)) { | 1969 | if (!IS_ERR(dentry)) { |
1968 | switch (mode & S_IFMT) { | 1970 | switch (mode & S_IFMT) { |
1969 | case 0: case S_IFREG: | 1971 | case 0: case S_IFREG: |
1970 | error = vfs_create(nd.dentry->d_inode,dentry,mode,&nd); | 1972 | error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); |
1971 | break; | 1973 | break; |
1972 | case S_IFCHR: case S_IFBLK: | 1974 | case S_IFCHR: case S_IFBLK: |
1973 | error = vfs_mknod(nd.dentry->d_inode,dentry,mode, | 1975 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode, |
1974 | new_decode_dev(dev)); | 1976 | new_decode_dev(dev)); |
1975 | break; | 1977 | break; |
1976 | case S_IFIFO: case S_IFSOCK: | 1978 | case S_IFIFO: case S_IFSOCK: |
1977 | error = vfs_mknod(nd.dentry->d_inode,dentry,mode,0); | 1979 | error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); |
1978 | break; | 1980 | break; |
1979 | case S_IFDIR: | 1981 | case S_IFDIR: |
1980 | error = -EPERM; | 1982 | error = -EPERM; |
@@ -1984,8 +1986,8 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, | |||
1984 | } | 1986 | } |
1985 | dput(dentry); | 1987 | dput(dentry); |
1986 | } | 1988 | } |
1987 | mutex_unlock(&nd.dentry->d_inode->i_mutex); | 1989 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
1988 | path_release(&nd); | 1990 | path_put(&nd.path); |
1989 | out: | 1991 | out: |
1990 | putname(tmp); | 1992 | putname(tmp); |
1991 | 1993 | ||
@@ -2039,13 +2041,13 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode) | |||
2039 | if (IS_ERR(dentry)) | 2041 | if (IS_ERR(dentry)) |
2040 | goto out_unlock; | 2042 | goto out_unlock; |
2041 | 2043 | ||
2042 | if (!IS_POSIXACL(nd.dentry->d_inode)) | 2044 | if (!IS_POSIXACL(nd.path.dentry->d_inode)) |
2043 | mode &= ~current->fs->umask; | 2045 | mode &= ~current->fs->umask; |
2044 | error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); | 2046 | error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); |
2045 | dput(dentry); | 2047 | dput(dentry); |
2046 | out_unlock: | 2048 | out_unlock: |
2047 | mutex_unlock(&nd.dentry->d_inode->i_mutex); | 2049 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
2048 | path_release(&nd); | 2050 | path_put(&nd.path); |
2049 | out: | 2051 | out: |
2050 | putname(tmp); | 2052 | putname(tmp); |
2051 | out_err: | 2053 | out_err: |
@@ -2143,17 +2145,17 @@ static long do_rmdir(int dfd, const char __user *pathname) | |||
2143 | error = -EBUSY; | 2145 | error = -EBUSY; |
2144 | goto exit1; | 2146 | goto exit1; |
2145 | } | 2147 | } |
2146 | mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT); | 2148 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); |
2147 | dentry = lookup_hash(&nd); | 2149 | dentry = lookup_hash(&nd); |
2148 | error = PTR_ERR(dentry); | 2150 | error = PTR_ERR(dentry); |
2149 | if (IS_ERR(dentry)) | 2151 | if (IS_ERR(dentry)) |
2150 | goto exit2; | 2152 | goto exit2; |
2151 | error = vfs_rmdir(nd.dentry->d_inode, dentry); | 2153 | error = vfs_rmdir(nd.path.dentry->d_inode, dentry); |
2152 | dput(dentry); | 2154 | dput(dentry); |
2153 | exit2: | 2155 | exit2: |
2154 | mutex_unlock(&nd.dentry->d_inode->i_mutex); | 2156 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
2155 | exit1: | 2157 | exit1: |
2156 | path_release(&nd); | 2158 | path_put(&nd.path); |
2157 | exit: | 2159 | exit: |
2158 | putname(name); | 2160 | putname(name); |
2159 | return error; | 2161 | return error; |
@@ -2188,6 +2190,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) | |||
2188 | 2190 | ||
2189 | /* We don't d_delete() NFS sillyrenamed files--they still exist. */ | 2191 | /* We don't d_delete() NFS sillyrenamed files--they still exist. */ |
2190 | if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { | 2192 | if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { |
2193 | fsnotify_link_count(dentry->d_inode); | ||
2191 | d_delete(dentry); | 2194 | d_delete(dentry); |
2192 | } | 2195 | } |
2193 | 2196 | ||
@@ -2218,7 +2221,7 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
2218 | error = -EISDIR; | 2221 | error = -EISDIR; |
2219 | if (nd.last_type != LAST_NORM) | 2222 | if (nd.last_type != LAST_NORM) |
2220 | goto exit1; | 2223 | goto exit1; |
2221 | mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT); | 2224 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); |
2222 | dentry = lookup_hash(&nd); | 2225 | dentry = lookup_hash(&nd); |
2223 | error = PTR_ERR(dentry); | 2226 | error = PTR_ERR(dentry); |
2224 | if (!IS_ERR(dentry)) { | 2227 | if (!IS_ERR(dentry)) { |
@@ -2228,15 +2231,15 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
2228 | inode = dentry->d_inode; | 2231 | inode = dentry->d_inode; |
2229 | if (inode) | 2232 | if (inode) |
2230 | atomic_inc(&inode->i_count); | 2233 | atomic_inc(&inode->i_count); |
2231 | error = vfs_unlink(nd.dentry->d_inode, dentry); | 2234 | error = vfs_unlink(nd.path.dentry->d_inode, dentry); |
2232 | exit2: | 2235 | exit2: |
2233 | dput(dentry); | 2236 | dput(dentry); |
2234 | } | 2237 | } |
2235 | mutex_unlock(&nd.dentry->d_inode->i_mutex); | 2238 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
2236 | if (inode) | 2239 | if (inode) |
2237 | iput(inode); /* truncate the inode here */ | 2240 | iput(inode); /* truncate the inode here */ |
2238 | exit1: | 2241 | exit1: |
2239 | path_release(&nd); | 2242 | path_put(&nd.path); |
2240 | exit: | 2243 | exit: |
2241 | putname(name); | 2244 | putname(name); |
2242 | return error; | 2245 | return error; |
@@ -2309,11 +2312,11 @@ asmlinkage long sys_symlinkat(const char __user *oldname, | |||
2309 | if (IS_ERR(dentry)) | 2312 | if (IS_ERR(dentry)) |
2310 | goto out_unlock; | 2313 | goto out_unlock; |
2311 | 2314 | ||
2312 | error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO); | 2315 | error = vfs_symlink(nd.path.dentry->d_inode, dentry, from, S_IALLUGO); |
2313 | dput(dentry); | 2316 | dput(dentry); |
2314 | out_unlock: | 2317 | out_unlock: |
2315 | mutex_unlock(&nd.dentry->d_inode->i_mutex); | 2318 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
2316 | path_release(&nd); | 2319 | path_put(&nd.path); |
2317 | out: | 2320 | out: |
2318 | putname(to); | 2321 | putname(to); |
2319 | out_putname: | 2322 | out_putname: |
@@ -2360,7 +2363,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de | |||
2360 | error = dir->i_op->link(old_dentry, dir, new_dentry); | 2363 | error = dir->i_op->link(old_dentry, dir, new_dentry); |
2361 | mutex_unlock(&old_dentry->d_inode->i_mutex); | 2364 | mutex_unlock(&old_dentry->d_inode->i_mutex); |
2362 | if (!error) | 2365 | if (!error) |
2363 | fsnotify_create(dir, new_dentry); | 2366 | fsnotify_link(dir, old_dentry->d_inode, new_dentry); |
2364 | return error; | 2367 | return error; |
2365 | } | 2368 | } |
2366 | 2369 | ||
@@ -2398,20 +2401,20 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname, | |||
2398 | if (error) | 2401 | if (error) |
2399 | goto out; | 2402 | goto out; |
2400 | error = -EXDEV; | 2403 | error = -EXDEV; |
2401 | if (old_nd.mnt != nd.mnt) | 2404 | if (old_nd.path.mnt != nd.path.mnt) |
2402 | goto out_release; | 2405 | goto out_release; |
2403 | new_dentry = lookup_create(&nd, 0); | 2406 | new_dentry = lookup_create(&nd, 0); |
2404 | error = PTR_ERR(new_dentry); | 2407 | error = PTR_ERR(new_dentry); |
2405 | if (IS_ERR(new_dentry)) | 2408 | if (IS_ERR(new_dentry)) |
2406 | goto out_unlock; | 2409 | goto out_unlock; |
2407 | error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); | 2410 | error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, new_dentry); |
2408 | dput(new_dentry); | 2411 | dput(new_dentry); |
2409 | out_unlock: | 2412 | out_unlock: |
2410 | mutex_unlock(&nd.dentry->d_inode->i_mutex); | 2413 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
2411 | out_release: | 2414 | out_release: |
2412 | path_release(&nd); | 2415 | path_put(&nd.path); |
2413 | out: | 2416 | out: |
2414 | path_release(&old_nd); | 2417 | path_put(&old_nd.path); |
2415 | exit: | 2418 | exit: |
2416 | putname(to); | 2419 | putname(to); |
2417 | 2420 | ||
@@ -2587,15 +2590,15 @@ static int do_rename(int olddfd, const char *oldname, | |||
2587 | goto exit1; | 2590 | goto exit1; |
2588 | 2591 | ||
2589 | error = -EXDEV; | 2592 | error = -EXDEV; |
2590 | if (oldnd.mnt != newnd.mnt) | 2593 | if (oldnd.path.mnt != newnd.path.mnt) |
2591 | goto exit2; | 2594 | goto exit2; |
2592 | 2595 | ||
2593 | old_dir = oldnd.dentry; | 2596 | old_dir = oldnd.path.dentry; |
2594 | error = -EBUSY; | 2597 | error = -EBUSY; |
2595 | if (oldnd.last_type != LAST_NORM) | 2598 | if (oldnd.last_type != LAST_NORM) |
2596 | goto exit2; | 2599 | goto exit2; |
2597 | 2600 | ||
2598 | new_dir = newnd.dentry; | 2601 | new_dir = newnd.path.dentry; |
2599 | if (newnd.last_type != LAST_NORM) | 2602 | if (newnd.last_type != LAST_NORM) |
2600 | goto exit2; | 2603 | goto exit2; |
2601 | 2604 | ||
@@ -2639,9 +2642,9 @@ exit4: | |||
2639 | exit3: | 2642 | exit3: |
2640 | unlock_rename(new_dir, old_dir); | 2643 | unlock_rename(new_dir, old_dir); |
2641 | exit2: | 2644 | exit2: |
2642 | path_release(&newnd); | 2645 | path_put(&newnd.path); |
2643 | exit1: | 2646 | exit1: |
2644 | path_release(&oldnd); | 2647 | path_put(&oldnd.path); |
2645 | exit: | 2648 | exit: |
2646 | return error; | 2649 | return error; |
2647 | } | 2650 | } |
@@ -2815,7 +2818,6 @@ EXPORT_SYMBOL(page_symlink); | |||
2815 | EXPORT_SYMBOL(page_symlink_inode_operations); | 2818 | EXPORT_SYMBOL(page_symlink_inode_operations); |
2816 | EXPORT_SYMBOL(path_lookup); | 2819 | EXPORT_SYMBOL(path_lookup); |
2817 | EXPORT_SYMBOL(vfs_path_lookup); | 2820 | EXPORT_SYMBOL(vfs_path_lookup); |
2818 | EXPORT_SYMBOL(path_release); | ||
2819 | EXPORT_SYMBOL(permission); | 2821 | EXPORT_SYMBOL(permission); |
2820 | EXPORT_SYMBOL(vfs_permission); | 2822 | EXPORT_SYMBOL(vfs_permission); |
2821 | EXPORT_SYMBOL(file_permission); | 2823 | EXPORT_SYMBOL(file_permission); |