Commit 9f3ced79 authored by Yu Kuai's avatar Yu Kuai Committed by Song Liu
Browse files

md/raid1: factor out choose_bb_rdev() from read_balance()



read_balance() is hard to understand because there are too many status
and branches, and it's overlong.

This patch factor out the case to read the rdev with bad blocks from
read_balance(), there are no functional changes.

Co-developed-by: default avatarPaul Luse <paul.e.luse@linux.intel.com>
Signed-off-by: default avatarPaul Luse <paul.e.luse@linux.intel.com>
Signed-off-by: default avatarYu Kuai <yukuai3@huawei.com>
Reviewed-by: default avatarXiao Ni <xni@redhat.com>
Signed-off-by: default avatarSong Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20240229095714.926789-10-yukuai1@huaweicloud.com
parent dfa8ecd1
Loading
Loading
Loading
Loading
+48 −31
Original line number Diff line number Diff line
@@ -620,6 +620,44 @@ static int choose_first_rdev(struct r1conf *conf, struct r1bio *r1_bio,
	return -1;
}

static int choose_bb_rdev(struct r1conf *conf, struct r1bio *r1_bio,
			  int *max_sectors)
{
	sector_t this_sector = r1_bio->sector;
	int best_disk = -1;
	int best_len = 0;
	int disk;

	for (disk = 0 ; disk < conf->raid_disks * 2 ; disk++) {
		struct md_rdev *rdev;
		int len;
		int read_len;

		if (r1_bio->bios[disk] == IO_BLOCKED)
			continue;

		rdev = conf->mirrors[disk].rdev;
		if (!rdev || test_bit(Faulty, &rdev->flags) ||
		    test_bit(WriteMostly, &rdev->flags))
			continue;

		/* keep track of the disk with the most readable sectors. */
		len = r1_bio->sectors;
		read_len = raid1_check_read_range(rdev, this_sector, &len);
		if (read_len > best_len) {
			best_disk = disk;
			best_len = read_len;
		}
	}

	if (best_disk != -1) {
		*max_sectors = best_len;
		update_read_sectors(conf, best_disk, this_sector, best_len);
	}

	return best_disk;
}

static int choose_slow_rdev(struct r1conf *conf, struct r1bio *r1_bio,
			    int *max_sectors)
{
@@ -708,8 +746,6 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect

	for (disk = 0 ; disk < conf->raid_disks * 2 ; disk++) {
		sector_t dist;
		sector_t first_bad;
		int bad_sectors;
		unsigned int pending;

		rdev = conf->mirrors[disk].rdev;
@@ -722,36 +758,8 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
			continue;
		if (test_bit(WriteMostly, &rdev->flags))
			continue;
		/* This is a reasonable device to use.  It might
		 * even be best.
		 */
		if (is_badblock(rdev, this_sector, sectors,
				&first_bad, &bad_sectors)) {
			if (best_dist < MaxSector)
				/* already have a better device */
		if (rdev_has_badblock(rdev, this_sector, sectors))
			continue;
			if (first_bad <= this_sector) {
				/* cannot read here. If this is the 'primary'
				 * device, then we must not read beyond
				 * bad_sectors from another device..
				 */
				bad_sectors -= (this_sector - first_bad);
				if (best_good_sectors > sectors)
					best_good_sectors = sectors;

			} else {
				sector_t good_sectors = first_bad - this_sector;
				if (good_sectors > best_good_sectors) {
					best_good_sectors = good_sectors;
					best_disk = disk;
				}
			}
			continue;
		} else {
			if ((sectors > best_good_sectors) && (best_disk >= 0))
				best_disk = -1;
			best_good_sectors = sectors;
		}

		if (best_disk >= 0)
			/* At least two disks to choose from so failfast is OK */
@@ -843,6 +851,15 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
	if (best_disk >= 0)
		return best_disk;

	/*
	 * If we are here it means we didn't find a perfectly good disk so
	 * now spend a bit more time trying to find one with the most good
	 * sectors.
	 */
	disk = choose_bb_rdev(conf, r1_bio, max_sectors);
	if (disk >= 0)
		return disk;

	return choose_slow_rdev(conf, r1_bio, max_sectors);
}