Commit 9ff7ddd3 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by David Sterba
Browse files

btrfs: do not allocate a btrfs_bio for low-level bios



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: default avatarQu Wenruo <wqu@suse.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent a316a259
Loading
Loading
Loading
Loading
+0 −13
Original line number Diff line number Diff line
@@ -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;
+0 −1
Original line number Diff line number Diff line
@@ -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);
+9 −10
Original line number Diff line number Diff line
@@ -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;
	/*
+6 −1
Original line number Diff line number Diff line
@@ -412,7 +412,12 @@ static inline void btrfs_bio_free_csum(struct btrfs_bio *bbio)

struct btrfs_io_stripe {
	struct btrfs_device *dev;
	union {
		/* Block mapping */
		u64 physical;
		/* For the endio handler */
		struct btrfs_io_context *bioc;
	};
	u64 length; /* only used for discard mappings */
};