Re: [PATCH 3/3] blk-mq: Use llist_head for blk_cpu_done

From: Sebastian Andrzej Siewior
Date: Mon Nov 02 2020 - 04:55:38 EST


On 2020-10-31 09:00:49 [-0600], Jens Axboe wrote:
> There really aren't any rules for this, and it's perfectly legit to
> complete from process context. Maybe you're a kthread driven driver and
> that's how you handle completions. The block completion path has always
> been hard IRQ safe, but possible to call from anywhere.

I'm not trying to put restrictions and forbidding completions from a
kthread. I'm trying to avoid the pointless softirq dance for no added
value. We could:

diff --git a/block/blk-mq.c b/block/blk-mq.c
index 4f53de48e5038..c4693b3750878 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -644,9 +644,11 @@ bool blk_mq_complete_request_remote(struct request *rq)
} else {
if (rq->q->nr_hw_queues > 1)
return false;
+ preempt_disable();
cpu_list = this_cpu_ptr(&blk_cpu_done);
if (llist_add(&rq->ipi_list, cpu_list))
raise_softirq(BLOCK_SOFTIRQ);
+ preempt_enable();
}

return true;

to not break that assumption you just mentioned and provide
|static inline void blk_mq_complete_request_local(struct request *rq)
|{
| rq->q->mq_ops->complete(rq);
|}

so that completion issued from from process context (like those from
usb-storage) don't end up waking `ksoftird' (running at SCHED_OTHER)
completing the requests but rather performing it right away. The softirq
dance makes no sense here.

As mentioned earlier, the alternative _could_ be to
s/preempt_/local_bh_/

in the above patch. This would ensure that any invocation outside of
IRQ/Softirq context would invoke the softirq _directly_ at
local_bh_enable() time rather than waking the daemon for that purpose.
It would also avoid another completion function for the direct case
which could be abused if used from outside the thread context.
The last one is currently my favorite.

Sebastian