diff options
-rw-r--r-- | fs/nfs/dir.c | 6 | ||||
-rw-r--r-- | fs/nfs/direct.c | 13 | ||||
-rw-r--r-- | fs/nfs/inode.c | 28 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 1 |
4 files changed, 30 insertions, 18 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 481f8892a919..58d44057813e 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -203,8 +203,10 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) | |||
203 | * Note: assumes we have exclusive access to this mapping either | 203 | * Note: assumes we have exclusive access to this mapping either |
204 | * through inode->i_mutex or some other mechanism. | 204 | * through inode->i_mutex or some other mechanism. |
205 | */ | 205 | */ |
206 | if (page->index == 0) | 206 | if (page->index == 0 && invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1) < 0) { |
207 | invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1); | 207 | /* Should never happen */ |
208 | nfs_zap_mapping(inode, inode->i_mapping); | ||
209 | } | ||
208 | unlock_page(page); | 210 | unlock_page(page); |
209 | return 0; | 211 | return 0; |
210 | error: | 212 | error: |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 1e873fcab947..bdfabf854a51 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -497,6 +497,7 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode | |||
497 | if (dreq->commit_data != NULL) | 497 | if (dreq->commit_data != NULL) |
498 | nfs_commit_free(dreq->commit_data); | 498 | nfs_commit_free(dreq->commit_data); |
499 | nfs_direct_free_writedata(dreq); | 499 | nfs_direct_free_writedata(dreq); |
500 | nfs_zap_mapping(inode, inode->i_mapping); | ||
500 | nfs_direct_complete(dreq); | 501 | nfs_direct_complete(dreq); |
501 | } | 502 | } |
502 | } | 503 | } |
@@ -517,6 +518,7 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode | |||
517 | { | 518 | { |
518 | nfs_end_data_update(inode); | 519 | nfs_end_data_update(inode); |
519 | nfs_direct_free_writedata(dreq); | 520 | nfs_direct_free_writedata(dreq); |
521 | nfs_zap_mapping(inode, inode->i_mapping); | ||
520 | nfs_direct_complete(dreq); | 522 | nfs_direct_complete(dreq); |
521 | } | 523 | } |
522 | #endif | 524 | #endif |
@@ -830,17 +832,6 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
830 | 832 | ||
831 | retval = nfs_direct_write(iocb, (unsigned long) buf, count, pos); | 833 | retval = nfs_direct_write(iocb, (unsigned long) buf, count, pos); |
832 | 834 | ||
833 | /* | ||
834 | * XXX: nfs_end_data_update() already ensures this file's | ||
835 | * cached data is subsequently invalidated. Do we really | ||
836 | * need to call invalidate_inode_pages2() again here? | ||
837 | * | ||
838 | * For aio writes, this invalidation will almost certainly | ||
839 | * occur before the writes complete. Kind of racey. | ||
840 | */ | ||
841 | if (mapping->nrpages) | ||
842 | invalidate_inode_pages2(mapping); | ||
843 | |||
844 | if (retval > 0) | 835 | if (retval > 0) |
845 | iocb->ki_pos = pos + retval; | 836 | iocb->ki_pos = pos + retval; |
846 | 837 | ||
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index bc9376ca86cd..9979ad1cf8eb 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -131,6 +131,15 @@ void nfs_zap_caches(struct inode *inode) | |||
131 | spin_unlock(&inode->i_lock); | 131 | spin_unlock(&inode->i_lock); |
132 | } | 132 | } |
133 | 133 | ||
134 | void nfs_zap_mapping(struct inode *inode, struct address_space *mapping) | ||
135 | { | ||
136 | if (mapping->nrpages != 0) { | ||
137 | spin_lock(&inode->i_lock); | ||
138 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA; | ||
139 | spin_unlock(&inode->i_lock); | ||
140 | } | ||
141 | } | ||
142 | |||
134 | static void nfs_zap_acl_cache(struct inode *inode) | 143 | static void nfs_zap_acl_cache(struct inode *inode) |
135 | { | 144 | { |
136 | void (*clear_acl_cache)(struct inode *); | 145 | void (*clear_acl_cache)(struct inode *); |
@@ -671,13 +680,20 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | |||
671 | if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) | 680 | if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) |
672 | || nfs_attribute_timeout(inode)) | 681 | || nfs_attribute_timeout(inode)) |
673 | ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode); | 682 | ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode); |
683 | if (ret < 0) | ||
684 | goto out; | ||
674 | 685 | ||
675 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) { | 686 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) { |
676 | nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); | 687 | if (mapping->nrpages != 0) { |
677 | if (S_ISREG(inode->i_mode)) | 688 | if (S_ISREG(inode->i_mode)) { |
678 | nfs_sync_mapping(mapping); | 689 | ret = nfs_sync_mapping(mapping); |
679 | invalidate_inode_pages2(mapping); | 690 | if (ret < 0) |
680 | 691 | goto out; | |
692 | } | ||
693 | ret = invalidate_inode_pages2(mapping); | ||
694 | if (ret < 0) | ||
695 | goto out; | ||
696 | } | ||
681 | spin_lock(&inode->i_lock); | 697 | spin_lock(&inode->i_lock); |
682 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; | 698 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; |
683 | if (S_ISDIR(inode->i_mode)) { | 699 | if (S_ISDIR(inode->i_mode)) { |
@@ -687,10 +703,12 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | |||
687 | } | 703 | } |
688 | spin_unlock(&inode->i_lock); | 704 | spin_unlock(&inode->i_lock); |
689 | 705 | ||
706 | nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); | ||
690 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", | 707 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", |
691 | inode->i_sb->s_id, | 708 | inode->i_sb->s_id, |
692 | (long long)NFS_FILEID(inode)); | 709 | (long long)NFS_FILEID(inode)); |
693 | } | 710 | } |
711 | out: | ||
694 | return ret; | 712 | return ret; |
695 | } | 713 | } |
696 | 714 | ||
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 76ff54846ada..6b2de1be5815 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -290,6 +290,7 @@ static inline int nfs_verify_change_attribute(struct inode *inode, unsigned long | |||
290 | * linux/fs/nfs/inode.c | 290 | * linux/fs/nfs/inode.c |
291 | */ | 291 | */ |
292 | extern int nfs_sync_mapping(struct address_space *mapping); | 292 | extern int nfs_sync_mapping(struct address_space *mapping); |
293 | extern void nfs_zap_mapping(struct inode *inode, struct address_space *mapping); | ||
293 | extern void nfs_zap_caches(struct inode *); | 294 | extern void nfs_zap_caches(struct inode *); |
294 | extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *, | 295 | extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *, |
295 | struct nfs_fattr *); | 296 | struct nfs_fattr *); |