blk-softirq vs smp_call_function_single_async()

From: Peter Zijlstra
Date: Mon Jun 08 2020 - 07:58:06 EST


Hi Jens,

I've been going through smp_call_function_single_async() users and
stumbled upon blk-softirq.c, which has:

static int raise_blk_irq(int cpu, struct request *rq)
{
if (cpu_online(cpu)) {
call_single_data_t *data = &rq->csd;

data->func = trigger_softirq;
data->info = rq;
data->flags = 0;

smp_call_function_single_async(cpu, data);
return 0;
}

return 1;
}

What, if anything, guarantees rq->csd is not already in use at that
time?

The purpose of that CSD is to make the BLOCK_SOFTIRQ go, but there's
plenty of other ways to tickle that, afaict. So if that races vs someone
else, and that completes whatever was needed, then can't we get to
raise_blk_irq() again, even though the csd is still enqueued?

Worse; it has: data->flags = 0; so our early exit will not happen, even
when it should.