From 141405fcc46b721b210a36367c24661d3d84eea6 Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Fri, 12 Dec 2014 23:18:53 -0800 Subject: [PATCH] btrfs: fix wrong bvec_len in btrfs_csum_one_bio() Fixed below WARNING. WARNING: CPU: 0 PID: 511 at /home/mlin/linux/fs/btrfs/ordered-data.c:288 btrfs_add_ordered_sum+0x5e/0x8e() Modules linked in: CPU: 0 PID: 511 Comm: kworker/u2:4 Not tainted 3.18.0-00029-g30fd029 #68 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Workqueue: btrfs-worker btrfs_worker_helper 0000000000000009 ffff88001e357c58 ffffffff81488839 0000000000000002 0000000000000000 ffff88001e357c98 ffffffff8103b8a3 ffff88001e357c88 ffffffff8124ec83 ffff88001ddd4000 ffff88001d8e8000 ffff88001df248a0 Call Trace: [] dump_stack+0x4f/0x7c [] warn_slowpath_common+0x81/0x9b [] ? btrfs_add_ordered_sum+0x5e/0x8e [] warn_slowpath_null+0x1a/0x1c [] btrfs_add_ordered_sum+0x5e/0x8e [] btrfs_csum_one_bio+0x16a/0x3de [] ? btrfs_async_submit_limit+0x28/0x28 [] __btrfs_submit_bio_start+0x1d/0x27 [] run_one_async_start+0x27/0x32 [] normal_work_helper+0xf9/0x2fd [] btrfs_worker_helper+0x12/0x14 [] process_one_work+0x1ca/0x376 [] worker_thread+0x267/0x366 [] ? process_scheduled_works+0x2f/0x2f [] kthread+0xd2/0xda [] ? br_multicast_set_hash_max+0x4d/0xcd [] ? kthread_freezable_should_stop+0x48/0x48 [] ret_from_fork+0x7c/0xb0 [] ? kthread_freezable_should_stop+0x48/0x48 Signed-off-by: Ming Lin --- fs/btrfs/extent_io.c | 22 +++++++++++----------- fs/btrfs/file-item.c | 8 +++++--- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 790a83b3fabfaa..61e22cca9b4753 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2462,6 +2462,7 @@ static void end_bio_extent_writepage(struct bio *bio, int err) bio_for_each_page_all(bvec, bio, iter) { struct page *page = bvec.bv_page; + unsigned int bv_len = min_t(unsigned int, bvec.bv_len, PAGE_CACHE_SIZE); /* We always issue full-page reads, but if some block * in a page fails to read, blk_update_request() will @@ -2469,20 +2470,19 @@ static void end_bio_extent_writepage(struct bio *bio, int err) * Print a warning for nonzero offsets, and an error * if they don't add up to a full page. */ if (bvec.bv_offset) { - if (bvec.bv_offset + bvec.bv_len != PAGE_CACHE_SIZE) + if (bvec.bv_offset + bv_len != PAGE_CACHE_SIZE) btrfs_err(BTRFS_I(page->mapping->host)->root->fs_info, "partial page write in btrfs with offset %u and length %u", - bvec.bv_offset, bvec.bv_len); + bvec.bv_offset, bv_len); else btrfs_info(BTRFS_I(page->mapping->host)->root->fs_info, "incomplete page write in btrfs with offset %u and " "length %u", - bvec.bv_offset, bvec.bv_len); + bvec.bv_offset, bv_len); } start = page_offset(page); - end = start + bvec.bv_offset - + min_t(unsigned int, bvec.bv_len, PAGE_CACHE_SIZE) - 1; + end = start + bvec.bv_offset + bv_len - 1; if (end_extent_writepage(page, err, start, end)) continue; @@ -2538,6 +2538,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err) bio_for_each_page_all(bvec, bio, iter) { struct page *page = bvec.bv_page; struct inode *inode = page->mapping->host; + unsigned int bv_len = min_t(unsigned int, bvec.bv_len, PAGE_CACHE_SIZE); pr_debug("end_bio_extent_readpage: bi_sector=%llu, err=%d, " "mirror=%u\n", (u64)bio->bi_iter.bi_sector, err, @@ -2550,21 +2551,20 @@ static void end_bio_extent_readpage(struct bio *bio, int err) * Print a warning for nonzero offsets, and an error * if they don't add up to a full page. */ if (bvec.bv_offset) { - if (bvec.bv_offset + bvec.bv_len != PAGE_CACHE_SIZE) + if (bvec.bv_offset + bv_len != PAGE_CACHE_SIZE) btrfs_err(BTRFS_I(page->mapping->host)->root->fs_info, "partial page read in btrfs with offset %u and length %u", - bvec.bv_offset, bvec.bv_len); + bvec.bv_offset, bv_len); else btrfs_info(BTRFS_I(page->mapping->host)->root->fs_info, "incomplete page read in btrfs with offset %u and " "length %u", - bvec.bv_offset, bvec.bv_len); + bvec.bv_offset, bv_len); } start = page_offset(page); - end = start + bvec.bv_offset - + min_t(unsigned int, bvec.bv_len, PAGE_CACHE_SIZE) - 1; - len = bvec.bv_len; + end = start + bvec.bv_offset + bv_len - 1; + len = bv_len; mirror = io_bio->mirror_num; if (likely(uptodate && tree->ops && diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index c7ae23c7fb7849..cc27f5bbbd2c90 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -448,6 +448,8 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, index = 0; bio_for_each_page(bvec, bio, iter) { + unsigned int bv_len = min_t(unsigned int, bvec.bv_len, PAGE_CACHE_SIZE); + if (!contig) offset = page_offset(bvec.bv_page) + bvec.bv_offset; @@ -472,14 +474,14 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, sums->sums[index] = ~(u32)0; sums->sums[index] = btrfs_csum_data(data + bvec.bv_offset, sums->sums[index], - bvec.bv_len); + bv_len); kunmap_atomic(data); btrfs_csum_final(sums->sums[index], (char *)(sums->sums + index)); index++; - offset += bvec.bv_len; - this_sum_bytes += bvec.bv_len; + offset += bv_len; + this_sum_bytes += bv_len; } this_sum_bytes = 0; btrfs_add_ordered_sum(inode, ordered, sums);