btrfs: do not allocate a btrfs_bio for low-level bios
authorChristoph Hellwig <hch@lst.de>
Thu, 26 May 2022 07:36:42 +0000 (09:36 +0200)
committerDavid Sterba <dsterba@suse.com>
Mon, 25 Jul 2022 15:45:33 +0000 (17:45 +0200)
The bios submitted from btrfs_map_bio don't really interact with the
rest of btrfs and the only btrfs_bio member actually used in the
low-level bios is the pointer to the btrfs_io_context used for endio
handler.

Use a union in struct btrfs_io_stripe that allows the endio handler to
find the btrfs_io_context and remove the spurious ->device assignment
so that a plain fs_bio_set bio can be used for the low-level bios
allocated inside btrfs_map_bio.

Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/volumes.c
fs/btrfs/volumes.h

index d7059a48cefcabc7cf328c9b693e85a6192ea566..5efe25bbee5e0d4b8f2f854cd4757306ca9e95d1 100644 (file)
@@ -3203,19 +3203,6 @@ struct bio *btrfs_bio_alloc(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(bbio);
-       bbio->iter = bio->bi_iter;
-       return new;
-}
-
 struct bio *btrfs_bio_clone_partial(struct bio *orig, u64 offset, u64 size)
 {
        struct bio *bio;
index 23d4103c88316014de77e612151ca49dddeb5c0c..72966cf21961ef99e73379c4c8a151565dde5329 100644 (file)
@@ -247,7 +247,6 @@ void extent_clear_unlock_delalloc(struct btrfs_inode *inode, u64 start, u64 end,
 
 int btrfs_alloc_page_array(unsigned int nr_pages, struct page **page_array);
 struct bio *btrfs_bio_alloc(unsigned int nr_iovecs);
-struct bio *btrfs_bio_clone(struct block_device *bdev, struct bio *bio);
 struct bio *btrfs_bio_clone_partial(struct bio *orig, u64 offset, u64 size);
 
 void end_extent_writepage(struct page *page, int err, u64 start, u64 end);
index 1e06b7ee6a815191a5a542031ef52e6c70778bf6..7513e45c0c42737b00d4094249f10344e890957a 100644 (file)
@@ -6661,23 +6661,21 @@ static void btrfs_end_bioc(struct btrfs_io_context *bioc, bool async)
 
 static void btrfs_end_bio(struct bio *bio)
 {
-       struct btrfs_io_context *bioc = bio->bi_private;
+       struct btrfs_io_stripe *stripe = bio->bi_private;
+       struct btrfs_io_context *bioc = stripe->bioc;
 
        if (bio->bi_status) {
                atomic_inc(&bioc->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);
                }
        }
@@ -6709,14 +6707,15 @@ static void submit_stripe_bio(struct btrfs_io_context *bioc,
        }
 
        if (clone) {
-               bio = btrfs_bio_clone(dev->bdev, orig_bio);
+               bio = bio_alloc_clone(dev->bdev, orig_bio, GFP_NOFS, &fs_bio_set);
        } else {
                bio = orig_bio;
                bio_set_dev(bio, dev->bdev);
+               btrfs_bio(bio)->device = dev;
        }
 
-       bio->bi_private = bioc;
-       btrfs_bio(bio)->device = dev;
+       bioc->stripes[dev_nr].bioc = bioc;
+       bio->bi_private = &bioc->stripes[dev_nr];
        bio->bi_end_io = btrfs_end_bio;
        bio->bi_iter.bi_sector = physical >> 9;
        /*
index 7973d11e5f5d898a25f4b8dadbab2a88b4307ad8..a3c3a0d716bdca384b263c0a167582d8173c95ad 100644 (file)
@@ -412,7 +412,12 @@ static inline void btrfs_bio_free_csum(struct btrfs_bio *bbio)
 
 struct btrfs_io_stripe {
        struct btrfs_device *dev;
-       u64 physical;
+       union {
+               /* Block mapping */
+               u64 physical;
+               /* For the endio handler */
+               struct btrfs_io_context *bioc;
+       };
        u64 length; /* only used for discard mappings */
 };