Re: [PATCH RFC v4 1/3] block: add BIO_COMPLETE_IN_TASK for task-context completion
From: Dave Chinner
Date: Wed Mar 25 2026 - 23:18:44 EST
On Wed, Mar 25, 2026 at 02:03:40PM -0700, Bart Van Assche wrote:
> On 3/25/26 11:43 AM, Tal Zussman wrote:
> > + schedule_work_on(smp_processor_id(), &batch->work);
>
> Since schedule_work_on() queues work on system_percpu_wq the above call
> has the same effect as schedule_work(&batch->work), isn't it?
No. Two words: Task preemption.
And in saying this, I realise the originally proposed code is dodgy.
It might work look ok because the common cases is that interrupt
context processing can't be preempted. However, I don't think that
is true for PREEMPT_RT kernels (IIRC interrupt processing runs as a
task that can be preempted). Also, bio completion can naturally run
from task context because the submitter can hold the last reference
to the bio.
Hence the queueing function can be preempted and scheduled to a
different CPU like so:
lock_lock_irq()
queue on CPU 0
local_lock_irq()
<preempt>
<run on CPU 1>
schedule_work_on(smp_processor_id())
That results in bio completion being queued on CPU 0, but the
processing work is scheduled for CPU 1. Oops.
> From the
> workqueue implementation:
>
> system_percpu_wq = alloc_workqueue("events", WQ_PERCPU, 0);
>
> [ ... ]
> if (req_cpu == WORK_CPU_UNBOUND) {
> if (wq->flags & WQ_UNBOUND)
> cpu = wq_select_unbound_cpu(raw_smp_processor_id());
> else
> cpu = raw_smp_processor_id();
Same preemption problem as above.
-Dave.
--
Dave Chinner
dgc@xxxxxxxxxx