diff options
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r-- | fs/nfs/dir.c | 263 |
1 files changed, 95 insertions, 168 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e4a04d16b8b0..8ec7fbd8240c 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -200,9 +200,6 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) | |||
200 | desc->timestamp = timestamp; | 200 | desc->timestamp = timestamp; |
201 | desc->timestamp_valid = 1; | 201 | desc->timestamp_valid = 1; |
202 | SetPageUptodate(page); | 202 | SetPageUptodate(page); |
203 | spin_lock(&inode->i_lock); | ||
204 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME; | ||
205 | spin_unlock(&inode->i_lock); | ||
206 | /* Ensure consistent page alignment of the data. | 203 | /* Ensure consistent page alignment of the data. |
207 | * Note: assumes we have exclusive access to this mapping either | 204 | * Note: assumes we have exclusive access to this mapping either |
208 | * through inode->i_mutex or some other mechanism. | 205 | * through inode->i_mutex or some other mechanism. |
@@ -214,9 +211,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) | |||
214 | unlock_page(page); | 211 | unlock_page(page); |
215 | return 0; | 212 | return 0; |
216 | error: | 213 | error: |
217 | SetPageError(page); | ||
218 | unlock_page(page); | 214 | unlock_page(page); |
219 | nfs_zap_caches(inode); | ||
220 | desc->error = error; | 215 | desc->error = error; |
221 | return -EIO; | 216 | return -EIO; |
222 | } | 217 | } |
@@ -407,7 +402,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
407 | struct file *file = desc->file; | 402 | struct file *file = desc->file; |
408 | struct nfs_entry *entry = desc->entry; | 403 | struct nfs_entry *entry = desc->entry; |
409 | struct dentry *dentry = NULL; | 404 | struct dentry *dentry = NULL; |
410 | unsigned long fileid; | 405 | u64 fileid; |
411 | int loop_count = 0, | 406 | int loop_count = 0, |
412 | res; | 407 | res; |
413 | 408 | ||
@@ -418,7 +413,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
418 | unsigned d_type = DT_UNKNOWN; | 413 | unsigned d_type = DT_UNKNOWN; |
419 | /* Note: entry->prev_cookie contains the cookie for | 414 | /* Note: entry->prev_cookie contains the cookie for |
420 | * retrieving the current dirent on the server */ | 415 | * retrieving the current dirent on the server */ |
421 | fileid = nfs_fileid_to_ino_t(entry->ino); | 416 | fileid = entry->ino; |
422 | 417 | ||
423 | /* Get a dentry if we have one */ | 418 | /* Get a dentry if we have one */ |
424 | if (dentry != NULL) | 419 | if (dentry != NULL) |
@@ -428,11 +423,12 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
428 | /* Use readdirplus info */ | 423 | /* Use readdirplus info */ |
429 | if (dentry != NULL && dentry->d_inode != NULL) { | 424 | if (dentry != NULL && dentry->d_inode != NULL) { |
430 | d_type = dt_type(dentry->d_inode); | 425 | d_type = dt_type(dentry->d_inode); |
431 | fileid = dentry->d_inode->i_ino; | 426 | fileid = NFS_FILEID(dentry->d_inode); |
432 | } | 427 | } |
433 | 428 | ||
434 | res = filldir(dirent, entry->name, entry->len, | 429 | res = filldir(dirent, entry->name, entry->len, |
435 | file->f_pos, fileid, d_type); | 430 | file->f_pos, nfs_compat_user_ino64(fileid), |
431 | d_type); | ||
436 | if (res < 0) | 432 | if (res < 0) |
437 | break; | 433 | break; |
438 | file->f_pos++; | 434 | file->f_pos++; |
@@ -490,9 +486,6 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
490 | page, | 486 | page, |
491 | NFS_SERVER(inode)->dtsize, | 487 | NFS_SERVER(inode)->dtsize, |
492 | desc->plus); | 488 | desc->plus); |
493 | spin_lock(&inode->i_lock); | ||
494 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME; | ||
495 | spin_unlock(&inode->i_lock); | ||
496 | desc->page = page; | 489 | desc->page = page; |
497 | desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ | 490 | desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ |
498 | if (desc->error >= 0) { | 491 | if (desc->error >= 0) { |
@@ -558,7 +551,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
558 | memset(desc, 0, sizeof(*desc)); | 551 | memset(desc, 0, sizeof(*desc)); |
559 | 552 | ||
560 | desc->file = filp; | 553 | desc->file = filp; |
561 | desc->dir_cookie = &((struct nfs_open_context *)filp->private_data)->dir_cookie; | 554 | desc->dir_cookie = &nfs_file_open_context(filp)->dir_cookie; |
562 | desc->decode = NFS_PROTO(inode)->decode_dirent; | 555 | desc->decode = NFS_PROTO(inode)->decode_dirent; |
563 | desc->plus = NFS_USE_READDIRPLUS(inode); | 556 | desc->plus = NFS_USE_READDIRPLUS(inode); |
564 | 557 | ||
@@ -623,7 +616,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) | |||
623 | } | 616 | } |
624 | if (offset != filp->f_pos) { | 617 | if (offset != filp->f_pos) { |
625 | filp->f_pos = offset; | 618 | filp->f_pos = offset; |
626 | ((struct nfs_open_context *)filp->private_data)->dir_cookie = 0; | 619 | nfs_file_open_context(filp)->dir_cookie = 0; |
627 | } | 620 | } |
628 | out: | 621 | out: |
629 | mutex_unlock(&filp->f_path.dentry->d_inode->i_mutex); | 622 | mutex_unlock(&filp->f_path.dentry->d_inode->i_mutex); |
@@ -650,36 +643,18 @@ static int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync) | |||
650 | */ | 643 | */ |
651 | static int nfs_check_verifier(struct inode *dir, struct dentry *dentry) | 644 | static int nfs_check_verifier(struct inode *dir, struct dentry *dentry) |
652 | { | 645 | { |
653 | unsigned long verf; | ||
654 | |||
655 | if (IS_ROOT(dentry)) | 646 | if (IS_ROOT(dentry)) |
656 | return 1; | 647 | return 1; |
657 | verf = dentry->d_time; | 648 | if (!nfs_verify_change_attribute(dir, dentry->d_time)) |
658 | if (nfs_caches_unstable(dir) | 649 | return 0; |
659 | || verf != NFS_I(dir)->cache_change_attribute) | 650 | /* Revalidate nfsi->cache_change_attribute before we declare a match */ |
651 | if (nfs_revalidate_inode(NFS_SERVER(dir), dir) < 0) | ||
652 | return 0; | ||
653 | if (!nfs_verify_change_attribute(dir, dentry->d_time)) | ||
660 | return 0; | 654 | return 0; |
661 | return 1; | 655 | return 1; |
662 | } | 656 | } |
663 | 657 | ||
664 | static inline void nfs_set_verifier(struct dentry * dentry, unsigned long verf) | ||
665 | { | ||
666 | dentry->d_time = verf; | ||
667 | } | ||
668 | |||
669 | static void nfs_refresh_verifier(struct dentry * dentry, unsigned long verf) | ||
670 | { | ||
671 | nfs_set_verifier(dentry, verf); | ||
672 | } | ||
673 | |||
674 | /* | ||
675 | * Whenever an NFS operation succeeds, we know that the dentry | ||
676 | * is valid, so we update the revalidation timestamp. | ||
677 | */ | ||
678 | static inline void nfs_renew_times(struct dentry * dentry) | ||
679 | { | ||
680 | dentry->d_time = jiffies; | ||
681 | } | ||
682 | |||
683 | /* | 658 | /* |
684 | * Return the intent data that applies to this particular path component | 659 | * Return the intent data that applies to this particular path component |
685 | * | 660 | * |
@@ -695,6 +670,19 @@ static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigne | |||
695 | } | 670 | } |
696 | 671 | ||
697 | /* | 672 | /* |
673 | * Use intent information to check whether or not we're going to do | ||
674 | * an O_EXCL create using this path component. | ||
675 | */ | ||
676 | static int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) | ||
677 | { | ||
678 | if (NFS_PROTO(dir)->version == 2) | ||
679 | return 0; | ||
680 | if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0) | ||
681 | return 0; | ||
682 | return (nd->intent.open.flags & O_EXCL) != 0; | ||
683 | } | ||
684 | |||
685 | /* | ||
698 | * Inode and filehandle revalidation for lookups. | 686 | * Inode and filehandle revalidation for lookups. |
699 | * | 687 | * |
700 | * We force revalidation in the cases where the VFS sets LOOKUP_REVAL, | 688 | * We force revalidation in the cases where the VFS sets LOOKUP_REVAL, |
@@ -717,6 +705,7 @@ int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) | |||
717 | (S_ISREG(inode->i_mode) || | 705 | (S_ISREG(inode->i_mode) || |
718 | S_ISDIR(inode->i_mode))) | 706 | S_ISDIR(inode->i_mode))) |
719 | goto out_force; | 707 | goto out_force; |
708 | return 0; | ||
720 | } | 709 | } |
721 | return nfs_revalidate_inode(server, inode); | 710 | return nfs_revalidate_inode(server, inode); |
722 | out_force: | 711 | out_force: |
@@ -759,7 +748,6 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
759 | int error; | 748 | int error; |
760 | struct nfs_fh fhandle; | 749 | struct nfs_fh fhandle; |
761 | struct nfs_fattr fattr; | 750 | struct nfs_fattr fattr; |
762 | unsigned long verifier; | ||
763 | 751 | ||
764 | parent = dget_parent(dentry); | 752 | parent = dget_parent(dentry); |
765 | lock_kernel(); | 753 | lock_kernel(); |
@@ -767,10 +755,6 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
767 | nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE); | 755 | nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE); |
768 | inode = dentry->d_inode; | 756 | inode = dentry->d_inode; |
769 | 757 | ||
770 | /* Revalidate parent directory attribute cache */ | ||
771 | if (nfs_revalidate_inode(NFS_SERVER(dir), dir) < 0) | ||
772 | goto out_zap_parent; | ||
773 | |||
774 | if (!inode) { | 758 | if (!inode) { |
775 | if (nfs_neg_need_reval(dir, dentry, nd)) | 759 | if (nfs_neg_need_reval(dir, dentry, nd)) |
776 | goto out_bad; | 760 | goto out_bad; |
@@ -785,7 +769,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
785 | } | 769 | } |
786 | 770 | ||
787 | /* Force a full look up iff the parent directory has changed */ | 771 | /* Force a full look up iff the parent directory has changed */ |
788 | if (nfs_check_verifier(dir, dentry)) { | 772 | if (!nfs_is_exclusive_create(dir, nd) && nfs_check_verifier(dir, dentry)) { |
789 | if (nfs_lookup_verify_inode(inode, nd)) | 773 | if (nfs_lookup_verify_inode(inode, nd)) |
790 | goto out_zap_parent; | 774 | goto out_zap_parent; |
791 | goto out_valid; | 775 | goto out_valid; |
@@ -794,7 +778,6 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
794 | if (NFS_STALE(inode)) | 778 | if (NFS_STALE(inode)) |
795 | goto out_bad; | 779 | goto out_bad; |
796 | 780 | ||
797 | verifier = nfs_save_change_attribute(dir); | ||
798 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); | 781 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); |
799 | if (error) | 782 | if (error) |
800 | goto out_bad; | 783 | goto out_bad; |
@@ -803,8 +786,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
803 | if ((error = nfs_refresh_inode(inode, &fattr)) != 0) | 786 | if ((error = nfs_refresh_inode(inode, &fattr)) != 0) |
804 | goto out_bad; | 787 | goto out_bad; |
805 | 788 | ||
806 | nfs_renew_times(dentry); | 789 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
807 | nfs_refresh_verifier(dentry, verifier); | ||
808 | out_valid: | 790 | out_valid: |
809 | unlock_kernel(); | 791 | unlock_kernel(); |
810 | dput(parent); | 792 | dput(parent); |
@@ -815,7 +797,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
815 | out_zap_parent: | 797 | out_zap_parent: |
816 | nfs_zap_caches(dir); | 798 | nfs_zap_caches(dir); |
817 | out_bad: | 799 | out_bad: |
818 | NFS_CACHEINV(dir); | 800 | nfs_mark_for_revalidate(dir); |
819 | if (inode && S_ISDIR(inode->i_mode)) { | 801 | if (inode && S_ISDIR(inode->i_mode)) { |
820 | /* Purge readdir caches. */ | 802 | /* Purge readdir caches. */ |
821 | nfs_zap_caches(inode); | 803 | nfs_zap_caches(inode); |
@@ -872,8 +854,6 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) | |||
872 | nfs_complete_unlink(dentry, inode); | 854 | nfs_complete_unlink(dentry, inode); |
873 | unlock_kernel(); | 855 | unlock_kernel(); |
874 | } | 856 | } |
875 | /* When creating a negative dentry, we want to renew d_time */ | ||
876 | nfs_renew_times(dentry); | ||
877 | iput(inode); | 857 | iput(inode); |
878 | } | 858 | } |
879 | 859 | ||
@@ -883,30 +863,6 @@ struct dentry_operations nfs_dentry_operations = { | |||
883 | .d_iput = nfs_dentry_iput, | 863 | .d_iput = nfs_dentry_iput, |
884 | }; | 864 | }; |
885 | 865 | ||
886 | /* | ||
887 | * Use intent information to check whether or not we're going to do | ||
888 | * an O_EXCL create using this path component. | ||
889 | */ | ||
890 | static inline | ||
891 | int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) | ||
892 | { | ||
893 | if (NFS_PROTO(dir)->version == 2) | ||
894 | return 0; | ||
895 | if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0) | ||
896 | return 0; | ||
897 | return (nd->intent.open.flags & O_EXCL) != 0; | ||
898 | } | ||
899 | |||
900 | static inline int nfs_reval_fsid(struct inode *dir, const struct nfs_fattr *fattr) | ||
901 | { | ||
902 | struct nfs_server *server = NFS_SERVER(dir); | ||
903 | |||
904 | if (!nfs_fsid_equal(&server->fsid, &fattr->fsid)) | ||
905 | /* Revalidate fsid using the parent directory */ | ||
906 | return __nfs_revalidate_inode(server, dir); | ||
907 | return 0; | ||
908 | } | ||
909 | |||
910 | static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) | 866 | static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) |
911 | { | 867 | { |
912 | struct dentry *res; | 868 | struct dentry *res; |
@@ -945,11 +901,6 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
945 | res = ERR_PTR(error); | 901 | res = ERR_PTR(error); |
946 | goto out_unlock; | 902 | goto out_unlock; |
947 | } | 903 | } |
948 | error = nfs_reval_fsid(dir, &fattr); | ||
949 | if (error < 0) { | ||
950 | res = ERR_PTR(error); | ||
951 | goto out_unlock; | ||
952 | } | ||
953 | inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr); | 904 | inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr); |
954 | res = (struct dentry *)inode; | 905 | res = (struct dentry *)inode; |
955 | if (IS_ERR(res)) | 906 | if (IS_ERR(res)) |
@@ -958,17 +909,10 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
958 | no_entry: | 909 | no_entry: |
959 | res = d_materialise_unique(dentry, inode); | 910 | res = d_materialise_unique(dentry, inode); |
960 | if (res != NULL) { | 911 | if (res != NULL) { |
961 | struct dentry *parent; | ||
962 | if (IS_ERR(res)) | 912 | if (IS_ERR(res)) |
963 | goto out_unlock; | 913 | goto out_unlock; |
964 | /* Was a directory renamed! */ | ||
965 | parent = dget_parent(res); | ||
966 | if (!IS_ROOT(parent)) | ||
967 | nfs_mark_for_revalidate(parent->d_inode); | ||
968 | dput(parent); | ||
969 | dentry = res; | 914 | dentry = res; |
970 | } | 915 | } |
971 | nfs_renew_times(dentry); | ||
972 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 916 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
973 | out_unlock: | 917 | out_unlock: |
974 | unlock_kernel(); | 918 | unlock_kernel(); |
@@ -1020,28 +964,16 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
1020 | } | 964 | } |
1021 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; | 965 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; |
1022 | 966 | ||
1023 | /* Let vfs_create() deal with O_EXCL */ | 967 | /* Let vfs_create() deal with O_EXCL. Instantiate, but don't hash |
968 | * the dentry. */ | ||
1024 | if (nd->intent.open.flags & O_EXCL) { | 969 | if (nd->intent.open.flags & O_EXCL) { |
1025 | d_add(dentry, NULL); | 970 | d_instantiate(dentry, NULL); |
1026 | goto out; | 971 | goto out; |
1027 | } | 972 | } |
1028 | 973 | ||
1029 | /* Open the file on the server */ | 974 | /* Open the file on the server */ |
1030 | lock_kernel(); | 975 | lock_kernel(); |
1031 | /* Revalidate parent directory attribute cache */ | 976 | res = nfs4_atomic_open(dir, dentry, nd); |
1032 | error = nfs_revalidate_inode(NFS_SERVER(dir), dir); | ||
1033 | if (error < 0) { | ||
1034 | res = ERR_PTR(error); | ||
1035 | unlock_kernel(); | ||
1036 | goto out; | ||
1037 | } | ||
1038 | |||
1039 | if (nd->intent.open.flags & O_CREAT) { | ||
1040 | nfs_begin_data_update(dir); | ||
1041 | res = nfs4_atomic_open(dir, dentry, nd); | ||
1042 | nfs_end_data_update(dir); | ||
1043 | } else | ||
1044 | res = nfs4_atomic_open(dir, dentry, nd); | ||
1045 | unlock_kernel(); | 977 | unlock_kernel(); |
1046 | if (IS_ERR(res)) { | 978 | if (IS_ERR(res)) { |
1047 | error = PTR_ERR(res); | 979 | error = PTR_ERR(res); |
@@ -1063,8 +995,6 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
1063 | } | 995 | } |
1064 | } else if (res != NULL) | 996 | } else if (res != NULL) |
1065 | dentry = res; | 997 | dentry = res; |
1066 | nfs_renew_times(dentry); | ||
1067 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
1068 | out: | 998 | out: |
1069 | return res; | 999 | return res; |
1070 | no_open: | 1000 | no_open: |
@@ -1076,7 +1006,6 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1076 | struct dentry *parent = NULL; | 1006 | struct dentry *parent = NULL; |
1077 | struct inode *inode = dentry->d_inode; | 1007 | struct inode *inode = dentry->d_inode; |
1078 | struct inode *dir; | 1008 | struct inode *dir; |
1079 | unsigned long verifier; | ||
1080 | int openflags, ret = 0; | 1009 | int openflags, ret = 0; |
1081 | 1010 | ||
1082 | parent = dget_parent(dentry); | 1011 | parent = dget_parent(dentry); |
@@ -1086,8 +1015,12 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1086 | /* We can't create new files in nfs_open_revalidate(), so we | 1015 | /* We can't create new files in nfs_open_revalidate(), so we |
1087 | * optimize away revalidation of negative dentries. | 1016 | * optimize away revalidation of negative dentries. |
1088 | */ | 1017 | */ |
1089 | if (inode == NULL) | 1018 | if (inode == NULL) { |
1019 | if (!nfs_neg_need_reval(dir, dentry, nd)) | ||
1020 | ret = 1; | ||
1090 | goto out; | 1021 | goto out; |
1022 | } | ||
1023 | |||
1091 | /* NFS only supports OPEN on regular files */ | 1024 | /* NFS only supports OPEN on regular files */ |
1092 | if (!S_ISREG(inode->i_mode)) | 1025 | if (!S_ISREG(inode->i_mode)) |
1093 | goto no_open; | 1026 | goto no_open; |
@@ -1104,10 +1037,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1104 | * change attribute *before* we do the RPC call. | 1037 | * change attribute *before* we do the RPC call. |
1105 | */ | 1038 | */ |
1106 | lock_kernel(); | 1039 | lock_kernel(); |
1107 | verifier = nfs_save_change_attribute(dir); | ||
1108 | ret = nfs4_open_revalidate(dir, dentry, openflags, nd); | 1040 | ret = nfs4_open_revalidate(dir, dentry, openflags, nd); |
1109 | if (!ret) | ||
1110 | nfs_refresh_verifier(dentry, verifier); | ||
1111 | unlock_kernel(); | 1041 | unlock_kernel(); |
1112 | out: | 1042 | out: |
1113 | dput(parent); | 1043 | dput(parent); |
@@ -1133,6 +1063,7 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) | |||
1133 | .len = entry->len, | 1063 | .len = entry->len, |
1134 | }; | 1064 | }; |
1135 | struct inode *inode; | 1065 | struct inode *inode; |
1066 | unsigned long verf = nfs_save_change_attribute(dir); | ||
1136 | 1067 | ||
1137 | switch (name.len) { | 1068 | switch (name.len) { |
1138 | case 2: | 1069 | case 2: |
@@ -1143,6 +1074,14 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) | |||
1143 | if (name.name[0] == '.') | 1074 | if (name.name[0] == '.') |
1144 | return dget(parent); | 1075 | return dget(parent); |
1145 | } | 1076 | } |
1077 | |||
1078 | spin_lock(&dir->i_lock); | ||
1079 | if (NFS_I(dir)->cache_validity & NFS_INO_INVALID_DATA) { | ||
1080 | spin_unlock(&dir->i_lock); | ||
1081 | return NULL; | ||
1082 | } | ||
1083 | spin_unlock(&dir->i_lock); | ||
1084 | |||
1146 | name.hash = full_name_hash(name.name, name.len); | 1085 | name.hash = full_name_hash(name.name, name.len); |
1147 | dentry = d_lookup(parent, &name); | 1086 | dentry = d_lookup(parent, &name); |
1148 | if (dentry != NULL) { | 1087 | if (dentry != NULL) { |
@@ -1183,12 +1122,8 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) | |||
1183 | dentry = alias; | 1122 | dentry = alias; |
1184 | } | 1123 | } |
1185 | 1124 | ||
1186 | nfs_renew_times(dentry); | ||
1187 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
1188 | return dentry; | ||
1189 | out_renew: | 1125 | out_renew: |
1190 | nfs_renew_times(dentry); | 1126 | nfs_set_verifier(dentry, verf); |
1191 | nfs_refresh_verifier(dentry, nfs_save_change_attribute(dir)); | ||
1192 | return dentry; | 1127 | return dentry; |
1193 | } | 1128 | } |
1194 | 1129 | ||
@@ -1198,32 +1133,40 @@ out_renew: | |||
1198 | int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, | 1133 | int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, |
1199 | struct nfs_fattr *fattr) | 1134 | struct nfs_fattr *fattr) |
1200 | { | 1135 | { |
1136 | struct dentry *parent = dget_parent(dentry); | ||
1137 | struct inode *dir = parent->d_inode; | ||
1201 | struct inode *inode; | 1138 | struct inode *inode; |
1202 | int error = -EACCES; | 1139 | int error = -EACCES; |
1203 | 1140 | ||
1141 | d_drop(dentry); | ||
1142 | |||
1204 | /* We may have been initialized further down */ | 1143 | /* We may have been initialized further down */ |
1205 | if (dentry->d_inode) | 1144 | if (dentry->d_inode) |
1206 | return 0; | 1145 | goto out; |
1207 | if (fhandle->size == 0) { | 1146 | if (fhandle->size == 0) { |
1208 | struct inode *dir = dentry->d_parent->d_inode; | ||
1209 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1147 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); |
1210 | if (error) | 1148 | if (error) |
1211 | return error; | 1149 | goto out_error; |
1212 | } | 1150 | } |
1151 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
1213 | if (!(fattr->valid & NFS_ATTR_FATTR)) { | 1152 | if (!(fattr->valid & NFS_ATTR_FATTR)) { |
1214 | struct nfs_server *server = NFS_SB(dentry->d_sb); | 1153 | struct nfs_server *server = NFS_SB(dentry->d_sb); |
1215 | error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr); | 1154 | error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr); |
1216 | if (error < 0) | 1155 | if (error < 0) |
1217 | return error; | 1156 | goto out_error; |
1218 | } | 1157 | } |
1219 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); | 1158 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); |
1220 | error = PTR_ERR(inode); | 1159 | error = PTR_ERR(inode); |
1221 | if (IS_ERR(inode)) | 1160 | if (IS_ERR(inode)) |
1222 | return error; | 1161 | goto out_error; |
1223 | d_instantiate(dentry, inode); | 1162 | d_add(dentry, inode); |
1224 | if (d_unhashed(dentry)) | 1163 | out: |
1225 | d_rehash(dentry); | 1164 | dput(parent); |
1226 | return 0; | 1165 | return 0; |
1166 | out_error: | ||
1167 | nfs_mark_for_revalidate(dir); | ||
1168 | dput(parent); | ||
1169 | return error; | ||
1227 | } | 1170 | } |
1228 | 1171 | ||
1229 | /* | 1172 | /* |
@@ -1249,13 +1192,9 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
1249 | open_flags = nd->intent.open.flags; | 1192 | open_flags = nd->intent.open.flags; |
1250 | 1193 | ||
1251 | lock_kernel(); | 1194 | lock_kernel(); |
1252 | nfs_begin_data_update(dir); | ||
1253 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd); | 1195 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd); |
1254 | nfs_end_data_update(dir); | ||
1255 | if (error != 0) | 1196 | if (error != 0) |
1256 | goto out_err; | 1197 | goto out_err; |
1257 | nfs_renew_times(dentry); | ||
1258 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
1259 | unlock_kernel(); | 1198 | unlock_kernel(); |
1260 | return 0; | 1199 | return 0; |
1261 | out_err: | 1200 | out_err: |
@@ -1283,13 +1222,9 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
1283 | attr.ia_valid = ATTR_MODE; | 1222 | attr.ia_valid = ATTR_MODE; |
1284 | 1223 | ||
1285 | lock_kernel(); | 1224 | lock_kernel(); |
1286 | nfs_begin_data_update(dir); | ||
1287 | status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev); | 1225 | status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev); |
1288 | nfs_end_data_update(dir); | ||
1289 | if (status != 0) | 1226 | if (status != 0) |
1290 | goto out_err; | 1227 | goto out_err; |
1291 | nfs_renew_times(dentry); | ||
1292 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
1293 | unlock_kernel(); | 1228 | unlock_kernel(); |
1294 | return 0; | 1229 | return 0; |
1295 | out_err: | 1230 | out_err: |
@@ -1313,13 +1248,9 @@ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
1313 | attr.ia_mode = mode | S_IFDIR; | 1248 | attr.ia_mode = mode | S_IFDIR; |
1314 | 1249 | ||
1315 | lock_kernel(); | 1250 | lock_kernel(); |
1316 | nfs_begin_data_update(dir); | ||
1317 | error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr); | 1251 | error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr); |
1318 | nfs_end_data_update(dir); | ||
1319 | if (error != 0) | 1252 | if (error != 0) |
1320 | goto out_err; | 1253 | goto out_err; |
1321 | nfs_renew_times(dentry); | ||
1322 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
1323 | unlock_kernel(); | 1254 | unlock_kernel(); |
1324 | return 0; | 1255 | return 0; |
1325 | out_err: | 1256 | out_err: |
@@ -1336,12 +1267,10 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1336 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); | 1267 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); |
1337 | 1268 | ||
1338 | lock_kernel(); | 1269 | lock_kernel(); |
1339 | nfs_begin_data_update(dir); | ||
1340 | error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); | 1270 | error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name); |
1341 | /* Ensure the VFS deletes this inode */ | 1271 | /* Ensure the VFS deletes this inode */ |
1342 | if (error == 0 && dentry->d_inode != NULL) | 1272 | if (error == 0 && dentry->d_inode != NULL) |
1343 | clear_nlink(dentry->d_inode); | 1273 | clear_nlink(dentry->d_inode); |
1344 | nfs_end_data_update(dir); | ||
1345 | unlock_kernel(); | 1274 | unlock_kernel(); |
1346 | 1275 | ||
1347 | return error; | 1276 | return error; |
@@ -1350,9 +1279,9 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1350 | static int nfs_sillyrename(struct inode *dir, struct dentry *dentry) | 1279 | static int nfs_sillyrename(struct inode *dir, struct dentry *dentry) |
1351 | { | 1280 | { |
1352 | static unsigned int sillycounter; | 1281 | static unsigned int sillycounter; |
1353 | const int i_inosize = sizeof(dir->i_ino)*2; | 1282 | const int fileidsize = sizeof(NFS_FILEID(dentry->d_inode))*2; |
1354 | const int countersize = sizeof(sillycounter)*2; | 1283 | const int countersize = sizeof(sillycounter)*2; |
1355 | const int slen = sizeof(".nfs") + i_inosize + countersize - 1; | 1284 | const int slen = sizeof(".nfs")+fileidsize+countersize-1; |
1356 | char silly[slen+1]; | 1285 | char silly[slen+1]; |
1357 | struct qstr qsilly; | 1286 | struct qstr qsilly; |
1358 | struct dentry *sdentry; | 1287 | struct dentry *sdentry; |
@@ -1370,8 +1299,9 @@ static int nfs_sillyrename(struct inode *dir, struct dentry *dentry) | |||
1370 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) | 1299 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) |
1371 | goto out; | 1300 | goto out; |
1372 | 1301 | ||
1373 | sprintf(silly, ".nfs%*.*lx", | 1302 | sprintf(silly, ".nfs%*.*Lx", |
1374 | i_inosize, i_inosize, dentry->d_inode->i_ino); | 1303 | fileidsize, fileidsize, |
1304 | (unsigned long long)NFS_FILEID(dentry->d_inode)); | ||
1375 | 1305 | ||
1376 | /* Return delegation in anticipation of the rename */ | 1306 | /* Return delegation in anticipation of the rename */ |
1377 | nfs_inode_return_delegation(dentry->d_inode); | 1307 | nfs_inode_return_delegation(dentry->d_inode); |
@@ -1398,19 +1328,14 @@ static int nfs_sillyrename(struct inode *dir, struct dentry *dentry) | |||
1398 | 1328 | ||
1399 | qsilly.name = silly; | 1329 | qsilly.name = silly; |
1400 | qsilly.len = strlen(silly); | 1330 | qsilly.len = strlen(silly); |
1401 | nfs_begin_data_update(dir); | ||
1402 | if (dentry->d_inode) { | 1331 | if (dentry->d_inode) { |
1403 | nfs_begin_data_update(dentry->d_inode); | ||
1404 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, | 1332 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, |
1405 | dir, &qsilly); | 1333 | dir, &qsilly); |
1406 | nfs_mark_for_revalidate(dentry->d_inode); | 1334 | nfs_mark_for_revalidate(dentry->d_inode); |
1407 | nfs_end_data_update(dentry->d_inode); | ||
1408 | } else | 1335 | } else |
1409 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, | 1336 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, |
1410 | dir, &qsilly); | 1337 | dir, &qsilly); |
1411 | nfs_end_data_update(dir); | ||
1412 | if (!error) { | 1338 | if (!error) { |
1413 | nfs_renew_times(dentry); | ||
1414 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1339 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1415 | d_move(dentry, sdentry); | 1340 | d_move(dentry, sdentry); |
1416 | error = nfs_async_unlink(dir, dentry); | 1341 | error = nfs_async_unlink(dir, dentry); |
@@ -1443,19 +1368,15 @@ static int nfs_safe_remove(struct dentry *dentry) | |||
1443 | goto out; | 1368 | goto out; |
1444 | } | 1369 | } |
1445 | 1370 | ||
1446 | nfs_begin_data_update(dir); | ||
1447 | if (inode != NULL) { | 1371 | if (inode != NULL) { |
1448 | nfs_inode_return_delegation(inode); | 1372 | nfs_inode_return_delegation(inode); |
1449 | nfs_begin_data_update(inode); | ||
1450 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1373 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
1451 | /* The VFS may want to delete this inode */ | 1374 | /* The VFS may want to delete this inode */ |
1452 | if (error == 0) | 1375 | if (error == 0) |
1453 | drop_nlink(inode); | 1376 | drop_nlink(inode); |
1454 | nfs_mark_for_revalidate(inode); | 1377 | nfs_mark_for_revalidate(inode); |
1455 | nfs_end_data_update(inode); | ||
1456 | } else | 1378 | } else |
1457 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1379 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
1458 | nfs_end_data_update(dir); | ||
1459 | out: | 1380 | out: |
1460 | return error; | 1381 | return error; |
1461 | } | 1382 | } |
@@ -1493,7 +1414,6 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1493 | spin_unlock(&dcache_lock); | 1414 | spin_unlock(&dcache_lock); |
1494 | error = nfs_safe_remove(dentry); | 1415 | error = nfs_safe_remove(dentry); |
1495 | if (!error) { | 1416 | if (!error) { |
1496 | nfs_renew_times(dentry); | ||
1497 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1417 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1498 | } else if (need_rehash) | 1418 | } else if (need_rehash) |
1499 | d_rehash(dentry); | 1419 | d_rehash(dentry); |
@@ -1548,9 +1468,7 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym | |||
1548 | memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen); | 1468 | memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen); |
1549 | kunmap_atomic(kaddr, KM_USER0); | 1469 | kunmap_atomic(kaddr, KM_USER0); |
1550 | 1470 | ||
1551 | nfs_begin_data_update(dir); | ||
1552 | error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr); | 1471 | error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr); |
1553 | nfs_end_data_update(dir); | ||
1554 | if (error != 0) { | 1472 | if (error != 0) { |
1555 | dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n", | 1473 | dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n", |
1556 | dir->i_sb->s_id, dir->i_ino, | 1474 | dir->i_sb->s_id, dir->i_ino, |
@@ -1590,15 +1508,12 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | |||
1590 | dentry->d_parent->d_name.name, dentry->d_name.name); | 1508 | dentry->d_parent->d_name.name, dentry->d_name.name); |
1591 | 1509 | ||
1592 | lock_kernel(); | 1510 | lock_kernel(); |
1593 | nfs_begin_data_update(dir); | 1511 | d_drop(dentry); |
1594 | nfs_begin_data_update(inode); | ||
1595 | error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); | 1512 | error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); |
1596 | if (error == 0) { | 1513 | if (error == 0) { |
1597 | atomic_inc(&inode->i_count); | 1514 | atomic_inc(&inode->i_count); |
1598 | d_instantiate(dentry, inode); | 1515 | d_add(dentry, inode); |
1599 | } | 1516 | } |
1600 | nfs_end_data_update(inode); | ||
1601 | nfs_end_data_update(dir); | ||
1602 | unlock_kernel(); | 1517 | unlock_kernel(); |
1603 | return error; | 1518 | return error; |
1604 | } | 1519 | } |
@@ -1701,22 +1616,16 @@ go_ahead: | |||
1701 | d_delete(new_dentry); | 1616 | d_delete(new_dentry); |
1702 | } | 1617 | } |
1703 | 1618 | ||
1704 | nfs_begin_data_update(old_dir); | ||
1705 | nfs_begin_data_update(new_dir); | ||
1706 | nfs_begin_data_update(old_inode); | ||
1707 | error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, | 1619 | error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, |
1708 | new_dir, &new_dentry->d_name); | 1620 | new_dir, &new_dentry->d_name); |
1709 | nfs_mark_for_revalidate(old_inode); | 1621 | nfs_mark_for_revalidate(old_inode); |
1710 | nfs_end_data_update(old_inode); | ||
1711 | nfs_end_data_update(new_dir); | ||
1712 | nfs_end_data_update(old_dir); | ||
1713 | out: | 1622 | out: |
1714 | if (rehash) | 1623 | if (rehash) |
1715 | d_rehash(rehash); | 1624 | d_rehash(rehash); |
1716 | if (!error) { | 1625 | if (!error) { |
1717 | d_move(old_dentry, new_dentry); | 1626 | d_move(old_dentry, new_dentry); |
1718 | nfs_renew_times(new_dentry); | 1627 | nfs_set_verifier(new_dentry, |
1719 | nfs_refresh_verifier(new_dentry, nfs_save_change_attribute(new_dir)); | 1628 | nfs_save_change_attribute(new_dir)); |
1720 | } | 1629 | } |
1721 | 1630 | ||
1722 | /* new dentry created? */ | 1631 | /* new dentry created? */ |
@@ -1842,7 +1751,7 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, st | |||
1842 | return NULL; | 1751 | return NULL; |
1843 | } | 1752 | } |
1844 | 1753 | ||
1845 | int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res) | 1754 | static int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res) |
1846 | { | 1755 | { |
1847 | struct nfs_inode *nfsi = NFS_I(inode); | 1756 | struct nfs_inode *nfsi = NFS_I(inode); |
1848 | struct nfs_access_entry *cache; | 1757 | struct nfs_access_entry *cache; |
@@ -1854,7 +1763,7 @@ int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs | |||
1854 | cache = nfs_access_search_rbtree(inode, cred); | 1763 | cache = nfs_access_search_rbtree(inode, cred); |
1855 | if (cache == NULL) | 1764 | if (cache == NULL) |
1856 | goto out; | 1765 | goto out; |
1857 | if (time_after(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))) | 1766 | if (!time_in_range(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo)) |
1858 | goto out_stale; | 1767 | goto out_stale; |
1859 | res->jiffies = cache->jiffies; | 1768 | res->jiffies = cache->jiffies; |
1860 | res->cred = cache->cred; | 1769 | res->cred = cache->cred; |
@@ -1909,7 +1818,7 @@ found: | |||
1909 | nfs_access_free_entry(entry); | 1818 | nfs_access_free_entry(entry); |
1910 | } | 1819 | } |
1911 | 1820 | ||
1912 | void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) | 1821 | static void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) |
1913 | { | 1822 | { |
1914 | struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL); | 1823 | struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL); |
1915 | if (cache == NULL) | 1824 | if (cache == NULL) |
@@ -1957,6 +1866,24 @@ out: | |||
1957 | return -EACCES; | 1866 | return -EACCES; |
1958 | } | 1867 | } |
1959 | 1868 | ||
1869 | static int nfs_open_permission_mask(int openflags) | ||
1870 | { | ||
1871 | int mask = 0; | ||
1872 | |||
1873 | if (openflags & FMODE_READ) | ||
1874 | mask |= MAY_READ; | ||
1875 | if (openflags & FMODE_WRITE) | ||
1876 | mask |= MAY_WRITE; | ||
1877 | if (openflags & FMODE_EXEC) | ||
1878 | mask |= MAY_EXEC; | ||
1879 | return mask; | ||
1880 | } | ||
1881 | |||
1882 | int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags) | ||
1883 | { | ||
1884 | return nfs_do_access(inode, cred, nfs_open_permission_mask(openflags)); | ||
1885 | } | ||
1886 | |||
1960 | int nfs_permission(struct inode *inode, int mask, struct nameidata *nd) | 1887 | int nfs_permission(struct inode *inode, int mask, struct nameidata *nd) |
1961 | { | 1888 | { |
1962 | struct rpc_cred *cred; | 1889 | struct rpc_cred *cred; |