[PATCH] reiserfs_write_full_page() should not get_block past eof
authorChris Mason <mason@suse.com>
Sat, 5 Aug 2006 19:15:10 +0000 (12:15 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sun, 6 Aug 2006 15:57:49 +0000 (08:57 -0700)
reiserfs_write_full_page does zero bytes in the file past eof, but it may
call get_block on those buffers as well.  On machines where the page size
is larger than the blocksize, this can result in mmaped files incorrectly
growing up to a block boundary during writepage.

The fix is to avoid calling get_block for any blocks that are entirely past
eof

Signed-off-by: Chris Mason <mason@suse.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/reiserfs/inode.c

index ac57305b1afc0d024022f126da76c0efe3994b6c..52f1e2136546f215f7bd13ea403735222a621e46 100644 (file)
@@ -2340,6 +2340,7 @@ static int reiserfs_write_full_page(struct page *page,
        unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
        int error = 0;
        unsigned long block;
+       sector_t last_block;
        struct buffer_head *head, *bh;
        int partial = 0;
        int nr = 0;
@@ -2387,10 +2388,19 @@ static int reiserfs_write_full_page(struct page *page,
        }
        bh = head;
        block = page->index << (PAGE_CACHE_SHIFT - s->s_blocksize_bits);
+       last_block = (i_size_read(inode) - 1) >> inode->i_blkbits;
        /* first map all the buffers, logging any direct items we find */
        do {
-               if ((checked || buffer_dirty(bh)) && (!buffer_mapped(bh) ||
-                                                     (buffer_mapped(bh)
+               if (block > last_block) {
+                       /*
+                        * This can happen when the block size is less than
+                        * the page size.  The corresponding bytes in the page
+                        * were zero filled above
+                        */
+                       clear_buffer_dirty(bh);
+                       set_buffer_uptodate(bh);
+               } else if ((checked || buffer_dirty(bh)) &&
+                          (!buffer_mapped(bh) || (buffer_mapped(bh)
                                                       && bh->b_blocknr ==
                                                       0))) {
                        /* not mapped yet, or it points to a direct item, search