@@ -941,8 +941,6 @@ blk_status_t btrfs_submit_metadata_bio(struct inode *inode, struct bio *bio,
return 0;
out_w_error:
- bio->bi_status = ret;
- bio_endio(bio);
return ret;
}
@@ -181,6 +181,10 @@ int __must_check submit_one_bio(struct bio *bio, int mirror_num,
ret = btrfs_submit_metadata_bio(tree->private_data, bio,
mirror_num, bio_flags);
+ if (ret) {
+ bio->bi_status = ret;
+ bio_endio(bio);
+ }
return blk_status_to_errno(ret);
}
@@ -2571,10 +2571,6 @@ blk_status_t btrfs_submit_data_bio(struct inode *inode, struct bio *bio,
ret = btrfs_map_bio(fs_info, bio, mirror_num);
out:
- if (ret) {
- bio->bi_status = ret;
- bio_endio(bio);
- }
return ret;
}
btrfs_repair_one_sector just wants to free the bio if submit_bio_hook fails, but btrfs_submit_data_bio will call bio_endio which will call into the submitter of the original bio and free the bio there as well. Move the bio_endio calls from btrfs_submit_data_bio and btrfs_submit_metadata_bio into submit_one_bio to fix this double free. Signed-off-by: Christoph Hellwig <hch@lst.de> --- fs/btrfs/disk-io.c | 2 -- fs/btrfs/extent_io.c | 4 ++++ fs/btrfs/inode.c | 4 ---- 3 files changed, 4 insertions(+), 6 deletions(-)