Skip to content

Commit 1076481

Browse files
GuoqingJiang-Linuxliu-song-6
authored andcommitted
md: add io accounting for raid0 and raid5
We introduce a new bioset (io_acct_set) for raid0 and raid5 since they don't own clone infrastructure to accounting io. And the bioset is added to mddev instead of to raid0 and raid5 layer, because with this way, we can put common functions to md.h and reuse them in raid0 and raid5. Also struct md_io_acct is added accordingly which includes io start_time, the origin bio and cloned bio. Then we can call bio_{start,end}_io_acct to get related io status. Signed-off-by: Guoqing Jiang <[email protected]> Signed-off-by: Song Liu <[email protected]>
1 parent ad3fc79 commit 1076481

File tree

4 files changed

+68
-3
lines changed

4 files changed

+68
-3
lines changed

drivers/md/md.c

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2340,7 +2340,8 @@ int md_integrity_register(struct mddev *mddev)
23402340
bdev_get_integrity(reference->bdev));
23412341

23422342
pr_debug("md: data integrity enabled on %s\n", mdname(mddev));
2343-
if (bioset_integrity_create(&mddev->bio_set, BIO_POOL_SIZE)) {
2343+
if (bioset_integrity_create(&mddev->bio_set, BIO_POOL_SIZE) ||
2344+
bioset_integrity_create(&mddev->io_acct_set, BIO_POOL_SIZE)) {
23442345
pr_err("md: failed to create integrity pool for %s\n",
23452346
mdname(mddev));
23462347
return -EINVAL;
@@ -5569,6 +5570,7 @@ static void md_free(struct kobject *ko)
55695570

55705571
bioset_exit(&mddev->bio_set);
55715572
bioset_exit(&mddev->sync_set);
5573+
bioset_exit(&mddev->io_acct_set);
55725574
kfree(mddev);
55735575
}
55745576

@@ -5862,7 +5864,13 @@ int md_run(struct mddev *mddev)
58625864
if (!bioset_initialized(&mddev->sync_set)) {
58635865
err = bioset_init(&mddev->sync_set, BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS);
58645866
if (err)
5865-
return err;
5867+
goto exit_bio_set;
5868+
}
5869+
if (!bioset_initialized(&mddev->io_acct_set)) {
5870+
err = bioset_init(&mddev->io_acct_set, BIO_POOL_SIZE,
5871+
offsetof(struct md_io_acct, bio_clone), 0);
5872+
if (err)
5873+
goto exit_sync_set;
58665874
}
58675875

58685876
spin_lock(&pers_lock);
@@ -5990,6 +5998,7 @@ int md_run(struct mddev *mddev)
59905998
blk_queue_flag_set(QUEUE_FLAG_NONROT, mddev->queue);
59915999
else
59926000
blk_queue_flag_clear(QUEUE_FLAG_NONROT, mddev->queue);
6001+
blk_queue_flag_set(QUEUE_FLAG_IO_STAT, mddev->queue);
59936002
}
59946003
if (pers->sync_request) {
59956004
if (mddev->kobj.sd &&
@@ -6039,8 +6048,11 @@ int md_run(struct mddev *mddev)
60396048
module_put(pers->owner);
60406049
md_bitmap_destroy(mddev);
60416050
abort:
6042-
bioset_exit(&mddev->bio_set);
6051+
bioset_exit(&mddev->io_acct_set);
6052+
exit_sync_set:
60436053
bioset_exit(&mddev->sync_set);
6054+
exit_bio_set:
6055+
bioset_exit(&mddev->bio_set);
60446056
return err;
60456057
}
60466058
EXPORT_SYMBOL_GPL(md_run);
@@ -6264,6 +6276,7 @@ void md_stop(struct mddev *mddev)
62646276
__md_stop(mddev);
62656277
bioset_exit(&mddev->bio_set);
62666278
bioset_exit(&mddev->sync_set);
6279+
bioset_exit(&mddev->io_acct_set);
62676280
}
62686281

62696282
EXPORT_SYMBOL_GPL(md_stop);
@@ -8568,6 +8581,38 @@ void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,
85688581
}
85698582
EXPORT_SYMBOL_GPL(md_submit_discard_bio);
85708583

