fs/nfs/direct.c | 7 +------ fs/nfs/inode.c | 23 +++++++++++++++++++++++ fs/nfs/write.c | 4 ++-- include/linux/nfs_fs.h | 1 + 4 files changed, 27 insertions(+), 8 deletions(-) diff -u --recursive --new-file --show-c-function linux-2.6.5-09-fix_integrity/fs/nfs/direct.c linux-2.6.5-10-attr2/fs/nfs/direct.c --- linux-2.6.5-09-fix_integrity/fs/nfs/direct.c 2004-03-24 00:46:06.000000000 -0500 +++ linux-2.6.5-10-attr2/fs/nfs/direct.c 2004-03-24 00:46:48.000000000 -0500 @@ -337,8 +337,7 @@ retry: VERF_SIZE) != 0) goto sync_retry; } - nfs_end_data_update(inode); - NFS_FLAGS(inode) |= NFS_INO_INVALID_DATA; + nfs_end_data_update_defer(inode); return tot_bytes; @@ -397,10 +396,6 @@ nfs_direct_write(struct inode *inode, st if (result < size) break; } - /* Zap the page cache if we managed to write */ - if (tot_bytes > 0) - invalidate_remote_inode(inode); - return tot_bytes; } diff -u --recursive --new-file --show-c-function linux-2.6.5-09-fix_integrity/fs/nfs/inode.c linux-2.6.5-10-attr2/fs/nfs/inode.c --- linux-2.6.5-09-fix_integrity/fs/nfs/inode.c 2004-03-23 10:33:39.000000000 -0500 +++ linux-2.6.5-10-attr2/fs/nfs/inode.c 2004-03-24 00:46:49.000000000 -0500 @@ -1012,6 +1012,8 @@ void nfs_begin_data_update(struct inode * nfs_end_data_update * @inode - pointer to inode * Declare end of the operations that will update file data + * This will mark the inode as immediately needing revalidation + * of its attribute cache. */ void nfs_end_data_update(struct inode *inode) { @@ -1027,6 +1029,27 @@ void nfs_end_data_update(struct inode *i } /** + * nfs_end_data_update_defer + * @inode - pointer to inode + * Declare end of the operations that will update file data + * This will defer marking the inode as needing revalidation + * unless there are no other pending updates. + */ +void nfs_end_data_update_defer(struct inode *inode) +{ + struct nfs_inode *nfsi = NFS_I(inode); + + if (atomic_dec_and_test(&nfsi->data_updates)) { + /* Mark the attribute cache for revalidation */ + nfsi->flags |= NFS_INO_INVALID_ATTR; + /* Directories and symlinks: invalidate page cache too */ + if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) + nfsi->flags |= NFS_INO_INVALID_DATA; + nfsi->cache_change_attribute ++; + } +} + +/** * nfs_refresh_inode - verify consistency of the inode attribute cache * @inode - pointer to inode * @fattr - updated attributes diff -u --recursive --new-file --show-c-function linux-2.6.5-09-fix_integrity/fs/nfs/write.c linux-2.6.5-10-attr2/fs/nfs/write.c --- linux-2.6.5-09-fix_integrity/fs/nfs/write.c 2004-03-24 00:46:33.000000000 -0500 +++ linux-2.6.5-10-attr2/fs/nfs/write.c 2004-03-24 00:46:49.000000000 -0500 @@ -233,7 +233,7 @@ static int nfs_writepage_sync(struct fil ClearPageError(page); io_error: - nfs_end_data_update(inode); + nfs_end_data_update_defer(inode); if (wdata.cred) put_rpccred(wdata.cred); @@ -404,7 +404,7 @@ nfs_inode_remove_request(struct nfs_page nfsi->npages--; if (!nfsi->npages) { spin_unlock(&nfs_wreq_lock); - nfs_end_data_update(inode); + nfs_end_data_update_defer(inode); iput(inode); } else spin_unlock(&nfs_wreq_lock); diff -u --recursive --new-file --show-c-function linux-2.6.5-09-fix_integrity/include/linux/nfs_fs.h linux-2.6.5-10-attr2/include/linux/nfs_fs.h --- linux-2.6.5-09-fix_integrity/include/linux/nfs_fs.h 2004-03-24 00:46:21.000000000 -0500 +++ linux-2.6.5-10-attr2/include/linux/nfs_fs.h 2004-03-24 00:46:49.000000000 -0500 @@ -277,6 +277,7 @@ extern void nfs_begin_attr_update(struct extern void nfs_end_attr_update(struct inode *); extern void nfs_begin_data_update(struct inode *); extern void nfs_end_data_update(struct inode *); +extern void nfs_end_data_update_defer(struct inode *); /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */ extern u32 root_nfs_parse_addr(char *name); /*__init*/