Skip to content

Commit

Permalink
Merge tag 'md-next-20230817' of https://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/song/md into for-6.6/block

Pull MD changes from Song:

"1. Fix perf regression for raid0 large sequential writes, by Jan Kara.
 2. Fix split bio iostat for raid0, by David Jeffery.
 3. Various raid1 fixes, by Heinz Mauelshagen and Xueshi Hu."

* tag 'md-next-20230817' of https://git.kernel.org/pub/scm/linux/kernel/git/song/md:
  md: raid0: account for split bio in iostat accounting
  md/raid0: Fix performance regression for large sequential writes
  md/raid0: Factor out helper for mapping and submitting a bio
  md raid1: allow writebehind to work on any leg device set WriteMostly
  md/raid1: hold the barrier until handle_read_error() finishes
  md/raid1: free the r1bio before waiting for blocked rdev
  md/raid1: call free_r1bio() before allow_barrier() in raid_end_bio_io()
  • Loading branch information
Jens Axboe committed Aug 18, 2023
2 parents ec14a87 + cc22b54 commit eb051b2
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 49 deletions.
82 changes: 41 additions & 41 deletions drivers/md/raid0.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,68 +545,34 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio)
bio_endio(bio);
}

static bool raid0_make_request(struct mddev *mddev, struct bio *bio)
static void raid0_map_submit_bio(struct mddev *mddev, struct bio *bio)
{
struct r0conf *conf = mddev->private;
struct strip_zone *zone;
struct md_rdev *tmp_dev;
sector_t bio_sector;
sector_t sector;
sector_t orig_sector;
unsigned chunk_sects;
unsigned sectors;

if (unlikely(bio->bi_opf & REQ_PREFLUSH)
&& md_flush_request(mddev, bio))
return true;
sector_t bio_sector = bio->bi_iter.bi_sector;
sector_t sector = bio_sector;

if (unlikely((bio_op(bio) == REQ_OP_DISCARD))) {
raid0_handle_discard(mddev, bio);
return true;
}
md_account_bio(mddev, &bio);

bio_sector = bio->bi_iter.bi_sector;
sector = bio_sector;
chunk_sects = mddev->chunk_sectors;

sectors = chunk_sects -
(likely(is_power_of_2(chunk_sects))
? (sector & (chunk_sects-1))
: sector_div(sector, chunk_sects));

/* Restore due to sector_div */
sector = bio_sector;

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

if (bio->bi_pool != &mddev->bio_set)
md_account_bio(mddev, &bio);

orig_sector = sector;
zone = find_zone(mddev->private, &sector);
switch (conf->layout) {
case RAID0_ORIG_LAYOUT:
tmp_dev = map_sector(mddev, zone, orig_sector, &sector);
tmp_dev = map_sector(mddev, zone, bio_sector, &sector);
break;
case RAID0_ALT_MULTIZONE_LAYOUT:
tmp_dev = map_sector(mddev, zone, sector, &sector);
break;
default:
WARN(1, "md/raid0:%s: Invalid layout\n", mdname(mddev));
bio_io_error(bio);
return true;
return;
}

if (unlikely(is_rdev_broken(tmp_dev))) {
bio_io_error(bio);
md_error(mddev, tmp_dev);
return true;
return;
}

bio_set_dev(bio, tmp_dev->bdev);
Expand All @@ -618,6 +584,40 @@ static bool raid0_make_request(struct mddev *mddev, struct bio *bio)
bio_sector);
mddev_check_write_zeroes(mddev, bio);
submit_bio_noacct(bio);
}

static bool raid0_make_request(struct mddev *mddev, struct bio *bio)
{
sector_t sector;
unsigned chunk_sects;
unsigned sectors;

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

if (unlikely((bio_op(bio) == REQ_OP_DISCARD))) {
raid0_handle_discard(mddev, bio);
return true;
}

sector = bio->bi_iter.bi_sector;
chunk_sects = mddev->chunk_sectors;

sectors = chunk_sects -
(likely(is_power_of_2(chunk_sects))
? (sector & (chunk_sects-1))
: sector_div(sector, chunk_sects));

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

raid0_map_submit_bio(mddev, bio);
return true;
}

Expand Down
18 changes: 10 additions & 8 deletions drivers/md/raid1.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ static void raid_end_bio_io(struct r1bio *r1_bio)
{
struct bio *bio = r1_bio->master_bio;
struct r1conf *conf = r1_bio->mddev->private;
sector_t sector = r1_bio->sector;

/* if nobody has done the final endio yet, do it now */
if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
Expand All @@ -321,13 +322,13 @@ static void raid_end_bio_io(struct r1bio *r1_bio)

call_bio_endio(r1_bio);
}

free_r1bio(r1_bio);
/*
* Wake up any possible resync thread that waits for the device
* to go idle. All I/Os, even write-behind writes, are done.
*/
allow_barrier(conf, r1_bio->sector);

free_r1bio(r1_bio);
allow_barrier(conf, sector);
}

/*
Expand Down Expand Up @@ -1377,6 +1378,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
return;
}

retry_write:
r1_bio = alloc_r1bio(mddev, bio);
r1_bio->sectors = max_write_sectors;

Expand All @@ -1392,7 +1394,6 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
*/

disks = conf->raid_disks * 2;
retry_write:
blocked_rdev = NULL;
rcu_read_lock();
max_sectors = r1_bio->sectors;
Expand Down Expand Up @@ -1472,7 +1473,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
for (j = 0; j < i; j++)
if (r1_bio->bios[j])
rdev_dec_pending(conf->mirrors[j].rdev, mddev);
r1_bio->state = 0;
free_r1bio(r1_bio);
allow_barrier(conf, bio->bi_iter.bi_sector);

if (bio->bi_opf & REQ_NOWAIT) {
Expand Down Expand Up @@ -1522,8 +1523,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
* Not if there are too many, or cannot
* allocate memory, or a reader on WriteMostly
* is waiting for behind writes to flush */
if (bitmap &&
test_bit(WriteMostly, &rdev->flags) &&
if (bitmap && write_behind &&
(atomic_read(&bitmap->behind_writes)
< mddev->bitmap_info.max_write_behind) &&
!waitqueue_active(&bitmap->behind_wait)) {
Expand Down Expand Up @@ -2510,6 +2510,7 @@ static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)
struct mddev *mddev = conf->mddev;
struct bio *bio;
struct md_rdev *rdev;
sector_t sector;

clear_bit(R1BIO_ReadError, &r1_bio->state);
/* we got a read error. Maybe the drive is bad. Maybe just
Expand Down Expand Up @@ -2539,12 +2540,13 @@ static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)
}

rdev_dec_pending(rdev, conf->mddev);
allow_barrier(conf, r1_bio->sector);
sector = r1_bio->sector;
bio = r1_bio->master_bio;

/* Reuse the old r1_bio so that the IO_BLOCKED settings are preserved */
r1_bio->state = 0;
raid1_read_request(mddev, bio, r1_bio->sectors, r1_bio);
allow_barrier(conf, sector);
}

static void raid1d(struct md_thread *thread)
Expand Down

0 comments on commit eb051b2

Please sign in to comment.