diff options
-rw-r--r-- | fs/nfs/file.c | 12 | ||||
-rw-r--r-- | fs/nfs/inode.c | 44 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 1 |
3 files changed, 39 insertions, 18 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index a606708264ed..40436857ed42 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -333,9 +333,15 @@ nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t | |||
333 | result = -EBUSY; | 333 | result = -EBUSY; |
334 | if (IS_SWAPFILE(inode)) | 334 | if (IS_SWAPFILE(inode)) |
335 | goto out_swapfile; | 335 | goto out_swapfile; |
336 | result = nfs_revalidate_inode(NFS_SERVER(inode), inode); | 336 | /* |
337 | if (result) | 337 | * O_APPEND implies that we must revalidate the file length. |
338 | goto out; | 338 | */ |
339 | if (iocb->ki_filp->f_flags & O_APPEND) { | ||
340 | result = nfs_revalidate_file_size(inode, iocb->ki_filp); | ||
341 | if (result) | ||
342 | goto out; | ||
343 | } else | ||
344 | nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping); | ||
339 | 345 | ||
340 | result = count; | 346 | result = count; |
341 | if (!count) | 347 | if (!count) |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index b2d16758ced8..a3922f4cc0a8 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -1062,21 +1062,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1062 | if (verifier == nfsi->cache_change_attribute) | 1062 | if (verifier == nfsi->cache_change_attribute) |
1063 | nfsi->flags &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | 1063 | nfsi->flags &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); |
1064 | /* Do the page cache invalidation */ | 1064 | /* Do the page cache invalidation */ |
1065 | if (flags & NFS_INO_INVALID_DATA) { | 1065 | nfs_revalidate_mapping(inode, inode->i_mapping); |
1066 | if (S_ISREG(inode->i_mode)) { | ||
1067 | if (filemap_fdatawrite(inode->i_mapping) == 0) | ||
1068 | filemap_fdatawait(inode->i_mapping); | ||
1069 | nfs_wb_all(inode); | ||
1070 | } | ||
1071 | nfsi->flags &= ~NFS_INO_INVALID_DATA; | ||
1072 | invalidate_inode_pages2(inode->i_mapping); | ||
1073 | memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); | ||
1074 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", | ||
1075 | inode->i_sb->s_id, | ||
1076 | (long long)NFS_FILEID(inode)); | ||
1077 | /* This ensures we revalidate dentries */ | ||
1078 | nfsi->cache_change_attribute++; | ||
1079 | } | ||
1080 | if (flags & NFS_INO_INVALID_ACL) | 1066 | if (flags & NFS_INO_INVALID_ACL) |
1081 | nfs_zap_acl_cache(inode); | 1067 | nfs_zap_acl_cache(inode); |
1082 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", | 1068 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", |
@@ -1116,6 +1102,34 @@ int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1116 | } | 1102 | } |
1117 | 1103 | ||
1118 | /** | 1104 | /** |
1105 | * nfs_revalidate_mapping - Revalidate the pagecache | ||
1106 | * @inode - pointer to host inode | ||
1107 | * @mapping - pointer to mapping | ||
1108 | */ | ||
1109 | void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | ||
1110 | { | ||
1111 | struct nfs_inode *nfsi = NFS_I(inode); | ||
1112 | |||
1113 | if (nfsi->flags & NFS_INO_INVALID_DATA) { | ||
1114 | if (S_ISREG(inode->i_mode)) { | ||
1115 | if (filemap_fdatawrite(mapping) == 0) | ||
1116 | filemap_fdatawait(mapping); | ||
1117 | nfs_wb_all(inode); | ||
1118 | } | ||
1119 | invalidate_inode_pages2(mapping); | ||
1120 | nfsi->flags &= ~NFS_INO_INVALID_DATA; | ||
1121 | if (S_ISDIR(inode->i_mode)) { | ||
1122 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | ||
1123 | /* This ensures we revalidate child dentries */ | ||
1124 | nfsi->cache_change_attribute++; | ||
1125 | } | ||
1126 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", | ||
1127 | inode->i_sb->s_id, | ||
1128 | (long long)NFS_FILEID(inode)); | ||
1129 | } | ||
1130 | } | ||
1131 | |||
1132 | /** | ||
1119 | * nfs_begin_data_update | 1133 | * nfs_begin_data_update |
1120 | * @inode - pointer to inode | 1134 | * @inode - pointer to inode |
1121 | * Declare that a set of operations will update file data on the server | 1135 | * Declare that a set of operations will update file data on the server |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 211266c56ce5..443103c13e53 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -289,6 +289,7 @@ extern int nfs_release(struct inode *, struct file *); | |||
289 | extern int nfs_attribute_timeout(struct inode *inode); | 289 | extern int nfs_attribute_timeout(struct inode *inode); |
290 | extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode); | 290 | extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode); |
291 | extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); | 291 | extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); |
292 | extern void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); | ||
292 | extern int nfs_setattr(struct dentry *, struct iattr *); | 293 | extern int nfs_setattr(struct dentry *, struct iattr *); |
293 | extern void nfs_begin_attr_update(struct inode *); | 294 | extern void nfs_begin_attr_update(struct inode *); |
294 | extern void nfs_end_attr_update(struct inode *); | 295 | extern void nfs_end_attr_update(struct inode *); |