aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-02-07 17:24:07 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-02-07 19:20:20 -0500
commit5d47a35600270e7115061cb1320ee60ae9bcb6b8 (patch)
tree63b6ac010939b45ce53e65dedae68f1296bd98e7 /fs/nfs/write.c
parentdf922075f2a55b1ae71a6fe589c1cc1b91381f4f (diff)
NFS: Fix a potential file corruption issue when writing
If the inode is flagged as having an invalid mapping, then we can't rely on the PageUptodate() flag. Ensure that we don't use the "anti-fragmentation" write optimisation in nfs_updatepage(), since that will cause NFS to write out areas of the page that are no longer guaranteed to be up to date. A potential corruption could occur in the following scenario: client 1 client 2 =============== =============== fd=open("f",O_CREAT|O_WRONLY,0644); write(fd,"fubar\n",6); // cache last page close(fd); fd=open("f",O_WRONLY|O_APPEND); write(fd,"foo\n",4); close(fd); fd=open("f",O_WRONLY|O_APPEND); write(fd,"bar\n",4); close(fd); ----- The bug may lead to the file "f" reading 'fubar\n\0\0\0\nbar\n' because client 2 does not update the cached page after re-opening the file for write. Instead it keeps it marked as PageUptodate() until someone calls invaldate_inode_pages2() (typically by calling read()). Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index b144b1957dd9..f55c437124a2 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -697,6 +697,17 @@ int nfs_flush_incompatible(struct file *file, struct page *page)
697} 697}
698 698
699/* 699/*
700 * If the page cache is marked as unsafe or invalid, then we can't rely on
701 * the PageUptodate() flag. In this case, we will need to turn off
702 * write optimisations that depend on the page contents being correct.
703 */
704static int nfs_write_pageuptodate(struct page *page, struct inode *inode)
705{
706 return PageUptodate(page) &&
707 !(NFS_I(inode)->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA));
708}
709
710/*
700 * Update and possibly write a cached page of an NFS file. 711 * Update and possibly write a cached page of an NFS file.
701 * 712 *
702 * XXX: Keep an eye on generic_file_read to make sure it doesn't do bad 713 * XXX: Keep an eye on generic_file_read to make sure it doesn't do bad
@@ -717,10 +728,13 @@ int nfs_updatepage(struct file *file, struct page *page,
717 (long long)(page_offset(page) +offset)); 728 (long long)(page_offset(page) +offset));
718 729
719 /* If we're not using byte range locks, and we know the page 730 /* If we're not using byte range locks, and we know the page
720 * is entirely in cache, it may be more efficient to avoid 731 * is up to date, it may be more efficient to extend the write
721 * fragmenting write requests. 732 * to cover the entire page in order to avoid fragmentation
733 * inefficiencies.
722 */ 734 */
723 if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) { 735 if (nfs_write_pageuptodate(page, inode) &&
736 inode->i_flock == NULL &&
737 !(file->f_mode & O_SYNC)) {
724 count = max(count + offset, nfs_page_length(page)); 738 count = max(count + offset, nfs_page_length(page));
725 offset = 0; 739 offset = 0;
726 } 740 }