summaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.com>2017-07-13 12:10:07 -0400
committerDavid Sterba <dsterba@suse.com>2017-07-14 14:39:31 -0400
commitc09abff87f90c81d74b6483837a665f97448a475 (patch)
tree72371fad2cc4dce6180e8399d94ff053a879c607 /fs/btrfs
parent1014f3d68fc4034966b15234dc12b81147ee83b2 (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')
-rw-r--r--fs/btrfs/compression.c1
-rw-r--r--fs/btrfs/disk-io.c1
-rw-r--r--fs/btrfs/extent_io.c3
-rw-r--r--fs/btrfs/inode.c2
4 files changed, 7 insertions, 0 deletions
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index fcd323eceb5b..8ba1b86c9b72 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -152,6 +152,7 @@ csum_failed:
152 * we have verified the checksum already, set page 152 * we have verified the checksum already, set page
153 * checked so the end_io handlers know about it 153 * checked so the end_io handlers know about it
154 */ 154 */
155 ASSERT(!bio_flagged(bio, BIO_CLONED));
155 bio_for_each_segment_all(bvec, cb->orig_bio, i) 156 bio_for_each_segment_all(bvec, cb->orig_bio, i)
156 SetPageChecked(bvec->bv_page); 157 SetPageChecked(bvec->bv_page);
157 158
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index b6758892874f..075beedb4352 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -964,6 +964,7 @@ static int btree_csum_one_bio(struct bio *bio)
964 struct btrfs_root *root; 964 struct btrfs_root *root;
965 int i, ret = 0; 965 int i, ret = 0;
966 966
967 ASSERT(!bio_flagged(bio, BIO_CLONED));
967 bio_for_each_segment_all(bvec, bio, i) { 968 bio_for_each_segment_all(bvec, bio, i) {
968 root = BTRFS_I(bvec->bv_page->mapping->host)->root; 969 root = BTRFS_I(bvec->bv_page->mapping->host)->root;
969 ret = csum_dirty_buffer(root->fs_info, bvec->bv_page); 970 ret = csum_dirty_buffer(root->fs_info, bvec->bv_page);
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
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 5d3c6ac960fd..529437c337b4 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -8060,6 +8060,7 @@ static void btrfs_retry_endio_nocsum(struct bio *bio)
8060 ASSERT(bio->bi_io_vec->bv_len == btrfs_inode_sectorsize(inode)); 8060 ASSERT(bio->bi_io_vec->bv_len == btrfs_inode_sectorsize(inode));
8061 8061
8062 done->uptodate = 1; 8062 done->uptodate = 1;
8063 ASSERT(!bio_flagged(bio, BIO_CLONED));
8063 bio_for_each_segment_all(bvec, bio, i) 8064 bio_for_each_segment_all(bvec, bio, i)
8064 clean_io_failure(BTRFS_I(inode)->root->fs_info, failure_tree, 8065 clean_io_failure(BTRFS_I(inode)->root->fs_info, failure_tree,
8065 io_tree, done->start, bvec->bv_page, 8066 io_tree, done->start, bvec->bv_page,
@@ -8151,6 +8152,7 @@ static void btrfs_retry_endio(struct bio *bio)
8151 io_tree = &BTRFS_I(inode)->io_tree; 8152 io_tree = &BTRFS_I(inode)->io_tree;
8152 failure_tree = &BTRFS_I(inode)->io_failure_tree; 8153 failure_tree = &BTRFS_I(inode)->io_failure_tree;
8153 8154
8155 ASSERT(!bio_flagged(bio, BIO_CLONED));
8154 bio_for_each_segment_all(bvec, bio, i) { 8156 bio_for_each_segment_all(bvec, bio, i) {
8155 ret = __readpage_endio_check(inode, io_bio, i, bvec->bv_page, 8157 ret = __readpage_endio_check(inode, io_bio, i, bvec->bv_page,
8156 bvec->bv_offset, done->start, 8158 bvec->bv_offset, done->start,