diff options
author | David Sterba <dsterba@suse.com> | 2017-07-13 12:10:07 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2017-07-14 14:39:31 -0400 |
commit | c09abff87f90c81d74b6483837a665f97448a475 (patch) | |
tree | 72371fad2cc4dce6180e8399d94ff053a879c607 /fs/btrfs/extent_io.c | |
parent | 1014f3d68fc4034966b15234dc12b81147ee83b2 (diff) |
btrfs: cloned bios must not be iterated by bio_for_each_segment_all
We've started using cloned bios more in 4.13, there are some specifics
regarding the iteration. Filipe found [1] that the raid56 iterated a
cloned bio using bio_for_each_segment_all, which is incorrect. The
cloned bios have wrong bi_vcnt and this could lead to silent
corruptions. This patch adds assertions to all remaining
bio_for_each_segment_all cases.
[1] https://patchwork.kernel.org/patch/9838535/
Reviewed-by: Liu Bo <bo.li.liu@oracle.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r-- | fs/btrfs/extent_io.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 2e6f69908303..a3122fba54e8 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -2452,6 +2452,7 @@ static void end_bio_extent_writepage(struct bio *bio) | |||
2452 | u64 end; | 2452 | u64 end; |
2453 | int i; | 2453 | int i; |
2454 | 2454 | ||
2455 | ASSERT(!bio_flagged(bio, BIO_CLONED)); | ||
2455 | bio_for_each_segment_all(bvec, bio, i) { | 2456 | bio_for_each_segment_all(bvec, bio, i) { |
2456 | struct page *page = bvec->bv_page; | 2457 | struct page *page = bvec->bv_page; |
2457 | struct inode *inode = page->mapping->host; | 2458 | struct inode *inode = page->mapping->host; |
@@ -2522,6 +2523,7 @@ static void end_bio_extent_readpage(struct bio *bio) | |||
2522 | int ret; | 2523 | int ret; |
2523 | int i; | 2524 | int i; |
2524 | 2525 | ||
2526 | ASSERT(!bio_flagged(bio, BIO_CLONED)); | ||
2525 | bio_for_each_segment_all(bvec, bio, i) { | 2527 | bio_for_each_segment_all(bvec, bio, i) { |
2526 | struct page *page = bvec->bv_page; | 2528 | struct page *page = bvec->bv_page; |
2527 | struct inode *inode = page->mapping->host; | 2529 | struct inode *inode = page->mapping->host; |
@@ -3675,6 +3677,7 @@ static void end_bio_extent_buffer_writepage(struct bio *bio) | |||
3675 | struct extent_buffer *eb; | 3677 | struct extent_buffer *eb; |
3676 | int i, done; | 3678 | int i, done; |
3677 | 3679 | ||
3680 | ASSERT(!bio_flagged(bio, BIO_CLONED)); | ||
3678 | bio_for_each_segment_all(bvec, bio, i) { | 3681 | bio_for_each_segment_all(bvec, bio, i) { |
3679 | struct page *page = bvec->bv_page; | 3682 | struct page *page = bvec->bv_page; |
3680 | 3683 | ||