Commit f00d7c85 authored by NeilBrown's avatar NeilBrown Committed by Shaohua Li
Browse files

md/raid0: fix up bio splitting.



raid0_make_request() should use a private bio_set rather than the
shared fs_bio_set, which is only meant for filesystems to use.

raid0_make_request() shouldn't loop around using the bio_set
multiple times as that can deadlock.

So use mddev->bio_set and pass the tail to generic_make_request()
instead of looping on it.

Signed-off-by: default avatarNeilBrown <neilb@suse.com>
Signed-off-by: default avatarShaohua Li <shli@fb.com>
parent 868f604b
Loading
Loading
Loading
Loading
+37 −36
Original line number Diff line number Diff line
@@ -462,19 +462,21 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio)
{
	struct strip_zone *zone;
	struct md_rdev *tmp_dev;
	struct bio *split;
	sector_t bio_sector;
	sector_t sector;
	unsigned chunk_sects;
	unsigned sectors;

	if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
		md_flush_request(mddev, bio);
		return;
	}

	do {
		sector_t bio_sector = bio->bi_iter.bi_sector;
		sector_t sector = bio_sector;
		unsigned chunk_sects = mddev->chunk_sectors;
	bio_sector = bio->bi_iter.bi_sector;
	sector = bio_sector;
	chunk_sects = mddev->chunk_sectors;

		unsigned sectors = chunk_sects -
	sectors = chunk_sects -
		(likely(is_power_of_2(chunk_sects))
		 ? (sector & (chunk_sects-1))
		 : sector_div(sector, chunk_sects));
@@ -483,31 +485,30 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio)
	sector = bio_sector;

	if (sectors < bio_sectors(bio)) {
			split = bio_split(bio, sectors, GFP_NOIO, fs_bio_set);
		struct bio *split = bio_split(bio, sectors, GFP_NOIO, mddev->bio_set);
		bio_chain(split, bio);
		} else {
			split = bio;
		generic_make_request(bio);
		bio = split;
	}

	zone = find_zone(mddev->private, &sector);
	tmp_dev = map_sector(mddev, zone, sector, &sector);
		split->bi_bdev = tmp_dev->bdev;
		split->bi_iter.bi_sector = sector + zone->dev_start +
	bio->bi_bdev = tmp_dev->bdev;
	bio->bi_iter.bi_sector = sector + zone->dev_start +
		tmp_dev->data_offset;

		if (unlikely((bio_op(split) == REQ_OP_DISCARD) &&
			 !blk_queue_discard(bdev_get_queue(split->bi_bdev)))) {
	if (unlikely((bio_op(bio) == REQ_OP_DISCARD) &&
		     !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) {
		/* Just ignore it */
			bio_endio(split);
		bio_endio(bio);
	} else {
		if (mddev->gendisk)
				trace_block_bio_remap(bdev_get_queue(split->bi_bdev),
						      split, disk_devt(mddev->gendisk),
			trace_block_bio_remap(bdev_get_queue(bio->bi_bdev),
					      bio, disk_devt(mddev->gendisk),
					      bio_sector);
			mddev_check_writesame(mddev, split);
			generic_make_request(split);
		mddev_check_writesame(mddev, bio);
		generic_make_request(bio);
	}
	} while (split != bio);
}

static void raid0_status(struct seq_file *seq, struct mddev *mddev)