Commit 02f130a7872d26bd6ceb4e86b531761d79ac76b7
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
Merge branch 'for-linus' of git://git.kernel.dk/linux-block
Pull one last block fix from Jens Axboe: "We've had an issue with scsi-mq where probing takes forever. This was bisected down to the percpu changes for blk_mq_queue_enter(), and the fact we now suffer an RCU grace period when killing a queue. SCSI creates and destroys tons of queues, so this let to 10s of seconds of stalls at boot for some. Tejun has a real fix for this, but it's too involved for 3.17. So this is a temporary workaround to expedite the queue killing until we can fold in the real fix for 3.18 when that merge window opens" * 'for-linus' of git://git.kernel.dk/linux-block: blk-mq, percpu_ref: implement a kludge for SCSI blk-mq stall during probe
Showing 3 changed files Side-by-side Diff
block/blk-mq.c
... | ... | @@ -119,7 +119,16 @@ |
119 | 119 | spin_unlock_irq(q->queue_lock); |
120 | 120 | |
121 | 121 | if (freeze) { |
122 | - percpu_ref_kill(&q->mq_usage_counter); | |
122 | + /* | |
123 | + * XXX: Temporary kludge to work around SCSI blk-mq stall. | |
124 | + * SCSI synchronously creates and destroys many queues | |
125 | + * back-to-back during probe leading to lengthy stalls. | |
126 | + * This will be fixed by keeping ->mq_usage_counter in | |
127 | + * atomic mode until genhd registration, but, for now, | |
128 | + * let's work around using expedited synchronization. | |
129 | + */ | |
130 | + __percpu_ref_kill_expedited(&q->mq_usage_counter); | |
131 | + | |
123 | 132 | blk_mq_run_queues(q, false); |
124 | 133 | } |
125 | 134 | wait_event(q->mq_freeze_wq, percpu_ref_is_zero(&q->mq_usage_counter)); |
include/linux/percpu-refcount.h
... | ... | @@ -71,6 +71,7 @@ |
71 | 71 | void percpu_ref_exit(struct percpu_ref *ref); |
72 | 72 | void percpu_ref_kill_and_confirm(struct percpu_ref *ref, |
73 | 73 | percpu_ref_func_t *confirm_kill); |
74 | +void __percpu_ref_kill_expedited(struct percpu_ref *ref); | |
74 | 75 | |
75 | 76 | /** |
76 | 77 | * percpu_ref_kill - drop the initial ref |
lib/percpu-refcount.c
... | ... | @@ -184,4 +184,20 @@ |
184 | 184 | call_rcu_sched(&ref->rcu, percpu_ref_kill_rcu); |
185 | 185 | } |
186 | 186 | EXPORT_SYMBOL_GPL(percpu_ref_kill_and_confirm); |
187 | + | |
188 | +/* | |
189 | + * XXX: Temporary kludge to work around SCSI blk-mq stall. Used only by | |
190 | + * block/blk-mq.c::blk_mq_freeze_queue(). Will be removed during v3.18 | |
191 | + * devel cycle. Do not use anywhere else. | |
192 | + */ | |
193 | +void __percpu_ref_kill_expedited(struct percpu_ref *ref) | |
194 | +{ | |
195 | + WARN_ONCE(ref->pcpu_count_ptr & PCPU_REF_DEAD, | |
196 | + "percpu_ref_kill() called more than once on %pf!", | |
197 | + ref->release); | |
198 | + | |
199 | + ref->pcpu_count_ptr |= PCPU_REF_DEAD; | |
200 | + synchronize_sched_expedited(); | |
201 | + percpu_ref_kill_rcu(&ref->rcu); | |
202 | +} |