Re: [PATCH 11/15] nvme: add Clang context annotations for nvme_queue::sq_lock
From: Nilay Shroff
Date: Thu Jun 11 2026 - 00:55:54 EST
On 6/10/26 10:03 PM, Bart Van Assche wrote:
On 6/10/26 7:27 AM, Nilay Shroff wrote:Yeah, I considered using guard(..._init), but it is a bit tricky in
static void nvme_free_queue(struct nvme_queue *nvmeq)
+ __context_unsafe(/* frees queue which is no longer in use */)
{
dma_free_coherent(nvmeq->dev->dev, CQ_SIZE(nvmeq),
(void *)nvmeq->cqes, nvmeq->cq_dma_addr);
@@ -2176,6 +2182,7 @@ static int queue_request_irq(struct nvme_queue *nvmeq)
}
static void nvme_init_queue(struct nvme_queue *nvmeq, u16 qid)
+ __context_unsafe(/* safe to init queue without any protection */)
{
struct nvme_dev *dev = nvmeq->dev;
__context_unsafe() is a big hammer that disables context analysis
for the entire function body. Has it been considered to use
guard(..._init)(...) instead?
this case. The lock (nvmeq->sq_lock) that protects nvmeq->sq_tail and
nvmeq->last_sq_tail is initialized in nvme_alloc_queue(), while those
fields are initialized later in nvme_init_queue(). Because the lock
initialization and the protected-field initialization happen in different
functions, I don't see a straightforward way to use guard() here to
create the synthetic acquire/release pattern around the accesses that
Clang complains about.
That said, I agree that __context_unsafe() is a fairly big hammer since
it disables context analysis for the entire function body. One alternative
would be to wrap the individual field initializations with context_unsafe(),
but that would require annotating several initialization/freeing operations
throughout these functions, which would add a fair amount of noise and make
the code less readable. Given that these functions operate on objects that
are still being initialized (or are already being torn down), using
__context_unsafe() seemed like the cleaner tradeoff.
Thanks,
--Nilay