Merge tag 'md-next-2023-04-28' of https://git.kernel.org/pub/scm/linux/kernel/git/song/md into for-6.4/block

Pull MD fixes from Song:

"1. Improve raid5 sequential IO performance on spinning disks, which fixes
    a regression since v6.0, by Jan Kara.
 2. Fix bitmap offset types, which fixes an issue introduced in this merge
    window, by Jonathan Derrick."

* tag 'md-next-2023-04-28' of https://git.kernel.org/pub/scm/linux/kernel/git/song/md:
  md: Fix bitmap offset type in sb writer
  md/raid5: Improve performance for sequential IO
This commit is contained in:
Jens Axboe 2023-04-28 10:36:27 -06:00
commit f40c153afe
2 changed files with 47 additions and 4 deletions

View file

@ -219,7 +219,7 @@ static unsigned int optimal_io_size(struct block_device *bdev,
}
static unsigned int bitmap_io_size(unsigned int io_size, unsigned int opt_size,
sector_t start, sector_t boundary)
loff_t start, loff_t boundary)
{
if (io_size != opt_size &&
start + opt_size / SECTOR_SIZE <= boundary)
@ -237,8 +237,8 @@ static int __write_sb_page(struct md_rdev *rdev, struct bitmap *bitmap,
struct block_device *bdev;
struct mddev *mddev = bitmap->mddev;
struct bitmap_storage *store = &bitmap->storage;
sector_t offset = mddev->bitmap_info.offset;
sector_t ps, sboff, doff;
loff_t sboff, offset = mddev->bitmap_info.offset;
sector_t ps, doff;
unsigned int size = PAGE_SIZE;
unsigned int opt_size = PAGE_SIZE;

View file

@ -6079,6 +6079,38 @@ static enum stripe_result make_stripe_request(struct mddev *mddev,
return ret;
}
/*
* If the bio covers multiple data disks, find sector within the bio that has
* the lowest chunk offset in the first chunk.
*/
static sector_t raid5_bio_lowest_chunk_sector(struct r5conf *conf,
struct bio *bi)
{
int sectors_per_chunk = conf->chunk_sectors;
int raid_disks = conf->raid_disks;
int dd_idx;
struct stripe_head sh;
unsigned int chunk_offset;
sector_t r_sector = bi->bi_iter.bi_sector & ~((sector_t)RAID5_STRIPE_SECTORS(conf)-1);
sector_t sector;
/* We pass in fake stripe_head to get back parity disk numbers */
sector = raid5_compute_sector(conf, r_sector, 0, &dd_idx, &sh);
chunk_offset = sector_div(sector, sectors_per_chunk);
if (sectors_per_chunk - chunk_offset >= bio_sectors(bi))
return r_sector;
/*
* Bio crosses to the next data disk. Check whether it's in the same
* chunk.
*/
dd_idx++;
while (dd_idx == sh.pd_idx || dd_idx == sh.qd_idx)
dd_idx++;
if (dd_idx >= raid_disks)
return r_sector;
return r_sector + sectors_per_chunk - chunk_offset;
}
static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
{
DEFINE_WAIT_FUNC(wait, woken_wake_function);
@ -6150,6 +6182,17 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
}
md_account_bio(mddev, &bi);
/*
* Lets start with the stripe with the lowest chunk offset in the first
* chunk. That has the best chances of creating IOs adjacent to
* previous IOs in case of sequential IO and thus creates the most
* sequential IO pattern. We don't bother with the optimization when
* reshaping as the performance benefit is not worth the complexity.
*/
if (likely(conf->reshape_progress == MaxSector))
logical_sector = raid5_bio_lowest_chunk_sector(conf, bi);
s = (logical_sector - ctx.first_sector) >> RAID5_STRIPE_SHIFT(conf);
add_wait_queue(&conf->wait_for_overlap, &wait);
while (1) {
res = make_stripe_request(mddev, conf, &ctx, logical_sector,
@ -6178,7 +6221,7 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
continue;
}
s = find_first_bit(ctx.sectors_to_do, stripe_cnt);
s = find_next_bit_wrap(ctx.sectors_to_do, stripe_cnt, s);
if (s == stripe_cnt)
break;