8584+
static void md_end_io_acct(struct bio *bio)
8585+
{
8586+
struct md_io_acct *md_io_acct = bio->bi_private;
8587+
struct bio *orig_bio = md_io_acct->orig_bio;
8588+
8589+
orig_bio->bi_status = bio->bi_status;
8590+
8591+
bio_end_io_acct(orig_bio, md_io_acct->start_time);
8592+
bio_put(bio);
8593+
bio_endio(orig_bio);
8594+
}
8595+
8596+
/* used by personalities (raid0 and raid5) to account io stats */
8597+
void md_account_bio(struct mddev *mddev, struct bio **bio)
8598+
{
8599+
struct md_io_acct *md_io_acct;
8600+
struct bio *clone;
8601+
8602+
if (!blk_queue_io_stat((*bio)->bi_bdev->bd_disk->queue))
8603+
return;
8604+
8605+
clone = bio_clone_fast(*bio, GFP_NOIO, &mddev->io_acct_set);
8606+
md_io_acct = container_of(clone, struct md_io_acct, bio_clone);
8607+
md_io_acct->orig_bio = *bio;
8608+
md_io_acct->start_time = bio_start_io_acct(*bio);
8609+
8610+
clone->bi_end_io = md_end_io_acct;
8611+
clone->bi_private = md_io_acct;
8612+
*bio = clone;
8613+
}
8614+
EXPORT_SYMBOL_GPL(md_account_bio);
8615+
85718616
/* md_allow_write(mddev)
85728617
* Calling this ensures that the array is marked 'active' so that writes
85738618
* may proceed without blocking. It is important to call this before

drivers/md/md.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,7 @@ struct mddev {
487487
struct bio_set sync_set; /* for sync operations like
488488
* metadata and bitmap writes
489489
*/
490+
struct bio_set io_acct_set; /* for raid0 and raid5 io accounting */
490491

491492
/* Generic flush handling.
492493
* The last to finish preflush schedules a worker to submit
@@ -683,6 +684,12 @@ struct md_thread {
683684
void *private;
684685
};
685686

687+
struct md_io_acct {
688+
struct bio *orig_bio;
689+
unsigned long start_time;
690+
struct bio bio_clone;
691+
};
692+
686693
#define THREAD_WAKEUP 0
687694

688695
static inline void safe_put_page(struct page *p)
@@ -714,6 +721,7 @@ extern void md_error(struct mddev *mddev, struct md_rdev *rdev);
714721
extern void md_finish_reshape(struct mddev *mddev);
715722
void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,
716723
struct bio *bio, sector_t start, sector_t size);
724+
void md_account_bio(struct mddev *mddev, struct bio **bio);
717725

718726
extern bool __must_check md_flush_request(struct mddev *mddev, struct bio *bio);
719727
extern void md_super_write(struct mddev *mddev, struct md_rdev *rdev,

drivers/md/raid0.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,9 @@ static bool raid0_make_request(struct mddev *mddev, struct bio *bio)
546546
bio = split;
547547
}
548548

549+
if (bio->bi_pool != &mddev->bio_set)
550+
md_account_bio(mddev, &bio);
551+
549552
orig_sector = sector;
550553
zone = find_zone(mddev->private, &sector);
551554
switch (conf->layout) {

drivers/md/raid5.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5468,6 +5468,7 @@ static struct bio *chunk_aligned_read(struct mddev *mddev, struct bio *raid_bio)
54685468
sector_t sector = raid_bio->bi_iter.bi_sector;
54695469
unsigned chunk_sects = mddev->chunk_sectors;
54705470
unsigned sectors = chunk_sects - (sector & (chunk_sects-1));
5471+
struct r5conf *conf = mddev->private;
54715472

54725473
if (sectors < bio_sectors(raid_bio)) {
54735474
struct r5conf *conf = mddev->private;
@@ -5477,6 +5478,9 @@ static struct bio *chunk_aligned_read(struct mddev *mddev, struct bio *raid_bio)
54775478
raid_bio = split;
54785479
}
54795480

5481+
if (raid_bio->bi_pool != &conf->bio_split)
5482+
md_account_bio(mddev, &raid_bio);
5483+
54805484
if (!raid5_read_one_chunk(mddev, raid_bio))
54815485
return raid_bio;
54825486

@@ -5756,6 +5760,7 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
57565760
DEFINE_WAIT(w);
57575761
bool do_prepare;
57585762
bool do_flush = false;
5763+
bool do_clone = false;
57595764

57605765
if (unlikely(bi->bi_opf & REQ_PREFLUSH)) {
57615766
int ret = log_handle_flush_request(conf, bi);
@@ -5784,6 +5789,7 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
57845789
if (rw == READ && mddev->degraded == 0 &&
57855790
mddev->reshape_position == MaxSector) {
57865791
bi = chunk_aligned_read(mddev, bi);
5792+
do_clone = true;
57875793
if (!bi)
57885794
return true;
57895795
}
@@ -5798,6 +5804,9 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
57985804
last_sector = bio_end_sector(bi);
57995805
bi->bi_next = NULL;
58005806

5807+
if (!do_clone)
5808+
md_account_bio(mddev, &bi);
5809+
58015810
prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE);
58025811
for (; logical_sector < last_sector; logical_sector += RAID5_STRIPE_SECTORS(conf)) {
58035812
int previous;

0 commit comments

Comments
 (0)