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: Paul Luse <paul.e.luse@linux.intel.com> Signed-off-by: Paul Luse <paul.e.luse@linux.intel.com> Signed-off-by: Yu Kuai <yukuai3@huawei.com> Reviewed-by: Xiao Ni <xni@redhat.com> Signed-off-by: Song Liu <song@kernel.org> Link: https://lore.kernel.org/r/20240229095714.926789-10-yukuai1@huaweicloud.com
This commit is contained in:
parent
dfa8ecd167
commit
9f3ced7922
1 changed files with 48 additions and 31 deletions
|
@ -620,6 +620,44 @@ static int choose_first_rdev(struct r1conf *conf, struct r1bio *r1_bio,
|
||||||
return -1;
|
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,
|
static int choose_slow_rdev(struct r1conf *conf, struct r1bio *r1_bio,
|
||||||
int *max_sectors)
|
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++) {
|
for (disk = 0 ; disk < conf->raid_disks * 2 ; disk++) {
|
||||||
sector_t dist;
|
sector_t dist;
|
||||||
sector_t first_bad;
|
|
||||||
int bad_sectors;
|
|
||||||
unsigned int pending;
|
unsigned int pending;
|
||||||
|
|
||||||
rdev = conf->mirrors[disk].rdev;
|
rdev = conf->mirrors[disk].rdev;
|
||||||
|
@ -722,36 +758,8 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
|
||||||
continue;
|
continue;
|
||||||
if (test_bit(WriteMostly, &rdev->flags))
|
if (test_bit(WriteMostly, &rdev->flags))
|
||||||
continue;
|
continue;
|
||||||
/* This is a reasonable device to use. It might
|
if (rdev_has_badblock(rdev, this_sector, sectors))
|
||||||
* even be best.
|
|
||||||
*/
|
|
||||||
if (is_badblock(rdev, this_sector, sectors,
|
|
||||||
&first_bad, &bad_sectors)) {
|
|
||||||
if (best_dist < MaxSector)
|
|
||||||
/* already have a better device */
|
|
||||||
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;
|
continue;
|
||||||
} else {
|
|
||||||
if ((sectors > best_good_sectors) && (best_disk >= 0))
|
|
||||||
best_disk = -1;
|
|
||||||
best_good_sectors = sectors;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (best_disk >= 0)
|
if (best_disk >= 0)
|
||||||
/* At least two disks to choose from so failfast is OK */
|
/* 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)
|
if (best_disk >= 0)
|
||||||
return best_disk;
|
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);
|
return choose_slow_rdev(conf, r1_bio, max_sectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue