aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_aops.c
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@sandeen.net>2010-06-24 09:45:30 +1000
committerAlex Elder <aelder@sgi.com>2010-07-26 13:16:40 -0500
commit3d9b02e3c76531687ab5314e0edf266256f13c2d (patch)
treef730a4da55eb1536227ebe0f976f878f0e08181b /fs/xfs/linux-2.6/xfs_aops.c
parentb4e9181e772b0c8b9038c5822ead368b96c2b533 (diff)
downloadlinux-3d9b02e3c76531687ab5314e0edf266256f13c2d.tar.gz
xfs: fix corruption case for block size < page size
xfstests 194 first truncats a file back and then extends it again by truncating it to a larger size. This causes discard_buffer to drop the mapped, but not the uptodate bit and thus creates something that xfs_page_state_convert takes for unmapped space created by mmap because it doesn't check for the dirty bit, which also gets cleared by discard_buffer and checked by other ->writepage implementations like block_write_full_page. Handle this kind of buffers early, and unlike Eric's first version of the patch simply ASSERT that the buffers is dirty, given that the mmap write case can't happen anymore since the introduction of ->page_mkwrite. The now dead code dealing with that will be deleted in a follow on patch. Signed-off-by: Eric Sandeen <sandeen@sandeen.net> Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com>
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_aops.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index b25d11a3d84ebb..bd5e1cf5428dcb 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -1125,6 +1125,16 @@ xfs_page_state_convert(
continue;
}
+ /*
+ * A hole may still be marked uptodate because discard_buffer
+ * leaves the flag set.
+ */
+ if (!buffer_mapped(bh) && buffer_uptodate(bh)) {
+ ASSERT(!buffer_dirty(bh));
+ imap_valid = 0;
+ continue;
+ }
+
if (imap_valid)
imap_valid = xfs_imap_valid(inode, &imap, offset);