The commit 41d2d848e5c0 ("md: improve io stats accounting") could cause
double fault problem per the report [1], and also it is not correct to
change ->bi_end_io if md don't own it, so let's revert it.
And io stats accounting will be replemented in later commits.
[1]. https://lore.kernel.org/linux-raid/3bf04253-3fad-434a-63a7-20214e38cf26@gmail.com/T/#t
Fixes: 41d2d848e5c0 ("md: improve io stats accounting")
Signed-off-by: Guoqing Jiang <redacted>
---
drivers/md/md.c | 45 ---------------------------------------------
drivers/md/md.h | 1 -
2 files changed, 46 deletions(-)
@@ -489,21 +465,6 @@ static blk_qc_t md_submit_bio(struct bio *bio)returnBLK_QC_T_NONE;}-if(bio->bi_end_io!=md_end_io){-structmd_io*md_io;--md_io=mempool_alloc(&mddev->md_io_pool,GFP_NOIO);-md_io->mddev=mddev;-md_io->orig_bi_end_io=bio->bi_end_io;-md_io->orig_bi_private=bio->bi_private;-md_io->orig_bi_bdev=bio->bi_bdev;--bio->bi_end_io=md_end_io;-bio->bi_private=md_io;--md_io->start_time=bio_start_io_acct(bio);-}-/* bio could be mergeable after passing to underlayer */bio->bi_opf&=~REQ_NOMERGE;
From: Artur Paszkiewicz <redacted>
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 <redacted>
[Guoqing: rebase and make generic accounting applies to personalities
which don't have clone infrastructure]
Signed-off-by: Guoqing Jiang <redacted>
---
drivers/md/md.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++-
drivers/md/md.h | 1 +
2 files changed, 54 insertions(+), 1 deletion(-)
@@ -465,6 +484,29 @@ static blk_qc_t md_submit_bio(struct bio *bio)returnBLK_QC_T_NONE;}+/*+*Wedon'tclonebioformultipath,raid1andraid10sincewecanreuse+*theircloneinfrastructure.+*/+if(blk_queue_io_stat(bio->bi_bdev->bd_disk->queue)&&+(bio->bi_pool!=&mddev->md_io_bs)&&+(mddev->level!=1)&&(mddev->level!=10)&&+(mddev->level!=LEVEL_MULTIPATH)){+structmd_io*md_io;+structbio*clone;++clone=bio_clone_fast(bio,GFP_NOIO,&mddev->md_io_bs);++md_io=container_of(clone,structmd_io,orig_bio_clone);+md_io->mddev=mddev;+md_io->orig_bio=bio;+md_io->start_time=bio_start_io_acct(bio);++clone->bi_end_io=md_end_io;+clone->bi_private=md_io;+bio=clone;+}+/* bio could be mergeable after passing to underlayer */bio->bi_opf&=~REQ_NOMERGE;
@@ -2340,7 +2382,8 @@ int md_integrity_register(struct mddev *mddev)bdev_get_integrity(reference->bdev));pr_debug("md: data integrity enabled on %s\n",mdname(mddev));-if(bioset_integrity_create(&mddev->bio_set,BIO_POOL_SIZE)){+if(bioset_integrity_create(&mddev->bio_set,BIO_POOL_SIZE)||+bioset_integrity_create(&mddev->md_io_bs,BIO_POOL_SIZE)){pr_err("md: failed to create integrity pool for %s\n",mdname(mddev));return-EINVAL;
We can do the accounting between make_request and io is finished, also
introduce start_time accordingly.
Signed-off-by: Guoqing Jiang <redacted>
---
drivers/md/md-multipath.c | 5 +++++
drivers/md/md-multipath.h | 1 +
2 files changed, 6 insertions(+)
For raid1, we record the start time between split bio and clone bio,
and finish the accounting in the final endio.
Also introduce start_time in r1bio accordingly.
Signed-off-by: Guoqing Jiang <redacted>
---
drivers/md/raid1.c | 11 +++++++++++
drivers/md/raid1.h | 1 +
2 files changed, 12 insertions(+)
For raid10, we record the start time between split bio and clone bio,
and finish the accounting in the final endio.
Also introduce start_time in r10bio accordingly.
Signed-off-by: Guoqing Jiang <redacted>
---
drivers/md/raid10.c | 7 +++++++
drivers/md/raid10.h | 1 +
2 files changed, 8 insertions(+)
From: Artur Paszkiewicz <hidden> Date: 2021-05-18 10:12:38
On 18.05.2021 07:32, Guoqing Jiang wrote:
+ /*
+ * We don't clone bio for multipath, raid1 and raid10 since we can reuse
+ * their clone infrastructure.
+ */
+ if (blk_queue_io_stat(bio->bi_bdev->bd_disk->queue) &&
+ (bio->bi_pool != &mddev->md_io_bs) &&
+ (mddev->level != 1) && (mddev->level != 10) &&
+ (mddev->level != LEVEL_MULTIPATH)) {
Maybe add a flag to struct md_personality and check it here? Something
that will be set only for the personalities which clone the bio
themselves.
Doesn't this need to check the bio->bi_pool also against mddev->bio_set
to skip the bios split by md? Similarly to the check against
bio_chain_endio which you did before.
Thanks,
Artur
From: Christoph Hellwig <hch@infradead.org> Date: 2021-05-18 13:42:25
On Tue, May 18, 2021 at 01:32:24PM +0800, Guoqing Jiang wrote:
quoted hunk
For raid1, we record the start time between split bio and clone bio,
and finish the accounting in the final endio.
Also introduce start_time in r1bio accordingly.
Signed-off-by: Guoqing Jiang <redacted>
---
drivers/md/raid1.c | 11 +++++++++++
drivers/md/raid1.h | 1 +
2 files changed, 12 insertions(+)
+ /*
+ * Reuse print_msg, if it is false then a fresh r1_bio is just
+ * allocated before.
+ */
+ if (!print_msg && blk_queue_io_stat(bio->bi_bdev->bd_disk->queue))
+ r1_bio->start_time = bio_start_io_acct(bio);
+
Please rename the print_msg vaiable to something sensible and drop the
comment.
From: Song Liu <song@kernel.org> Date: 2021-05-19 00:14:35
On Mon, May 17, 2021 at 10:33 PM Guoqing Jiang [off-list ref] wrote:
Hi Song,
Based on previous discussion, this set reverts current mechanism, then
switches back to the v1 version from Artur.
Also reuses the current clone infrastructer for mpath, raid1 and raid10.
Thanks,
Guoqing
Thanks Guoqing! Please address Christoph's feedback and send v2.
Song
+ /*
+ * We don't clone bio for multipath, raid1 and raid10 since we can reuse
+ * their clone infrastructure.
+ */
+ if (blk_queue_io_stat(bio->bi_bdev->bd_disk->queue) &&
+ (bio->bi_pool != &mddev->md_io_bs) &&
+ (mddev->level != 1) && (mddev->level != 10) &&
+ (mddev->level != LEVEL_MULTIPATH)) {
Maybe add a flag to struct md_personality and check it here? Something
that will be set only for the personalities which clone the bio
themselves.
Good point.
Doesn't this need to check the bio->bi_pool also against mddev->bio_set
to skip the bios split by md? Similarly to the check against
bio_chain_endio which you did before.
Hmm, raid0 allocates split bio from mddev->bio_set, but raid5 is
different, it splits bio from r5conf->bio_split. So either let raid5 also
splits bio from mddev->bio_set, or add an additional checking for
raid5. Thoughts?
Thanks,
Guoqing
Is anyone actually still using MD multipathing? I wonder if we just
need to deprecate and eventually remove this code..
Not sure about it, only linear is marked with deprecated.
drivers/md/md-linear.c:MODULE_ALIAS("md-personality-1"); /* LINEAR -
deprecated*/
Perhaps better to mention they are deprecated in Kconfig.
Thanks,
Guoqing
On Tue, May 18, 2021 at 01:32:24PM +0800, Guoqing Jiang wrote:
quoted
For raid1, we record the start time between split bio and clone bio,
and finish the accounting in the final endio.
Also introduce start_time in r1bio accordingly.
Signed-off-by: Guoqing Jiang <redacted>
---
drivers/md/raid1.c | 11 +++++++++++
drivers/md/raid1.h | 1 +
2 files changed, 12 insertions(+)
+ /*
+ * Reuse print_msg, if it is false then a fresh r1_bio is just
+ * allocated before.
+ */
+ if (!print_msg && blk_queue_io_stat(bio->bi_bdev->bd_disk->queue))
+ r1_bio->start_time = bio_start_io_acct(bio);
+
Please rename the print_msg vaiable to something sensible and drop the
comment.
On Mon, May 17, 2021 at 10:33 PM Guoqing Jiang [off-list ref] wrote:
quoted
Hi Song,
Based on previous discussion, this set reverts current mechanism, then
switches back to the v1 version from Artur.
Also reuses the current clone infrastructer for mpath, raid1 and raid10.
Thanks,
Guoqing
Thanks Guoqing! Please address Christoph's feedback and send v2.
Sure, please comment about the checking about skip the split by md.
Thanks,
Guoqing
From: Artur Paszkiewicz <hidden> Date: 2021-05-19 07:26:25
On 19.05.2021 03:30, Guoqing Jiang wrote:
Hmm, raid0 allocates split bio from mddev->bio_set, but raid5 is
different, it splits bio from r5conf->bio_split. So either let raid5 also
splits bio from mddev->bio_set, or add an additional checking for
raid5. Thoughts?
It looks like raid5 has a different bio set for that because it uses
mddev->bio_set for something else - allocating a bio for rdev. So I
think it can be changed to split from mddev->bio_set and have a private
bio set for the rdev bio allocation.
From: Christoph Hellwig <hch@infradead.org> Date: 2021-05-19 07:47:10
On Wed, May 19, 2021 at 09:26:21AM +0200, Artur Paszkiewicz wrote:
On 19.05.2021 03:30, Guoqing Jiang wrote:
quoted
Hmm, raid0 allocates split bio from mddev->bio_set, but raid5 is
different, it splits bio from r5conf->bio_split. So either let raid5 also
splits bio from mddev->bio_set, or add an additional checking for
raid5. Thoughts?
It looks like raid5 has a different bio set for that because it uses
mddev->bio_set for something else - allocating a bio for rdev. So I
think it can be changed to split from mddev->bio_set and have a private
bio set for the rdev bio allocation.
Just wondering: what about moving the allocation of the clone into the
personalities entirely?
Hmm, raid0 allocates split bio from mddev->bio_set, but raid5 is
different, it splits bio from r5conf->bio_split. So either let raid5 also
splits bio from mddev->bio_set, or add an additional checking for
raid5. Thoughts?
It looks like raid5 has a different bio set for that because it uses
mddev->bio_set for something else - allocating a bio for rdev. So I
think it can be changed to split from mddev->bio_set and have a private
bio set for the rdev bio allocation.
From: Song Liu <song@kernel.org> Date: 2021-05-20 00:45:15
On Wed, May 19, 2021 at 1:09 AM Guoqing Jiang [off-list ref] wrote:
quoted hunk
On 5/19/21 3:26 PM, Artur Paszkiewicz wrote:
quoted
On 19.05.2021 03:30, Guoqing Jiang wrote:
quoted
Hmm, raid0 allocates split bio from mddev->bio_set, but raid5 is
different, it splits bio from r5conf->bio_split. So either let raid5 also
splits bio from mddev->bio_set, or add an additional checking for
raid5. Thoughts?
It looks like raid5 has a different bio set for that because it uses
mddev->bio_set for something else - allocating a bio for rdev. So I
think it can be changed to split from mddev->bio_set and have a private
bio set for the rdev bio allocation.