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 | 162 | ||||
-rw-r--r-- | fs/nfs/nfs3acl.c | 4 | ||||
-rw-r--r-- | fs/nfs/read.c | 8 | ||||
-rw-r--r-- | fs/nfs/symlink.c | 37 |
6 files changed, 144 insertions, 100 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 bb7ca022bcb2..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 |
@@ -841,7 +847,9 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | |||
841 | inode->i_uid = attr->ia_uid; | 847 | inode->i_uid = attr->ia_uid; |
842 | if ((attr->ia_valid & ATTR_GID) != 0) | 848 | if ((attr->ia_valid & ATTR_GID) != 0) |
843 | inode->i_gid = attr->ia_gid; | 849 | inode->i_gid = attr->ia_gid; |
844 | NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 850 | spin_lock(&inode->i_lock); |
851 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
852 | spin_unlock(&inode->i_lock); | ||
845 | } | 853 | } |
846 | if ((attr->ia_valid & ATTR_SIZE) != 0) { | 854 | if ((attr->ia_valid & ATTR_SIZE) != 0) { |
847 | inode->i_size = attr->ia_size; | 855 | inode->i_size = attr->ia_size; |
@@ -849,31 +857,47 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | |||
849 | } | 857 | } |
850 | } | 858 | } |
851 | 859 | ||
860 | static int nfs_wait_schedule(void *word) | ||
861 | { | ||
862 | if (signal_pending(current)) | ||
863 | return -ERESTARTSYS; | ||
864 | schedule(); | ||
865 | return 0; | ||
866 | } | ||
867 | |||
852 | /* | 868 | /* |
853 | * Wait for the inode to get unlocked. | 869 | * Wait for the inode to get unlocked. |
854 | * (Used for NFS_INO_LOCKED and NFS_INO_REVALIDATING). | ||
855 | */ | 870 | */ |
856 | static int | 871 | static int nfs_wait_on_inode(struct inode *inode) |
857 | nfs_wait_on_inode(struct inode *inode, int flag) | ||
858 | { | 872 | { |
859 | struct rpc_clnt *clnt = NFS_CLIENT(inode); | 873 | struct rpc_clnt *clnt = NFS_CLIENT(inode); |
860 | struct nfs_inode *nfsi = NFS_I(inode); | 874 | struct nfs_inode *nfsi = NFS_I(inode); |
861 | 875 | sigset_t oldmask; | |
862 | int error; | 876 | int error; |
863 | if (!(NFS_FLAGS(inode) & flag)) | 877 | |
864 | return 0; | ||
865 | atomic_inc(&inode->i_count); | 878 | atomic_inc(&inode->i_count); |
866 | error = nfs_wait_event(clnt, nfsi->nfs_i_wait, | 879 | rpc_clnt_sigmask(clnt, &oldmask); |
867 | !(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); | ||
868 | iput(inode); | 883 | iput(inode); |
884 | |||
869 | return error; | 885 | return error; |
870 | } | 886 | } |
871 | 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 | |||
872 | 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) |
873 | { | 898 | { |
874 | struct inode *inode = dentry->d_inode; | 899 | struct inode *inode = dentry->d_inode; |
875 | struct nfs_inode *nfsi = NFS_I(inode); | 900 | int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; |
876 | int need_atime = nfsi->flags & NFS_INO_INVALID_ATIME; | ||
877 | int err; | 901 | int err; |
878 | 902 | ||
879 | if (__IS_FLG(inode, MS_NOATIME)) | 903 | if (__IS_FLG(inode, MS_NOATIME)) |
@@ -1019,7 +1043,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1019 | struct nfs_fattr fattr; | 1043 | struct nfs_fattr fattr; |
1020 | struct nfs_inode *nfsi = NFS_I(inode); | 1044 | struct nfs_inode *nfsi = NFS_I(inode); |
1021 | unsigned long verifier; | 1045 | unsigned long verifier; |
1022 | unsigned int flags; | 1046 | unsigned long cache_validity; |
1023 | 1047 | ||
1024 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", | 1048 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", |
1025 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); | 1049 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); |
@@ -1030,18 +1054,19 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1030 | if (NFS_STALE(inode)) | 1054 | if (NFS_STALE(inode)) |
1031 | goto out_nowait; | 1055 | goto out_nowait; |
1032 | 1056 | ||
1033 | while (NFS_REVALIDATING(inode)) { | 1057 | status = nfs_wait_on_inode(inode); |
1034 | status = nfs_wait_on_inode(inode, NFS_INO_REVALIDATING); | 1058 | if (status < 0) |
1035 | if (status < 0) | 1059 | goto out; |
1036 | goto out_nowait; | 1060 | if (NFS_STALE(inode)) { |
1037 | if (NFS_ATTRTIMEO(inode) == 0) | 1061 | status = -ESTALE; |
1038 | continue; | 1062 | /* Do we trust the cached ESTALE? */ |
1039 | if (NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME)) | 1063 | if (NFS_ATTRTIMEO(inode) != 0) { |
1040 | continue; | 1064 | if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME)) { |
1041 | status = NFS_STALE(inode) ? -ESTALE : 0; | 1065 | /* no */ |
1042 | goto out_nowait; | 1066 | } else |
1067 | goto out; | ||
1068 | } | ||
1043 | } | 1069 | } |
1044 | NFS_FLAGS(inode) |= NFS_INO_REVALIDATING; | ||
1045 | 1070 | ||
1046 | /* Protect against RPC races by saving the change attribute */ | 1071 | /* Protect against RPC races by saving the change attribute */ |
1047 | verifier = nfs_save_change_attribute(inode); | 1072 | verifier = nfs_save_change_attribute(inode); |
@@ -1053,7 +1078,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1053 | if (status == -ESTALE) { | 1078 | if (status == -ESTALE) { |
1054 | nfs_zap_caches(inode); | 1079 | nfs_zap_caches(inode); |
1055 | if (!S_ISDIR(inode->i_mode)) | 1080 | if (!S_ISDIR(inode->i_mode)) |
1056 | NFS_FLAGS(inode) |= NFS_INO_STALE; | 1081 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); |
1057 | } | 1082 | } |
1058 | goto out; | 1083 | goto out; |
1059 | } | 1084 | } |
@@ -1065,25 +1090,30 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1065 | (long long)NFS_FILEID(inode), status); | 1090 | (long long)NFS_FILEID(inode), status); |
1066 | goto out; | 1091 | goto out; |
1067 | } | 1092 | } |
1068 | flags = nfsi->flags; | 1093 | spin_lock(&inode->i_lock); |
1069 | nfsi->flags &= ~NFS_INO_REVAL_PAGECACHE; | 1094 | cache_validity = nfsi->cache_validity; |
1095 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; | ||
1096 | |||
1070 | /* | 1097 | /* |
1071 | * We may need to keep the attributes marked as invalid if | 1098 | * We may need to keep the attributes marked as invalid if |
1072 | * we raced with nfs_end_attr_update(). | 1099 | * we raced with nfs_end_attr_update(). |
1073 | */ | 1100 | */ |
1074 | if (verifier == nfsi->cache_change_attribute) | 1101 | if (verifier == nfsi->cache_change_attribute) |
1075 | nfsi->flags &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | 1102 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); |
1076 | /* Do the page cache invalidation */ | 1103 | spin_unlock(&inode->i_lock); |
1104 | |||
1077 | nfs_revalidate_mapping(inode, inode->i_mapping); | 1105 | nfs_revalidate_mapping(inode, inode->i_mapping); |
1078 | if (flags & NFS_INO_INVALID_ACL) | 1106 | |
1107 | if (cache_validity & NFS_INO_INVALID_ACL) | ||
1079 | nfs_zap_acl_cache(inode); | 1108 | nfs_zap_acl_cache(inode); |
1109 | |||
1080 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", | 1110 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", |
1081 | inode->i_sb->s_id, | 1111 | inode->i_sb->s_id, |
1082 | (long long)NFS_FILEID(inode)); | 1112 | (long long)NFS_FILEID(inode)); |
1083 | 1113 | ||
1084 | out: | 1114 | out: |
1085 | NFS_FLAGS(inode) &= ~NFS_INO_REVALIDATING; | 1115 | nfs_wake_up_inode(inode); |
1086 | wake_up(&nfsi->nfs_i_wait); | 1116 | |
1087 | out_nowait: | 1117 | out_nowait: |
1088 | unlock_kernel(); | 1118 | unlock_kernel(); |
1089 | return status; | 1119 | return status; |
@@ -1107,7 +1137,7 @@ int nfs_attribute_timeout(struct inode *inode) | |||
1107 | */ | 1137 | */ |
1108 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | 1138 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) |
1109 | { | 1139 | { |
1110 | 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)) |
1111 | && !nfs_attribute_timeout(inode)) | 1141 | && !nfs_attribute_timeout(inode)) |
1112 | return NFS_STALE(inode) ? -ESTALE : 0; | 1142 | return NFS_STALE(inode) ? -ESTALE : 0; |
1113 | return __nfs_revalidate_inode(server, inode); | 1143 | return __nfs_revalidate_inode(server, inode); |
@@ -1122,19 +1152,23 @@ void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | |||
1122 | { | 1152 | { |
1123 | struct nfs_inode *nfsi = NFS_I(inode); | 1153 | struct nfs_inode *nfsi = NFS_I(inode); |
1124 | 1154 | ||
1125 | if (nfsi->flags & NFS_INO_INVALID_DATA) { | 1155 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) { |
1126 | if (S_ISREG(inode->i_mode)) { | 1156 | if (S_ISREG(inode->i_mode)) { |
1127 | if (filemap_fdatawrite(mapping) == 0) | 1157 | if (filemap_fdatawrite(mapping) == 0) |
1128 | filemap_fdatawait(mapping); | 1158 | filemap_fdatawait(mapping); |
1129 | nfs_wb_all(inode); | 1159 | nfs_wb_all(inode); |
1130 | } | 1160 | } |
1131 | invalidate_inode_pages2(mapping); | 1161 | invalidate_inode_pages2(mapping); |
1132 | nfsi->flags &= ~NFS_INO_INVALID_DATA; | 1162 | |
1163 | spin_lock(&inode->i_lock); | ||
1164 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; | ||
1133 | if (S_ISDIR(inode->i_mode)) { | 1165 | if (S_ISDIR(inode->i_mode)) { |
1134 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | 1166 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); |
1135 | /* This ensures we revalidate child dentries */ | 1167 | /* This ensures we revalidate child dentries */ |
1136 | nfsi->cache_change_attribute++; | 1168 | nfsi->cache_change_attribute++; |
1137 | } | 1169 | } |
1170 | spin_unlock(&inode->i_lock); | ||
1171 | |||
1138 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", | 1172 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", |
1139 | inode->i_sb->s_id, | 1173 | inode->i_sb->s_id, |
1140 | (long long)NFS_FILEID(inode)); | 1174 | (long long)NFS_FILEID(inode)); |
@@ -1164,10 +1198,12 @@ void nfs_end_data_update(struct inode *inode) | |||
1164 | 1198 | ||
1165 | if (!nfs_have_delegation(inode, FMODE_READ)) { | 1199 | if (!nfs_have_delegation(inode, FMODE_READ)) { |
1166 | /* Mark the attribute cache for revalidation */ | 1200 | /* Mark the attribute cache for revalidation */ |
1167 | nfsi->flags |= NFS_INO_INVALID_ATTR; | 1201 | spin_lock(&inode->i_lock); |
1202 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | ||
1168 | /* Directories and symlinks: invalidate page cache too */ | 1203 | /* Directories and symlinks: invalidate page cache too */ |
1169 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) | 1204 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) |
1170 | nfsi->flags |= NFS_INO_INVALID_DATA; | 1205 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
1206 | spin_unlock(&inode->i_lock); | ||
1171 | } | 1207 | } |
1172 | nfsi->cache_change_attribute ++; | 1208 | nfsi->cache_change_attribute ++; |
1173 | atomic_dec(&nfsi->data_updates); | 1209 | atomic_dec(&nfsi->data_updates); |
@@ -1192,6 +1228,8 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1192 | if (nfs_have_delegation(inode, FMODE_READ)) | 1228 | if (nfs_have_delegation(inode, FMODE_READ)) |
1193 | return 0; | 1229 | return 0; |
1194 | 1230 | ||
1231 | spin_lock(&inode->i_lock); | ||
1232 | |||
1195 | /* Are we in the process of updating data on the server? */ | 1233 | /* Are we in the process of updating data on the server? */ |
1196 | data_unstable = nfs_caches_unstable(inode); | 1234 | data_unstable = nfs_caches_unstable(inode); |
1197 | 1235 | ||
@@ -1200,19 +1238,23 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1200 | && nfsi->change_attr == fattr->pre_change_attr) | 1238 | && nfsi->change_attr == fattr->pre_change_attr) |
1201 | nfsi->change_attr = fattr->change_attr; | 1239 | nfsi->change_attr = fattr->change_attr; |
1202 | if (nfsi->change_attr != fattr->change_attr) { | 1240 | if (nfsi->change_attr != fattr->change_attr) { |
1203 | nfsi->flags |= NFS_INO_INVALID_ATTR; | 1241 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; |
1204 | if (!data_unstable) | 1242 | if (!data_unstable) |
1205 | nfsi->flags |= NFS_INO_REVAL_PAGECACHE; | 1243 | nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE; |
1206 | } | 1244 | } |
1207 | } | 1245 | } |
1208 | 1246 | ||
1209 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | 1247 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) { |
1248 | spin_unlock(&inode->i_lock); | ||
1210 | return 0; | 1249 | return 0; |
1250 | } | ||
1211 | 1251 | ||
1212 | /* Has the inode gone and changed behind our back? */ | 1252 | /* Has the inode gone and changed behind our back? */ |
1213 | if (nfsi->fileid != fattr->fileid | 1253 | if (nfsi->fileid != fattr->fileid |
1214 | || (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); | ||
1215 | return -EIO; | 1256 | return -EIO; |
1257 | } | ||
1216 | 1258 | ||
1217 | cur_size = i_size_read(inode); | 1259 | cur_size = i_size_read(inode); |
1218 | new_isize = nfs_size_to_loff_t(fattr->size); | 1260 | new_isize = nfs_size_to_loff_t(fattr->size); |
@@ -1227,30 +1269,31 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1227 | 1269 | ||
1228 | /* Verify a few of the more important attributes */ | 1270 | /* Verify a few of the more important attributes */ |
1229 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { | 1271 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { |
1230 | nfsi->flags |= NFS_INO_INVALID_ATTR; | 1272 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; |
1231 | if (!data_unstable) | 1273 | if (!data_unstable) |
1232 | nfsi->flags |= NFS_INO_REVAL_PAGECACHE; | 1274 | nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE; |
1233 | } | 1275 | } |
1234 | if (cur_size != new_isize) { | 1276 | if (cur_size != new_isize) { |
1235 | nfsi->flags |= NFS_INO_INVALID_ATTR; | 1277 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; |
1236 | if (nfsi->npages == 0) | 1278 | if (nfsi->npages == 0) |
1237 | nfsi->flags |= NFS_INO_REVAL_PAGECACHE; | 1279 | nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE; |
1238 | } | 1280 | } |
1239 | 1281 | ||
1240 | /* Have any file permissions changed? */ | 1282 | /* Have any file permissions changed? */ |
1241 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) | 1283 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) |
1242 | || inode->i_uid != fattr->uid | 1284 | || inode->i_uid != fattr->uid |
1243 | || inode->i_gid != fattr->gid) | 1285 | || inode->i_gid != fattr->gid) |
1244 | 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; |
1245 | 1287 | ||
1246 | /* Has the link count changed? */ | 1288 | /* Has the link count changed? */ |
1247 | if (inode->i_nlink != fattr->nlink) | 1289 | if (inode->i_nlink != fattr->nlink) |
1248 | nfsi->flags |= NFS_INO_INVALID_ATTR; | 1290 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; |
1249 | 1291 | ||
1250 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) | 1292 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) |
1251 | nfsi->flags |= NFS_INO_INVALID_ATIME; | 1293 | nfsi->cache_validity |= NFS_INO_INVALID_ATIME; |
1252 | 1294 | ||
1253 | nfsi->read_cache_jiffies = fattr->timestamp; | 1295 | nfsi->read_cache_jiffies = fattr->timestamp; |
1296 | spin_unlock(&inode->i_lock); | ||
1254 | return 0; | 1297 | return 0; |
1255 | } | 1298 | } |
1256 | 1299 | ||
@@ -1289,11 +1332,15 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1289 | goto out_err; | 1332 | goto out_err; |
1290 | } | 1333 | } |
1291 | 1334 | ||
1335 | spin_lock(&inode->i_lock); | ||
1336 | |||
1292 | /* | 1337 | /* |
1293 | * Make sure the inode's type hasn't changed. | 1338 | * Make sure the inode's type hasn't changed. |
1294 | */ | 1339 | */ |
1295 | 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); | ||
1296 | goto out_changed; | 1342 | goto out_changed; |
1343 | } | ||
1297 | 1344 | ||
1298 | /* | 1345 | /* |
1299 | * Update the read time so we don't revalidate too often. | 1346 | * Update the read time so we don't revalidate too often. |
@@ -1384,8 +1431,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1384 | || S_ISLNK(inode->i_mode))) | 1431 | || S_ISLNK(inode->i_mode))) |
1385 | invalid &= ~NFS_INO_INVALID_DATA; | 1432 | invalid &= ~NFS_INO_INVALID_DATA; |
1386 | if (!nfs_have_delegation(inode, FMODE_READ)) | 1433 | if (!nfs_have_delegation(inode, FMODE_READ)) |
1387 | nfsi->flags |= invalid; | 1434 | nfsi->cache_validity |= invalid; |
1388 | 1435 | ||
1436 | spin_unlock(&inode->i_lock); | ||
1389 | return 0; | 1437 | return 0; |
1390 | out_changed: | 1438 | out_changed: |
1391 | /* | 1439 | /* |
@@ -1402,7 +1450,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1402 | */ | 1450 | */ |
1403 | nfs_invalidate_inode(inode); | 1451 | nfs_invalidate_inode(inode); |
1404 | out_err: | 1452 | out_err: |
1405 | NFS_FLAGS(inode) |= NFS_INO_STALE; | 1453 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); |
1406 | return -ESTALE; | 1454 | return -ESTALE; |
1407 | } | 1455 | } |
1408 | 1456 | ||
@@ -1961,7 +2009,8 @@ static struct inode *nfs_alloc_inode(struct super_block *sb) | |||
1961 | 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); |
1962 | if (!nfsi) | 2010 | if (!nfsi) |
1963 | return NULL; | 2011 | return NULL; |
1964 | nfsi->flags = 0; | 2012 | nfsi->flags = 0UL; |
2013 | nfsi->cache_validity = 0UL; | ||
1965 | #ifdef CONFIG_NFS_V3_ACL | 2014 | #ifdef CONFIG_NFS_V3_ACL |
1966 | nfsi->acl_access = ERR_PTR(-EAGAIN); | 2015 | nfsi->acl_access = ERR_PTR(-EAGAIN); |
1967 | nfsi->acl_default = ERR_PTR(-EAGAIN); | 2016 | nfsi->acl_default = ERR_PTR(-EAGAIN); |
@@ -1993,7 +2042,6 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) | |||
1993 | nfsi->ndirty = 0; | 2042 | nfsi->ndirty = 0; |
1994 | nfsi->ncommit = 0; | 2043 | nfsi->ncommit = 0; |
1995 | nfsi->npages = 0; | 2044 | nfsi->npages = 0; |
1996 | init_waitqueue_head(&nfsi->nfs_i_wait); | ||
1997 | nfs4_init_once(nfsi); | 2045 | nfs4_init_once(nfsi); |
1998 | } | 2046 | } |
1999 | } | 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/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 | } |