On Thu, Feb 22, 2024 at 4:04 PM Yu Kuai <yukuai1@xxxxxxxxxxxxxxx> wrote: > > From: Yu Kuai <yukuai3@xxxxxxxxxx> > > The checking and handler of bad blocks appear many timers during > read_balance() in raid1 and raid10. This helper will be used in later > patches to simplify read_balance() a lot. > > Co-developed-by: Paul Luse <paul.e.luse@xxxxxxxxxxxxxxx> > Signed-off-by: Paul Luse <paul.e.luse@xxxxxxxxxxxxxxx> > Signed-off-by: Yu Kuai <yukuai3@xxxxxxxxxx> > --- > drivers/md/raid1-10.c | 49 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 49 insertions(+) > > diff --git a/drivers/md/raid1-10.c b/drivers/md/raid1-10.c > index 512746551f36..9bc0f0022a6c 100644 > --- a/drivers/md/raid1-10.c > +++ b/drivers/md/raid1-10.c > @@ -227,3 +227,52 @@ static inline bool exceed_read_errors(struct mddev *mddev, struct md_rdev *rdev) > > return false; > } > + > +/** > + * raid1_check_read_range() - check a given read range for bad blocks, > + * available read length is returned; > + * @rdev: the rdev to read; > + * @this_sector: read position; > + * @len: read length; > + * > + * helper function for read_balance() > + * > + * 1) If there are no bad blocks in the range, @len is returned; > + * 2) If the range are all bad blocks, 0 is returned; > + * 3) If there are partial bad blocks: > + * - If the bad block range starts after @this_sector, the length of first > + * good region is returned; > + * - If the bad block range starts before @this_sector, 0 is returned and > + * the @len is updated to the offset into the region before we get to the > + * good blocks; > + */ > +static inline int raid1_check_read_range(struct md_rdev *rdev, > + sector_t this_sector, int *len) > +{ > + sector_t first_bad; > + int bad_sectors; > + > + /* no bad block overlap */ > + if (!is_badblock(rdev, this_sector, *len, &first_bad, &bad_sectors)) > + return *len; > + > + /* > + * bad block range starts offset into our range so we can return the > + * number of sectors before the bad blocks start. > + */ > + if (first_bad > this_sector) > + return first_bad - this_sector; > + > + /* read range is fully consumed by bad blocks. */ > + if (this_sector + *len <= first_bad + bad_sectors) > + return 0; > + > + /* > + * final case, bad block range starts before or at the start of our > + * range but does not cover our entire range so we still return 0 but > + * update the length with the number of sectors before we get to the > + * good ones. > + */ > + *len = first_bad + bad_sectors - this_sector; > + return 0; > +} > -- > 2.39.2 > > This patch looks good to me. Reviewed-by: Xiao Ni <xni@xxxxxxxxxx>