diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/dir.c | 28 | ||||
-rw-r--r-- | fs/nfs/file.c | 5 | ||||
-rw-r--r-- | fs/nfs/inode.c | 197 | ||||
-rw-r--r-- | fs/nfs/nfs3acl.c | 4 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 4 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 10 | ||||
-rw-r--r-- | fs/nfs/proc.c | 2 | ||||
-rw-r--r-- | fs/nfs/read.c | 8 | ||||
-rw-r--r-- | fs/nfs/symlink.c | 37 |
9 files changed, 181 insertions, 114 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index b38a57e78a63..2df639f143e8 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -182,14 +182,16 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) | |||
182 | /* We requested READDIRPLUS, but the server doesn't grok it */ | 182 | /* We requested READDIRPLUS, but the server doesn't grok it */ |
183 | if (error == -ENOTSUPP && desc->plus) { | 183 | if (error == -ENOTSUPP && desc->plus) { |
184 | NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS; | 184 | NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS; |
185 | NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS; | 185 | clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); |
186 | desc->plus = 0; | 186 | desc->plus = 0; |
187 | goto again; | 187 | goto again; |
188 | } | 188 | } |
189 | goto error; | 189 | goto error; |
190 | } | 190 | } |
191 | SetPageUptodate(page); | 191 | SetPageUptodate(page); |
192 | NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME; | 192 | spin_lock(&inode->i_lock); |
193 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME; | ||
194 | spin_unlock(&inode->i_lock); | ||
193 | /* Ensure consistent page alignment of the data. | 195 | /* Ensure consistent page alignment of the data. |
194 | * Note: assumes we have exclusive access to this mapping either | 196 | * Note: assumes we have exclusive access to this mapping either |
195 | * through inode->i_sem or some other mechanism. | 197 | * through inode->i_sem or some other mechanism. |
@@ -462,7 +464,9 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
462 | page, | 464 | page, |
463 | NFS_SERVER(inode)->dtsize, | 465 | NFS_SERVER(inode)->dtsize, |
464 | desc->plus); | 466 | desc->plus); |
465 | NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME; | 467 | spin_lock(&inode->i_lock); |
468 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME; | ||
469 | spin_unlock(&inode->i_lock); | ||
466 | desc->page = page; | 470 | desc->page = page; |
467 | desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ | 471 | desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ |
468 | if (desc->error >= 0) { | 472 | if (desc->error >= 0) { |
@@ -545,7 +549,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
545 | break; | 549 | break; |
546 | } | 550 | } |
547 | if (res == -ETOOSMALL && desc->plus) { | 551 | if (res == -ETOOSMALL && desc->plus) { |
548 | NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS; | 552 | clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); |
549 | nfs_zap_caches(inode); | 553 | nfs_zap_caches(inode); |
550 | desc->plus = 0; | 554 | desc->plus = 0; |
551 | desc->entry->eof = 0; | 555 | desc->entry->eof = 0; |
@@ -608,7 +612,7 @@ static inline int nfs_check_verifier(struct inode *dir, struct dentry *dentry) | |||
608 | { | 612 | { |
609 | if (IS_ROOT(dentry)) | 613 | if (IS_ROOT(dentry)) |
610 | return 1; | 614 | return 1; |
611 | if ((NFS_FLAGS(dir) & NFS_INO_INVALID_ATTR) != 0 | 615 | if ((NFS_I(dir)->cache_validity & NFS_INO_INVALID_ATTR) != 0 |
612 | || nfs_attribute_timeout(dir)) | 616 | || nfs_attribute_timeout(dir)) |
613 | return 0; | 617 | return 0; |
614 | return nfs_verify_change_attribute(dir, (unsigned long)dentry->d_fsdata); | 618 | return nfs_verify_change_attribute(dir, (unsigned long)dentry->d_fsdata); |
@@ -935,6 +939,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
935 | error = nfs_revalidate_inode(NFS_SERVER(dir), dir); | 939 | error = nfs_revalidate_inode(NFS_SERVER(dir), dir); |
936 | if (error < 0) { | 940 | if (error < 0) { |
937 | res = ERR_PTR(error); | 941 | res = ERR_PTR(error); |
942 | unlock_kernel(); | ||
938 | goto out; | 943 | goto out; |
939 | } | 944 | } |
940 | 945 | ||
@@ -1575,11 +1580,12 @@ out: | |||
1575 | 1580 | ||
1576 | int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res) | 1581 | int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res) |
1577 | { | 1582 | { |
1578 | struct nfs_access_entry *cache = &NFS_I(inode)->cache_access; | 1583 | struct nfs_inode *nfsi = NFS_I(inode); |
1584 | struct nfs_access_entry *cache = &nfsi->cache_access; | ||
1579 | 1585 | ||
1580 | if (cache->cred != cred | 1586 | if (cache->cred != cred |
1581 | || time_after(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode)) | 1587 | || time_after(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode)) |
1582 | || (NFS_FLAGS(inode) & NFS_INO_INVALID_ACCESS)) | 1588 | || (nfsi->cache_validity & NFS_INO_INVALID_ACCESS)) |
1583 | return -ENOENT; | 1589 | return -ENOENT; |
1584 | memcpy(res, cache, sizeof(*res)); | 1590 | memcpy(res, cache, sizeof(*res)); |
1585 | return 0; | 1591 | return 0; |
@@ -1587,14 +1593,18 @@ int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs | |||
1587 | 1593 | ||
1588 | void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) | 1594 | void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) |
1589 | { | 1595 | { |
1590 | struct nfs_access_entry *cache = &NFS_I(inode)->cache_access; | 1596 | struct nfs_inode *nfsi = NFS_I(inode); |
1597 | struct nfs_access_entry *cache = &nfsi->cache_access; | ||
1591 | 1598 | ||
1592 | if (cache->cred != set->cred) { | 1599 | if (cache->cred != set->cred) { |
1593 | if (cache->cred) | 1600 | if (cache->cred) |
1594 | put_rpccred(cache->cred); | 1601 | put_rpccred(cache->cred); |
1595 | cache->cred = get_rpccred(set->cred); | 1602 | cache->cred = get_rpccred(set->cred); |
1596 | } | 1603 | } |
1597 | NFS_FLAGS(inode) &= ~NFS_INO_INVALID_ACCESS; | 1604 | /* FIXME: replace current access_cache BKL reliance with inode->i_lock */ |
1605 | spin_lock(&inode->i_lock); | ||
1606 | nfsi->cache_validity &= ~NFS_INO_INVALID_ACCESS; | ||
1607 | spin_unlock(&inode->i_lock); | ||
1598 | cache->jiffies = set->jiffies; | 1608 | cache->jiffies = set->jiffies; |
1599 | cache->mask = set->mask; | 1609 | cache->mask = set->mask; |
1600 | } | 1610 | } |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 5621ba9885f4..f6b9eda925c5 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -134,9 +134,10 @@ nfs_file_release(struct inode *inode, struct file *filp) | |||
134 | */ | 134 | */ |
135 | static int nfs_revalidate_file(struct inode *inode, struct file *filp) | 135 | static int nfs_revalidate_file(struct inode *inode, struct file *filp) |
136 | { | 136 | { |
137 | struct nfs_inode *nfsi = NFS_I(inode); | ||
137 | int retval = 0; | 138 | int retval = 0; |
138 | 139 | ||
139 | if ((NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) || nfs_attribute_timeout(inode)) | 140 | if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) || nfs_attribute_timeout(inode)) |
140 | retval = __nfs_revalidate_inode(NFS_SERVER(inode), inode); | 141 | retval = __nfs_revalidate_inode(NFS_SERVER(inode), inode); |
141 | nfs_revalidate_mapping(inode, filp->f_mapping); | 142 | nfs_revalidate_mapping(inode, filp->f_mapping); |
142 | return 0; | 143 | return 0; |
@@ -164,7 +165,7 @@ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp) | |||
164 | goto force_reval; | 165 | goto force_reval; |
165 | if (nfsi->npages != 0) | 166 | if (nfsi->npages != 0) |
166 | return 0; | 167 | return 0; |
167 | if (!(NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode)) | 168 | if (!(nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode)) |
168 | return 0; | 169 | return 0; |
169 | force_reval: | 170 | force_reval: |
170 | return __nfs_revalidate_inode(server, inode); | 171 | return __nfs_revalidate_inode(server, inode); |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 4845911f1c63..541b418327c8 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -615,14 +615,18 @@ nfs_zap_caches(struct inode *inode) | |||
615 | struct nfs_inode *nfsi = NFS_I(inode); | 615 | struct nfs_inode *nfsi = NFS_I(inode); |
616 | int mode = inode->i_mode; | 616 | int mode = inode->i_mode; |
617 | 617 | ||
618 | spin_lock(&inode->i_lock); | ||
619 | |||
618 | NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); | 620 | NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); |
619 | NFS_ATTRTIMEO_UPDATE(inode) = jiffies; | 621 | NFS_ATTRTIMEO_UPDATE(inode) = jiffies; |
620 | 622 | ||
621 | memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); | 623 | memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); |
622 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) | 624 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) |
623 | nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | 625 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; |
624 | else | 626 | else |
625 | nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | 627 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; |
628 | |||
629 | spin_unlock(&inode->i_lock); | ||
626 | } | 630 | } |
627 | 631 | ||
628 | static void nfs_zap_acl_cache(struct inode *inode) | 632 | static void nfs_zap_acl_cache(struct inode *inode) |
@@ -632,7 +636,9 @@ static void nfs_zap_acl_cache(struct inode *inode) | |||
632 | clear_acl_cache = NFS_PROTO(inode)->clear_acl_cache; | 636 | clear_acl_cache = NFS_PROTO(inode)->clear_acl_cache; |
633 | if (clear_acl_cache != NULL) | 637 | if (clear_acl_cache != NULL) |
634 | clear_acl_cache(inode); | 638 | clear_acl_cache(inode); |
635 | NFS_I(inode)->flags &= ~NFS_INO_INVALID_ACL; | 639 | spin_lock(&inode->i_lock); |
640 | NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_ACL; | ||
641 | spin_unlock(&inode->i_lock); | ||
636 | } | 642 | } |
637 | 643 | ||
638 | /* | 644 | /* |
@@ -739,7 +745,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
739 | inode->i_fop = &nfs_dir_operations; | 745 | inode->i_fop = &nfs_dir_operations; |
740 | if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS) | 746 | if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS) |
741 | && fattr->size <= NFS_LIMIT_READDIRPLUS) | 747 | && fattr->size <= NFS_LIMIT_READDIRPLUS) |
742 | NFS_FLAGS(inode) |= NFS_INO_ADVISE_RDPLUS; | 748 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); |
743 | } else if (S_ISLNK(inode->i_mode)) | 749 | } else if (S_ISLNK(inode->i_mode)) |
744 | inode->i_op = &nfs_symlink_inode_operations; | 750 | inode->i_op = &nfs_symlink_inode_operations; |
745 | else | 751 | else |
@@ -814,55 +820,84 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
814 | nfs_wb_all(inode); | 820 | nfs_wb_all(inode); |
815 | } | 821 | } |
816 | error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); | 822 | error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); |
817 | if (error == 0) { | 823 | if (error == 0) |
818 | nfs_refresh_inode(inode, &fattr); | 824 | nfs_refresh_inode(inode, &fattr); |
825 | nfs_end_data_update(inode); | ||
826 | unlock_kernel(); | ||
827 | return error; | ||
828 | } | ||
829 | |||
830 | /** | ||
831 | * nfs_setattr_update_inode - Update inode metadata after a setattr call. | ||
832 | * @inode: pointer to struct inode | ||
833 | * @attr: pointer to struct iattr | ||
834 | * | ||
835 | * Note: we do this in the *proc.c in order to ensure that | ||
836 | * it works for things like exclusive creates too. | ||
837 | */ | ||
838 | void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | ||
839 | { | ||
840 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { | ||
819 | if ((attr->ia_valid & ATTR_MODE) != 0) { | 841 | if ((attr->ia_valid & ATTR_MODE) != 0) { |
820 | int mode; | 842 | int mode = attr->ia_mode & S_IALLUGO; |
821 | mode = inode->i_mode & ~S_IALLUGO; | 843 | mode |= inode->i_mode & ~S_IALLUGO; |
822 | mode |= attr->ia_mode & S_IALLUGO; | ||
823 | inode->i_mode = mode; | 844 | inode->i_mode = mode; |
824 | } | 845 | } |
825 | if ((attr->ia_valid & ATTR_UID) != 0) | 846 | if ((attr->ia_valid & ATTR_UID) != 0) |
826 | inode->i_uid = attr->ia_uid; | 847 | inode->i_uid = attr->ia_uid; |
827 | if ((attr->ia_valid & ATTR_GID) != 0) | 848 | if ((attr->ia_valid & ATTR_GID) != 0) |
828 | inode->i_gid = attr->ia_gid; | 849 | inode->i_gid = attr->ia_gid; |
829 | if ((attr->ia_valid & ATTR_SIZE) != 0) { | 850 | spin_lock(&inode->i_lock); |
830 | inode->i_size = attr->ia_size; | 851 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
831 | vmtruncate(inode, attr->ia_size); | 852 | spin_unlock(&inode->i_lock); |
832 | } | ||
833 | } | 853 | } |
834 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) | 854 | if ((attr->ia_valid & ATTR_SIZE) != 0) { |
835 | NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 855 | inode->i_size = attr->ia_size; |
836 | nfs_end_data_update(inode); | 856 | vmtruncate(inode, attr->ia_size); |
837 | unlock_kernel(); | 857 | } |
838 | return error; | 858 | } |
859 | |||
860 | static int nfs_wait_schedule(void *word) | ||
861 | { | ||
862 | if (signal_pending(current)) | ||
863 | return -ERESTARTSYS; | ||
864 | schedule(); | ||
865 | return 0; | ||
839 | } | 866 | } |
840 | 867 | ||
841 | /* | 868 | /* |
842 | * Wait for the inode to get unlocked. | 869 | * Wait for the inode to get unlocked. |
843 | * (Used for NFS_INO_LOCKED and NFS_INO_REVALIDATING). | ||
844 | */ | 870 | */ |
845 | static int | 871 | static int nfs_wait_on_inode(struct inode *inode) |
846 | nfs_wait_on_inode(struct inode *inode, int flag) | ||
847 | { | 872 | { |
848 | struct rpc_clnt *clnt = NFS_CLIENT(inode); | 873 | struct rpc_clnt *clnt = NFS_CLIENT(inode); |
849 | struct nfs_inode *nfsi = NFS_I(inode); | 874 | struct nfs_inode *nfsi = NFS_I(inode); |
850 | 875 | sigset_t oldmask; | |
851 | int error; | 876 | int error; |
852 | if (!(NFS_FLAGS(inode) & flag)) | 877 | |
853 | return 0; | ||
854 | atomic_inc(&inode->i_count); | 878 | atomic_inc(&inode->i_count); |
855 | error = nfs_wait_event(clnt, nfsi->nfs_i_wait, | 879 | rpc_clnt_sigmask(clnt, &oldmask); |
856 | !(NFS_FLAGS(inode) & flag)); | 880 | error = wait_on_bit_lock(&nfsi->flags, NFS_INO_REVALIDATING, |
881 | nfs_wait_schedule, TASK_INTERRUPTIBLE); | ||
882 | rpc_clnt_sigunmask(clnt, &oldmask); | ||
857 | iput(inode); | 883 | iput(inode); |
884 | |||
858 | return error; | 885 | return error; |
859 | } | 886 | } |
860 | 887 | ||
888 | static void nfs_wake_up_inode(struct inode *inode) | ||
889 | { | ||
890 | struct nfs_inode *nfsi = NFS_I(inode); | ||
891 | |||
892 | clear_bit(NFS_INO_REVALIDATING, &nfsi->flags); | ||
893 | smp_mb__after_clear_bit(); | ||
894 | wake_up_bit(&nfsi->flags, NFS_INO_REVALIDATING); | ||
895 | } | ||
896 | |||
861 | int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | 897 | int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) |
862 | { | 898 | { |
863 | struct inode *inode = dentry->d_inode; | 899 | struct inode *inode = dentry->d_inode; |
864 | struct nfs_inode *nfsi = NFS_I(inode); | 900 | int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; |
865 | int need_atime = nfsi->flags & NFS_INO_INVALID_ATIME; | ||
866 | int err; | 901 | int err; |
867 | 902 | ||
868 | if (__IS_FLG(inode, MS_NOATIME)) | 903 | if (__IS_FLG(inode, MS_NOATIME)) |
@@ -1008,7 +1043,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1008 | struct nfs_fattr fattr; | 1043 | struct nfs_fattr fattr; |
1009 | struct nfs_inode *nfsi = NFS_I(inode); | 1044 | struct nfs_inode *nfsi = NFS_I(inode); |
1010 | unsigned long verifier; | 1045 | unsigned long verifier; |
1011 | unsigned int flags; | 1046 | unsigned long cache_validity; |
1012 | 1047 | ||
1013 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", | 1048 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", |
1014 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); | 1049 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); |
@@ -1019,18 +1054,19 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1019 | if (NFS_STALE(inode)) | 1054 | if (NFS_STALE(inode)) |
1020 | goto out_nowait; | 1055 | goto out_nowait; |
1021 | 1056 | ||
1022 | while (NFS_REVALIDATING(inode)) { | 1057 | status = nfs_wait_on_inode(inode); |
1023 | status = nfs_wait_on_inode(inode, NFS_INO_REVALIDATING); | 1058 | if (status < 0) |
1024 | if (status < 0) | 1059 | goto out; |
1025 | goto out_nowait; | 1060 | if (NFS_STALE(inode)) { |
1026 | if (NFS_ATTRTIMEO(inode) == 0) | 1061 | status = -ESTALE; |
1027 | continue; | 1062 | /* Do we trust the cached ESTALE? */ |
1028 | if (NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME)) | 1063 | if (NFS_ATTRTIMEO(inode) != 0) { |
1029 | continue; | 1064 | if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME)) { |
1030 | status = NFS_STALE(inode) ? -ESTALE : 0; | 1065 | /* no */ |
1031 | goto out_nowait; | 1066 | } else |
1067 | goto out; | ||
1068 | } | ||
1032 | } | 1069 | } |
1033 | NFS_FLAGS(inode) |= NFS_INO_REVALIDATING; | ||
1034 | 1070 | ||
1035 | /* Protect against RPC races by saving the change attribute */ | 1071 | /* Protect against RPC races by saving the change attribute */ |
1036 | verifier = nfs_save_change_attribute(inode); | 1072 | verifier = nfs_save_change_attribute(inode); |
@@ -1042,7 +1078,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1042 | if (status == -ESTALE) { | 1078 | if (status == -ESTALE) { |
1043 | nfs_zap_caches(inode); | 1079 | nfs_zap_caches(inode); |
1044 | if (!S_ISDIR(inode->i_mode)) | 1080 | if (!S_ISDIR(inode->i_mode)) |
1045 | NFS_FLAGS(inode) |= NFS_INO_STALE; | 1081 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); |
1046 | } | 1082 | } |
1047 | goto out; | 1083 | goto out; |
1048 | } | 1084 | } |
@@ -1054,25 +1090,30 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1054 | (long long)NFS_FILEID(inode), status); | 1090 | (long long)NFS_FILEID(inode), status); |
1055 | goto out; | 1091 | goto out; |
1056 | } | 1092 | } |
1057 | flags = nfsi->flags; | 1093 | spin_lock(&inode->i_lock); |
1058 | nfsi->flags &= ~NFS_INO_REVAL_PAGECACHE; | 1094 | cache_validity = nfsi->cache_validity; |
1095 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; | ||
1096 | |||
1059 | /* | 1097 | /* |
1060 | * We may need to keep the attributes marked as invalid if | 1098 | * We may need to keep the attributes marked as invalid if |
1061 | * we raced with nfs_end_attr_update(). | 1099 | * we raced with nfs_end_attr_update(). |
1062 | */ | 1100 | */ |
1063 | if (verifier == nfsi->cache_change_attribute) | 1101 | if (verifier == nfsi->cache_change_attribute) |
1064 | nfsi->flags &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | 1102 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); |
1065 | /* Do the page cache invalidation */ | 1103 | spin_unlock(&inode->i_lock); |
1104 | |||
1066 | nfs_revalidate_mapping(inode, inode->i_mapping); | 1105 | nfs_revalidate_mapping(inode, inode->i_mapping); |
1067 | if (flags & NFS_INO_INVALID_ACL) | 1106 | |
1107 | if (cache_validity & NFS_INO_INVALID_ACL) | ||
1068 | nfs_zap_acl_cache(inode); | 1108 | nfs_zap_acl_cache(inode); |
1109 | |||
1069 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", | 1110 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", |
1070 | inode->i_sb->s_id, | 1111 | inode->i_sb->s_id, |
1071 | (long long)NFS_FILEID(inode)); | 1112 | (long long)NFS_FILEID(inode)); |
1072 | 1113 | ||
1073 | out: | 1114 | out: |
1074 | NFS_FLAGS(inode) &= ~NFS_INO_REVALIDATING; | 1115 | nfs_wake_up_inode(inode); |
1075 | wake_up(&nfsi->nfs_i_wait); | 1116 | |
1076 | out_nowait: | 1117 | out_nowait: |
1077 | unlock_kernel(); | 1118 | unlock_kernel(); |
1078 | return status; | 1119 | return status; |
@@ -1096,7 +1137,7 @@ int nfs_attribute_timeout(struct inode *inode) | |||
1096 | */ | 1137 | */ |
1097 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | 1138 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) |
1098 | { | 1139 | { |
1099 | if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA)) | 1140 | if (!(NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA)) |
1100 | && !nfs_attribute_timeout(inode)) | 1141 | && !nfs_attribute_timeout(inode)) |
1101 | return NFS_STALE(inode) ? -ESTALE : 0; | 1142 | return NFS_STALE(inode) ? -ESTALE : 0; |
1102 | return __nfs_revalidate_inode(server, inode); | 1143 | return __nfs_revalidate_inode(server, inode); |
@@ -1111,19 +1152,23 @@ void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | |||
1111 | { | 1152 | { |
1112 | struct nfs_inode *nfsi = NFS_I(inode); | 1153 | struct nfs_inode *nfsi = NFS_I(inode); |
1113 | 1154 | ||
1114 | if (nfsi->flags & NFS_INO_INVALID_DATA) { | 1155 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) { |
1115 | if (S_ISREG(inode->i_mode)) { | 1156 | if (S_ISREG(inode->i_mode)) { |
1116 | if (filemap_fdatawrite(mapping) == 0) | 1157 | if (filemap_fdatawrite(mapping) == 0) |
1117 | filemap_fdatawait(mapping); | 1158 | filemap_fdatawait(mapping); |
1118 | nfs_wb_all(inode); | 1159 | nfs_wb_all(inode); |
1119 | } | 1160 | } |
1120 | invalidate_inode_pages2(mapping); | 1161 | invalidate_inode_pages2(mapping); |
1121 | nfsi->flags &= ~NFS_INO_INVALID_DATA; | 1162 | |
1163 | spin_lock(&inode->i_lock); | ||
1164 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; | ||
1122 | if (S_ISDIR(inode->i_mode)) { | 1165 | if (S_ISDIR(inode->i_mode)) { |
1123 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | 1166 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); |
1124 | /* This ensures we revalidate child dentries */ | 1167 | /* This ensures we revalidate child dentries */ |
1125 | nfsi->cache_change_attribute++; | 1168 | nfsi->cache_change_attribute++; |
1126 | } | 1169 | } |
1170 | spin_unlock(&inode->i_lock); | ||
1171 | |||
1127 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", | 1172 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", |
1128 | inode->i_sb->s_id, | 1173 | inode->i_sb->s_id, |
1129 | (long long)NFS_FILEID(inode)); | 1174 | (long long)NFS_FILEID(inode)); |
@@ -1153,10 +1198,12 @@ void nfs_end_data_update(struct inode *inode) | |||
1153 | 1198 | ||
1154 | if (!nfs_have_delegation(inode, FMODE_READ)) { | 1199 | if (!nfs_have_delegation(inode, FMODE_READ)) { |
1155 | /* Mark the attribute cache for revalidation */ | 1200 | /* Mark the attribute cache for revalidation */ |
1156 | nfsi->flags |= NFS_INO_INVALID_ATTR; | 1201 | spin_lock(&inode->i_lock); |
1202 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | ||
1157 | /* Directories and symlinks: invalidate page cache too */ | 1203 | /* Directories and symlinks: invalidate page cache too */ |
1158 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) | 1204 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) |
1159 | nfsi->flags |= NFS_INO_INVALID_DATA; | 1205 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
1206 | spin_unlock(&inode->i_lock); | ||
1160 | } | 1207 | } |
1161 | nfsi->cache_change_attribute ++; | 1208 | nfsi->cache_change_attribute ++; |
1162 | atomic_dec(&nfsi->data_updates); | 1209 | atomic_dec(&nfsi->data_updates); |
@@ -1181,6 +1228,8 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1181 | if (nfs_have_delegation(inode, FMODE_READ)) | 1228 | if (nfs_have_delegation(inode, FMODE_READ)) |
1182 | return 0; | 1229 | return 0; |
1183 | 1230 | ||
1231 | spin_lock(&inode->i_lock); | ||
1232 | |||
1184 | /* Are we in the process of updating data on the server? */ | 1233 | /* Are we in the process of updating data on the server? */ |
1185 | data_unstable = nfs_caches_unstable(inode); | 1234 | data_unstable = nfs_caches_unstable(inode); |
1186 | 1235 | ||
@@ -1189,19 +1238,23 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1189 | && nfsi->change_attr == fattr->pre_change_attr) | 1238 | && nfsi->change_attr == fattr->pre_change_attr) |
1190 | nfsi->change_attr = fattr->change_attr; | 1239 | nfsi->change_attr = fattr->change_attr; |
1191 | if (nfsi->change_attr != fattr->change_attr) { | 1240 | if (nfsi->change_attr != fattr->change_attr) { |
1192 | nfsi->flags |= NFS_INO_INVALID_ATTR; | 1241 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; |
1193 | if (!data_unstable) | 1242 | if (!data_unstable) |
1194 | nfsi->flags |= NFS_INO_REVAL_PAGECACHE; | 1243 | nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE; |
1195 | } | 1244 | } |
1196 | } | 1245 | } |
1197 | 1246 | ||
1198 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | 1247 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) { |
1248 | spin_unlock(&inode->i_lock); | ||
1199 | return 0; | 1249 | return 0; |
1250 | } | ||
1200 | 1251 | ||
1201 | /* Has the inode gone and changed behind our back? */ | 1252 | /* Has the inode gone and changed behind our back? */ |
1202 | if (nfsi->fileid != fattr->fileid | 1253 | if (nfsi->fileid != fattr->fileid |
1203 | || (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) | 1254 | || (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { |
1255 | spin_unlock(&inode->i_lock); | ||
1204 | return -EIO; | 1256 | return -EIO; |
1257 | } | ||
1205 | 1258 | ||
1206 | cur_size = i_size_read(inode); | 1259 | cur_size = i_size_read(inode); |
1207 | new_isize = nfs_size_to_loff_t(fattr->size); | 1260 | new_isize = nfs_size_to_loff_t(fattr->size); |
@@ -1216,30 +1269,31 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1216 | 1269 | ||
1217 | /* Verify a few of the more important attributes */ | 1270 | /* Verify a few of the more important attributes */ |
1218 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { | 1271 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { |
1219 | nfsi->flags |= NFS_INO_INVALID_ATTR; | 1272 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; |
1220 | if (!data_unstable) | 1273 | if (!data_unstable) |
1221 | nfsi->flags |= NFS_INO_REVAL_PAGECACHE; | 1274 | nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE; |
1222 | } | 1275 | } |
1223 | if (cur_size != new_isize) { | 1276 | if (cur_size != new_isize) { |
1224 | nfsi->flags |= NFS_INO_INVALID_ATTR; | 1277 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; |
1225 | if (nfsi->npages == 0) | 1278 | if (nfsi->npages == 0) |
1226 | nfsi->flags |= NFS_INO_REVAL_PAGECACHE; | 1279 | nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE; |
1227 | } | 1280 | } |
1228 | 1281 | ||
1229 | /* Have any file permissions changed? */ | 1282 | /* Have any file permissions changed? */ |
1230 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) | 1283 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) |
1231 | || inode->i_uid != fattr->uid | 1284 | || inode->i_uid != fattr->uid |
1232 | || inode->i_gid != fattr->gid) | 1285 | || inode->i_gid != fattr->gid) |
1233 | nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; | 1286 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; |
1234 | 1287 | ||
1235 | /* Has the link count changed? */ | 1288 | /* Has the link count changed? */ |
1236 | if (inode->i_nlink != fattr->nlink) | 1289 | if (inode->i_nlink != fattr->nlink) |
1237 | nfsi->flags |= NFS_INO_INVALID_ATTR; | 1290 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; |
1238 | 1291 | ||
1239 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) | 1292 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) |
1240 | nfsi->flags |= NFS_INO_INVALID_ATIME; | 1293 | nfsi->cache_validity |= NFS_INO_INVALID_ATIME; |
1241 | 1294 | ||
1242 | nfsi->read_cache_jiffies = fattr->timestamp; | 1295 | nfsi->read_cache_jiffies = fattr->timestamp; |
1296 | spin_unlock(&inode->i_lock); | ||
1243 | return 0; | 1297 | return 0; |
1244 | } | 1298 | } |
1245 | 1299 | ||
@@ -1278,11 +1332,15 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1278 | goto out_err; | 1332 | goto out_err; |
1279 | } | 1333 | } |
1280 | 1334 | ||
1335 | spin_lock(&inode->i_lock); | ||
1336 | |||
1281 | /* | 1337 | /* |
1282 | * Make sure the inode's type hasn't changed. | 1338 | * Make sure the inode's type hasn't changed. |
1283 | */ | 1339 | */ |
1284 | if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) | 1340 | if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { |
1341 | spin_unlock(&inode->i_lock); | ||
1285 | goto out_changed; | 1342 | goto out_changed; |
1343 | } | ||
1286 | 1344 | ||
1287 | /* | 1345 | /* |
1288 | * Update the read time so we don't revalidate too often. | 1346 | * Update the read time so we don't revalidate too often. |
@@ -1373,8 +1431,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1373 | || S_ISLNK(inode->i_mode))) | 1431 | || S_ISLNK(inode->i_mode))) |
1374 | invalid &= ~NFS_INO_INVALID_DATA; | 1432 | invalid &= ~NFS_INO_INVALID_DATA; |
1375 | if (!nfs_have_delegation(inode, FMODE_READ)) | 1433 | if (!nfs_have_delegation(inode, FMODE_READ)) |
1376 | nfsi->flags |= invalid; | 1434 | nfsi->cache_validity |= invalid; |
1377 | 1435 | ||
1436 | spin_unlock(&inode->i_lock); | ||
1378 | return 0; | 1437 | return 0; |
1379 | out_changed: | 1438 | out_changed: |
1380 | /* | 1439 | /* |
@@ -1391,7 +1450,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1391 | */ | 1450 | */ |
1392 | nfs_invalidate_inode(inode); | 1451 | nfs_invalidate_inode(inode); |
1393 | out_err: | 1452 | out_err: |
1394 | NFS_FLAGS(inode) |= NFS_INO_STALE; | 1453 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); |
1395 | return -ESTALE; | 1454 | return -ESTALE; |
1396 | } | 1455 | } |
1397 | 1456 | ||
@@ -1950,7 +2009,8 @@ static struct inode *nfs_alloc_inode(struct super_block *sb) | |||
1950 | nfsi = (struct nfs_inode *)kmem_cache_alloc(nfs_inode_cachep, SLAB_KERNEL); | 2009 | nfsi = (struct nfs_inode *)kmem_cache_alloc(nfs_inode_cachep, SLAB_KERNEL); |
1951 | if (!nfsi) | 2010 | if (!nfsi) |
1952 | return NULL; | 2011 | return NULL; |
1953 | nfsi->flags = 0; | 2012 | nfsi->flags = 0UL; |
2013 | nfsi->cache_validity = 0UL; | ||
1954 | #ifdef CONFIG_NFS_V3_ACL | 2014 | #ifdef CONFIG_NFS_V3_ACL |
1955 | nfsi->acl_access = ERR_PTR(-EAGAIN); | 2015 | nfsi->acl_access = ERR_PTR(-EAGAIN); |
1956 | nfsi->acl_default = ERR_PTR(-EAGAIN); | 2016 | nfsi->acl_default = ERR_PTR(-EAGAIN); |
@@ -1982,7 +2042,6 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) | |||
1982 | nfsi->ndirty = 0; | 2042 | nfsi->ndirty = 0; |
1983 | nfsi->ncommit = 0; | 2043 | nfsi->ncommit = 0; |
1984 | nfsi->npages = 0; | 2044 | nfsi->npages = 0; |
1985 | init_waitqueue_head(&nfsi->nfs_i_wait); | ||
1986 | nfs4_init_once(nfsi); | 2045 | nfs4_init_once(nfsi); |
1987 | } | 2046 | } |
1988 | } | 2047 | } |
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index 1b7a3ef2f813..6a5bbc0ae941 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c | |||
@@ -308,7 +308,9 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, | |||
308 | nfs_begin_data_update(inode); | 308 | nfs_begin_data_update(inode); |
309 | status = rpc_call(server->client_acl, ACLPROC3_SETACL, | 309 | status = rpc_call(server->client_acl, ACLPROC3_SETACL, |
310 | &args, &fattr, 0); | 310 | &args, &fattr, 0); |
311 | NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS; | 311 | spin_lock(&inode->i_lock); |
312 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS; | ||
313 | spin_unlock(&inode->i_lock); | ||
312 | nfs_end_data_update(inode); | 314 | nfs_end_data_update(inode); |
313 | dprintk("NFS reply setacl: %d\n", status); | 315 | dprintk("NFS reply setacl: %d\n", status); |
314 | 316 | ||
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 7851569b31c6..2681485cf2d0 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -120,6 +120,8 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
120 | dprintk("NFS call setattr\n"); | 120 | dprintk("NFS call setattr\n"); |
121 | fattr->valid = 0; | 121 | fattr->valid = 0; |
122 | status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0); | 122 | status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0); |
123 | if (status == 0) | ||
124 | nfs_setattr_update_inode(inode, sattr); | ||
123 | dprintk("NFS reply setattr: %d\n", status); | 125 | dprintk("NFS reply setattr: %d\n", status); |
124 | return status; | 126 | return status; |
125 | } | 127 | } |
@@ -370,6 +372,8 @@ again: | |||
370 | * not sure this buys us anything (and I'd have | 372 | * not sure this buys us anything (and I'd have |
371 | * to revamp the NFSv3 XDR code) */ | 373 | * to revamp the NFSv3 XDR code) */ |
372 | status = nfs3_proc_setattr(dentry, &fattr, sattr); | 374 | status = nfs3_proc_setattr(dentry, &fattr, sattr); |
375 | if (status == 0) | ||
376 | nfs_setattr_update_inode(dentry->d_inode, sattr); | ||
373 | nfs_refresh_inode(dentry->d_inode, &fattr); | 377 | nfs_refresh_inode(dentry->d_inode, &fattr); |
374 | dprintk("NFS reply setattr (post-create): %d\n", status); | 378 | dprintk("NFS reply setattr (post-create): %d\n", status); |
375 | } | 379 | } |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 1b76f80aedb9..0c5a308e4963 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -753,6 +753,7 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr, | |||
753 | .rpc_argp = &arg, | 753 | .rpc_argp = &arg, |
754 | .rpc_resp = &res, | 754 | .rpc_resp = &res, |
755 | }; | 755 | }; |
756 | int status; | ||
756 | 757 | ||
757 | fattr->valid = 0; | 758 | fattr->valid = 0; |
758 | 759 | ||
@@ -762,7 +763,8 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr, | |||
762 | } else | 763 | } else |
763 | memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); | 764 | memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); |
764 | 765 | ||
765 | return rpc_call_sync(server->client, &msg, 0); | 766 | status = rpc_call_sync(server->client, &msg, 0); |
767 | return status; | ||
766 | } | 768 | } |
767 | 769 | ||
768 | static int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr, | 770 | static int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr, |
@@ -1145,6 +1147,8 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
1145 | 1147 | ||
1146 | status = nfs4_do_setattr(NFS_SERVER(inode), fattr, | 1148 | status = nfs4_do_setattr(NFS_SERVER(inode), fattr, |
1147 | NFS_FH(inode), sattr, state); | 1149 | NFS_FH(inode), sattr, state); |
1150 | if (status == 0) | ||
1151 | nfs_setattr_update_inode(inode, sattr); | ||
1148 | if (state != NULL) | 1152 | if (state != NULL) |
1149 | nfs4_close_state(state, FMODE_WRITE); | 1153 | nfs4_close_state(state, FMODE_WRITE); |
1150 | put_rpccred(cred); | 1154 | put_rpccred(cred); |
@@ -1449,8 +1453,10 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
1449 | struct nfs_fattr fattr; | 1453 | struct nfs_fattr fattr; |
1450 | status = nfs4_do_setattr(NFS_SERVER(dir), &fattr, | 1454 | status = nfs4_do_setattr(NFS_SERVER(dir), &fattr, |
1451 | NFS_FH(state->inode), sattr, state); | 1455 | NFS_FH(state->inode), sattr, state); |
1452 | if (status == 0) | 1456 | if (status == 0) { |
1457 | nfs_setattr_update_inode(state->inode, sattr); | ||
1453 | goto out; | 1458 | goto out; |
1459 | } | ||
1454 | } else if (flags != 0) | 1460 | } else if (flags != 0) |
1455 | goto out; | 1461 | goto out; |
1456 | nfs4_close_state(state, flags); | 1462 | nfs4_close_state(state, flags); |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index cedf636bcf3c..be23c3fb9260 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -114,6 +114,8 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
114 | dprintk("NFS call setattr\n"); | 114 | dprintk("NFS call setattr\n"); |
115 | fattr->valid = 0; | 115 | fattr->valid = 0; |
116 | status = rpc_call(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, 0); | 116 | status = rpc_call(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, 0); |
117 | if (status == 0) | ||
118 | nfs_setattr_update_inode(inode, sattr); | ||
117 | dprintk("NFS reply setattr: %d\n", status); | 119 | dprintk("NFS reply setattr: %d\n", status); |
118 | return status; | 120 | return status; |
119 | } | 121 | } |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 6f866b8aa2d5..6ceb1d471f20 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -140,7 +140,9 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode, | |||
140 | if (rdata->res.eof != 0 || result == 0) | 140 | if (rdata->res.eof != 0 || result == 0) |
141 | break; | 141 | break; |
142 | } while (count); | 142 | } while (count); |
143 | NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME; | 143 | spin_lock(&inode->i_lock); |
144 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME; | ||
145 | spin_unlock(&inode->i_lock); | ||
144 | 146 | ||
145 | if (count) | 147 | if (count) |
146 | memclear_highpage_flush(page, rdata->args.pgbase, count); | 148 | memclear_highpage_flush(page, rdata->args.pgbase, count); |
@@ -473,7 +475,9 @@ void nfs_readpage_result(struct rpc_task *task) | |||
473 | } | 475 | } |
474 | task->tk_status = -EIO; | 476 | task->tk_status = -EIO; |
475 | } | 477 | } |
476 | NFS_FLAGS(data->inode) |= NFS_INO_INVALID_ATIME; | 478 | spin_lock(&data->inode->i_lock); |
479 | NFS_I(data->inode)->cache_validity |= NFS_INO_INVALID_ATIME; | ||
480 | spin_unlock(&data->inode->i_lock); | ||
477 | data->complete(data, status); | 481 | data->complete(data, status); |
478 | } | 482 | } |
479 | 483 | ||
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c index 35f106599144..18dc95b0b646 100644 --- a/fs/nfs/symlink.c +++ b/fs/nfs/symlink.c | |||
@@ -27,26 +27,14 @@ | |||
27 | 27 | ||
28 | /* Symlink caching in the page cache is even more simplistic | 28 | /* Symlink caching in the page cache is even more simplistic |
29 | * and straight-forward than readdir caching. | 29 | * and straight-forward than readdir caching. |
30 | * | ||
31 | * At the beginning of the page we store pointer to struct page in question, | ||
32 | * simplifying nfs_put_link() (if inode got invalidated we can't find the page | ||
33 | * to be freed via pagecache lookup). | ||
34 | * The NUL-terminated string follows immediately thereafter. | ||
35 | */ | 30 | */ |
36 | 31 | ||
37 | struct nfs_symlink { | ||
38 | struct page *page; | ||
39 | char body[0]; | ||
40 | }; | ||
41 | |||
42 | static int nfs_symlink_filler(struct inode *inode, struct page *page) | 32 | static int nfs_symlink_filler(struct inode *inode, struct page *page) |
43 | { | 33 | { |
44 | const unsigned int pgbase = offsetof(struct nfs_symlink, body); | ||
45 | const unsigned int pglen = PAGE_SIZE - pgbase; | ||
46 | int error; | 34 | int error; |
47 | 35 | ||
48 | lock_kernel(); | 36 | lock_kernel(); |
49 | error = NFS_PROTO(inode)->readlink(inode, page, pgbase, pglen); | 37 | error = NFS_PROTO(inode)->readlink(inode, page, 0, PAGE_SIZE); |
50 | unlock_kernel(); | 38 | unlock_kernel(); |
51 | if (error < 0) | 39 | if (error < 0) |
52 | goto error; | 40 | goto error; |
@@ -60,11 +48,10 @@ error: | |||
60 | return -EIO; | 48 | return -EIO; |
61 | } | 49 | } |
62 | 50 | ||
63 | static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd) | 51 | static void *nfs_follow_link(struct dentry *dentry, struct nameidata *nd) |
64 | { | 52 | { |
65 | struct inode *inode = dentry->d_inode; | 53 | struct inode *inode = dentry->d_inode; |
66 | struct page *page; | 54 | struct page *page; |
67 | struct nfs_symlink *p; | ||
68 | void *err = ERR_PTR(nfs_revalidate_inode(NFS_SERVER(inode), inode)); | 55 | void *err = ERR_PTR(nfs_revalidate_inode(NFS_SERVER(inode), inode)); |
69 | if (err) | 56 | if (err) |
70 | goto read_failed; | 57 | goto read_failed; |
@@ -78,28 +65,20 @@ static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
78 | err = ERR_PTR(-EIO); | 65 | err = ERR_PTR(-EIO); |
79 | goto getlink_read_error; | 66 | goto getlink_read_error; |
80 | } | 67 | } |
81 | p = kmap(page); | 68 | nd_set_link(nd, kmap(page)); |
82 | p->page = page; | 69 | return page; |
83 | nd_set_link(nd, p->body); | ||
84 | return 0; | ||
85 | 70 | ||
86 | getlink_read_error: | 71 | getlink_read_error: |
87 | page_cache_release(page); | 72 | page_cache_release(page); |
88 | read_failed: | 73 | read_failed: |
89 | nd_set_link(nd, err); | 74 | nd_set_link(nd, err); |
90 | return 0; | 75 | return NULL; |
91 | } | 76 | } |
92 | 77 | ||
93 | static void nfs_put_link(struct dentry *dentry, struct nameidata *nd) | 78 | static void nfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) |
94 | { | 79 | { |
95 | char *s = nd_get_link(nd); | 80 | if (cookie) { |
96 | if (!IS_ERR(s)) { | 81 | struct page *page = cookie; |
97 | struct nfs_symlink *p; | ||
98 | struct page *page; | ||
99 | |||
100 | p = container_of(s, struct nfs_symlink, body[0]); | ||
101 | page = p->page; | ||
102 | |||
103 | kunmap(page); | 82 | kunmap(page); |
104 | page_cache_release(page); | 83 | page_cache_release(page); |
105 | } | 84 | } |