Skip to content

Commit c09abff

Browse files
committed
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 <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 1014f3d commit c09abff

File tree

4 files changed

+7
-0
lines changed

4 files changed

+7
-0
lines changed

fs/btrfs/compression.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ static void end_compressed_bio_read(struct bio *bio)
152152
* we have verified the checksum already, set page
153153
* checked so the end_io handlers know about it
154154
*/
155+
ASSERT(!bio_flagged(bio, BIO_CLONED));
155156
bio_for_each_segment_all(bvec, cb->orig_bio, i)
156157
SetPageChecked(bvec->bv_page);
157158

fs/btrfs/disk-io.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,7 @@ static int btree_csum_one_bio(struct bio *bio)
964964
struct btrfs_root *root;
965965
int i, ret = 0;
966966

967+
ASSERT(!bio_flagged(bio, BIO_CLONED));
967968
bio_for_each_segment_all(bvec, bio, i) {
968969
root = BTRFS_I(bvec->bv_page->mapping->host)->root;
969970
ret = csum_dirty_buffer(root->fs_info, bvec->bv_page);

fs/btrfs/extent_io.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2452,6 +2452,7 @@ static void end_bio_extent_writepage(struct bio *bio)
24522452
u64 end;
24532453
int i;
24542454

2455+
ASSERT(!bio_flagged(bio, BIO_CLONED));
24552456
bio_for_each_segment_all(bvec, bio, i) {
24562457
struct page *page = bvec->bv_page;
24572458
struct inode *inode = page->mapping->host;
@@ -2522,6 +2523,7 @@ static void end_bio_extent_readpage(struct bio *bio)
25222523
int ret;
25232524
int i;
25242525

2526+
ASSERT(!bio_flagged(bio, BIO_CLONED));
25252527
bio_for_each_segment_all(bvec, bio, i) {
25262528
struct page *page = bvec->bv_page;
25272529
struct inode *inode = page->mapping->host;
@@ -3675,6 +3677,7 @@ static void end_bio_extent_buffer_writepage(struct bio *bio)
36753677
struct extent_buffer *eb;
36763678
int i, done;
36773679

3680+
ASSERT(!bio_flagged(bio, BIO_CLONED));
36783681
bio_for_each_segment_all(bvec, bio, i) {
36793682
struct page *page = bvec->bv_page;
36803683

fs/btrfs/inode.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8060,6 +8060,7 @@ static void btrfs_retry_endio_nocsum(struct bio *bio)
80608060
ASSERT(bio->bi_io_vec->bv_len == btrfs_inode_sectorsize(inode));
80618061

80628062
done->uptodate = 1;
8063+
ASSERT(!bio_flagged(bio, BIO_CLONED));
80638064
bio_for_each_segment_all(bvec, bio, i)
80648065
clean_io_failure(BTRFS_I(inode)->root->fs_info, failure_tree,
80658066
io_tree, done->start, bvec->bv_page,
@@ -8151,6 +8152,7 @@ static void btrfs_retry_endio(struct bio *bio)
81518152
io_tree = &BTRFS_I(inode)->io_tree;
81528153
failure_tree = &BTRFS_I(inode)->io_failure_tree;
81538154

8155+
ASSERT(!bio_flagged(bio, BIO_CLONED));
81548156
bio_for_each_segment_all(bvec, bio, i) {
81558157
ret = __readpage_endio_check(inode, io_bio, i, bvec->bv_page,
81568158
bvec->bv_offset, done->start,

0 commit comments

Comments
 (0)