From: Yan Date: Tue, 6 Nov 2007 15:26:26 +0000 (-0500) Subject: Btrfs: Fix u32 overflow in dirty_and_release_pages. X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=dcfec0dcb1b1a037fb26177789e8f108bc429cb3;p=openwrt%2Fstaging%2Fblogic.git Btrfs: Fix u32 overflow in dirty_and_release_pages. When calculating the size of inline extent, inode->i_size should also be take into consideration, otherwise sys_write may drop some data silently. You can test this bug by: #dd if=/dev/zero bs=4k count=1 of=test_file #dd if=/dev/zero bs=2k count=1 of=test_file conv=notrunc Signed-off-by: Chris Mason --- diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 4e52f7ec1cbe..bb98f52f4ea4 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -239,9 +239,8 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, u64 start_pos; u64 end_of_last_block; u64 end_pos = pos + write_bytes; - u32 inline_size; + u64 inline_size; loff_t isize = i_size_read(inode); - em = alloc_extent_map(GFP_NOFS); if (!em) return -ENOMEM; @@ -328,9 +327,11 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, aligned_end, aligned_end, &hint_byte); if (err) goto failed; + if (isize > inline_size) + inline_size = min_t(u64, isize, aligned_end); + inline_size -= start_pos; err = insert_inline_extent(trans, root, inode, start_pos, - end_pos - start_pos, pages, 0, - num_pages); + inline_size, pages, 0, num_pages); BUG_ON(err); } if (end_pos > isize) {