From: Allison Henderson Date: Mon, 22 Aug 2011 19:06:53 +0000 (-0400) Subject: ext4: fix partial page writes X-Git-Tag: next-20110824~74^2 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=aefd045e1b15cb179ce43ac4a76dcd711b10a684;p=karo-tx-linux.git ext4: fix partial page writes These bugs were also found during extended fsx testing for blocksize = 1k. When ever a write operation begins or ends in a hole, or extends EOF, the partial page contained in the hole or beyond EOF needs to be zeroed out. To correct this the new ext4_discard_partial_page_buffers_no_lock routine is used to zero out the partial page, but only for buffer heads that are already unmapped. Signed-off-by: Allison Henderson Signed-off-by: "Theodore Ts'o" --- diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index e908788ec386..c3ce7547e315 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2258,6 +2258,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, pgoff_t index; struct inode *inode = mapping->host; handle_t *handle; + loff_t page_len; index = pos >> PAGE_CACHE_SHIFT; @@ -2304,6 +2305,11 @@ retry: */ if (pos + len > inode->i_size) ext4_truncate_failed_write(inode); + } else { + page_len = pos & (PAGE_CACHE_SIZE - 1); + ext4_discard_partial_page_buffers_no_lock(handle, + inode, page, pos - page_len, page_len, + EXT4_DSCRD_PARTIAL_PG_ZERO_UNMAPED); } if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) @@ -2346,6 +2352,7 @@ static int ext4_da_write_end(struct file *file, loff_t new_i_size; unsigned long start, end; int write_mode = (int)(unsigned long)fsdata; + loff_t page_len; if (write_mode == FALL_BACK_TO_NONDELALLOC) { if (ext4_should_order_data(inode)) { @@ -2394,6 +2401,14 @@ static int ext4_da_write_end(struct file *file, } ret2 = generic_write_end(file, mapping, pos, len, copied, page, fsdata); + + page_len = PAGE_CACHE_SIZE - + ((pos + copied) & (PAGE_CACHE_SIZE - 1)); + + ext4_discard_partial_page_buffers_no_lock(handle, + inode, page, pos + copied, page_len, + EXT4_DSCRD_PARTIAL_PG_ZERO_UNMAPED); + copied = ret2; if (ret2 < 0) ret = ret2;