xfs
[Top] [All Lists]

[PATCH 02/12] xfs: fix corruption case for block size < page size

To: xfs@xxxxxxxxxxx
Subject: [PATCH 02/12] xfs: fix corruption case for block size < page size
From: Christoph Hellwig <hch@xxxxxxxxxxxxx>
Date: Mon, 21 Jun 2010 04:35:45 -0400
Cc: Eric Sandeen <sandeen@xxxxxxxxxxx>
References: <20100621083543.125860679@xxxxxxxxxxxxxxxxxxxxxx>
User-agent: quilt/0.47-1
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@xxxxxxxxxxx>
Signed-off-by: Christoph Hellwig <hch@xxxxxx>
Reviewed-by: Dave Chinner <dchinner@xxxxxxxxxx>

Index: xfs/fs/xfs/linux-2.6/xfs_aops.c
===================================================================
--- xfs.orig/fs/xfs/linux-2.6/xfs_aops.c        2010-06-10 08:59:49.598004335 
+0200
+++ xfs/fs/xfs/linux-2.6/xfs_aops.c     2010-06-11 09:20:31.292254712 +0200
@@ -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);
 

<Prev in Thread] Current Thread [Next in Thread>