re-iter the tags per hctx. Howeverblk_mq_queue_tag_busy_iter() needn't such change? >> I didn't think so.>>>> blk_mq_queue_tag_busy_iter() will indeed
in bt_iter(), we check rq->mq_hctx == hctx for calling the iter callback:It is true for both shared and non-shared sbitmap since we don't share
static bool bt_iter(struct sbitmap *bitmap, unsigned int bitnr, void *data)
{
...
if (rq->q == hctx->queue && rq->mq_hctx == hctx)
ret = iter_data->fn(hctx, rq, iter_data->data, reserved);
And this would only pass for the correct hctx which we're iter'ing for.
hctx, so what does matter?
With single shared tags, you can iterate overRight, for the same request queue, we should do that.
all requests originated from all hw queues, right?
Indeed, it would be nice not to iter excessive times, but I didn't see a
straightforward way to change that.
In Kashyap's report, the lock contention is actually from
blk_mq_queue_tag_busy_iter(), see:
https://lore.kernel.org/linux-block/8867352d-2107-1f8a-0f1c-ef73450bf256@xxxxxxxxxx/
There is also blk_mq_all_tag_iter():This above one only iterates over the specified hctx/tags, it won't be
void blk_mq_all_tag_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn,
void *priv)
{
__blk_mq_all_tag_iter(tags, fn, priv, BT_TAG_ITER_STATIC_RQS);
}
But then the only user is blk_mq_hctx_has_requests():
static bool blk_mq_hctx_has_requests(struct blk_mq_hw_ctx *hctx)
{
struct blk_mq_tags *tags = hctx->sched_tags ?
hctx->sched_tags : hctx->tags;
struct rq_iter_data data = {
.hctx = hctx,
};
blk_mq_all_tag_iter(tags, blk_mq_has_request, &data);
return data.has_rq;
}
affected.
But, again like bt_iter(), blk_mq_has_request() will check the hctx matches:Not see what matters wrt. checking hctx.