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>

+17 -3
+17 -3
fs/nfs/write.c
··· 697 } 698 699 /* 700 * Update and possibly write a cached page of an NFS file. 701 * 702 * XXX: Keep an eye on generic_file_read to make sure it doesn't do bad ··· 728 (long long)(page_offset(page) +offset)); 729 730 /* If we're not using byte range locks, and we know the page 731 - * is entirely in cache, it may be more efficient to avoid 732 - * fragmenting write requests. 733 */ 734 - if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) { 735 count = max(count + offset, nfs_page_length(page)); 736 offset = 0; 737 }
··· 697 } 698 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 + */ 704 + static 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 + /* 711 * Update and possibly write a cached page of an NFS file. 712 * 713 * XXX: Keep an eye on generic_file_read to make sure it doesn't do bad ··· 717 (long long)(page_offset(page) +offset)); 718 719 /* If we're not using byte range locks, and we know the page 720 + * is up to date, it may be more efficient to extend the write 721 + * to cover the entire page in order to avoid fragmentation 722 + * inefficiencies. 723 */ 724 + if (nfs_write_pageuptodate(page, inode) && 725 + inode->i_flock == NULL && 726 + !(file->f_mode & O_SYNC)) { 727 count = max(count + offset, nfs_page_length(page)); 728 offset = 0; 729 }