boot stall regression due to blk-mq: use percpu_ref for mq usage count
Subsystems (4)
Hi Jens, hi Tejun,
I've seen multi-second boot stalls in one of my KVM setups during the initial scsi scan:
[ 0.949892] scsi host0: Virtio SCSI HBA [ 1.007864] scsi 0:0:0:0: Direct-Access QEMU QEMU HARDDISK 1.1. PQ: 0 ANSI: 5 [ 1.021299] scsi 0:0:1:0: Direct-Access QEMU QEMU HARDDISK 1.1. PQ: 0 ANSI: 5 [ 1.520356] tsc: Refined TSC clocksource calibration: 2491.910 MHz
<stall>
[ 16.186549] sd 0:0:0:0: Attached scsi generic sg0 type 0 [ 16.190478] sd 0:0:1:0: Attached scsi generic sg1 type 0 [ 16.194099] osd: LOADED open-osd 0.2.1 [ 16.203202] sd 0:0:0:0: [sda] 31457280 512-byte logical blocks: (16.1 GB/15.0 GiB) [ 16.208478] sd 0:0:0:0: [sda] Write Protect is off [ 16.211439] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA [ 16.218771] sd 0:0:1:0: [sdb] 31457280 512-byte logical blocks: (16.1 GB/15.0 GiB) [ 16.223264] sd 0:0:1:0: [sdb] Write Protect is off [ 16.225682] sd 0:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
I've tracked this down to "blk-mq: use percpu_ref for mq usage count" in a rather painful way as that one introduced enough other regressions to mess up bisect.
If I revert the following commits:
dd840087086f3b93ac20f7472b4fca59aff7b79fcddd5d17642cc6881352732693c2ae6930e9ce65add703fda981b9719d37f371498b9f129acbd997
which are the above mentioned commit and two fixes to it the problem goes away.
My qemu command line is below:
kvm \ -m 2048 \ -smp 1 \ -kernel arch/x86/boot/bzImage \ -append "root=/dev/vda console=tty0 console=ttyS0,115200n8 scsi_mod.use_blk_mq=Y" \ -nographic \ -drive if=virtio,file=/work/images/debian.qcow2,cache=none,serial="test1234" \ -drive if=none,id=test,file=/work/images/test.img,cache=none,aio=native \ -drive if=none,id=scratch,file=/work/images/scratch.img,cache=none,aio=native \ -device virtio-scsi-pci,id=scsi \ -device scsi-hd,drive=test \ -device scsi-hd,drive=scratch \ -drive file=/work/images/debian-7.3.0-amd64-netinst.iso,index=2,media=cdrom
Jens Axboe
maintainerQuoted 28 lines · Christoph Hellwig
Hi Jens, hi Tejun,
I've seen multi-second boot stalls in one of my KVM setups during the initial scsi scan:
[ 0.949892] scsi host0: Virtio SCSI HBA [ 1.007864] scsi 0:0:0:0: Direct-Access QEMU QEMU HARDDISK 1.1. PQ: 0 ANSI: 5 [ 1.021299] scsi 0:0:1:0: Direct-Access QEMU QEMU HARDDISK 1.1. PQ: 0 ANSI: 5 [ 1.520356] tsc: Refined TSC clocksource calibration: 2491.910 MHz<stall>
[ 16.186549] sd 0:0:0:0: Attached scsi generic sg0 type 0 [ 16.190478] sd 0:0:1:0: Attached scsi generic sg1 type 0 [ 16.194099] osd: LOADED open-osd 0.2.1 [ 16.203202] sd 0:0:0:0: [sda] 31457280 512-byte logical blocks: (16.1 GB/15.0 GiB) [ 16.208478] sd 0:0:0:0: [sda] Write Protect is off [ 16.211439] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA [ 16.218771] sd 0:0:1:0: [sdb] 31457280 512-byte logical blocks: (16.1 GB/15.0 GiB) [ 16.223264] sd 0:0:1:0: [sdb] Write Protect is off [ 16.225682] sd 0:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUAI've tracked this down to "blk-mq: use
percpu_reffor mq usage count" in a rather painful way as that one introduced enough other regressions to mess up bisect.
Quoted 8 lines
If I revert the following commits:
dd840087086f3b93ac20f7472b4fca59aff7b79fcddd5d17642cc6881352732693c2ae6930e9ce65add703fda981b9719d37f371498b9f129acbd997which are the above mentioned commit and two fixes to it the problem goes away.
Thanks for bisecting this, I ran into something that I think is the same issue about a week ago. Tejun, any ideas before I dig into this one?
Signature · 1 line
Jens Axboe
Jens,
can we simply get these commits reverted from now if there's no better fix? I'd hate to have this boot stall in the first kernel with blk-mq support for scsi.
Tejun Heo
maintainerQuoted 5 lines · Christoph Hellwig
Jens,
can we simply get these commits reverted from now if there's no better fix? I'd hate to have this boot stall in the first kernel with blk-mq support for scsi.
Patches going out right now.
Thanks.
Signature · 1 line
tejun
Tejun Heo
maintainerQuoted 8 lines · Tejun Heo
Quoted 5 lines · Christoph Hellwig
Jens,
can we simply get these commits reverted from now if there's no better fix? I'd hate to have this boot stall in the first kernel with blk-mq support for scsi.
Patches going out right now.
And the original implementation was broken, so...
Signature · 1 line
tejun
Quoted 8 lines · Tejun Heo
Quoted 5 lines · Christoph Hellwig
Jens,
can we simply get these commits reverted from now if there's no better fix? I'd hate to have this boot stall in the first kernel with blk-mq support for scsi.
Patches going out right now.
"[PATCHSET percpu/for-3.18] percpu_ref: implement switch_to_atomic/percpu()"
looks way to big for 3.17, and the regression was introduced in the 3.17 merge window. I'm not sure what was broken before, but it defintively survived a lot of testing.
Tejun Heo
maintainerQuoted 5 lines · Christoph Hellwig
"[PATCHSET percpu/for-3.18]
percpu_ref: implement switch_to_atomic/percpu()"looks way to big for 3.17, and the regression was introduced in the 3.17 merge window. I'm not sure what was broken before, but it defintively survived a lot of testing.
Do we even care about fixing it for 3.17? scsi-mq isn't enabled by default even for 3.18. The open-coded percpu ref thing was subtly broken there. It'd be difficult to trigger but I'm fairly sure it'd crap out in the wild once in a blue moon.
Thanks.
Signature · 1 line
tejun
Tejun Heo
maintainerQuoted 11 lines · Tejun Heo
Quoted 5 lines · Christoph Hellwig
"[PATCHSET percpu/for-3.18]
percpu_ref: implement switch_to_atomic/percpu()"looks way to big for 3.17, and the regression was introduced in the 3.17 merge window. I'm not sure what was broken before, but it defintively survived a lot of testing.
Do we even care about fixing it for 3.17? scsi-mq isn't enabled by default even for 3.18. The open-coded percpu ref thing was subtly broken there. It'd be difficult to trigger but I'm fairly sure it'd crap out in the wild once in a blue moon.
Hmmm... also, this is actually an issue with scsi that block layer is working around. For other drivers (virtio), the latency during shutdown should be completely fine.
Signature · 1 line
tejun
Quoted 11 lines · Tejun Heo
Quoted 5 lines · Christoph Hellwig
"[PATCHSET percpu/for-3.18]
percpu_ref: implement switch_to_atomic/percpu()"looks way to big for 3.17, and the regression was introduced in the 3.17 merge window. I'm not sure what was broken before, but it defintively survived a lot of testing.
Do we even care about fixing it for 3.17? scsi-mq isn't enabled by default even for 3.18. The open-coded percpu ref thing was subtly broken there. It'd be difficult to trigger but I'm fairly sure it'd crap out in the wild once in a blue moon.
It's compiled in by default, and people are extremly eager to test it.
Tejun Heo
maintainerQuoted 8 lines · Christoph Hellwig
Quoted 7 lines · Tejun Heo
Quoted 5 lines · Christoph Hellwig
"[PATCHSET percpu/for-3.18]
percpu_ref: implement switch_to_atomic/percpu()"looks way to big for 3.17, and the regression was introduced in the 3.17 merge window. I'm not sure what was broken before, but it defintively survived a lot of testing.
Quoted 6 lines
Quoted 4 lines
Do we even care about fixing it for 3.17? scsi-mq isn't enabled by default even for 3.18. The open-coded percpu ref thing was subtly broken there. It'd be difficult to trigger but I'm fairly sure it'd crap out in the wild once in a blue moon.
It's compiled in by default, and people are extremly eager to test it.
Ugh, I don't know. It's not like we have a very good baseline we can go back to and reverting it for -stable and then redoing it seems kinda excessive for a yet experimental feature. Jens?
Signature · 1 line
tejun
Quoted 27 lines
-----Original Message-----
From: [email protected] [mailto:linux-kernel- [email protected]] On Behalf Of Tejun Heo
Sent: Tuesday, 23 September, 2014 1:12 AM
To: Christoph Hellwig
Cc: Jens Axboe; [email protected]; [email protected]
Subject: Re: boot stall regression due to blk-mq: usepercpu_reffor mq usage countQuoted 3 lines · Christoph Hellwig
Quoted 2 lines · Tejun Heo
Quoted 1 line · Christoph Hellwig
"[PATCHSET percpu/for-3.18]
percpu_ref: implementswitch_to_atomic/percpu()"
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
looks way to big for 3.17, and the regression was introduced in the
3.17
Quoted 8 lines
Quoted 7 lines
Quoted 2 lines
merge window. I'm not sure what was broken before, but it defintively survived a lot of testing.
Do we even care about fixing it for 3.17? scsi-mq isn't enabled by default even for 3.18. The open-coded percpu ref thing was subtly broken there. It'd be difficult to trigger but I'm fairly sure it'd crap out in the wild once in a blue moon.
Quoted 5 lines
Quoted 1 line
It's compiled in by default, and people are extremly eager to test it.
Ugh, I don't know. It's not like we have a very good baseline we can go back to and reverting it for -stable and then redoing it seems kinda excessive for a yet experimental feature. Jens?
scsi_mod.use_blk_mq is not listed in 3.17rc6 Documentation/kernel- parameters.txt or Documentation/scsi/scsi-parameters.txt (which does admit "This document may not be entirely up to date and comprehensive.").
Perhaps a description with an "experimental" warning could be slipped into scsi-parameters.txt in 3.17, with plans to remove that warning in 3.18.
---
Rob Elliott HP Server Storage
Jens Axboe
maintainerQuoted 14 lines · Tejun Heo
Quoted 13 lines · Christoph Hellwig
Quoted 11 lines · Tejun Heo
Quoted 5 lines · Christoph Hellwig
"[PATCHSET percpu/for-3.18]
percpu_ref: implement switch_to_atomic/percpu()"looks way to big for 3.17, and the regression was introduced in the 3.17 merge window. I'm not sure what was broken before, but it defintively survived a lot of testing.
Do we even care about fixing it for 3.17? scsi-mq isn't enabled by default even for 3.18. The open-coded percpu ref thing was subtly broken there. It'd be difficult to trigger but I'm fairly sure it'd crap out in the wild once in a blue moon.
Quoted 5 lines
Quoted 1 line
It's compiled in by default, and people are extremly eager to test it.
Ugh, I don't know. It's not like we have a very good baseline we can go back to and reverting it for -stable and then redoing it seems kinda excessive for a yet experimental feature. Jens?
It's not just scsi-mq, there are active users of blk-mq in the current tree - like virtio_blk, mtip32xx. None of those are affected by the RCU slowdown due to these changes, so it's not a big deal to them. But it is a big deal if we can't tell people to test scsi-mq in 3.17, that was the entire point of having it there but not default to on. So yeah, this really should be fixed for 3.17.
I'm not aware of any reports on the existing enter count breaking things for them. So while it may not be perfect, reverting the percpu ref count changes for 3.17 may be the best option that we have.
Signature · 1 line
Jens Axboe
Tejun Heo
maintainerPATCH 1/1 blk-mq, percpu_ref: implement a kludge for SCSI blk-mq stall during probe
blk-mq uses percpu_ref for its usage counter which tracks the number of in-flight commands and used to synchronously drain the queue on freeze. percpu_ref shutdown takes measureable wallclock time as it involves a sched RCU grace period. This means that draining a blk-mq takes measureable wallclock time. One would think that this shouldn't matter as queue shutdown should be a rare event which takes place asynchronously w.r.t. userland.
Unfortunately, SCSI probing involves synchronously setting up and then tearing down a lot of request_queues back-to-back for non-existent LUNs. This means that SCSI probing may take more than ten seconds when scsi-mq is used.
This will be properly fixed by implementing a mechanism to keep q->mq_usage_counter in atomic mode till genhd registration; however, that involves rather big updates to percpu_ref which is difficult to apply late in the devel cycle (v3.17-rc6 at the moment). As a stop-gap measure till the proper fix can be implemented in the next cycle, this patch introduces __percpu_ref_kill_expedited() and makes blk_mq_freeze_queue() use it. This is heavy-handed but should work for testing the experimental SCSI blk-mq implementation.
---
Hello, Jens, Christoph.
How about this one? This is kinda ugly but should work fine in most cases and easy to apply to v3.17 and take out during v3.18.
Thanks.
block/blk-mq.c | 11 ++++++++++- include/linux/percpu-refcount.h | 1 + lib/percpu-refcount.c | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-)
block/blk-mq.c +10 -1
@@ -120,7 +120,16 @@ void blk_mq_freeze_queue(struct request_spin_unlock_irq (q->queue_lock);if (freeze) { -percpu_ref_kill (&q->mq_usage_counter); +/* +* XXX: Temporary kludge to work around SCSI blk-mq stall. +* SCSI synchronously creates and destroys many queues +* back-to-back during probe leading to lengthy stalls. +* This will be fixed by keeping ->mq_usage_counter in +* atomic mode until genhd registration, but, for now, +* let's work around using expedited synchronization. +*/ +__percpu_ref_kill_expedited (&q->mq_usage_counter); +blk_mq_run_queues (q, false); }wait_event (q->mq_freeze_wq,percpu_ref_is_zero (&q->mq_usage_counter));
include/linux/percpu-refcount.h +1 -0
@@ -72,6 +72,7 @@ void percpu_ref_reinit(struct percpu_refvoid percpu_ref_exit (struct percpu_ref *ref);void percpu_ref_kill_and_confirm (struct percpu_ref *ref,percpu_ref_func_t *confirm_kill); +void __percpu_ref_kill_expedited (struct percpu_ref *ref);/** * percpu_ref_kill - drop the initial ref
lib/percpu-refcount.c +16 -0
@@ -189,3 +189,19 @@ void percpu_ref_kill_and_confirm(structcall_rcu_sched (&ref->rcu, percpu_ref_kill_rcu); }EXPORT_SYMBOL_GPL (percpu_ref_kill_and_confirm); + +/* +* XXX: Temporary kludge to work around SCSI blk-mq stall. Used only by +* block/blk-mq.c::blk_mq_freeze_queue(). Will be removed during v3.18 +* devel cycle. Do not use anywhere else. +*/ +void __percpu_ref_kill_expedited (struct percpu_ref *ref) +{ +WARN_ONCE (ref->pcpu_count_ptr &PCPU_REF_DEAD , +"percpu_ref_kill() called more than once on %pf!" , + ref->release); + + ref->pcpu_count_ptr |=PCPU_REF_DEAD ; +synchronize_sched_expedited (); +percpu_ref_kill_rcu (&ref->rcu); +}
Jens Axboe
maintainerRe: [PATCH block/for-3.17-fixes/core] blk-mq, percpu_ref: implement a kludge for SCSI blk-mq stall during probe
Quoted 28 lines · Tejun Heo
blk-mq uses
percpu_reffor its usage counter which tracks the number of in-flight commands and used to synchronously drain the queue on freeze.percpu_refshutdown takes measureable wallclock time as it involves a sched RCU grace period. This means that draining a blk-mq takes measureable wallclock time. One would think that this shouldn't matter as queue shutdown should be a rare event which takes place asynchronously w.r.t. userland.Unfortunately, SCSI probing involves synchronously setting up and then tearing down a lot of
request_queuesback-to-back for non-existent LUNs. This means that SCSI probing may take more than ten seconds when scsi-mq is used.This will be properly fixed by implementing a mechanism to keep
q->mq_usage_counterin atomic mode till genhd registration; however, that involves rather big updates topercpu_refwhich is difficult to apply late in the devel cycle (v3.17-rc6 at the moment). As a stop-gap measure till the proper fix can be implemented in the next cycle, this patch introduces__percpu_ref_kill_expedited()and makesblk_mq_freeze_queue()use it. This is heavy-handed but should work for testing the experimental SCSI blk-mq implementation.Signed-off-by Tejun Heo <[email protected]>Reported-by Christoph Hellwig <[email protected]>Fixes add703fda981 ("blk-mq: use percpu_ref for mq usage count")Cc Kent Overstreet <[email protected]>Cc Jens Axboe <[email protected]>
Quoted 5 lines
---
Hello, Jens, Christoph.How about this one? This is kinda ugly but should work fine in most cases and easy to apply to v3.17 and take out during v3.18.
The hack looks fine to me, if it passes Christophs boot stall test. The hack isn't THAT nasty, since you already have a series queued up to fix it for real for 3.18.
Signature · 1 line
Jens Axboe
Tejun Heo
maintainerRe: [PATCH block/for-3.17-fixes/core] blk-mq, percpu_ref: implement a kludge for SCSI blk-mq stall during probe
Oops, I forgot to cc Kent. Kent, the patch is at
http://lkml.kernel.org/g/[email protected]
Quoted 3 lines · Jens Axboe
The hack looks fine to me, if it passes Christophs boot stall test. The hack isn't THAT nasty, since you already have a series queued up to fix it for real for 3.18.
Yeah, then I can pull in block fixes branch into a percpu for-3.18 branch, revert the hack and then apply the patches to implement the proper fix.
Thanks.
Signature · 1 line
tejun
Re: [PATCH block/for-3.17-fixes/core] blk-mq, percpu_ref: implement a kludge for SCSI blk-mq stall during probe
In reply to Tejun HeoThanks, this fixes the boot stall for me.
Jens Axboe
maintainerRe: [PATCH block/for-3.17-fixes/core] blk-mq, percpu_ref: implement a kludge for SCSI blk-mq stall during probe
Quoted 3 lines · Christoph Hellwig
Thanks, this fixes the boot stall for me.
Tested-by Christoph Hellwig <[email protected]>
Sweet, I'll shove this off today, so we are done for 3.17 release.
Signature · 1 line
Jens Axboe
Tejun Heo
maintainerRe: [PATCH block/for-3.17-fixes/core] blk-mq, percpu_ref: implement a kludge for SCSI blk-mq stall during probe
Quoted 6 lines · Jens Axboe
Quoted 3 lines · Christoph Hellwig
Thanks, this fixes the boot stall for me.
Tested-by Christoph Hellwig <[email protected]>Sweet, I'll shove this off today, so we are done for 3.17 release.
Cool, once it hits the block branch, I'll pull it into percpu/for-3.18 and apply the patches for proper fix on top.
Thanks.
Signature · 1 line
tejun
Jens Axboe
maintainerRe: [PATCH block/for-3.17-fixes/core] blk-mq, percpu_ref: implement a kludge for SCSI blk-mq stall during probe
Quoted 10 lines · Tejun Heo
Quoted 6 lines · Jens Axboe
Quoted 3 lines · Christoph Hellwig
Thanks, this fixes the boot stall for me.
Tested-by Christoph Hellwig <[email protected]>Sweet, I'll shove this off today, so we are done for 3.17 release.
Cool, once it hits the block branch, I'll pull it into percpu/for-3.18 and apply the patches for proper fix on top.
It's in for-linus now.
Signature · 1 line
Jens Axboe
Tejun Heo
maintainerPATCH 1/1 Revert "blk-mq, percpu_ref: implement a kludge for SCSI blk-mq stall during probe"
Quoted 1 line
From
9eca80461a45177e456219a9cd944c27675d6512Mon Sep 17 00:00:00 2001
From: Tejun Heo <[email protected]>
Date: Wed, 24 Sep 2014 13:07:33 -0400
This reverts commit 0a30288da1aec914e158c2d7a3482a85f632750f, which was a temporary fix for SCSI blk-mq stall issue. The following patches will fix the issue properly by introducing atomic mode to percpu_ref.
---
Hello,
I pulled in block/for-linus into percpu/for-3.18 and reverted the temp fix. Will apply the patchset to implement the proper fix on top of it.
Thanks.
block/blk-mq.c | 11 +---------- include/linux/percpu-refcount.h | 1 - lib/percpu-refcount.c | 16 ---------------- 3 files changed, 1 insertion(+), 27 deletions(-)
block/blk-mq.c +1 -10
@@ -119,16 +119,7 @@ void blk_mq_freeze_queue(struct request_queue *q)spin_unlock_irq (q->queue_lock);if (freeze) { -/* -* XXX: Temporary kludge to work around SCSI blk-mq stall. -* SCSI synchronously creates and destroys many queues -* back-to-back during probe leading to lengthy stalls. -* This will be fixed by keeping ->mq_usage_counter in -* atomic mode until genhd registration, but, for now, -* let's work around using expedited synchronization. -*/ -__percpu_ref_kill_expedited (&q->mq_usage_counter); - +percpu_ref_kill (&q->mq_usage_counter);blk_mq_run_queues (q, false); }wait_event (q->mq_freeze_wq,percpu_ref_is_zero (&q->mq_usage_counter));
include/linux/percpu-refcount.h +0 -1
@@ -72,7 +72,6 @@ void percpu_ref_reinit(struct percpu_ref *ref);void percpu_ref_exit (struct percpu_ref *ref);void percpu_ref_kill_and_confirm (struct percpu_ref *ref,percpu_ref_func_t *confirm_kill); -void __percpu_ref_kill_expedited (struct percpu_ref *ref);/** * percpu_ref_kill - drop the initial ref
lib/percpu-refcount.c +0 -16
@@ -189,19 +189,3 @@ void percpu_ref_kill_and_confirm(struct percpu_ref *ref,call_rcu_sched (&ref->rcu, percpu_ref_kill_rcu); }EXPORT_SYMBOL_GPL (percpu_ref_kill_and_confirm); - -/* -* XXX: Temporary kludge to work around SCSI blk-mq stall. Used only by -* block/blk-mq.c::blk_mq_freeze_queue(). Will be removed during v3.18 -* devel cycle. Do not use anywhere else. -*/ -void __percpu_ref_kill_expedited (struct percpu_ref *ref) -{ -WARN_ONCE (ref->pcpu_count_ptr &PCPU_REF_DEAD , -"percpu_ref_kill() called more than once on %pf!" , - ref->release); - - ref->pcpu_count_ptr |=PCPU_REF_DEAD ; -synchronize_sched_expedited (); -percpu_ref_kill_rcu (&ref->rcu); -}
Signature · 1 line
1.9.3
Tejun Heo
maintainerPATCH 1/1 blk-mq: start q->mq_usage_counter in atomic mode
In reply to Christoph HellwigQuoted 1 line
From
83b06f4fc6ca2f7f3d706a168b71c248bdada668Mon Sep 17 00:00:00 2001
From: Tejun Heo <[email protected]>
Date: Tue, 23 Sep 2014 01:58:34 -0400
blk-mq uses percpu_ref for its usage counter which tracks the number of in-flight commands and used to synchronously drain the queue on freeze. percpu_ref shutdown takes measureable wallclock time as it involves a sched RCU grace period. This means that draining a blk-mq takes measureable wallclock time. One would think that this shouldn't matter as queue shutdown should be a rare event which takes place asynchronously w.r.t. userland.
Unfortunately, SCSI probing involves synchronously setting up and then tearing down a lot of request_queues back-to-back for non-existent LUNs. This means that SCSI probing may take above ten seconds when scsi-mq is used.
[ 0.949892] scsi host0: Virtio SCSI HBA [ 1.007864] scsi 0:0:0:0: Direct-Access QEMU QEMU HARDDISK 1.1. PQ: 0 ANSI: 5 [ 1.021299] scsi 0:0:1:0: Direct-Access QEMU QEMU HARDDISK 1.1. PQ: 0 ANSI: 5 [ 1.520356] tsc: Refined TSC clocksource calibration: 2491.910 MHz
<stall>
[ 16.186549] sd 0:0:0:0: Attached scsi generic sg0 type 0 [ 16.190478] sd 0:0:1:0: Attached scsi generic sg1 type 0 [ 16.194099] osd: LOADED open-osd 0.2.1 [ 16.203202] sd 0:0:0:0: [sda] 31457280 512-byte logical blocks: (16.1 GB/15.0 GiB) [ 16.208478] sd 0:0:0:0: [sda] Write Protect is off [ 16.211439] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA [ 16.218771] sd 0:0:1:0: [sdb] 31457280 512-byte logical blocks: (16.1 GB/15.0 GiB) [ 16.223264] sd 0:0:1:0: [sdb] Write Protect is off [ 16.225682] sd 0:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
This is also the reason why request_queues start in bypass mode which is ended on blk_register_queue() as shutting down a fully functional queue also involves a RCU grace period and the queues for non-existent SCSI devices never reach registration.
blk-mq basically needs to do the same thing - start the mq in a degraded mode which is faster to shut down and then make it fully functional only after the queue reaches registration. percpu_ref recently grew facilities to force atomic operation until explicitly switched to percpu mode, which can be used for this purpose. This patch makes blk-mq initialize q->mq_usage_counter in atomic mode and switch it to percpu mode only once blk_register_queue() is reached.
---
Hello,
This patch is on top of
block/for-3.18/core fe052529e465 ("scsi: move blk_mq_start_request call earlier")
+ [PATCHSET percpu/for-3.18] percpu_ref: implement switch_to_atomic/percpu()
http://lkml.kernel.org/g/[email protected]
and available in the following git branch.
git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu.git review-blk_mq-latency-fix
Thanks.
block/blk-mq-sysfs.c | 6 ++++++ block/blk-mq.c | 6 +++++- block/blk-sysfs.c | 11 +++++++++-- include/linux/blk-mq.h | 1 + 4 files changed, 21 insertions(+), 3 deletions(-)
block/blk-mq-sysfs.c +6 -0
@@ -402,6 +402,12 @@ static void blk_mq_sysfs_init(struct request_queue *q) } } +/* see blk_register_queue() */ +void blk_mq_finish_init (struct request_queue *q) +{ +percpu_ref_switch_to_percpu (&q->mq_usage_counter); +} +int blk_mq_register_disk (struct gendisk *disk) {struct device *dev =disk_to_dev (disk);
block/blk-mq.c +5 -1
@@ -1783,8 +1783,12 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *set)if (!q) goto err_hctxs; +/* +* Init percpu_ref in atomic mode so that it's faster to shutdown. +* See blk_register_queue() for details. +*/ if (percpu_ref_init (&q->mq_usage_counter, blk_mq_usage_counter_release, -0 ,GFP_KERNEL )) +PERCPU_REF_INIT_ATOMIC ,GFP_KERNEL )) goto err_map;setup_timer (&q->timeout, blk_mq_rq_timer, (unsigned long ) q);
block/blk-sysfs.c +9 -2
@@ -551,12 +551,19 @@ int blk_register_queue(struct gendisk *disk)return -ENXIO ;/* -* Initialization must be complete by now. Finish the initial -* bypass from queue allocation. +* SCSI probing may synchronously create and destroy a lot of +* request_queues for non-existent devices. Shutting down a fully +* functional queue takes measureable wallclock time as RCU grace +* periods are involved. To avoid excessive latency in these +* cases, a request_queue starts out in a degraded mode which is +* faster to shut down and is made fully functional here as +* request_queues for non-existent devices never get registered. */ if (!blk_queue_init_done (q)) {queue_flag_set_unlocked (QUEUE_FLAG_INIT_DONE , q);blk_queue_bypass_end (q); +if (q->mq_ops) +blk_mq_finish_init (q); } ret =blk_trace_init_sysfs (dev);
include/linux/blk-mq.h +1 -0
@@ -144,6 +144,7 @@ enum { };struct request_queue *blk_mq_init_queue (struct blk_mq_tag_set *); +void blk_mq_finish_init (struct request_queue *q);int blk_mq_register_disk (struct gendisk *);void blk_mq_unregister_disk (struct gendisk *);
Signature · 5 lines
1.9.3 -- tejun
Tejun Heo
maintainerRe: [PATCH block/for-3.18/core] blk-mq: start q->mq_usage_counter in atomic mode
Quoted 11 lines · Tejun Heo
From
83b06f4fc6ca2f7f3d706a168b71c248bdada668Mon Sep 17 00:00:00 2001
From: Tejun Heo <[email protected]>
Date: Tue, 23 Sep 2014 01:58:34 -0400blk-mq uses
percpu_reffor its usage counter which tracks the number of in-flight commands and used to synchronously drain the queue on freeze.percpu_refshutdown takes measureable wallclock time as it involves a sched RCU grace period. This means that draining a blk-mq takes measureable wallclock time. One would think that this shouldn't matter as queue shutdown should be a rare event which takes place asynchronously w.r.t. userland.
Applied to percpu/for-3.18 on top of the klude, its revert and the required percpu_ref changes.
Thanks.
Signature · 1 line
tejun
Tejun Heo
maintainerPATCH 1/1 blk-mq, percpu_ref: start q->mq_usage_counter in atomic mode
FYI, I added a paragraph explaining what happened to the temp fix at the end. The following is the applied version.
Thanks.
----- 8< -----
Quoted 1 line
From
17497acbdce9506fd6a75115dee4ab80c3cc5ee5Mon Sep 17 00:00:00 2001
From: Tejun Heo <[email protected]>
Date: Wed, 24 Sep 2014 13:31:50 -0400
blk-mq uses percpu_ref for its usage counter which tracks the number of in-flight commands and used to synchronously drain the queue on freeze. percpu_ref shutdown takes measureable wallclock time as it involves a sched RCU grace period. This means that draining a blk-mq takes measureable wallclock time. One would think that this shouldn't matter as queue shutdown should be a rare event which takes place asynchronously w.r.t. userland.
Unfortunately, SCSI probing involves synchronously setting up and then tearing down a lot of request_queues back-to-back for non-existent LUNs. This means that SCSI probing may take above ten seconds when scsi-mq is used.
[ 0.949892] scsi host0: Virtio SCSI HBA [ 1.007864] scsi 0:0:0:0: Direct-Access QEMU QEMU HARDDISK 1.1. PQ: 0 ANSI: 5 [ 1.021299] scsi 0:0:1:0: Direct-Access QEMU QEMU HARDDISK 1.1. PQ: 0 ANSI: 5 [ 1.520356] tsc: Refined TSC clocksource calibration: 2491.910 MHz
<stall>
[ 16.186549] sd 0:0:0:0: Attached scsi generic sg0 type 0 [ 16.190478] sd 0:0:1:0: Attached scsi generic sg1 type 0 [ 16.194099] osd: LOADED open-osd 0.2.1 [ 16.203202] sd 0:0:0:0: [sda] 31457280 512-byte logical blocks: (16.1 GB/15.0 GiB) [ 16.208478] sd 0:0:0:0: [sda] Write Protect is off [ 16.211439] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA [ 16.218771] sd 0:0:1:0: [sdb] 31457280 512-byte logical blocks: (16.1 GB/15.0 GiB) [ 16.223264] sd 0:0:1:0: [sdb] Write Protect is off [ 16.225682] sd 0:0:1:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
This is also the reason why request_queues start in bypass mode which is ended on blk_register_queue() as shutting down a fully functional queue also involves a RCU grace period and the queues for non-existent SCSI devices never reach registration.
blk-mq basically needs to do the same thing - start the mq in a degraded mode which is faster to shut down and then make it fully functional only after the queue reaches registration. percpu_ref recently grew facilities to force atomic operation until explicitly switched to percpu mode, which can be used for this purpose. This patch makes blk-mq initialize q->mq_usage_counter in atomic mode and switch it to percpu mode only once blk_register_queue() is reached.
Note that this issue was previously worked around by 0a30288da1ae ("blk-mq, percpu_ref: implement a kludge for SCSI blk-mq stall during probe") for v3.17. The temp fix was reverted in preparation of adding persistent atomic mode to percpu_ref by 9eca80461a45 ("Revert "blk-mq,percpu_ref: implement a kludge for SCSI blk-mq stall during probe""). This patch and the prerequisite percpu_ref changes will be merged during v3.18 devel cycle.
--- block/blk-mq-sysfs.c | 6 ++++++ block/blk-mq.c | 6 +++++- block/blk-sysfs.c | 11 +++++++++-- include/linux/blk-mq.h | 1 + 4 files changed, 21 insertions(+), 3 deletions(-)
block/blk-mq-sysfs.c +6 -0
@@ -402,6 +402,12 @@ static void blk_mq_sysfs_init(struct request_queue *q) } } +/* see blk_register_queue() */ +void blk_mq_finish_init (struct request_queue *q) +{ +percpu_ref_switch_to_percpu (&q->mq_usage_counter); +} +int blk_mq_register_disk (struct gendisk *disk) {struct device *dev =disk_to_dev (disk);
block/blk-mq.c +5 -1
@@ -1795,8 +1795,12 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *set)if (!q) goto err_hctxs; +/* +* Init percpu_ref in atomic mode so that it's faster to shutdown. +* See blk_register_queue() for details. +*/ if (percpu_ref_init (&q->mq_usage_counter, blk_mq_usage_counter_release, -0 ,GFP_KERNEL )) +PERCPU_REF_INIT_ATOMIC ,GFP_KERNEL )) goto err_map;setup_timer (&q->timeout, blk_mq_rq_timer, (unsigned long ) q);
block/blk-sysfs.c +9 -2
@@ -551,12 +551,19 @@ int blk_register_queue(struct gendisk *disk)return -ENXIO ;/* -* Initialization must be complete by now. Finish the initial -* bypass from queue allocation. +* SCSI probing may synchronously create and destroy a lot of +* request_queues for non-existent devices. Shutting down a fully +* functional queue takes measureable wallclock time as RCU grace +* periods are involved. To avoid excessive latency in these +* cases, a request_queue starts out in a degraded mode which is +* faster to shut down and is made fully functional here as +* request_queues for non-existent devices never get registered. */ if (!blk_queue_init_done (q)) {queue_flag_set_unlocked (QUEUE_FLAG_INIT_DONE , q);blk_queue_bypass_end (q); +if (q->mq_ops) +blk_mq_finish_init (q); } ret =blk_trace_init_sysfs (dev);
include/linux/blk-mq.h +1 -0
@@ -140,6 +140,7 @@ enum { };struct request_queue *blk_mq_init_queue (struct blk_mq_tag_set *); +void blk_mq_finish_init (struct request_queue *q);int blk_mq_register_disk (struct gendisk *);void blk_mq_unregister_disk (struct gendisk *);
Signature · 1 line
1.9.3