Re: [PATCH RFC v4 1/3] block: add BIO_COMPLETE_IN_TASK for task-context completion
From: Matthew Wilcox
Date: Wed Mar 25 2026 - 15:57:23 EST
On Wed, Mar 25, 2026 at 02:43:00PM -0400, Tal Zussman wrote:
> +static void bio_complete_work_fn(struct work_struct *w)
> +{
> + struct bio_complete_batch *batch;
> + struct bio_list list;
> +
> +again:
> + local_lock_irq(&bio_complete_batch.lock);
> + batch = this_cpu_ptr(&bio_complete_batch);
> + list = batch->list;
> + bio_list_init(&batch->list);
> + local_unlock_irq(&bio_complete_batch.lock);
> +
> + while (!bio_list_empty(&list)) {
> + struct bio *bio = bio_list_pop(&list);
> + bio->bi_end_io(bio);
> + }
> +
> + local_lock_irq(&bio_complete_batch.lock);
> + batch = this_cpu_ptr(&bio_complete_batch);
> + if (!bio_list_empty(&batch->list)) {
> + local_unlock_irq(&bio_complete_batch.lock);
> +
> + if (!need_resched())
> + goto again;
> +
> + schedule_work_on(smp_processor_id(), &batch->work);
> + return;
> + }
I don't know how often we see this actually trigger, but wouldn't this
be slightly more efficient?
+ local_lock_irq(&bio_complete_batch.lock);
+ batch = this_cpu_ptr(&bio_complete_batch);
+ list = batch->list;
+again:
+ bio_list_init(&batch->list);
+ local_unlock_irq(&bio_complete_batch.lock);
+
+ while (!bio_list_empty(&list)) {
+ struct bio *bio = bio_list_pop(&list);
+ bio->bi_end_io(bio);
+ }
+
+ local_lock_irq(&bio_complete_batch.lock);
+ batch = this_cpu_ptr(&bio_complete_batch);
+ list = batch->list;
+ if (!bio_list_empty(&list)) {
+ if (!need_resched())
+ goto again;
+
+ local_unlock_irq(&bio_complete_batch.lock);
+ schedule_work_on(smp_processor_id(), &batch->work);
+ return;
+ }
Overall I like this. I think this is a better approach than the earlier
patches, and I'm looking forward to the simplifications that it's going
to enable.