On Fri, May 21, 2021 at 1:01 AM Guoqing Jiang <jgq516@xxxxxxxxx> wrote: > > From: Artur Paszkiewicz <artur.paszkiewicz@xxxxxxxxx> > > Use generic io accounting functions to manage io stats. There was an > attempt to do this earlier in commit 18c0b223cf990172 ("md: use generic > io stats accounting functions to simplify io stat accounting"), but it > did not include a call to generic_end_io_acct() and caused issues with > tracking in-flight IOs, so it was later removed in commit 74672d069b29 > ("md: fix md io stats accounting broken"). > > This patch attempts to fix this by using both generic_start_io_acct() > and generic_end_io_acct(). To make it possible, in md_make_request() a > bio is cloned with additional data - struct md_io, which includes the io > start_time. A new bioset is introduced for this purpose. We call > generic_start_io_acct() and pass the clone instead of the original to > md_handle_request(). When it completes, we call generic_end_io_acct() > and complete the original bio. > > This adds correct statistics about in-flight IOs and IO processing time, > interpreted e.g. in iostat as await, svctm, aqu-sz and %util. > > It also fixes a situation where too many IOs where reported if a bio was > re-submitted to the mddev, because io accounting is now performed only > on newly arriving bios. > > Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@xxxxxxxxx> > [Guoqing: rebase and make generic accounting applies to personalities > which don't have clone infrastructure] > Signed-off-by: Guoqing Jiang <jiangguoqing@xxxxxxxxxx> > --- > Delete not necessary bioset_exit in md_integrity_register, thanks for > Artur's review. > > drivers/md/md.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++- > drivers/md/md.h | 1 + > 2 files changed, 55 insertions(+), 1 deletion(-) > > diff --git a/drivers/md/md.c b/drivers/md/md.c > index 7ba00e4c862d..d8823db843db 100644 > --- a/drivers/md/md.c > +++ b/drivers/md/md.c > @@ -441,6 +441,25 @@ void md_handle_request(struct mddev *mddev, struct bio *bio) > } > EXPORT_SYMBOL(md_handle_request); > > +struct md_io { > + struct mddev *mddev; > + struct bio *orig_bio; > + unsigned long start_time; > + struct bio bio_clone; > +}; > + > +static void md_end_io(struct bio *bio) > +{ > + struct md_io *md_io = bio->bi_private; > + struct bio *orig_bio = md_io->orig_bio; > + > + orig_bio->bi_status = bio->bi_status; > + > + bio_end_io_acct(orig_bio, md_io->start_time); > + bio_put(bio); > + bio_endio(orig_bio); > +} > + > static blk_qc_t md_submit_bio(struct bio *bio) > { > const int rw = bio_data_dir(bio); > @@ -465,6 +484,30 @@ static blk_qc_t md_submit_bio(struct bio *bio) > return BLK_QC_T_NONE; > } > > + /* > + * clone bio under conditions: > + * 1. QUEUE_FLAG_IO_STAT flag is set. > + * 2. bio just enters md and it is not split from personality. > + */ We had iostat on by default. So, let set QUEUE_FLAG_IO_STAT in md_run(). Thanks, Song