The bios submitted from btrfs_map_bio don't interact with the rest of btrfs. The only btrfs_bio field is the device. Add a bbio backpointer pointer to struct btrfs_bio_stripe so that the private data can point to the stripe and just use a normal bio allocation for them. Signed-off-by: Christoph Hellwig <hch@xxxxxx> --- fs/btrfs/extent_io.c | 13 ------------- fs/btrfs/extent_io.h | 1 - fs/btrfs/volumes.c | 21 +++++++++++---------- fs/btrfs/volumes.h | 5 ++++- 4 files changed, 15 insertions(+), 25 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 116a65787e314..bfd91ed27bd14 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3149,19 +3149,6 @@ struct bio *btrfs_bio_alloc(struct inode *inode, unsigned int nr_iovecs, return bio; } -struct bio *btrfs_bio_clone(struct block_device *bdev, struct bio *bio) -{ - struct btrfs_bio *bbio; - struct bio *new; - - /* Bio allocation backed by a bioset does not fail */ - new = bio_alloc_clone(bdev, bio, GFP_NOFS, &btrfs_bioset); - bbio = btrfs_bio(new); - btrfs_bio_init(btrfs_bio(new), btrfs_bio(bio)->inode); - bbio->iter = bio->bi_iter; - return new; -} - struct bio *btrfs_bio_clone_partial(struct inode *inode, struct bio *orig, u64 offset, u64 size) { diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index d5f3d9692ea29..3f0cb1ef5fdff 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -279,7 +279,6 @@ void extent_clear_unlock_delalloc(struct btrfs_inode *inode, u64 start, u64 end, u32 bits_to_clear, unsigned long page_ops); struct bio *btrfs_bio_alloc(struct inode *inode, unsigned int nr_iovecs, unsigned int opf); -struct bio *btrfs_bio_clone(struct block_device *bdev, struct bio *bio); struct bio *btrfs_bio_clone_partial(struct inode *inode, struct bio *orig, u64 offset, u64 size); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index cec3f6b9f5c21..7392b9f2a3323 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -6749,23 +6749,21 @@ static void btrfs_end_bbio(struct btrfs_bio *bbio, bool async) static void btrfs_end_bio(struct bio *bio) { - struct btrfs_bio *bbio = bio->bi_private; + struct btrfs_bio_stripe *stripe = bio->bi_private; + struct btrfs_bio *bbio = stripe->bbio; if (bio->bi_status) { atomic_inc(&bbio->error); if (bio->bi_status == BLK_STS_IOERR || bio->bi_status == BLK_STS_TARGET) { - struct btrfs_device *dev = btrfs_bio(bio)->device; - - ASSERT(dev->bdev); if (btrfs_op(bio) == BTRFS_MAP_WRITE) - btrfs_dev_stat_inc_and_print(dev, + btrfs_dev_stat_inc_and_print(stripe->dev, BTRFS_DEV_STAT_WRITE_ERRS); else if (!(bio->bi_opf & REQ_RAHEAD)) - btrfs_dev_stat_inc_and_print(dev, + btrfs_dev_stat_inc_and_print(stripe->dev, BTRFS_DEV_STAT_READ_ERRS); if (bio->bi_opf & REQ_PREFLUSH) - btrfs_dev_stat_inc_and_print(dev, + btrfs_dev_stat_inc_and_print(stripe->dev, BTRFS_DEV_STAT_FLUSH_ERRS); } } @@ -6796,14 +6794,17 @@ static void submit_stripe_bio(struct btrfs_bio *bbio, int dev_nr, bool clone) } if (clone) { - bio = btrfs_bio_clone(dev->bdev, &bbio->bio); + bio = bio_alloc_clone(dev->bdev, &bbio->bio, GFP_NOFS, + &fs_bio_set); } else { bio = &bbio->bio; bio_set_dev(bio, dev->bdev); + btrfs_bio(bio)->device = dev; } - bio->bi_private = bbio; - btrfs_bio(bio)->device = dev; + bbio->stripes[dev_nr].bbio = bbio; + bio->bi_private = &bbio->stripes[dev_nr]; + bio->bi_end_io = btrfs_end_bio; bio->bi_iter.bi_sector = physical >> 9; /* diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index cd71cd33a9df2..5b0e7602434b0 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -325,7 +325,10 @@ enum btrfs_endio_type { struct btrfs_bio_stripe { struct btrfs_device *dev; - u64 physical; + union { + u64 physical; /* block mapping */ + struct btrfs_bio *bbio; /* for end I/O */ + }; }; /* -- 2.30.2