From: Chris Mason Subject: [PATCH] reiserfs_write_full_page should not get_block past eof Date: Fri, 4 Aug 2006 10:02:23 -0400 Message-ID: <20060804140223.GE1134@watt.suse.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Return-path: Received: from mx1.suse.de ([195.135.220.2]:8637 "EHLO mx1.suse.de") by vger.kernel.org with ESMTP id S1161214AbWHDOCp (ORCPT ); Fri, 4 Aug 2006 10:02:45 -0400 To: linux-fsdevel@vger.kernel.org, akpm@osdl.org, reiserfs-dev@namesys.com Content-Disposition: inline Sender: linux-fsdevel-owner@vger.kernel.org List-Id: linux-fsdevel.vger.kernel.org From: mason@suse.com Subject: reiserfs_write_full_page should not get_block past eof 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 --- a/fs/reiserfs/inode.c Mon May 08 14:36:37 2006 -0400 +++ b/fs/reiserfs/inode.c Mon May 08 15:37:35 2006 -0400 @@ -2350,6 +2350,7 @@ static int reiserfs_write_full_page(stru 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; @@ -2397,10 +2398,19 @@ static int reiserfs_write_full_page(stru } 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 --