* [PATCH v2 01/26] block: Annotate the queue limits functions
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-26 6:23 ` Christoph Hellwig
2026-03-25 21:44 ` [PATCH v2 02/26] block: Annotate the block device functions Bart Van Assche
` (25 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche
Let the thread-safety checker verify whether every start of a queue
limits update is followed by a call to a function that finishes a queue
limits update.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
include/linux/blkdev.h | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index b8e7f42aee71..57b256948ee9 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1092,15 +1092,17 @@ static inline unsigned int blk_boundary_sectors_left(sector_t offset,
*/
static inline struct queue_limits
queue_limits_start_update(struct request_queue *q)
+ __acquires(&q->limits_lock)
{
mutex_lock(&q->limits_lock);
return q->limits;
}
int queue_limits_commit_update_frozen(struct request_queue *q,
- struct queue_limits *lim);
+ struct queue_limits *lim) __releases(&q->limits_lock);
int queue_limits_commit_update(struct request_queue *q,
- struct queue_limits *lim);
-int queue_limits_set(struct request_queue *q, struct queue_limits *lim);
+ struct queue_limits *lim) __releases(&q->limits_lock);
+int queue_limits_set(struct request_queue *q, struct queue_limits *lim)
+ __must_not_hold(&q->limits_lock);
int blk_validate_limits(struct queue_limits *lim);
/**
@@ -1112,6 +1114,7 @@ int blk_validate_limits(struct queue_limits *lim);
* starting update.
*/
static inline void queue_limits_cancel_update(struct request_queue *q)
+ __releases(&q->limits_lock)
{
mutex_unlock(&q->limits_lock);
}
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH v2 02/26] block: Annotate the block device functions
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
2026-03-25 21:44 ` [PATCH v2 01/26] block: Annotate the queue limits functions Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-26 6:25 ` Christoph Hellwig
2026-03-25 21:44 ` [PATCH v2 03/26] block/cgroup: Split blkg_conf_prep() Bart Van Assche
` (24 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Nathan Chancellor
Prepare for enabling thread-safety analysis by adding __release()
annotations where appropriate. Explicit __release() annotations have
been added since Clang does not support adding a __releases() annotation
to a function pointer.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
block/bdev.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/block/bdev.c b/block/bdev.c
index ed022f8c48c7..1f710b8bfb9f 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -312,7 +312,9 @@ int bdev_freeze(struct block_device *bdev)
mutex_lock(&bdev->bd_holder_lock);
if (bdev->bd_holder_ops && bdev->bd_holder_ops->freeze) {
error = bdev->bd_holder_ops->freeze(bdev);
+ /* bdev->bd_holder_ops->freeze() released bd_holder_lock */
lockdep_assert_not_held(&bdev->bd_holder_lock);
+ __release(&bdev->bd_holder_lock);
} else {
mutex_unlock(&bdev->bd_holder_lock);
error = sync_blockdev(bdev);
@@ -355,7 +357,9 @@ int bdev_thaw(struct block_device *bdev)
mutex_lock(&bdev->bd_holder_lock);
if (bdev->bd_holder_ops && bdev->bd_holder_ops->thaw) {
error = bdev->bd_holder_ops->thaw(bdev);
+ /* bdev->bd_holder_ops->freeze() released bd_holder_lock */
lockdep_assert_not_held(&bdev->bd_holder_lock);
+ __release(&bdev->bd_holder_lock);
} else {
mutex_unlock(&bdev->bd_holder_lock);
}
@@ -1254,9 +1258,11 @@ EXPORT_SYMBOL(lookup_bdev);
void bdev_mark_dead(struct block_device *bdev, bool surprise)
{
mutex_lock(&bdev->bd_holder_lock);
- if (bdev->bd_holder_ops && bdev->bd_holder_ops->mark_dead)
+ if (bdev->bd_holder_ops && bdev->bd_holder_ops->mark_dead) {
bdev->bd_holder_ops->mark_dead(bdev, surprise);
- else {
+ /* bdev->bd_holder_ops->mark_dead() released bd_holder_lock */
+ __release(&bdev->bd_holder_lock);
+ } else {
mutex_unlock(&bdev->bd_holder_lock);
sync_blockdev(bdev);
}
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH v2 02/26] block: Annotate the block device functions
2026-03-25 21:44 ` [PATCH v2 02/26] block: Annotate the block device functions Bart Van Assche
@ 2026-03-26 6:25 ` Christoph Hellwig
2026-03-26 15:55 ` Bart Van Assche
0 siblings, 1 reply; 51+ messages in thread
From: Christoph Hellwig @ 2026-03-26 6:25 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Tejun Heo, Nathan Chancellor
On Wed, Mar 25, 2026 at 02:44:43PM -0700, Bart Van Assche wrote:
> Prepare for enabling thread-safety analysis by adding __release()
> annotations where appropriate. Explicit __release() annotations have
> been added since Clang does not support adding a __releases() annotation
> to a function pointer.
>
> Signed-off-by: Bart Van Assche <bvanassche@acm.org>
> ---
> block/bdev.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/block/bdev.c b/block/bdev.c
> index ed022f8c48c7..1f710b8bfb9f 100644
> --- a/block/bdev.c
> +++ b/block/bdev.c
> @@ -312,7 +312,9 @@ int bdev_freeze(struct block_device *bdev)
> mutex_lock(&bdev->bd_holder_lock);
> if (bdev->bd_holder_ops && bdev->bd_holder_ops->freeze) {
> error = bdev->bd_holder_ops->freeze(bdev);
> + /* bdev->bd_holder_ops->freeze() released bd_holder_lock */
> lockdep_assert_not_held(&bdev->bd_holder_lock);
> + __release(&bdev->bd_holder_lock);
> } else {
> mutex_unlock(&bdev->bd_holder_lock);
> error = sync_blockdev(bdev);
> @@ -355,7 +357,9 @@ int bdev_thaw(struct block_device *bdev)
> mutex_lock(&bdev->bd_holder_lock);
> if (bdev->bd_holder_ops && bdev->bd_holder_ops->thaw) {
> error = bdev->bd_holder_ops->thaw(bdev);
> + /* bdev->bd_holder_ops->freeze() released bd_holder_lock */
> lockdep_assert_not_held(&bdev->bd_holder_lock);
> + __release(&bdev->bd_holder_lock);
> } else {
> mutex_unlock(&bdev->bd_holder_lock);
> }
> @@ -1254,9 +1258,11 @@ EXPORT_SYMBOL(lookup_bdev);
> void bdev_mark_dead(struct block_device *bdev, bool surprise)
> {
> mutex_lock(&bdev->bd_holder_lock);
> - if (bdev->bd_holder_ops && bdev->bd_holder_ops->mark_dead)
> + if (bdev->bd_holder_ops && bdev->bd_holder_ops->mark_dead) {
> bdev->bd_holder_ops->mark_dead(bdev, surprise);
> - else {
> + /* bdev->bd_holder_ops->mark_dead() released bd_holder_lock */
> + __release(&bdev->bd_holder_lock);
This sounds like ->mark_dead also needs matching annotations. Or
can we have a way to annotate the expexcted lock context changes on
indirect function calls, as that would be very useful in general.
^ permalink raw reply [flat|nested] 51+ messages in thread* Re: [PATCH v2 02/26] block: Annotate the block device functions
2026-03-26 6:25 ` Christoph Hellwig
@ 2026-03-26 15:55 ` Bart Van Assche
2026-03-27 18:17 ` Marco Elver
0 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-26 15:55 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jens Axboe, linux-block, Damien Le Moal, Tejun Heo,
Nathan Chancellor, Marco Elver
On 3/25/26 11:25 PM, Christoph Hellwig wrote:
> On Wed, Mar 25, 2026 at 02:44:43PM -0700, Bart Van Assche wrote:
>> mutex_lock(&bdev->bd_holder_lock);
>> - if (bdev->bd_holder_ops && bdev->bd_holder_ops->mark_dead)
>> + if (bdev->bd_holder_ops && bdev->bd_holder_ops->mark_dead) {
>> bdev->bd_holder_ops->mark_dead(bdev, surprise);
>> - else {
>> + /* bdev->bd_holder_ops->mark_dead() released bd_holder_lock */
>> + __release(&bdev->bd_holder_lock);
>
> This sounds like ->mark_dead also needs matching annotations. Or
> can we have a way to annotate the expexcted lock context changes on
> indirect function calls, as that would be very useful in general.
(+Marco)
Agreed that this would be useful.
Marco, is my understanding correct that Clang does not yet support
adding lock context annotations to function pointers and hence that
adding this support would require modifying the Clang compiler?
Thanks,
Bart.
^ permalink raw reply [flat|nested] 51+ messages in thread* Re: [PATCH v2 02/26] block: Annotate the block device functions
2026-03-26 15:55 ` Bart Van Assche
@ 2026-03-27 18:17 ` Marco Elver
2026-03-27 18:27 ` Bart Van Assche
0 siblings, 1 reply; 51+ messages in thread
From: Marco Elver @ 2026-03-27 18:17 UTC (permalink / raw)
To: Bart Van Assche
Cc: Christoph Hellwig, Jens Axboe, linux-block, Damien Le Moal,
Tejun Heo, Nathan Chancellor
On Thu, 26 Mar 2026 at 16:55, Bart Van Assche <bvanassche@acm.org> wrote:
>
> On 3/25/26 11:25 PM, Christoph Hellwig wrote:
> > On Wed, Mar 25, 2026 at 02:44:43PM -0700, Bart Van Assche wrote:
> >> mutex_lock(&bdev->bd_holder_lock);
> >> - if (bdev->bd_holder_ops && bdev->bd_holder_ops->mark_dead)
> >> + if (bdev->bd_holder_ops && bdev->bd_holder_ops->mark_dead) {
> >> bdev->bd_holder_ops->mark_dead(bdev, surprise);
> >> - else {
> >> + /* bdev->bd_holder_ops->mark_dead() released bd_holder_lock */
> >> + __release(&bdev->bd_holder_lock);
> >
> > This sounds like ->mark_dead also needs matching annotations. Or
> > can we have a way to annotate the expexcted lock context changes on
> > indirect function calls, as that would be very useful in general.
>
> (+Marco)
>
> Agreed that this would be useful.
>
> Marco, is my understanding correct that Clang does not yet support
> adding lock context annotations to function pointers and hence that
> adding this support would require modifying the Clang compiler?
No that's not supported (yet). There are various design options, each
with their own pros/cons: the one question is if attributes should
behave more like type qualifiers in this case (enforces functions to
match), or just be a best-effort thing (functions may not match
function pointer).
^ permalink raw reply [flat|nested] 51+ messages in thread* Re: [PATCH v2 02/26] block: Annotate the block device functions
2026-03-27 18:17 ` Marco Elver
@ 2026-03-27 18:27 ` Bart Van Assche
0 siblings, 0 replies; 51+ messages in thread
From: Bart Van Assche @ 2026-03-27 18:27 UTC (permalink / raw)
To: Marco Elver
Cc: Christoph Hellwig, Jens Axboe, linux-block, Damien Le Moal,
Tejun Heo, Nathan Chancellor
On 3/27/26 11:17 AM, Marco Elver wrote:
> No that's not supported (yet). There are various design options, each
> with their own pros/cons: the one question is if attributes should
> behave more like type qualifiers in this case (enforces functions to
> match), or just be a best-effort thing (functions may not match
> function pointer).
It would be great if lock context annotations would be integrated in the
function pointer type because today these annotations are lost if one
function pointer is assigned to a function pointer variable.
Maybe there is something that I'm overlooking?
Thanks,
Bart.
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH v2 03/26] block/cgroup: Split blkg_conf_prep()
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
2026-03-25 21:44 ` [PATCH v2 01/26] block: Annotate the queue limits functions Bart Van Assche
2026-03-25 21:44 ` [PATCH v2 02/26] block: Annotate the block device functions Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-26 6:25 ` Christoph Hellwig
2026-03-25 21:44 ` [PATCH v2 04/26] block/cgroup: Split blkg_conf_exit() Bart Van Assche
` (23 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Yu Kuai, Josef Bacik
Move the blkg_conf_open_bdev() call out of blkg_conf_prep() to make it
possible to add lock context annotations to blkg_conf_prep(). Change an
if-statement in blkg_conf_open_bdev() into a WARN_ON_ONCE() call. Export
blkg_conf_open_bdev() because it is called by the BFQ I/O scheduler and
the BFQ I/O scheduler may be built as a kernel module.
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
block/bfq-cgroup.c | 4 ++++
block/blk-cgroup.c | 16 ++++++----------
block/blk-iocost.c | 4 ++++
3 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
index ac83b0668764..38396df9dce7 100644
--- a/block/bfq-cgroup.c
+++ b/block/bfq-cgroup.c
@@ -1051,6 +1051,10 @@ static ssize_t bfq_io_set_device_weight(struct kernfs_open_file *of,
blkg_conf_init(&ctx, buf);
+ ret = blkg_conf_open_bdev(&ctx);
+ if (ret)
+ goto out;
+
ret = blkg_conf_prep(blkcg, &blkcg_policy_bfq, &ctx);
if (ret)
goto out;
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 2d7b18eb7291..8cfdbe9fffdc 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -771,10 +771,7 @@ EXPORT_SYMBOL_GPL(blkg_conf_init);
* @ctx->input and get and store the matching bdev in @ctx->bdev. @ctx->body is
* set to point past the device node prefix.
*
- * This function may be called multiple times on @ctx and the extra calls become
- * NOOPs. blkg_conf_prep() implicitly calls this function. Use this function
- * explicitly if bdev access is needed without resolving the blkcg / policy part
- * of @ctx->input. Returns -errno on error.
+ * Returns: -errno on error.
*/
int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx)
{
@@ -783,8 +780,7 @@ int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx)
struct block_device *bdev;
int key_len;
- if (ctx->bdev)
- return 0;
+ WARN_ON_ONCE(ctx->bdev);
if (sscanf(input, "%u:%u%n", &major, &minor, &key_len) != 2)
return -EINVAL;
@@ -813,6 +809,8 @@ int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx)
ctx->bdev = bdev;
return 0;
}
+EXPORT_SYMBOL_GPL(blkg_conf_open_bdev);
+
/*
* Similar to blkg_conf_open_bdev, but additionally freezes the queue,
* ensures the correct locking order between freeze queue and q->rq_qos_mutex.
@@ -857,7 +855,7 @@ unsigned long __must_check blkg_conf_open_bdev_frozen(struct blkg_conf_ctx *ctx)
* following MAJ:MIN, @ctx->bdev points to the target block device and
* @ctx->blkg to the blkg being configured.
*
- * blkg_conf_open_bdev() may be called on @ctx beforehand. On success, this
+ * blkg_conf_open_bdev() must be called on @ctx beforehand. On success, this
* function returns with queue lock held and must be followed by
* blkg_conf_exit().
*/
@@ -870,9 +868,7 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
struct blkcg_gq *blkg;
int ret;
- ret = blkg_conf_open_bdev(ctx);
- if (ret)
- return ret;
+ WARN_ON_ONCE(!ctx->bdev);
disk = ctx->bdev->bd_disk;
q = disk->queue;
diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index d145db61e5c3..7c90241a1dbd 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -3129,6 +3129,10 @@ static ssize_t ioc_weight_write(struct kernfs_open_file *of, char *buf,
blkg_conf_init(&ctx, buf);
+ ret = blkg_conf_open_bdev(&ctx);
+ if (ret)
+ goto err;
+
ret = blkg_conf_prep(blkcg, &blkcg_policy_iocost, &ctx);
if (ret)
goto err;
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH v2 03/26] block/cgroup: Split blkg_conf_prep()
2026-03-25 21:44 ` [PATCH v2 03/26] block/cgroup: Split blkg_conf_prep() Bart Van Assche
@ 2026-03-26 6:25 ` Christoph Hellwig
0 siblings, 0 replies; 51+ messages in thread
From: Christoph Hellwig @ 2026-03-26 6:25 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Tejun Heo, Yu Kuai, Josef Bacik
On Wed, Mar 25, 2026 at 02:44:44PM -0700, Bart Van Assche wrote:
> Move the blkg_conf_open_bdev() call out of blkg_conf_prep() to make it
> possible to add lock context annotations to blkg_conf_prep(). Change an
> if-statement in blkg_conf_open_bdev() into a WARN_ON_ONCE() call. Export
> blkg_conf_open_bdev() because it is called by the BFQ I/O scheduler and
> the BFQ I/O scheduler may be built as a kernel module.
>
> Cc: Tejun Heo <tj@kernel.org>
> Signed-off-by: Bart Van Assche <bvanassche@acm.org>
> ---
> block/bfq-cgroup.c | 4 ++++
> block/blk-cgroup.c | 16 ++++++----------
> block/blk-iocost.c | 4 ++++
> 3 files changed, 14 insertions(+), 10 deletions(-)
>
> diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
> index ac83b0668764..38396df9dce7 100644
> --- a/block/bfq-cgroup.c
> +++ b/block/bfq-cgroup.c
> @@ -1051,6 +1051,10 @@ static ssize_t bfq_io_set_device_weight(struct kernfs_open_file *of,
>
> blkg_conf_init(&ctx, buf);
>
> + ret = blkg_conf_open_bdev(&ctx);
> + if (ret)
> + goto out;
> +
> ret = blkg_conf_prep(blkcg, &blkcg_policy_bfq, &ctx);
> if (ret)
> goto out;
> diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
> index 2d7b18eb7291..8cfdbe9fffdc 100644
> --- a/block/blk-cgroup.c
> +++ b/block/blk-cgroup.c
> @@ -771,10 +771,7 @@ EXPORT_SYMBOL_GPL(blkg_conf_init);
> * @ctx->input and get and store the matching bdev in @ctx->bdev. @ctx->body is
> * set to point past the device node prefix.
> *
> - * This function may be called multiple times on @ctx and the extra calls become
> - * NOOPs. blkg_conf_prep() implicitly calls this function. Use this function
> - * explicitly if bdev access is needed without resolving the blkcg / policy part
> - * of @ctx->input. Returns -errno on error.
> + * Returns: -errno on error.
> */
> int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx)
> {
> @@ -783,8 +780,7 @@ int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx)
> struct block_device *bdev;
> int key_len;
>
> - if (ctx->bdev)
> - return 0;
> + WARN_ON_ONCE(ctx->bdev);
Return on this case?
Otherwise looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH v2 04/26] block/cgroup: Split blkg_conf_exit()
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (2 preceding siblings ...)
2026-03-25 21:44 ` [PATCH v2 03/26] block/cgroup: Split blkg_conf_prep() Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-26 6:26 ` Christoph Hellwig
2026-03-25 21:44 ` [PATCH v2 05/26] block/cgroup: Modify the blkg_conf_open_bdev_frozen() calling convention Bart Van Assche
` (22 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Josef Bacik, Yu Kuai, Nathan Chancellor
Split blkg_conf_exit() into blkg_conf_unprep() and blkg_conf_close_bdev()
because blkg_conf_exit() is not compatible with the Clang thread-safety
annotations. Remove blkg_conf_exit(). Rename blkg_conf_exit_frozen() into
blkg_conf_close_bdev_frozen(). Add thread-safety annotations to the new
functions.
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
block/bfq-cgroup.c | 9 ++++--
block/blk-cgroup.c | 58 ++++++++++++++++++-------------------
block/blk-cgroup.h | 15 +++++++---
block/blk-iocost.c | 67 +++++++++++++++++++++----------------------
block/blk-iolatency.c | 19 ++++++------
block/blk-throttle.c | 34 +++++++++++++---------
6 files changed, 108 insertions(+), 94 deletions(-)
diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
index 38396df9dce7..5d40279d6c9d 100644
--- a/block/bfq-cgroup.c
+++ b/block/bfq-cgroup.c
@@ -1053,11 +1053,11 @@ static ssize_t bfq_io_set_device_weight(struct kernfs_open_file *of,
ret = blkg_conf_open_bdev(&ctx);
if (ret)
- goto out;
+ return ret;
ret = blkg_conf_prep(blkcg, &blkcg_policy_bfq, &ctx);
if (ret)
- goto out;
+ goto close_bdev;
if (sscanf(ctx.body, "%llu", &v) == 1) {
/* require "default" on dfl */
@@ -1078,8 +1078,11 @@ static ssize_t bfq_io_set_device_weight(struct kernfs_open_file *of,
bfq_group_set_weight(bfqg, bfqg->entity.weight, v);
ret = 0;
}
+
out:
- blkg_conf_exit(&ctx);
+ blkg_conf_unprep(&ctx);
+close_bdev:
+ blkg_conf_close_bdev(&ctx);
return ret ?: nbytes;
}
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 8cfdbe9fffdc..8c4052babffb 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -755,7 +755,7 @@ EXPORT_SYMBOL_GPL(__blkg_prfill_u64);
*
* Initialize @ctx which can be used to parse blkg config input string @input.
* Once initialized, @ctx can be used with blkg_conf_open_bdev() and
- * blkg_conf_prep(), and must be cleaned up with blkg_conf_exit().
+ * blkg_conf_prep().
*/
void blkg_conf_init(struct blkg_conf_ctx *ctx, char *input)
{
@@ -816,8 +816,8 @@ EXPORT_SYMBOL_GPL(blkg_conf_open_bdev);
* ensures the correct locking order between freeze queue and q->rq_qos_mutex.
*
* This function returns negative error on failure. On success it returns
- * memflags which must be saved and later passed to blkg_conf_exit_frozen
- * for restoring the memalloc scope.
+ * memflags which must be saved and later passed to
+ * blkg_conf_close_bdev_frozen() for restoring the memalloc scope.
*/
unsigned long __must_check blkg_conf_open_bdev_frozen(struct blkg_conf_ctx *ctx)
{
@@ -857,11 +857,10 @@ unsigned long __must_check blkg_conf_open_bdev_frozen(struct blkg_conf_ctx *ctx)
*
* blkg_conf_open_bdev() must be called on @ctx beforehand. On success, this
* function returns with queue lock held and must be followed by
- * blkg_conf_exit().
+ * blkg_conf_close_bdev().
*/
int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
struct blkg_conf_ctx *ctx)
- __acquires(&bdev->bd_queue->queue_lock)
{
struct gendisk *disk;
struct request_queue *q;
@@ -966,42 +965,41 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
EXPORT_SYMBOL_GPL(blkg_conf_prep);
/**
- * blkg_conf_exit - clean up per-blkg config update
+ * blkg_conf_unprep - counterpart of blkg_conf_prep()
* @ctx: blkg_conf_ctx initialized with blkg_conf_init()
- *
- * Clean up after per-blkg config update. This function must be called on all
- * blkg_conf_ctx's initialized with blkg_conf_init().
*/
-void blkg_conf_exit(struct blkg_conf_ctx *ctx)
- __releases(&ctx->bdev->bd_queue->queue_lock)
- __releases(&ctx->bdev->bd_queue->rq_qos_mutex)
+void blkg_conf_unprep(struct blkg_conf_ctx *ctx)
{
- if (ctx->blkg) {
- spin_unlock_irq(&bdev_get_queue(ctx->bdev)->queue_lock);
- ctx->blkg = NULL;
- }
+ WARN_ON_ONCE(!ctx->blkg);
+ spin_unlock_irq(&ctx->bdev->bd_disk->queue->queue_lock);
+ ctx->blkg = NULL;
+}
+EXPORT_SYMBOL_GPL(blkg_conf_unprep);
- if (ctx->bdev) {
- mutex_unlock(&ctx->bdev->bd_queue->rq_qos_mutex);
- blkdev_put_no_open(ctx->bdev);
- ctx->body = NULL;
- ctx->bdev = NULL;
- }
+/**
+ * blkg_conf_close_bdev - counterpart of blkg_conf_open_bdev()
+ * @ctx: blkg_conf_ctx initialized with blkg_conf_init()
+ */
+void blkg_conf_close_bdev(struct blkg_conf_ctx *ctx)
+{
+ mutex_unlock(&ctx->bdev->bd_queue->rq_qos_mutex);
+ blkdev_put_no_open(ctx->bdev);
+ ctx->body = NULL;
+ ctx->bdev = NULL;
}
-EXPORT_SYMBOL_GPL(blkg_conf_exit);
+EXPORT_SYMBOL_GPL(blkg_conf_close_bdev);
/*
- * Similar to blkg_conf_exit, but also unfreezes the queue. Should be used
+ * Similar to blkg_close_bdev, but also unfreezes the queue. Should be used
* when blkg_conf_open_bdev_frozen is used to open the bdev.
*/
-void blkg_conf_exit_frozen(struct blkg_conf_ctx *ctx, unsigned long memflags)
+void blkg_conf_close_bdev_frozen(struct blkg_conf_ctx *ctx,
+ unsigned long memflags)
{
- if (ctx->bdev) {
- struct request_queue *q = ctx->bdev->bd_queue;
+ struct request_queue *q = ctx->bdev->bd_queue;
- blkg_conf_exit(ctx);
- blk_mq_unfreeze_queue(q, memflags);
- }
+ blkg_conf_close_bdev(ctx);
+ blk_mq_unfreeze_queue(q, memflags);
}
static void blkg_iostat_add(struct blkg_iostat *dst, struct blkg_iostat *src)
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
index 1cce3294634d..f0a3af520c55 100644
--- a/block/blk-cgroup.h
+++ b/block/blk-cgroup.h
@@ -218,12 +218,19 @@ struct blkg_conf_ctx {
};
void blkg_conf_init(struct blkg_conf_ctx *ctx, char *input);
-int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx);
+int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx)
+ __cond_acquires(0, &ctx->bdev->bd_queue->rq_qos_mutex);
unsigned long blkg_conf_open_bdev_frozen(struct blkg_conf_ctx *ctx);
int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
- struct blkg_conf_ctx *ctx);
-void blkg_conf_exit(struct blkg_conf_ctx *ctx);
-void blkg_conf_exit_frozen(struct blkg_conf_ctx *ctx, unsigned long memflags);
+ struct blkg_conf_ctx *ctx)
+ __cond_acquires(0, &ctx->bdev->bd_disk->queue->queue_lock);
+void blkg_conf_unprep(struct blkg_conf_ctx *ctx)
+ __releases(ctx->bdev->bd_disk->queue->queue_lock);
+void blkg_conf_close_bdev(struct blkg_conf_ctx *ctx)
+ __releases(&ctx->bdev->bd_queue->rq_qos_mutex);
+void blkg_conf_close_bdev_frozen(struct blkg_conf_ctx *ctx,
+ unsigned long memflags)
+ __releases(&ctx->bdev->bd_queue->rq_qos_mutex);
/**
* bio_issue_as_root_blkg - see if this bio needs to be issued as root blkg
diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index 7c90241a1dbd..e435ac0c41e5 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -3131,21 +3131,23 @@ static ssize_t ioc_weight_write(struct kernfs_open_file *of, char *buf,
ret = blkg_conf_open_bdev(&ctx);
if (ret)
- goto err;
+ return ret;
ret = blkg_conf_prep(blkcg, &blkcg_policy_iocost, &ctx);
if (ret)
- goto err;
+ goto close_bdev;
iocg = blkg_to_iocg(ctx.blkg);
+ ret = -EINVAL;
+
if (!strncmp(ctx.body, "default", 7)) {
v = 0;
} else {
if (!sscanf(ctx.body, "%u", &v))
- goto einval;
+ goto unprep;
if (v < CGROUP_WEIGHT_MIN || v > CGROUP_WEIGHT_MAX)
- goto einval;
+ goto unprep;
}
spin_lock(&iocg->ioc->lock);
@@ -3154,14 +3156,15 @@ static ssize_t ioc_weight_write(struct kernfs_open_file *of, char *buf,
weight_updated(iocg, &now);
spin_unlock(&iocg->ioc->lock);
- blkg_conf_exit(&ctx);
- return nbytes;
+ ret = 0;
-einval:
- ret = -EINVAL;
-err:
- blkg_conf_exit(&ctx);
- return ret;
+unprep:
+ blkg_conf_unprep(&ctx);
+
+close_bdev:
+ blkg_conf_close_bdev(&ctx);
+
+ return ret ? ret : nbytes;
}
static u64 ioc_qos_prfill(struct seq_file *sf, struct blkg_policy_data *pd,
@@ -3230,10 +3233,8 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
blkg_conf_init(&ctx, input);
memflags = blkg_conf_open_bdev_frozen(&ctx);
- if (IS_ERR_VALUE(memflags)) {
- ret = memflags;
- goto err;
- }
+ if (IS_ERR_VALUE(memflags))
+ return memflags;
body = ctx.body;
disk = ctx.bdev->bd_disk;
@@ -3350,14 +3351,14 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
blk_mq_unquiesce_queue(disk->queue);
- blkg_conf_exit_frozen(&ctx, memflags);
+ blkg_conf_close_bdev_frozen(&ctx, memflags);
return nbytes;
einval:
spin_unlock_irq(&ioc->lock);
blk_mq_unquiesce_queue(disk->queue);
ret = -EINVAL;
err:
- blkg_conf_exit_frozen(&ctx, memflags);
+ blkg_conf_close_bdev_frozen(&ctx, memflags);
return ret;
}
@@ -3423,20 +3424,20 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
ret = blkg_conf_open_bdev(&ctx);
if (ret)
- goto err;
+ return ret;
body = ctx.body;
q = bdev_get_queue(ctx.bdev);
if (!queue_is_mq(q)) {
ret = -EOPNOTSUPP;
- goto err;
+ goto close_bdev;
}
ioc = q_to_ioc(q);
if (!ioc) {
ret = blk_iocost_init(ctx.bdev->bd_disk);
if (ret)
- goto err;
+ goto close_bdev;
ioc = q_to_ioc(q);
}
@@ -3447,6 +3448,8 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
memcpy(u, ioc->params.i_lcoefs, sizeof(u));
user = ioc->user_cost_model;
+ ret = -EINVAL;
+
while ((p = strsep(&body, " \t\n"))) {
substring_t args[MAX_OPT_ARGS];
char buf[32];
@@ -3464,20 +3467,20 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
else if (!strcmp(buf, "user"))
user = true;
else
- goto einval;
+ goto unlock;
continue;
case COST_MODEL:
match_strlcpy(buf, &args[0], sizeof(buf));
if (strcmp(buf, "linear"))
- goto einval;
+ goto unlock;
continue;
}
tok = match_token(p, i_lcoef_tokens, args);
if (tok == NR_I_LCOEFS)
- goto einval;
+ goto unlock;
if (match_u64(&args[0], &v))
- goto einval;
+ goto unlock;
u[tok] = v;
user = true;
}
@@ -3489,24 +3492,18 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
ioc->user_cost_model = false;
}
ioc_refresh_params(ioc, true);
- spin_unlock_irq(&ioc->lock);
- blk_mq_unquiesce_queue(q);
- blk_mq_unfreeze_queue(q, memflags);
-
- blkg_conf_exit(&ctx);
- return nbytes;
+ ret = 0;
-einval:
+unlock:
spin_unlock_irq(&ioc->lock);
blk_mq_unquiesce_queue(q);
blk_mq_unfreeze_queue(q, memflags);
- ret = -EINVAL;
-err:
- blkg_conf_exit(&ctx);
- return ret;
+close_bdev:
+ blkg_conf_close_bdev(&ctx);
+ return ret ? ret : nbytes;
}
static struct cftype ioc_files[] = {
diff --git a/block/blk-iolatency.c b/block/blk-iolatency.c
index 53e8dd2dfa8a..1aaee6fb0f59 100644
--- a/block/blk-iolatency.c
+++ b/block/blk-iolatency.c
@@ -840,7 +840,7 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
ret = blkg_conf_open_bdev(&ctx);
if (ret)
- goto out;
+ return ret;
/*
* blk_iolatency_init() may fail after rq_qos_add() succeeds which can
@@ -850,11 +850,11 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
if (!iolat_rq_qos(ctx.bdev->bd_queue))
ret = blk_iolatency_init(ctx.bdev->bd_disk);
if (ret)
- goto out;
+ goto close_bdev;
ret = blkg_conf_prep(blkcg, &blkcg_policy_iolatency, &ctx);
if (ret)
- goto out;
+ goto close_bdev;
iolat = blkg_to_lat(ctx.blkg);
p = ctx.body;
@@ -865,7 +865,7 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
char val[21]; /* 18446744073709551616 */
if (sscanf(tok, "%15[^=]=%20s", key, val) != 2)
- goto out;
+ goto unprep;
if (!strcmp(key, "target")) {
u64 v;
@@ -875,9 +875,9 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
else if (sscanf(val, "%llu", &v) == 1)
lat_val = v * NSEC_PER_USEC;
else
- goto out;
+ goto unprep;
} else {
- goto out;
+ goto unprep;
}
}
@@ -889,8 +889,11 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
if (oldval != iolat->min_lat_nsec)
iolatency_clear_scaling(blkg);
ret = 0;
-out:
- blkg_conf_exit(&ctx);
+
+unprep:
+ blkg_conf_unprep(&ctx);
+close_bdev:
+ blkg_conf_close_bdev(&ctx);
return ret ?: nbytes;
}
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 97188a795848..11b571246f45 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -1353,21 +1353,21 @@ static ssize_t tg_set_conf(struct kernfs_open_file *of,
ret = blkg_conf_open_bdev(&ctx);
if (ret)
- goto out_finish;
+ return ret;
if (!blk_throtl_activated(ctx.bdev->bd_queue)) {
ret = blk_throtl_init(ctx.bdev->bd_disk);
if (ret)
- goto out_finish;
+ goto close_bdev;
}
ret = blkg_conf_prep(blkcg, &blkcg_policy_throtl, &ctx);
if (ret)
- goto out_finish;
+ goto close_bdev;
ret = -EINVAL;
if (sscanf(ctx.body, "%llu", &v) != 1)
- goto out_finish;
+ goto unprep;
if (!v)
v = U64_MAX;
@@ -1381,8 +1381,12 @@ static ssize_t tg_set_conf(struct kernfs_open_file *of,
tg_conf_updated(tg, false);
ret = 0;
-out_finish:
- blkg_conf_exit(&ctx);
+
+unprep:
+ blkg_conf_unprep(&ctx);
+
+close_bdev:
+ blkg_conf_close_bdev(&ctx);
return ret ?: nbytes;
}
@@ -1537,17 +1541,17 @@ static ssize_t tg_set_limit(struct kernfs_open_file *of,
ret = blkg_conf_open_bdev(&ctx);
if (ret)
- goto out_finish;
+ return ret;
if (!blk_throtl_activated(ctx.bdev->bd_queue)) {
ret = blk_throtl_init(ctx.bdev->bd_disk);
if (ret)
- goto out_finish;
+ goto close_bdev;
}
ret = blkg_conf_prep(blkcg, &blkcg_policy_throtl, &ctx);
if (ret)
- goto out_finish;
+ goto close_bdev;
tg = blkg_to_tg(ctx.blkg);
tg_update_carryover(tg);
@@ -1573,11 +1577,11 @@ static ssize_t tg_set_limit(struct kernfs_open_file *of,
p = tok;
strsep(&p, "=");
if (!p || (sscanf(p, "%llu", &val) != 1 && strcmp(p, "max")))
- goto out_finish;
+ goto unprep;
ret = -ERANGE;
if (!val)
- goto out_finish;
+ goto unprep;
ret = -EINVAL;
if (!strcmp(tok, "rbps"))
@@ -1589,7 +1593,7 @@ static ssize_t tg_set_limit(struct kernfs_open_file *of,
else if (!strcmp(tok, "wiops"))
v[3] = min_t(u64, val, UINT_MAX);
else
- goto out_finish;
+ goto unprep;
}
tg->bps[READ] = v[0];
@@ -1599,8 +1603,10 @@ static ssize_t tg_set_limit(struct kernfs_open_file *of,
tg_conf_updated(tg, false);
ret = 0;
-out_finish:
- blkg_conf_exit(&ctx);
+unprep:
+ blkg_conf_unprep(&ctx);
+close_bdev:
+ blkg_conf_close_bdev(&ctx);
return ret ?: nbytes;
}
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH v2 05/26] block/cgroup: Modify the blkg_conf_open_bdev_frozen() calling convention
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (3 preceding siblings ...)
2026-03-25 21:44 ` [PATCH v2 04/26] block/cgroup: Split blkg_conf_exit() Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-26 6:28 ` Christoph Hellwig
2026-03-25 21:44 ` [PATCH v2 06/26] block/crypto: Annotate the crypto functions Bart Van Assche
` (21 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Josef Bacik
Instead of returning either a negative error number or a positive memory
flags value, pass a memory flags pointer as an argument and return zero
upon success. This patch prepares for adding thread-safety annotations
by changing the calling convention into something that is supported by
__cond_acquires().
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
block/blk-cgroup.c | 12 +++++-------
block/blk-cgroup.h | 4 +++-
block/blk-iocost.c | 6 +++---
3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 8c4052babffb..5b246020aced 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -815,14 +815,12 @@ EXPORT_SYMBOL_GPL(blkg_conf_open_bdev);
* Similar to blkg_conf_open_bdev, but additionally freezes the queue,
* ensures the correct locking order between freeze queue and q->rq_qos_mutex.
*
- * This function returns negative error on failure. On success it returns
- * memflags which must be saved and later passed to
- * blkg_conf_close_bdev_frozen() for restoring the memalloc scope.
+ * Returns: a negative error on failure or zero if successful.
*/
-unsigned long __must_check blkg_conf_open_bdev_frozen(struct blkg_conf_ctx *ctx)
+int blkg_conf_open_bdev_frozen(struct blkg_conf_ctx *ctx,
+ unsigned long *memflags)
{
int ret;
- unsigned long memflags;
if (ctx->bdev)
return -EINVAL;
@@ -838,10 +836,10 @@ unsigned long __must_check blkg_conf_open_bdev_frozen(struct blkg_conf_ctx *ctx)
*/
mutex_unlock(&ctx->bdev->bd_queue->rq_qos_mutex);
- memflags = blk_mq_freeze_queue(ctx->bdev->bd_queue);
+ *memflags = blk_mq_freeze_queue(ctx->bdev->bd_queue);
mutex_lock(&ctx->bdev->bd_queue->rq_qos_mutex);
- return memflags;
+ return 0;
}
/**
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
index f0a3af520c55..f56fab637093 100644
--- a/block/blk-cgroup.h
+++ b/block/blk-cgroup.h
@@ -220,7 +220,9 @@ struct blkg_conf_ctx {
void blkg_conf_init(struct blkg_conf_ctx *ctx, char *input);
int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx)
__cond_acquires(0, &ctx->bdev->bd_queue->rq_qos_mutex);
-unsigned long blkg_conf_open_bdev_frozen(struct blkg_conf_ctx *ctx);
+int blkg_conf_open_bdev_frozen(struct blkg_conf_ctx *ctx,
+ unsigned long *memflags)
+ __cond_acquires(0, &ctx->bdev->bd_queue->rq_qos_mutex);
int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
struct blkg_conf_ctx *ctx)
__cond_acquires(0, &ctx->bdev->bd_disk->queue->queue_lock);
diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index e435ac0c41e5..9f8bdae5a4b3 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -3232,9 +3232,9 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
blkg_conf_init(&ctx, input);
- memflags = blkg_conf_open_bdev_frozen(&ctx);
- if (IS_ERR_VALUE(memflags))
- return memflags;
+ ret = blkg_conf_open_bdev_frozen(&ctx, &memflags);
+ if (ret)
+ return ret;
body = ctx.body;
disk = ctx.bdev->bd_disk;
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH v2 05/26] block/cgroup: Modify the blkg_conf_open_bdev_frozen() calling convention
2026-03-25 21:44 ` [PATCH v2 05/26] block/cgroup: Modify the blkg_conf_open_bdev_frozen() calling convention Bart Van Assche
@ 2026-03-26 6:28 ` Christoph Hellwig
0 siblings, 0 replies; 51+ messages in thread
From: Christoph Hellwig @ 2026-03-26 6:28 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Tejun Heo, Josef Bacik
On Wed, Mar 25, 2026 at 02:44:46PM -0700, Bart Van Assche wrote:
> Instead of returning either a negative error number or a positive memory
> flags value, pass a memory flags pointer as an argument and return zero
> upon success. This patch prepares for adding thread-safety annotations
> by changing the calling convention into something that is supported by
> __cond_acquires().
Looking at this code it seems like a really messy API. It seems
like blkg_conf_open_bdev_frozen and blkg_conf_exit_frozen should
just be open coded in the only caller using the lower-level helpers
you just added earlier.
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH v2 06/26] block/crypto: Annotate the crypto functions
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (4 preceding siblings ...)
2026-03-25 21:44 ` [PATCH v2 05/26] block/cgroup: Modify the blkg_conf_open_bdev_frozen() calling convention Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-26 6:28 ` Christoph Hellwig
2026-03-25 21:44 ` [PATCH v2 07/26] block/blk-iocost: Add lock context annotations Bart Van Assche
` (20 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Eric Biggers, Nathan Chancellor
Add the lock context annotations required for Clang's thread-safety
analysis.
Cc: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
block/blk-crypto-profile.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/block/blk-crypto-profile.c b/block/blk-crypto-profile.c
index 4ac74443687a..cf447ba4a66e 100644
--- a/block/blk-crypto-profile.c
+++ b/block/blk-crypto-profile.c
@@ -43,6 +43,7 @@ struct blk_crypto_keyslot {
};
static inline void blk_crypto_hw_enter(struct blk_crypto_profile *profile)
+ __acquires(&profile->lock)
{
/*
* Calling into the driver requires profile->lock held and the device
@@ -55,6 +56,7 @@ static inline void blk_crypto_hw_enter(struct blk_crypto_profile *profile)
}
static inline void blk_crypto_hw_exit(struct blk_crypto_profile *profile)
+ __releases(&profile->lock)
{
up_write(&profile->lock);
if (profile->dev)
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH v2 07/26] block/blk-iocost: Add lock context annotations
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (5 preceding siblings ...)
2026-03-25 21:44 ` [PATCH v2 06/26] block/crypto: Annotate the crypto functions Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-26 6:31 ` Christoph Hellwig
2026-03-25 21:44 ` [PATCH v2 08/26] block/blk-mq-debugfs: Improve " Bart Van Assche
` (19 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Josef Bacik
Since iocg_lock() and iocg_unlock() both use conditional locking,
annotate both with __no_context_analysis and use token_context_lock() to
introduce a new lock context.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
block/blk-iocost.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index 9f8bdae5a4b3..f161c78e0f21 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -727,7 +727,11 @@ static void iocg_commit_bio(struct ioc_gq *iocg, struct bio *bio,
put_cpu_ptr(gcs);
}
+token_context_lock(ioc_lock);
+
static void iocg_lock(struct ioc_gq *iocg, bool lock_ioc, unsigned long *flags)
+ __acquires(ioc_lock)
+ __no_context_analysis /* conditional locking */
{
if (lock_ioc) {
spin_lock_irqsave(&iocg->ioc->lock, *flags);
@@ -738,6 +742,8 @@ static void iocg_lock(struct ioc_gq *iocg, bool lock_ioc, unsigned long *flags)
}
static void iocg_unlock(struct ioc_gq *iocg, bool unlock_ioc, unsigned long *flags)
+ __releases(ioc_lock)
+ __no_context_analysis /* conditional locking */
{
if (unlock_ioc) {
spin_unlock(&iocg->waitq.lock);
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH v2 07/26] block/blk-iocost: Add lock context annotations
2026-03-25 21:44 ` [PATCH v2 07/26] block/blk-iocost: Add lock context annotations Bart Van Assche
@ 2026-03-26 6:31 ` Christoph Hellwig
0 siblings, 0 replies; 51+ messages in thread
From: Christoph Hellwig @ 2026-03-26 6:31 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Tejun Heo, Josef Bacik
On Wed, Mar 25, 2026 at 02:44:48PM -0700, Bart Van Assche wrote:
> Since iocg_lock() and iocg_unlock() both use conditional locking,
> annotate both with __no_context_analysis and use token_context_lock() to
> introduce a new lock context.
Looking at the two callers it seems like these helpers should simply
go away in favour of refactoring the callers. iocg_waitq_timer_fn
only calls a single function inside the lock, which can be turned into
a conditional trivially, and ioc_rqos_throttle does basically totally
different things based on the same paramter passed as the lock_ioc
argument to iocg_lock/iocg_unlock.
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH v2 08/26] block/blk-mq-debugfs: Improve lock context annotations
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (6 preceding siblings ...)
2026-03-25 21:44 ` [PATCH v2 07/26] block/blk-iocost: Add lock context annotations Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-26 6:32 ` Christoph Hellwig
2026-03-25 21:44 ` [PATCH v2 09/26] block/blk-zoned: Add " Bart Van Assche
` (18 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Nathan Chancellor
Make the existing lock context annotations compatible with Clang. Add
the lock context annotations that are missing.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
block/blk-mq-debugfs.c | 12 ++++++------
block/blk.h | 4 ++++
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index 047ec887456b..5c168e82273e 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -20,7 +20,7 @@ static int queue_poll_stat_show(void *data, struct seq_file *m)
}
static void *queue_requeue_list_start(struct seq_file *m, loff_t *pos)
- __acquires(&q->requeue_lock)
+ __acquires(&((struct request_queue *)m->private)->requeue_lock)
{
struct request_queue *q = m->private;
@@ -36,7 +36,7 @@ static void *queue_requeue_list_next(struct seq_file *m, void *v, loff_t *pos)
}
static void queue_requeue_list_stop(struct seq_file *m, void *v)
- __releases(&q->requeue_lock)
+ __releases(&((struct request_queue *)m->private)->requeue_lock)
{
struct request_queue *q = m->private;
@@ -298,7 +298,7 @@ int blk_mq_debugfs_rq_show(struct seq_file *m, void *v)
EXPORT_SYMBOL_GPL(blk_mq_debugfs_rq_show);
static void *hctx_dispatch_start(struct seq_file *m, loff_t *pos)
- __acquires(&hctx->lock)
+ __acquires(&((struct blk_mq_hw_ctx *)m->private)->lock)
{
struct blk_mq_hw_ctx *hctx = m->private;
@@ -314,7 +314,7 @@ static void *hctx_dispatch_next(struct seq_file *m, void *v, loff_t *pos)
}
static void hctx_dispatch_stop(struct seq_file *m, void *v)
- __releases(&hctx->lock)
+ __releases(&((struct blk_mq_hw_ctx *)m->private)->lock)
{
struct blk_mq_hw_ctx *hctx = m->private;
@@ -486,7 +486,7 @@ static int hctx_dispatch_busy_show(void *data, struct seq_file *m)
#define CTX_RQ_SEQ_OPS(name, type) \
static void *ctx_##name##_rq_list_start(struct seq_file *m, loff_t *pos) \
- __acquires(&ctx->lock) \
+ __acquires(&((struct blk_mq_ctx *)m->private)->lock) \
{ \
struct blk_mq_ctx *ctx = m->private; \
\
@@ -503,7 +503,7 @@ static void *ctx_##name##_rq_list_next(struct seq_file *m, void *v, \
} \
\
static void ctx_##name##_rq_list_stop(struct seq_file *m, void *v) \
- __releases(&ctx->lock) \
+ __releases(&((struct blk_mq_ctx *)m->private)->lock) \
{ \
struct blk_mq_ctx *ctx = m->private; \
\
diff --git a/block/blk.h b/block/blk.h
index 103cb1d0b9cb..7082dd5a87f9 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -733,16 +733,19 @@ static inline void blk_unfreeze_release_lock(struct request_queue *q)
* reclaim from triggering block I/O.
*/
static inline void blk_debugfs_lock_nomemsave(struct request_queue *q)
+ __acquires(&q->debugfs_mutex)
{
mutex_lock(&q->debugfs_mutex);
}
static inline void blk_debugfs_unlock_nomemrestore(struct request_queue *q)
+ __releases(&q->debugfs_mutex)
{
mutex_unlock(&q->debugfs_mutex);
}
static inline unsigned int __must_check blk_debugfs_lock(struct request_queue *q)
+ __acquires(&q->debugfs_mutex)
{
unsigned int memflags = memalloc_noio_save();
@@ -752,6 +755,7 @@ static inline unsigned int __must_check blk_debugfs_lock(struct request_queue *q
static inline void blk_debugfs_unlock(struct request_queue *q,
unsigned int memflags)
+ __releases(&q->debugfs_mutex)
{
blk_debugfs_unlock_nomemrestore(q);
memalloc_noio_restore(memflags);
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH v2 09/26] block/blk-zoned: Add lock context annotations
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (7 preceding siblings ...)
2026-03-25 21:44 ` [PATCH v2 08/26] block/blk-mq-debugfs: Improve " Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-26 6:42 ` Christoph Hellwig
2026-03-25 21:44 ` [PATCH v2 10/26] block/ioctl: " Bart Van Assche
` (17 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Nathan Chancellor
Add the lock context annotations required for Clang's thread-safety
analysis.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
block/blk-zoned.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/block/blk-zoned.c b/block/blk-zoned.c
index e1a23c8b676d..df0800e69ad7 100644
--- a/block/blk-zoned.c
+++ b/block/blk-zoned.c
@@ -439,6 +439,7 @@ static int blkdev_truncate_zone_range(struct block_device *bdev,
*/
int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode,
unsigned int cmd, unsigned long arg)
+ __cond_acquires(0, bdev->bd_mapping->host->i_rwsem)
{
void __user *argp = (void __user *)arg;
struct blk_zone_range zrange;
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH v2 09/26] block/blk-zoned: Add lock context annotations
2026-03-25 21:44 ` [PATCH v2 09/26] block/blk-zoned: Add " Bart Van Assche
@ 2026-03-26 6:42 ` Christoph Hellwig
0 siblings, 0 replies; 51+ messages in thread
From: Christoph Hellwig @ 2026-03-26 6:42 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Tejun Heo, Nathan Chancellor
On Wed, Mar 25, 2026 at 02:44:50PM -0700, Bart Van Assche wrote:
> int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode,
> unsigned int cmd, unsigned long arg)
> + __cond_acquires(0, bdev->bd_mapping->host->i_rwsem)
> {
> void __user *argp = (void __user *)arg;
> struct blk_zone_range zrange;
This looks wrong, the lock is just conditionally taken inside the
function and dropped again. This cleanup should fix the lock annotation
issues:
---
From 99e701882a9026f56cf6940d858e92ce51d86638 Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <hch@lst.de>
Date: Thu, 26 Mar 2026 07:37:43 +0100
Subject: block: refactor blkdev_zone_mgmt_ioctl
Split the zone reset case into a separate helper so that the conditional
locking goes away.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
block/blk-zoned.c | 41 ++++++++++++++++++-----------------------
1 file changed, 18 insertions(+), 23 deletions(-)
diff --git a/block/blk-zoned.c b/block/blk-zoned.c
index 9d1dd6ccfad7..d370d871d019 100644
--- a/block/blk-zoned.c
+++ b/block/blk-zoned.c
@@ -412,20 +412,32 @@ int blkdev_report_zones_ioctl(struct block_device *bdev, unsigned int cmd,
return 0;
}
-static int blkdev_truncate_zone_range(struct block_device *bdev,
- blk_mode_t mode, const struct blk_zone_range *zrange)
+static int blkdev_reset_zone(struct block_device *bdev, blk_mode_t mode,
+ struct blk_zone_range *zrange)
{
loff_t start, end;
+ int ret = -EINVAL;
+ inode_lock(bdev->bd_mapping->host);
+ filemap_invalidate_lock(bdev->bd_mapping);
if (zrange->sector + zrange->nr_sectors <= zrange->sector ||
zrange->sector + zrange->nr_sectors > get_capacity(bdev->bd_disk))
/* Out of range */
- return -EINVAL;
+ goto out_unlock;
start = zrange->sector << SECTOR_SHIFT;
end = ((zrange->sector + zrange->nr_sectors) << SECTOR_SHIFT) - 1;
- return truncate_bdev_range(bdev, mode, start, end);
+ ret = truncate_bdev_range(bdev, mode, start, end);
+ if (ret)
+ goto out_unlock;
+
+ ret = blkdev_zone_mgmt(bdev, REQ_OP_ZONE_RESET, zrange->sector,
+ zrange->nr_sectors);
+out_unlock:
+ filemap_invalidate_unlock(bdev->bd_mapping);
+ inode_unlock(bdev->bd_mapping->host);
+ return ret;
}
/*
@@ -438,7 +450,6 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode,
void __user *argp = (void __user *)arg;
struct blk_zone_range zrange;
enum req_op op;
- int ret;
if (!argp)
return -EINVAL;
@@ -454,15 +465,7 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode,
switch (cmd) {
case BLKRESETZONE:
- op = REQ_OP_ZONE_RESET;
-
- /* Invalidate the page cache, including dirty pages. */
- inode_lock(bdev->bd_mapping->host);
- filemap_invalidate_lock(bdev->bd_mapping);
- ret = blkdev_truncate_zone_range(bdev, mode, &zrange);
- if (ret)
- goto fail;
- break;
+ return blkdev_reset_zone(bdev, mode, &zrange);
case BLKOPENZONE:
op = REQ_OP_ZONE_OPEN;
break;
@@ -476,15 +479,7 @@ int blkdev_zone_mgmt_ioctl(struct block_device *bdev, blk_mode_t mode,
return -ENOTTY;
}
- ret = blkdev_zone_mgmt(bdev, op, zrange.sector, zrange.nr_sectors);
-
-fail:
- if (cmd == BLKRESETZONE) {
- filemap_invalidate_unlock(bdev->bd_mapping);
- inode_unlock(bdev->bd_mapping->host);
- }
-
- return ret;
+ return blkdev_zone_mgmt(bdev, op, zrange.sector, zrange.nr_sectors);
}
static bool disk_zone_is_last(struct gendisk *disk, struct blk_zone *zone)
--
2.47.3
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [PATCH v2 10/26] block/ioctl: Add lock context annotations
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (8 preceding siblings ...)
2026-03-25 21:44 ` [PATCH v2 09/26] block/blk-zoned: Add " Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-26 6:39 ` Christoph Hellwig
2026-03-25 21:44 ` [PATCH v2 11/26] block/Kyber: Make the lock context annotations compatible with Clang Bart Van Assche
` (16 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Nathan Chancellor
Add a lock context annotation that is required for Clang's thread-safety
analysis.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
block/ioctl.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/block/ioctl.c b/block/ioctl.c
index 0b04661ac809..784f2965f8bd 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -518,6 +518,7 @@ static int blkdev_pr_read_reservation(struct block_device *bdev,
static int blkdev_flushbuf(struct block_device *bdev, unsigned cmd,
unsigned long arg)
+ __cond_acquires(0, bdev->bd_holder_lock)
{
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH v2 10/26] block/ioctl: Add lock context annotations
2026-03-25 21:44 ` [PATCH v2 10/26] block/ioctl: " Bart Van Assche
@ 2026-03-26 6:39 ` Christoph Hellwig
0 siblings, 0 replies; 51+ messages in thread
From: Christoph Hellwig @ 2026-03-26 6:39 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Tejun Heo, Nathan Chancellor
On Wed, Mar 25, 2026 at 02:44:51PM -0700, Bart Van Assche wrote:
> Add a lock context annotation that is required for Clang's thread-safety
> analysis.
This doesn't explain much. The problem seems to be that ->synmc
can drop the holder lock. I think we need a proper way to identify
how function pointers acquire or drop locks as said before instead of
using a big, misleading and incorrectly documented hammer like this.
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH v2 11/26] block/Kyber: Make the lock context annotations compatible with Clang
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (9 preceding siblings ...)
2026-03-25 21:44 ` [PATCH v2 10/26] block/ioctl: " Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-26 6:40 ` Christoph Hellwig
2026-03-25 21:44 ` [PATCH v2 12/26] block/mq-deadline: " Bart Van Assche
` (15 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Nathan Chancellor
Prepare for enabling lock context analysis.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
block/kyber-iosched.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/block/kyber-iosched.c b/block/kyber-iosched.c
index b84163d1f851..971818bcdc9d 100644
--- a/block/kyber-iosched.c
+++ b/block/kyber-iosched.c
@@ -882,6 +882,9 @@ static const struct elv_fs_entry kyber_sched_attrs[] = {
};
#undef KYBER_LAT_ATTR
+#define HCTX_FROM_SEQ_FILE(m) ((struct blk_mq_hw_ctx *)(m)->private)
+#define KYBER_HCTX_DATA(hctx) ((struct kyber_hctx_data *)(hctx)->sched_data)
+
#ifdef CONFIG_BLK_DEBUG_FS
#define KYBER_DEBUGFS_DOMAIN_ATTRS(domain, name) \
static int kyber_##name##_tokens_show(void *data, struct seq_file *m) \
@@ -894,7 +897,7 @@ static int kyber_##name##_tokens_show(void *data, struct seq_file *m) \
} \
\
static void *kyber_##name##_rqs_start(struct seq_file *m, loff_t *pos) \
- __acquires(&khd->lock) \
+ __acquires(&KYBER_HCTX_DATA(HCTX_FROM_SEQ_FILE(m))->lock) \
{ \
struct blk_mq_hw_ctx *hctx = m->private; \
struct kyber_hctx_data *khd = hctx->sched_data; \
@@ -913,7 +916,7 @@ static void *kyber_##name##_rqs_next(struct seq_file *m, void *v, \
} \
\
static void kyber_##name##_rqs_stop(struct seq_file *m, void *v) \
- __releases(&khd->lock) \
+ __releases(&KYBER_HCTX_DATA(HCTX_FROM_SEQ_FILE(m))->lock) \
{ \
struct blk_mq_hw_ctx *hctx = m->private; \
struct kyber_hctx_data *khd = hctx->sched_data; \
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH v2 12/26] block/mq-deadline: Make the lock context annotations compatible with Clang
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (10 preceding siblings ...)
2026-03-25 21:44 ` [PATCH v2 11/26] block/Kyber: Make the lock context annotations compatible with Clang Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-25 21:44 ` [PATCH v2 13/26] block: Enable lock context analysis Bart Van Assche
` (14 subsequent siblings)
26 siblings, 0 replies; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Nathan Chancellor
Prepare for enabling lock context analysis.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
block/mq-deadline.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/block/mq-deadline.c b/block/mq-deadline.c
index 95917a88976f..824bfc17b2c6 100644
--- a/block/mq-deadline.c
+++ b/block/mq-deadline.c
@@ -794,11 +794,15 @@ static const struct elv_fs_entry deadline_attrs[] = {
__ATTR_NULL
};
+#define RQ_FROM_SEQ_FILE(m) ((struct request_queue *)(m)->private)
+#define DD_DATA_FROM_RQ(rq) \
+ ((struct deadline_data *)(rq)->elevator->elevator_data)
+
#ifdef CONFIG_BLK_DEBUG_FS
#define DEADLINE_DEBUGFS_DDIR_ATTRS(prio, data_dir, name) \
static void *deadline_##name##_fifo_start(struct seq_file *m, \
loff_t *pos) \
- __acquires(&dd->lock) \
+ __acquires(&DD_DATA_FROM_RQ(RQ_FROM_SEQ_FILE(m))->lock) \
{ \
struct request_queue *q = m->private; \
struct deadline_data *dd = q->elevator->elevator_data; \
@@ -819,7 +823,7 @@ static void *deadline_##name##_fifo_next(struct seq_file *m, void *v, \
} \
\
static void deadline_##name##_fifo_stop(struct seq_file *m, void *v) \
- __releases(&dd->lock) \
+ __releases(&DD_DATA_FROM_RQ(RQ_FROM_SEQ_FILE(m))->lock) \
{ \
struct request_queue *q = m->private; \
struct deadline_data *dd = q->elevator->elevator_data; \
@@ -921,7 +925,7 @@ static int dd_owned_by_driver_show(void *data, struct seq_file *m)
}
static void *deadline_dispatch_start(struct seq_file *m, loff_t *pos)
- __acquires(&dd->lock)
+ __acquires(&DD_DATA_FROM_RQ(RQ_FROM_SEQ_FILE(m))->lock)
{
struct request_queue *q = m->private;
struct deadline_data *dd = q->elevator->elevator_data;
@@ -939,7 +943,7 @@ static void *deadline_dispatch_next(struct seq_file *m, void *v, loff_t *pos)
}
static void deadline_dispatch_stop(struct seq_file *m, void *v)
- __releases(&dd->lock)
+ __releases(&DD_DATA_FROM_RQ(RQ_FROM_SEQ_FILE(m))->lock)
{
struct request_queue *q = m->private;
struct deadline_data *dd = q->elevator->elevator_data;
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH v2 13/26] block: Enable lock context analysis
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (11 preceding siblings ...)
2026-03-25 21:44 ` [PATCH v2 12/26] block/mq-deadline: " Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-25 21:44 ` [PATCH v2 14/26] aoe: Add a lock context annotation Bart Van Assche
` (13 subsequent siblings)
26 siblings, 0 replies; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche
Now that all block/*.c files have been annotated, enable lock context
analysis for all these source files.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
block/Makefile | 2 ++
1 file changed, 2 insertions(+)
diff --git a/block/Makefile b/block/Makefile
index 7dce2e44276c..54130faacc21 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -3,6 +3,8 @@
# Makefile for the kernel block layer
#
+CONTEXT_ANALYSIS := y
+
obj-y := bdev.o fops.o bio.o elevator.o blk-core.o blk-sysfs.o \
blk-flush.o blk-settings.o blk-ioc.o blk-map.o \
blk-merge.o blk-timeout.o blk-lib.o blk-mq.o \
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH v2 14/26] aoe: Add a lock context annotation
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (12 preceding siblings ...)
2026-03-25 21:44 ` [PATCH v2 13/26] block: Enable lock context analysis Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-26 14:13 ` Christoph Hellwig
2026-03-25 21:44 ` [PATCH v2 15/26] drbd: Balance RCU calls in drbd_adm_dump_devices() Bart Van Assche
` (12 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Justin Sanders
Add a missing __must_hold() annotation. Enable lock context analysis in the
Makefile.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/aoe/Makefile | 2 ++
drivers/block/aoe/aoecmd.c | 1 +
2 files changed, 3 insertions(+)
diff --git a/drivers/block/aoe/Makefile b/drivers/block/aoe/Makefile
index b7545ce2f1b0..27bff6359a56 100644
--- a/drivers/block/aoe/Makefile
+++ b/drivers/block/aoe/Makefile
@@ -3,5 +3,7 @@
# Makefile for ATA over Ethernet
#
+CONTEXT_ANALYSIS := y
+
obj-$(CONFIG_ATA_OVER_ETH) += aoe.o
aoe-y := aoeblk.o aoechr.o aoecmd.o aoedev.o aoemain.o aoenet.o
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index a4744a30a8af..54c57b9f8894 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -1193,6 +1193,7 @@ noskb: if (buf)
*/
static int
ktio(int id)
+ __must_hold(&iocq[id].lock)
{
struct frame *f;
struct list_head *pos;
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH v2 15/26] drbd: Balance RCU calls in drbd_adm_dump_devices()
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (13 preceding siblings ...)
2026-03-25 21:44 ` [PATCH v2 14/26] aoe: Add a lock context annotation Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-26 14:14 ` Christoph Hellwig
2026-03-25 21:44 ` [PATCH v2 16/26] drbd: Make the lock context annotations compatible with Clang Bart Van Assche
` (11 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Christoph Böhmwalder, Andreas Gruenbacher,
Philipp Reisner, Lars Ellenberg, Nathan Chancellor
Make drbd_adm_dump_devices() call rcu_read_lock() before
rcu_read_unlock() is called. This has been detected by the Clang
thread-safety analyzer.
Tested-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
Cc: Andreas Gruenbacher <agruenba@redhat.com>
Fixes: a55bbd375d18 ("drbd: Backport the "status" command")
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/drbd/drbd_nl.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index e18fa260a662..1f8ffdf9b24e 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -3443,8 +3443,10 @@ int drbd_adm_dump_devices(struct sk_buff *skb, struct netlink_callback *cb)
if (resource_filter) {
retcode = ERR_RES_NOT_KNOWN;
resource = drbd_find_resource(nla_data(resource_filter));
- if (!resource)
+ if (!resource) {
+ rcu_read_lock();
goto put_result;
+ }
cb->args[0] = (long)resource;
}
}
@@ -3693,8 +3695,10 @@ int drbd_adm_dump_peer_devices(struct sk_buff *skb, struct netlink_callback *cb)
if (resource_filter) {
retcode = ERR_RES_NOT_KNOWN;
resource = drbd_find_resource(nla_data(resource_filter));
- if (!resource)
+ if (!resource) {
+ rcu_read_lock();
goto put_result;
+ }
}
cb->args[0] = (long)resource;
}
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH v2 15/26] drbd: Balance RCU calls in drbd_adm_dump_devices()
2026-03-25 21:44 ` [PATCH v2 15/26] drbd: Balance RCU calls in drbd_adm_dump_devices() Bart Van Assche
@ 2026-03-26 14:14 ` Christoph Hellwig
0 siblings, 0 replies; 51+ messages in thread
From: Christoph Hellwig @ 2026-03-26 14:14 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Tejun Heo, Christoph Böhmwalder, Andreas Gruenbacher,
Philipp Reisner, Lars Ellenberg, Nathan Chancellor
On Wed, Mar 25, 2026 at 02:44:56PM -0700, Bart Van Assche wrote:
> Make drbd_adm_dump_devices() call rcu_read_lock() before
> rcu_read_unlock() is called. This has been detected by the Clang
> thread-safety analyzer.
Please split out fixes so they:
a) stand out
b) can be queued up in the current merge window
The patch itself looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH v2 16/26] drbd: Make the lock context annotations compatible with Clang
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (14 preceding siblings ...)
2026-03-25 21:44 ` [PATCH v2 15/26] drbd: Balance RCU calls in drbd_adm_dump_devices() Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-26 14:18 ` Christoph Hellwig
2026-03-25 21:44 ` [PATCH v2 17/26] loop: Add lock context annotations Bart Van Assche
` (10 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Christoph Böhmwalder, Philipp Reisner,
Lars Ellenberg, Nathan Chancellor
Clang performs more strict checking of lock context annotations than
sparse. This patch makes the DRBD lock context annotations compatible
with Clang and enables lock context analysis in the Makefile.
Reviewed-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/drbd/Makefile | 3 +
drivers/block/drbd/drbd_bitmap.c | 26 ++++++---
drivers/block/drbd/drbd_int.h | 88 ++++++++++++++++++------------
drivers/block/drbd/drbd_main.c | 40 ++++++++++----
drivers/block/drbd/drbd_nl.c | 5 +-
drivers/block/drbd/drbd_receiver.c | 31 ++++++++---
drivers/block/drbd/drbd_req.c | 3 +
drivers/block/drbd/drbd_state.c | 2 +
drivers/block/drbd/drbd_state.h | 4 --
drivers/block/drbd/drbd_worker.c | 6 +-
10 files changed, 138 insertions(+), 70 deletions(-)
diff --git a/drivers/block/drbd/Makefile b/drivers/block/drbd/Makefile
index 67a8b352a1d5..8eaa83a7592b 100644
--- a/drivers/block/drbd/Makefile
+++ b/drivers/block/drbd/Makefile
@@ -1,4 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
+
+CONTEXT_ANALYSIS := y
+
drbd-y := drbd_buildtag.o drbd_bitmap.o drbd_proc.o
drbd-y += drbd_worker.o drbd_receiver.o drbd_req.o drbd_actlog.o
drbd-y += drbd_main.o drbd_strings.o drbd_nl.o
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index 65ea6ec66bfd..3c521f0dc9ad 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -122,12 +122,16 @@ static void __bm_print_lock_info(struct drbd_device *device, const char *func)
}
void drbd_bm_lock(struct drbd_device *device, char *why, enum bm_flag flags)
+ __acquires(&device->bitmap->bm_change)
{
struct drbd_bitmap *b = device->bitmap;
int trylock_failed;
if (!b) {
drbd_err(device, "FIXME no bitmap in drbd_bm_lock!?\n");
+ /* Fake __acquire() to keep the compiler happy. */
+ __acquire(&b->bm_change);
+ __acquire(drbd_bitmap_lock);
return;
}
@@ -146,13 +150,18 @@ void drbd_bm_lock(struct drbd_device *device, char *why, enum bm_flag flags)
b->bm_why = why;
b->bm_task = current;
+ __acquire(drbd_bitmap_lock);
}
void drbd_bm_unlock(struct drbd_device *device)
+ __releases(&device->bitmap->bm_change)
{
struct drbd_bitmap *b = device->bitmap;
if (!b) {
drbd_err(device, "FIXME no bitmap in drbd_bm_unlock!?\n");
+ /* Fake __release() to keep the compiler happy. */
+ __release(&b->bm_change);
+ __release(drbd_bitmap_lock);
return;
}
@@ -163,6 +172,7 @@ void drbd_bm_unlock(struct drbd_device *device)
b->bm_why = NULL;
b->bm_task = NULL;
mutex_unlock(&b->bm_change);
+ __release(drbd_bitmap_lock);
}
/* we store some "meta" info about our pages in page->private */
@@ -987,7 +997,7 @@ static inline sector_t drbd_md_last_bitmap_sector(struct drbd_backing_dev *bdev)
}
}
-static void bm_page_io_async(struct drbd_bm_aio_ctx *ctx, int page_nr) __must_hold(local)
+static void bm_page_io_async(struct drbd_bm_aio_ctx *ctx, int page_nr)
{
struct drbd_device *device = ctx->device;
enum req_op op = ctx->flags & BM_AIO_READ ? REQ_OP_READ : REQ_OP_WRITE;
@@ -1060,7 +1070,7 @@ static void bm_page_io_async(struct drbd_bm_aio_ctx *ctx, int page_nr) __must_ho
/*
* bm_rw: read/write the whole bitmap from/to its on disk location.
*/
-static int bm_rw(struct drbd_device *device, const unsigned int flags, unsigned lazy_writeout_upper_idx) __must_hold(local)
+static int bm_rw(struct drbd_device *device, const unsigned int flags, unsigned lazy_writeout_upper_idx)
{
struct drbd_bm_aio_ctx *ctx;
struct drbd_bitmap *b = device->bitmap;
@@ -1215,7 +1225,7 @@ static int bm_rw(struct drbd_device *device, const unsigned int flags, unsigned
* @device: DRBD device.
*/
int drbd_bm_read(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local)
+ struct drbd_peer_device *peer_device)
{
return bm_rw(device, BM_AIO_READ, 0);
@@ -1228,7 +1238,7 @@ int drbd_bm_read(struct drbd_device *device,
* Will only write pages that have changed since last IO.
*/
int drbd_bm_write(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local)
+ struct drbd_peer_device *peer_device)
{
return bm_rw(device, 0, 0);
}
@@ -1240,7 +1250,7 @@ int drbd_bm_write(struct drbd_device *device,
* Will write all pages.
*/
int drbd_bm_write_all(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local)
+ struct drbd_peer_device *peer_device)
{
return bm_rw(device, BM_AIO_WRITE_ALL_PAGES, 0);
}
@@ -1250,7 +1260,7 @@ int drbd_bm_write_all(struct drbd_device *device,
* @device: DRBD device.
* @upper_idx: 0: write all changed pages; +ve: page index to stop scanning for changed pages
*/
-int drbd_bm_write_lazy(struct drbd_device *device, unsigned upper_idx) __must_hold(local)
+int drbd_bm_write_lazy(struct drbd_device *device, unsigned upper_idx)
{
return bm_rw(device, BM_AIO_COPY_PAGES, upper_idx);
}
@@ -1267,7 +1277,7 @@ int drbd_bm_write_lazy(struct drbd_device *device, unsigned upper_idx) __must_ho
* pending resync acks are still being processed.
*/
int drbd_bm_write_copy_pages(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local)
+ struct drbd_peer_device *peer_device)
{
return bm_rw(device, BM_AIO_COPY_PAGES, 0);
}
@@ -1276,7 +1286,7 @@ int drbd_bm_write_copy_pages(struct drbd_device *device,
* drbd_bm_write_hinted() - Write bitmap pages with "hint" marks, if they have changed.
* @device: DRBD device.
*/
-int drbd_bm_write_hinted(struct drbd_device *device) __must_hold(local)
+int drbd_bm_write_hinted(struct drbd_device *device)
{
return bm_rw(device, BM_AIO_WRITE_HINTED | BM_AIO_COPY_PAGES, 0);
}
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index f6d6276974ee..46546e6e9f6b 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -193,10 +193,14 @@ struct drbd_device_work {
#include "drbd_interval.h"
-extern int drbd_wait_misc(struct drbd_device *, struct drbd_interval *);
+/*
+ * Alias for &resources_mutex because &resources_mutex is not visible in this
+ * context.
+ */
+token_context_lock(all_drbd_resources);
-extern void lock_all_resources(void);
-extern void unlock_all_resources(void);
+extern void lock_all_resources(void) __acquires(all_drbd_resources);
+extern void unlock_all_resources(void) __releases(all_drbd_resources);
struct drbd_request {
struct drbd_work w;
@@ -1056,14 +1060,14 @@ extern void conn_md_sync(struct drbd_connection *connection);
extern void drbd_md_write(struct drbd_device *device, void *buffer);
extern void drbd_md_sync(struct drbd_device *device);
extern int drbd_md_read(struct drbd_device *device, struct drbd_backing_dev *bdev);
-extern void drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(local);
-extern void _drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(local);
-extern void drbd_uuid_new_current(struct drbd_device *device) __must_hold(local);
-extern void drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local);
-extern void drbd_uuid_move_history(struct drbd_device *device) __must_hold(local);
-extern void __drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(local);
-extern void drbd_md_set_flag(struct drbd_device *device, int flags) __must_hold(local);
-extern void drbd_md_clear_flag(struct drbd_device *device, int flags)__must_hold(local);
+extern void drbd_uuid_set(struct drbd_device *device, int idx, u64 val);
+extern void _drbd_uuid_set(struct drbd_device *device, int idx, u64 val);
+extern void drbd_uuid_new_current(struct drbd_device *device);
+extern void drbd_uuid_set_bm(struct drbd_device *device, u64 val);
+extern void drbd_uuid_move_history(struct drbd_device *device);
+extern void __drbd_uuid_set(struct drbd_device *device, int idx, u64 val);
+extern void drbd_md_set_flag(struct drbd_device *device, int flags);
+extern void drbd_md_clear_flag(struct drbd_device *device, int flags);
extern int drbd_md_test_flag(struct drbd_backing_dev *, int);
extern void drbd_md_mark_dirty(struct drbd_device *device);
extern void drbd_queue_bitmap_io(struct drbd_device *device,
@@ -1080,9 +1084,15 @@ extern int drbd_bitmap_io_from_worker(struct drbd_device *device,
char *why, enum bm_flag flags,
struct drbd_peer_device *peer_device);
extern int drbd_bmio_set_n_write(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local);
+ struct drbd_peer_device *peer_device);
extern int drbd_bmio_clear_n_write(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local);
+ struct drbd_peer_device *peer_device);
+extern enum drbd_state_rv
+_drbd_request_state_holding_state_mutex(struct drbd_device *device, union drbd_state,
+ union drbd_state, enum chg_state_flags)
+ __must_hold(&device->state_mutex);
+extern int drbd_wait_misc(struct drbd_device *device, struct drbd_interval *)
+ __must_hold(&device->resource->req_lock);
/* Meta data layout
*
@@ -1292,17 +1302,17 @@ extern void _drbd_bm_set_bits(struct drbd_device *device,
extern int drbd_bm_test_bit(struct drbd_device *device, unsigned long bitnr);
extern int drbd_bm_e_weight(struct drbd_device *device, unsigned long enr);
extern int drbd_bm_read(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local);
+ struct drbd_peer_device *peer_device);
extern void drbd_bm_mark_for_writeout(struct drbd_device *device, int page_nr);
extern int drbd_bm_write(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local);
-extern void drbd_bm_reset_al_hints(struct drbd_device *device) __must_hold(local);
-extern int drbd_bm_write_hinted(struct drbd_device *device) __must_hold(local);
-extern int drbd_bm_write_lazy(struct drbd_device *device, unsigned upper_idx) __must_hold(local);
+ struct drbd_peer_device *peer_device);
+extern void drbd_bm_reset_al_hints(struct drbd_device *device);
+extern int drbd_bm_write_hinted(struct drbd_device *device);
+extern int drbd_bm_write_lazy(struct drbd_device *device, unsigned upper_idx);
extern int drbd_bm_write_all(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local);
+ struct drbd_peer_device *peer_device);
extern int drbd_bm_write_copy_pages(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local);
+ struct drbd_peer_device *peer_device);
extern size_t drbd_bm_words(struct drbd_device *device);
extern unsigned long drbd_bm_bits(struct drbd_device *device);
extern sector_t drbd_bm_capacity(struct drbd_device *device);
@@ -1321,8 +1331,16 @@ extern void drbd_bm_merge_lel(struct drbd_device *device, size_t offset,
extern void drbd_bm_get_lel(struct drbd_device *device, size_t offset,
size_t number, unsigned long *buffer);
-extern void drbd_bm_lock(struct drbd_device *device, char *why, enum bm_flag flags);
-extern void drbd_bm_unlock(struct drbd_device *device);
+/*
+ * Alias for &device->bitmap->bm_change because not all type information for
+ * &device->bitmap->bm_change is available in this context.
+ */
+token_context_lock(drbd_bitmap_lock);
+
+extern void drbd_bm_lock(struct drbd_device *device, char *why, enum bm_flag flags)
+ __acquires(drbd_bitmap_lock);
+extern void drbd_bm_unlock(struct drbd_device *device)
+ __releases(drbd_bitmap_lock);
/* drbd_main.c */
extern struct kmem_cache *drbd_request_cache;
@@ -1389,7 +1407,8 @@ enum determine_dev_size {
DS_GREW_FROM_ZERO = 3,
};
extern enum determine_dev_size
-drbd_determine_dev_size(struct drbd_device *, enum dds_flags, struct resize_parms *) __must_hold(local);
+drbd_determine_dev_size(struct drbd_device *device, enum dds_flags,
+ struct resize_parms *);
extern void resync_after_online_grow(struct drbd_device *);
extern void drbd_reconsider_queue_parameters(struct drbd_device *device,
struct drbd_backing_dev *bdev, struct o_qlim *o);
@@ -1473,7 +1492,7 @@ extern int drbd_free_peer_reqs(struct drbd_device *, struct list_head *);
extern struct drbd_peer_request *drbd_alloc_peer_req(struct drbd_peer_device *, u64,
sector_t, unsigned int,
unsigned int,
- gfp_t) __must_hold(local);
+ gfp_t);
extern void drbd_free_peer_req(struct drbd_device *device, struct drbd_peer_request *req);
extern struct page *drbd_alloc_pages(struct drbd_peer_device *, unsigned int, bool);
extern void _drbd_clear_done_ee(struct drbd_device *device, struct list_head *to_be_freed);
@@ -1488,7 +1507,6 @@ void drbd_set_my_capacity(struct drbd_device *device, sector_t size);
static inline void drbd_submit_bio_noacct(struct drbd_device *device,
int fault_type, struct bio *bio)
{
- __release(local);
if (!bio->bi_bdev) {
drbd_err(device, "drbd_submit_bio_noacct: bio->bi_bdev == NULL\n");
bio->bi_status = BLK_STS_IOERR;
@@ -1839,14 +1857,18 @@ static inline void request_ping(struct drbd_connection *connection)
wake_ack_receiver(connection);
}
-extern void *conn_prepare_command(struct drbd_connection *, struct drbd_socket *);
-extern void *drbd_prepare_command(struct drbd_peer_device *, struct drbd_socket *);
-extern int conn_send_command(struct drbd_connection *, struct drbd_socket *,
+extern void *conn_prepare_command(struct drbd_connection *, struct drbd_socket *sock)
+ __cond_acquires(nonnull, sock->mutex);
+extern void *drbd_prepare_command(struct drbd_peer_device *, struct drbd_socket *sock)
+ __cond_acquires(nonnull, sock->mutex);
+extern int conn_send_command(struct drbd_connection *, struct drbd_socket *sock,
enum drbd_packet, unsigned int, void *,
- unsigned int);
-extern int drbd_send_command(struct drbd_peer_device *, struct drbd_socket *,
+ unsigned int)
+ __releases(sock->mutex);
+extern int drbd_send_command(struct drbd_peer_device *, struct drbd_socket *sock,
enum drbd_packet, unsigned int, void *,
- unsigned int);
+ unsigned int)
+ __releases(sock->mutex);
extern int drbd_send_ping(struct drbd_connection *connection);
extern int drbd_send_ping_ack(struct drbd_connection *connection);
@@ -1975,8 +1997,7 @@ static inline bool is_sync_state(enum drbd_conns connection_state)
* You have to call put_ldev() when finished working with device->ldev.
*/
#define get_ldev_if_state(_device, _min_state) \
- (_get_ldev_if_state((_device), (_min_state)) ? \
- ({ __acquire(x); true; }) : false)
+ (_get_ldev_if_state((_device), (_min_state)))
#define get_ldev(_device) get_ldev_if_state(_device, D_INCONSISTENT)
static inline void put_ldev(struct drbd_device *device)
@@ -1991,7 +2012,6 @@ static inline void put_ldev(struct drbd_device *device)
/* This may be called from some endio handler,
* so we must not sleep here. */
- __release(local);
D_ASSERT(device, i >= 0);
if (i == 0) {
if (disk_state == D_DISKLESS)
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 200d464e984b..0bbee2afb7e5 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -3282,7 +3282,7 @@ void drbd_md_mark_dirty(struct drbd_device *device)
mod_timer(&device->md_sync_timer, jiffies + 5*HZ);
}
-void drbd_uuid_move_history(struct drbd_device *device) __must_hold(local)
+void drbd_uuid_move_history(struct drbd_device *device)
{
int i;
@@ -3290,7 +3290,7 @@ void drbd_uuid_move_history(struct drbd_device *device) __must_hold(local)
device->ldev->md.uuid[i+1] = device->ldev->md.uuid[i];
}
-void __drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(local)
+void __drbd_uuid_set(struct drbd_device *device, int idx, u64 val)
{
if (idx == UI_CURRENT) {
if (device->state.role == R_PRIMARY)
@@ -3305,7 +3305,7 @@ void __drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(l
drbd_md_mark_dirty(device);
}
-void _drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(local)
+void _drbd_uuid_set(struct drbd_device *device, int idx, u64 val)
{
unsigned long flags;
spin_lock_irqsave(&device->ldev->md.uuid_lock, flags);
@@ -3313,7 +3313,7 @@ void _drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(lo
spin_unlock_irqrestore(&device->ldev->md.uuid_lock, flags);
}
-void drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(local)
+void drbd_uuid_set(struct drbd_device *device, int idx, u64 val)
{
unsigned long flags;
spin_lock_irqsave(&device->ldev->md.uuid_lock, flags);
@@ -3332,7 +3332,7 @@ void drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(loc
* Creates a new current UUID, and rotates the old current UUID into
* the bitmap slot. Causes an incremental resync upon next connect.
*/
-void drbd_uuid_new_current(struct drbd_device *device) __must_hold(local)
+void drbd_uuid_new_current(struct drbd_device *device)
{
u64 val;
unsigned long long bm_uuid;
@@ -3354,7 +3354,7 @@ void drbd_uuid_new_current(struct drbd_device *device) __must_hold(local)
drbd_md_sync(device);
}
-void drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local)
+void drbd_uuid_set_bm(struct drbd_device *device, u64 val)
{
unsigned long flags;
spin_lock_irqsave(&device->ldev->md.uuid_lock, flags);
@@ -3387,7 +3387,7 @@ void drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local)
* Sets all bits in the bitmap and writes the whole bitmap to stable storage.
*/
int drbd_bmio_set_n_write(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local)
+ struct drbd_peer_device *peer_device)
{
int rv = -EIO;
@@ -3414,7 +3414,7 @@ int drbd_bmio_set_n_write(struct drbd_device *device,
* Clears all bits in the bitmap and writes the whole bitmap to stable storage.
*/
int drbd_bmio_clear_n_write(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local)
+ struct drbd_peer_device *peer_device)
{
drbd_resume_al(device);
@@ -3541,7 +3541,7 @@ int drbd_bitmap_io(struct drbd_device *device,
return rv;
}
-void drbd_md_set_flag(struct drbd_device *device, int flag) __must_hold(local)
+void drbd_md_set_flag(struct drbd_device *device, int flag)
{
if ((device->ldev->md.flags & flag) != flag) {
drbd_md_mark_dirty(device);
@@ -3549,7 +3549,7 @@ void drbd_md_set_flag(struct drbd_device *device, int flag) __must_hold(local)
}
}
-void drbd_md_clear_flag(struct drbd_device *device, int flag) __must_hold(local)
+void drbd_md_clear_flag(struct drbd_device *device, int flag)
{
if ((device->ldev->md.flags & flag) != 0) {
drbd_md_mark_dirty(device);
@@ -3678,24 +3678,44 @@ int drbd_wait_misc(struct drbd_device *device, struct drbd_interval *i)
}
void lock_all_resources(void)
+ __acquires(all_drbd_resources)
+ __acquires(&resources_mutex)
{
struct drbd_resource *resource;
int __maybe_unused i = 0;
mutex_lock(&resources_mutex);
local_irq_disable();
+ /*
+ * context_unsafe() because the thread-safety analyzer does not support
+ * locking inside loops.
+ */
+ context_unsafe(
for_each_resource(resource, &drbd_resources)
spin_lock_nested(&resource->req_lock, i++);
+ );
+
+ __acquire(all_drbd_resources);
}
void unlock_all_resources(void)
+ __releases(all_drbd_resources)
+ __releases(&resources_mutex)
{
struct drbd_resource *resource;
+ /*
+ * context_unsafe() because the thread-safety analyzer does not support
+ * locking inside loops.
+ */
+ context_unsafe(
for_each_resource(resource, &drbd_resources)
spin_unlock(&resource->req_lock);
+ );
local_irq_enable();
mutex_unlock(&resources_mutex);
+
+ __release(all_drbd_resources);
}
#ifdef CONFIG_DRBD_FAULT_INJECTION
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 1f8ffdf9b24e..67dec3403edc 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -993,7 +993,7 @@ void drbd_resume_io(struct drbd_device *device)
* You should call drbd_md_sync() after calling this function.
*/
enum determine_dev_size
-drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct resize_parms *rs) __must_hold(local)
+drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct resize_parms *rs)
{
struct md_offsets_and_sizes {
u64 last_agreed_sect;
@@ -3090,7 +3090,7 @@ static int drbd_adm_simple_request_state(struct sk_buff *skb, struct genl_info *
}
static int drbd_bmio_set_susp_al(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local)
+ struct drbd_peer_device *peer_device)
{
int rv;
@@ -3518,6 +3518,7 @@ int drbd_adm_dump_connections_done(struct netlink_callback *cb)
enum { SINGLE_RESOURCE, ITERATE_RESOURCES };
int drbd_adm_dump_connections(struct sk_buff *skb, struct netlink_callback *cb)
+ __no_context_analysis /* too complex for Clang */
{
struct nlattr *resource_filter;
struct drbd_resource *resource = NULL, *next_resource;
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 58b95bf4bdca..b0ef6c5470f8 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -175,7 +175,7 @@ You must not have the req_lock:
* trim: payload_size == 0 */
struct drbd_peer_request *
drbd_alloc_peer_req(struct drbd_peer_device *peer_device, u64 id, sector_t sector,
- unsigned int request_size, unsigned int payload_size, gfp_t gfp_mask) __must_hold(local)
+ unsigned int request_size, unsigned int payload_size, gfp_t gfp_mask)
{
struct drbd_device *device = peer_device->device;
struct drbd_peer_request *peer_req;
@@ -287,6 +287,7 @@ static int drbd_finish_peer_reqs(struct drbd_device *device)
static void _drbd_wait_ee_list_empty(struct drbd_device *device,
struct list_head *head)
+ __must_hold(&device->resource->req_lock)
{
DEFINE_WAIT(wait);
@@ -896,6 +897,11 @@ static int conn_connect(struct drbd_connection *connection)
if (drbd_send_protocol(connection) == -EOPNOTSUPP)
return -1;
+ /*
+ * context_unsafe() because the thread-safety analyzer does not support
+ * locking inside loops.
+ */
+ context_unsafe(
/* Prevent a race between resync-handshake and
* being promoted to Primary.
*
@@ -905,14 +911,21 @@ static int conn_connect(struct drbd_connection *connection)
*/
idr_for_each_entry(&connection->peer_devices, peer_device, vnr)
mutex_lock(peer_device->device->state_mutex);
+ );
/* avoid a race with conn_request_state( C_DISCONNECTING ) */
spin_lock_irq(&connection->resource->req_lock);
set_bit(STATE_SENT, &connection->flags);
spin_unlock_irq(&connection->resource->req_lock);
+ /*
+ * context_unsafe() because the thread-safety analyzer does not support
+ * locking inside loops.
+ */
+ context_unsafe(
idr_for_each_entry(&connection->peer_devices, peer_device, vnr)
mutex_unlock(peer_device->device->state_mutex);
+ );
rcu_read_lock();
idr_for_each_entry(&connection->peer_devices, peer_device, vnr) {
@@ -1657,7 +1670,7 @@ static void drbd_csum_ee_size(struct crypto_shash *h,
*/
static struct drbd_peer_request *
read_in_block(struct drbd_peer_device *peer_device, u64 id, sector_t sector,
- struct packet_info *pi) __must_hold(local)
+ struct packet_info *pi)
{
struct drbd_device *device = peer_device->device;
const sector_t capacity = get_capacity(device->vdisk);
@@ -1869,7 +1882,7 @@ static int e_end_resync_block(struct drbd_work *w, int unused)
}
static int recv_resync_read(struct drbd_peer_device *peer_device, sector_t sector,
- struct packet_info *pi) __releases(local)
+ struct packet_info *pi)
{
struct drbd_device *device = peer_device->device;
struct drbd_peer_request *peer_req;
@@ -2230,6 +2243,7 @@ static blk_opf_t wire_flags_to_bio(struct drbd_connection *connection, u32 dpf)
static void fail_postponed_requests(struct drbd_device *device, sector_t sector,
unsigned int size)
+ __must_hold(&device->resource->req_lock)
{
struct drbd_peer_device *peer_device = first_peer_device(device);
struct drbd_interval *i;
@@ -2256,6 +2270,7 @@ static void fail_postponed_requests(struct drbd_device *device, sector_t sector,
static int handle_write_conflicts(struct drbd_device *device,
struct drbd_peer_request *peer_req)
+ __must_hold(&device->resource->req_lock)
{
struct drbd_connection *connection = peer_req->peer_device->connection;
bool resolve_conflicts = test_bit(RESOLVE_CONFLICTS, &connection->flags);
@@ -2826,7 +2841,7 @@ static int receive_DataRequest(struct drbd_connection *connection, struct packet
/*
* drbd_asb_recover_0p - Recover after split-brain with no remaining primaries
*/
-static int drbd_asb_recover_0p(struct drbd_peer_device *peer_device) __must_hold(local)
+static int drbd_asb_recover_0p(struct drbd_peer_device *peer_device)
{
struct drbd_device *device = peer_device->device;
int self, peer, rv = -100;
@@ -2909,7 +2924,7 @@ static int drbd_asb_recover_0p(struct drbd_peer_device *peer_device) __must_hold
/*
* drbd_asb_recover_1p - Recover after split-brain with one remaining primary
*/
-static int drbd_asb_recover_1p(struct drbd_peer_device *peer_device) __must_hold(local)
+static int drbd_asb_recover_1p(struct drbd_peer_device *peer_device)
{
struct drbd_device *device = peer_device->device;
int hg, rv = -100;
@@ -2966,7 +2981,7 @@ static int drbd_asb_recover_1p(struct drbd_peer_device *peer_device) __must_hold
/*
* drbd_asb_recover_2p - Recover after split-brain with two remaining primaries
*/
-static int drbd_asb_recover_2p(struct drbd_peer_device *peer_device) __must_hold(local)
+static int drbd_asb_recover_2p(struct drbd_peer_device *peer_device)
{
struct drbd_device *device = peer_device->device;
int hg, rv = -100;
@@ -3044,7 +3059,7 @@ static void drbd_uuid_dump(struct drbd_device *device, char *text, u64 *uuid,
*/
static int drbd_uuid_compare(struct drbd_peer_device *const peer_device,
- enum drbd_role const peer_role, int *rule_nr) __must_hold(local)
+ enum drbd_role const peer_role, int *rule_nr)
{
struct drbd_connection *const connection = peer_device->connection;
struct drbd_device *device = peer_device->device;
@@ -3264,7 +3279,7 @@ static int drbd_uuid_compare(struct drbd_peer_device *const peer_device,
*/
static enum drbd_conns drbd_sync_handshake(struct drbd_peer_device *peer_device,
enum drbd_role peer_role,
- enum drbd_disk_state peer_disk) __must_hold(local)
+ enum drbd_disk_state peer_disk)
{
struct drbd_device *device = peer_device->device;
enum drbd_conns rv = C_MASK;
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 70f75ef07945..a758d0f66e3f 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -952,6 +952,7 @@ static bool remote_due_to_read_balancing(struct drbd_device *device, sector_t se
* Only way out: remove the conflicting intervals from the tree.
*/
static void complete_conflicting_writes(struct drbd_request *req)
+ __must_hold(&req->device->resource->req_lock)
{
DEFINE_WAIT(wait);
struct drbd_device *device = req->device;
@@ -1325,6 +1326,8 @@ static void drbd_send_and_submit(struct drbd_device *device, struct drbd_request
bool submit_private_bio = false;
spin_lock_irq(&resource->req_lock);
+ /* Tell the compiler that &resource->req_lock == &req->device->resource->req_lock. */
+ __assume_ctx_lock(&req->device->resource->req_lock);
if (rw == WRITE) {
/* This may temporarily give up the req_lock,
* but will re-aquire it before it returns here.
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c
index adcba7f1d8ea..1c18d9f81e03 100644
--- a/drivers/block/drbd/drbd_state.c
+++ b/drivers/block/drbd/drbd_state.c
@@ -562,6 +562,7 @@ _req_st_cond(struct drbd_device *device, union drbd_state mask,
static enum drbd_state_rv
drbd_req_state(struct drbd_device *device, union drbd_state mask,
union drbd_state val, enum chg_state_flags f)
+ __no_context_analysis /* conditional locking */
{
struct completion done;
unsigned long flags;
@@ -2292,6 +2293,7 @@ _conn_rq_cond(struct drbd_connection *connection, union drbd_state mask, union d
enum drbd_state_rv
_conn_request_state(struct drbd_connection *connection, union drbd_state mask, union drbd_state val,
enum chg_state_flags flags)
+ __no_context_analysis /* conditional locking */
{
enum drbd_state_rv rv = SS_SUCCESS;
struct after_conn_state_chg_work *acscw;
diff --git a/drivers/block/drbd/drbd_state.h b/drivers/block/drbd/drbd_state.h
index cbaeb8018dbf..e6fded8b14ee 100644
--- a/drivers/block/drbd/drbd_state.h
+++ b/drivers/block/drbd/drbd_state.h
@@ -123,10 +123,6 @@ extern enum drbd_state_rv _drbd_request_state(struct drbd_device *,
union drbd_state,
enum chg_state_flags);
-extern enum drbd_state_rv
-_drbd_request_state_holding_state_mutex(struct drbd_device *, union drbd_state,
- union drbd_state, enum chg_state_flags);
-
extern enum drbd_state_rv _drbd_set_state(struct drbd_device *, union drbd_state,
enum chg_state_flags,
struct completion *done);
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 0697f99fed18..6fec59bbf0e9 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -78,7 +78,7 @@ void drbd_md_endio(struct bio *bio)
/* reads on behalf of the partner,
* "submitted" by the receiver
*/
-static void drbd_endio_read_sec_final(struct drbd_peer_request *peer_req) __releases(local)
+static void drbd_endio_read_sec_final(struct drbd_peer_request *peer_req)
{
unsigned long flags = 0;
struct drbd_peer_device *peer_device = peer_req->peer_device;
@@ -99,7 +99,7 @@ static void drbd_endio_read_sec_final(struct drbd_peer_request *peer_req) __rele
/* writes on behalf of the partner, or resync writes,
* "submitted" by the receiver, final stage. */
-void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req) __releases(local)
+void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req)
{
unsigned long flags = 0;
struct drbd_peer_device *peer_device = peer_req->peer_device;
@@ -1923,10 +1923,8 @@ static void drbd_ldev_destroy(struct drbd_device *device)
lc_destroy(device->act_log);
device->act_log = NULL;
- __acquire(local);
drbd_backing_dev_free(device, device->ldev);
device->ldev = NULL;
- __release(local);
clear_bit(GOING_DISKLESS, &device->flags);
wake_up(&device->misc_wait);
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH v2 16/26] drbd: Make the lock context annotations compatible with Clang
2026-03-25 21:44 ` [PATCH v2 16/26] drbd: Make the lock context annotations compatible with Clang Bart Van Assche
@ 2026-03-26 14:18 ` Christoph Hellwig
0 siblings, 0 replies; 51+ messages in thread
From: Christoph Hellwig @ 2026-03-26 14:18 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Tejun Heo, Christoph Böhmwalder, Philipp Reisner,
Lars Ellenberg, Nathan Chancellor
On Wed, Mar 25, 2026 at 02:44:57PM -0700, Bart Van Assche wrote:
> Clang performs more strict checking of lock context annotations than
> sparse. This patch makes the DRBD lock context annotations compatible
> with Clang and enables lock context analysis in the Makefile.
>
> Reviewed-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
> Signed-off-by: Bart Van Assche <bvanassche@acm.org>
> ---
> drivers/block/drbd/Makefile | 3 +
> drivers/block/drbd/drbd_bitmap.c | 26 ++++++---
> drivers/block/drbd/drbd_int.h | 88 ++++++++++++++++++------------
> drivers/block/drbd/drbd_main.c | 40 ++++++++++----
> drivers/block/drbd/drbd_nl.c | 5 +-
> drivers/block/drbd/drbd_receiver.c | 31 ++++++++---
> drivers/block/drbd/drbd_req.c | 3 +
> drivers/block/drbd/drbd_state.c | 2 +
> drivers/block/drbd/drbd_state.h | 4 --
> drivers/block/drbd/drbd_worker.c | 6 +-
> 10 files changed, 138 insertions(+), 70 deletions(-)
>
> diff --git a/drivers/block/drbd/Makefile b/drivers/block/drbd/Makefile
> index 67a8b352a1d5..8eaa83a7592b 100644
> --- a/drivers/block/drbd/Makefile
> +++ b/drivers/block/drbd/Makefile
> @@ -1,4 +1,7 @@
> # SPDX-License-Identifier: GPL-2.0-only
> +
> +CONTEXT_ANALYSIS := y
> +
> drbd-y := drbd_buildtag.o drbd_bitmap.o drbd_proc.o
> drbd-y += drbd_worker.o drbd_receiver.o drbd_req.o drbd_actlog.o
> drbd-y += drbd_main.o drbd_strings.o drbd_nl.o
> diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
> index 65ea6ec66bfd..3c521f0dc9ad 100644
> --- a/drivers/block/drbd/drbd_bitmap.c
> +++ b/drivers/block/drbd/drbd_bitmap.c
> @@ -122,12 +122,16 @@ static void __bm_print_lock_info(struct drbd_device *device, const char *func)
> }
>
> void drbd_bm_lock(struct drbd_device *device, char *why, enum bm_flag flags)
> + __acquires(&device->bitmap->bm_change)
> {
> struct drbd_bitmap *b = device->bitmap;
> int trylock_failed;
>
> if (!b) {
> drbd_err(device, "FIXME no bitmap in drbd_bm_lock!?\n");
> + /* Fake __acquire() to keep the compiler happy. */
> + __acquire(&b->bm_change);
> + __acquire(drbd_bitmap_lock);
> return;
This looks like an impossible to hit case with cargo cult code. I'd
suggest to remove it instead.
Similarly please kill the trylock_faiuled code, which has weird
debugging that is strictly inferior to what lockdep already provides.
> void drbd_bm_unlock(struct drbd_device *device)
> + __releases(&device->bitmap->bm_change)
> {
> struct drbd_bitmap *b = device->bitmap;
> if (!b) {
> drbd_err(device, "FIXME no bitmap in drbd_bm_unlock!?\n");
> + /* Fake __release() to keep the compiler happy. */
> + __release(&b->bm_change);
> + __release(drbd_bitmap_lock);
> return;
> }
Same comment as above.
> +extern void drbd_uuid_set(struct drbd_device *device, int idx, u64 val);
> +extern void _drbd_uuid_set(struct drbd_device *device, int idx, u64 val);
> +extern void drbd_uuid_new_current(struct drbd_device *device);
> +extern void drbd_uuid_set_bm(struct drbd_device *device, u64 val);
> +extern void drbd_uuid_move_history(struct drbd_device *device);
> +extern void __drbd_uuid_set(struct drbd_device *device, int idx, u64 val);
> +extern void drbd_md_set_flag(struct drbd_device *device, int flags);
> +extern void drbd_md_clear_flag(struct drbd_device *device, int flags);
All these externs should go away.
In general this still mixes up way too many things. Address one
lock/issue at a time, and write proper commit logs explain why a
given solution is taken.
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH v2 17/26] loop: Add lock context annotations
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (15 preceding siblings ...)
2026-03-25 21:44 ` [PATCH v2 16/26] drbd: Make the lock context annotations compatible with Clang Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-26 14:18 ` Christoph Hellwig
2026-03-25 21:44 ` [PATCH v2 18/26] mtip32: Enable lock context analysis Bart Van Assche
` (9 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Nathan Chancellor
Add lock context annotations that are compatible with Clang and enable
lock context analysis.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/loop.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 0000913f7efc..9c7ed9e8a442 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -107,6 +107,8 @@ static DEFINE_MUTEX(loop_validate_mutex);
* loop_configure()/loop_change_fd()/__loop_clr_fd() calls.
*/
static int loop_global_lock_killable(struct loop_device *lo, bool global)
+ __cond_acquires(0, &lo->lo_mutex)
+ __no_context_analysis /* conditional locking */
{
int err;
@@ -128,6 +130,8 @@ static int loop_global_lock_killable(struct loop_device *lo, bool global)
* @global: true if @lo was about to bind another "struct loop_device", false otherwise
*/
static void loop_global_unlock(struct loop_device *lo, bool global)
+ __releases(&lo->lo_mutex)
+ __no_context_analysis /* conditional locking */
{
mutex_unlock(&lo->lo_mutex);
if (global)
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH v2 17/26] loop: Add lock context annotations
2026-03-25 21:44 ` [PATCH v2 17/26] loop: Add lock context annotations Bart Van Assche
@ 2026-03-26 14:18 ` Christoph Hellwig
0 siblings, 0 replies; 51+ messages in thread
From: Christoph Hellwig @ 2026-03-26 14:18 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Tejun Heo, Nathan Chancellor
On Wed, Mar 25, 2026 at 02:44:58PM -0700, Bart Van Assche wrote:
> Add lock context annotations that are compatible with Clang and enable
> lock context analysis.
>
> Signed-off-by: Bart Van Assche <bvanassche@acm.org>
> ---
> drivers/block/loop.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/drivers/block/loop.c b/drivers/block/loop.c
> index 0000913f7efc..9c7ed9e8a442 100644
> --- a/drivers/block/loop.c
> +++ b/drivers/block/loop.c
> @@ -107,6 +107,8 @@ static DEFINE_MUTEX(loop_validate_mutex);
> * loop_configure()/loop_change_fd()/__loop_clr_fd() calls.
> */
> static int loop_global_lock_killable(struct loop_device *lo, bool global)
> + __cond_acquires(0, &lo->lo_mutex)
> + __no_context_analysis /* conditional locking */
There's not explanation here why this is needed.
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH v2 18/26] mtip32: Enable lock context analysis
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (16 preceding siblings ...)
2026-03-25 21:44 ` [PATCH v2 17/26] loop: Add lock context annotations Bart Van Assche
@ 2026-03-25 21:44 ` Bart Van Assche
2026-03-26 14:18 ` Christoph Hellwig
2026-03-25 21:45 ` [PATCH v2 19/26] nbd: " Bart Van Assche
` (8 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:44 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche
Let the compiler verify lock and unlock calls. Enable lock context analysis
in the Makefile.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/mtip32xx/Makefile | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/block/mtip32xx/Makefile b/drivers/block/mtip32xx/Makefile
index bff32b5d3c19..233961fdb41b 100644
--- a/drivers/block/mtip32xx/Makefile
+++ b/drivers/block/mtip32xx/Makefile
@@ -3,4 +3,6 @@
# Makefile for Block device driver for Micron PCIe SSD
#
+CONTEXT_ANALYSIS := y
+
obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX) += mtip32xx.o
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH v2 19/26] nbd: Enable lock context analysis
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (17 preceding siblings ...)
2026-03-25 21:44 ` [PATCH v2 18/26] mtip32: Enable lock context analysis Bart Van Assche
@ 2026-03-25 21:45 ` Bart Van Assche
2026-03-26 14:18 ` Christoph Hellwig
2026-03-25 21:45 ` [PATCH v2 20/26] null_blk: " Bart Van Assche
` (7 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:45 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Josef Bacik
Add the missing __must_hold() annotations. Enable lock context analysis in
the Makefile.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/nbd.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index fe63f3c55d0d..28bb89bc7de3 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -1469,6 +1469,7 @@ static void nbd_config_put(struct nbd_device *nbd)
}
static int nbd_start_device(struct nbd_device *nbd)
+ __must_hold(&nbd->config_lock)
{
struct nbd_config *config = nbd->config;
int num_connections = config->num_connections;
@@ -1541,6 +1542,7 @@ static int nbd_start_device(struct nbd_device *nbd)
}
static int nbd_start_device_ioctl(struct nbd_device *nbd)
+ __must_hold(nbd->config_lock)
{
struct nbd_config *config = nbd->config;
int ret;
@@ -1592,6 +1594,7 @@ static void nbd_set_cmd_timeout(struct nbd_device *nbd, u64 timeout)
/* Must be called with config_lock held */
static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
unsigned int cmd, unsigned long arg)
+ __must_hold(nbd->config_lock)
{
struct nbd_config *config = nbd->config;
loff_t bytesize;
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH v2 20/26] null_blk: Enable lock context analysis
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (18 preceding siblings ...)
2026-03-25 21:45 ` [PATCH v2 19/26] nbd: " Bart Van Assche
@ 2026-03-25 21:45 ` Bart Van Assche
2026-03-26 14:19 ` Christoph Hellwig
2026-03-25 21:45 ` [PATCH v2 21/26] rbd: " Bart Van Assche
` (6 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:45 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Keith Busch, Chaitanya Kulkarni,
Johannes Thumshirn, Kees Cook, Genjian Zhang, Nilay Shroff
Convert __releases() __acquires() into __must_hold(). Add __must_hold()
annotations where these are missing. Annotate two functions that use
conditional locking with __no_context_analysis. Enable lock context
analysis in the Makefile.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/null_blk/Makefile | 2 ++
drivers/block/null_blk/main.c | 7 +++++--
drivers/block/null_blk/zoned.c | 2 ++
3 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/block/null_blk/Makefile b/drivers/block/null_blk/Makefile
index 84c36e512ab8..282b0d51a477 100644
--- a/drivers/block/null_blk/Makefile
+++ b/drivers/block/null_blk/Makefile
@@ -1,5 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
+CONTEXT_ANALYSIS := y
+
# needed for trace events
ccflags-y += -I$(src)
diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c
index f8c0fd57e041..677ac829ef80 100644
--- a/drivers/block/null_blk/main.c
+++ b/drivers/block/null_blk/main.c
@@ -1004,8 +1004,7 @@ static struct nullb_page *null_lookup_page(struct nullb *nullb,
static struct nullb_page *null_insert_page(struct nullb *nullb,
sector_t sector, bool ignore_cache)
- __releases(&nullb->lock)
- __acquires(&nullb->lock)
+ __must_hold(&nullb->lock)
{
u64 idx;
struct nullb_page *t_page;
@@ -1038,6 +1037,7 @@ static struct nullb_page *null_insert_page(struct nullb *nullb,
}
static int null_flush_cache_page(struct nullb *nullb, struct nullb_page *c_page)
+ __must_hold(&nullb->lock)
{
int i;
unsigned int offset;
@@ -1087,6 +1087,7 @@ static int null_flush_cache_page(struct nullb *nullb, struct nullb_page *c_page)
}
static int null_make_cache_space(struct nullb *nullb, unsigned long n)
+ __must_hold(&nullb->lock)
{
int i, err, nr_pages;
struct nullb_page *c_pages[FREE_BATCH];
@@ -1141,6 +1142,7 @@ static int null_make_cache_space(struct nullb *nullb, unsigned long n)
static blk_status_t copy_to_nullb(struct nullb *nullb, void *source,
loff_t pos, size_t n, bool is_fua)
+ __must_hold(&nullb->lock)
{
size_t temp, count = 0;
struct nullb_page *t_page;
@@ -1242,6 +1244,7 @@ static blk_status_t null_handle_flush(struct nullb *nullb)
static blk_status_t null_transfer(struct nullb *nullb, struct page *page,
unsigned int len, unsigned int off, bool is_write, loff_t pos,
bool is_fua)
+ __must_hold(&nullb->lock)
{
struct nullb_device *dev = nullb->dev;
blk_status_t err = BLK_STS_OK;
diff --git a/drivers/block/null_blk/zoned.c b/drivers/block/null_blk/zoned.c
index 384bdce6a9b7..a7f94e76034f 100644
--- a/drivers/block/null_blk/zoned.c
+++ b/drivers/block/null_blk/zoned.c
@@ -32,6 +32,7 @@ static inline void null_init_zone_lock(struct nullb_device *dev,
static inline void null_lock_zone(struct nullb_device *dev,
struct nullb_zone *zone)
+ __no_context_analysis /* conditional locking */
{
if (!dev->memory_backed)
spin_lock_irq(&zone->spinlock);
@@ -41,6 +42,7 @@ static inline void null_lock_zone(struct nullb_device *dev,
static inline void null_unlock_zone(struct nullb_device *dev,
struct nullb_zone *zone)
+ __no_context_analysis /* conditional locking */
{
if (!dev->memory_backed)
spin_unlock_irq(&zone->spinlock);
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH v2 20/26] null_blk: Enable lock context analysis
2026-03-25 21:45 ` [PATCH v2 20/26] null_blk: " Bart Van Assche
@ 2026-03-26 14:19 ` Christoph Hellwig
0 siblings, 0 replies; 51+ messages in thread
From: Christoph Hellwig @ 2026-03-26 14:19 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Tejun Heo, Keith Busch, Chaitanya Kulkarni, Johannes Thumshirn,
Kees Cook, Genjian Zhang, Nilay Shroff
On Wed, Mar 25, 2026 at 02:45:01PM -0700, Bart Van Assche wrote:
> Convert __releases() __acquires() into __must_hold(). Add __must_hold()
> annotations where these are missing. Annotate two functions that use
> conditional locking with __no_context_analysis. Enable lock context
> analysis in the Makefile.
Not a very good explanation why this is needed and there's not better
way to avoid the big hammer.
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH v2 21/26] rbd: Enable lock context analysis
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (19 preceding siblings ...)
2026-03-25 21:45 ` [PATCH v2 20/26] null_blk: " Bart Van Assche
@ 2026-03-25 21:45 ` Bart Van Assche
2026-03-25 21:45 ` [PATCH v2 22/26] ublk: " Bart Van Assche
` (5 subsequent siblings)
26 siblings, 0 replies; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:45 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Ilya Dryomov
Add lock context annotations and enable lock context analysis.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/rbd.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index e7da06200c1e..31fe81b82548 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -4185,6 +4185,7 @@ static void rbd_acquire_lock(struct work_struct *work)
}
static bool rbd_quiesce_lock(struct rbd_device *rbd_dev)
+ __must_hold(&rbd_dev->lock_rwsem)
{
dout("%s rbd_dev %p\n", __func__, rbd_dev);
lockdep_assert_held_write(&rbd_dev->lock_rwsem);
@@ -4229,6 +4230,7 @@ static void __rbd_release_lock(struct rbd_device *rbd_dev)
* lock_rwsem must be held for write
*/
static void rbd_release_lock(struct rbd_device *rbd_dev)
+ __must_hold(&rbd_dev->lock_rwsem)
{
if (!rbd_quiesce_lock(rbd_dev))
return;
@@ -4597,6 +4599,7 @@ static void rbd_unregister_watch(struct rbd_device *rbd_dev)
* lock_rwsem must be held for write
*/
static void rbd_reacquire_lock(struct rbd_device *rbd_dev)
+ __must_hold(&rbd_dev->lock_rwsem)
{
struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
char cookie[32];
@@ -6789,6 +6792,7 @@ static void rbd_dev_device_release(struct rbd_device *rbd_dev)
* upon return.
*/
static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
+ __releases(&rbd_dev->header_rwsem)
{
int ret;
@@ -6890,6 +6894,7 @@ static void rbd_dev_image_release(struct rbd_device *rbd_dev)
* with @depth == 0.
*/
static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
+ __no_context_analysis /* conditional locking */
{
bool need_watch = !rbd_is_ro(rbd_dev);
int ret;
@@ -7143,6 +7148,9 @@ static ssize_t do_rbd_add(const char *buf, size_t count)
if (rc < 0)
goto err_out_rbd_dev;
+ /* Acquired by rbd_dev_image_probe(rbd_dev, 0) */
+ __acquire(&rbd_dev->header_rwsem);
+
if (rbd_dev->opts->alloc_size > rbd_dev->layout.object_size) {
rbd_warn(rbd_dev, "alloc_size adjusted to %u",
rbd_dev->layout.object_size);
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH v2 22/26] ublk: Enable lock context analysis
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (20 preceding siblings ...)
2026-03-25 21:45 ` [PATCH v2 21/26] rbd: " Bart Van Assche
@ 2026-03-25 21:45 ` Bart Van Assche
2026-03-25 21:45 ` [PATCH v2 23/26] xen-blkback: " Bart Van Assche
` (4 subsequent siblings)
26 siblings, 0 replies; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:45 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Ming Lei, Nathan Chancellor
Add the lock context annotations that are required by Clang and enable
lock context analysis.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/ublk_drv.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 3ba7da94d314..14b59e13b16f 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -353,11 +353,13 @@ static inline bool ublk_support_batch_io(const struct ublk_queue *ubq)
}
static inline void ublk_io_lock(struct ublk_io *io)
+ __acquires(&io->lock)
{
spin_lock(&io->lock);
}
static inline void ublk_io_unlock(struct ublk_io *io)
+ __releases(&io->lock)
{
spin_unlock(&io->lock);
}
@@ -3166,6 +3168,7 @@ static int ublk_check_fetch_buf(const struct ublk_device *ub, __u64 buf_addr)
static int __ublk_fetch(struct io_uring_cmd *cmd, struct ublk_device *ub,
struct ublk_io *io, u16 q_id)
+ __must_hold(&ub->mutex)
{
/* UBLK_IO_FETCH_REQ is only allowed before dev is setup */
if (ublk_dev_ready(ub))
@@ -3587,6 +3590,7 @@ static void ublk_batch_revert_prep_cmd(struct ublk_batch_io_iter *iter,
static int ublk_batch_prep_io(struct ublk_queue *ubq,
const struct ublk_batch_io_data *data,
const struct ublk_elem_header *elem)
+ __must_hold(&data->ub->mutex)
{
struct ublk_io *io = &ubq->ios[elem->tag];
const struct ublk_batch_io *uc = &data->header;
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH v2 23/26] xen-blkback: Enable lock context analysis
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (21 preceding siblings ...)
2026-03-25 21:45 ` [PATCH v2 22/26] ublk: " Bart Van Assche
@ 2026-03-25 21:45 ` Bart Van Assche
2026-03-26 9:25 ` Roger Pau Monné
2026-03-25 21:45 ` [PATCH v2 24/26] zram: " Bart Van Assche
` (3 subsequent siblings)
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:45 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Roger Pau Monné, Nathan Chancellor
Let Clang verify lock and unlock calls. Enable lock context analysis in the
Makefile.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/xen-blkback/Makefile | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/block/xen-blkback/Makefile b/drivers/block/xen-blkback/Makefile
index b0ea5ab5b9a1..864ef423226c 100644
--- a/drivers/block/xen-blkback/Makefile
+++ b/drivers/block/xen-blkback/Makefile
@@ -1,4 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
+
+CONTEXT_ANALYSIS := y
+
obj-$(CONFIG_XEN_BLKDEV_BACKEND) := xen-blkback.o
xen-blkback-y := blkback.o xenbus.o
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH v2 23/26] xen-blkback: Enable lock context analysis
2026-03-25 21:45 ` [PATCH v2 23/26] xen-blkback: " Bart Van Assche
@ 2026-03-26 9:25 ` Roger Pau Monné
0 siblings, 0 replies; 51+ messages in thread
From: Roger Pau Monné @ 2026-03-26 9:25 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Tejun Heo, Nathan Chancellor
On Wed, Mar 25, 2026 at 02:45:04PM -0700, Bart Van Assche wrote:
> Let Clang verify lock and unlock calls. Enable lock context analysis in the
> Makefile.
>
> Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Acked-by: Roger Pau Monné <roger.pau@citrix.com>
Thanks, Roger.
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH v2 24/26] zram: Enable lock context analysis
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (22 preceding siblings ...)
2026-03-25 21:45 ` [PATCH v2 23/26] xen-blkback: " Bart Van Assche
@ 2026-03-25 21:45 ` Bart Van Assche
2026-03-25 21:45 ` [PATCH v2 25/26] rnbd: " Bart Van Assche
` (2 subsequent siblings)
26 siblings, 0 replies; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:45 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Sergey Senozhatsky, Minchan Kim,
Nathan Chancellor
Add the lock context annotations that are required by Clang. Enable lock
context analysis in the Makefile.
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/zram/Makefile | 2 ++
drivers/block/zram/zcomp.c | 3 ++-
drivers/block/zram/zcomp.h | 6 ++++--
drivers/block/zram/zram_drv.c | 1 +
4 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/block/zram/Makefile b/drivers/block/zram/Makefile
index 0fdefd576691..a5663ab01653 100644
--- a/drivers/block/zram/Makefile
+++ b/drivers/block/zram/Makefile
@@ -1,5 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
+CONTEXT_ANALYSIS := y
+
zram-y := zcomp.o zram_drv.o
zram-$(CONFIG_ZRAM_BACKEND_LZO) += backend_lzorle.o backend_lzo.o
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index a771a8ecc540..5f431596f3b5 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -107,7 +107,8 @@ ssize_t zcomp_available_show(const char *comp, char *buf, ssize_t at)
return at;
}
-struct zcomp_strm *zcomp_stream_get(struct zcomp *comp)
+struct zcomp_strm *__zcomp_stream_get(struct zcomp *comp)
+ __no_context_analysis /* __acquires(&raw_cpu_ptr(comp->stream)->lock) */
{
for (;;) {
struct zcomp_strm *zstrm = raw_cpu_ptr(comp->stream);
diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h
index eacfd3f7d61d..4814087e8ac9 100644
--- a/drivers/block/zram/zcomp.h
+++ b/drivers/block/zram/zcomp.h
@@ -85,8 +85,10 @@ bool zcomp_available_algorithm(const char *comp);
struct zcomp *zcomp_create(const char *alg, struct zcomp_params *params);
void zcomp_destroy(struct zcomp *comp);
-struct zcomp_strm *zcomp_stream_get(struct zcomp *comp);
-void zcomp_stream_put(struct zcomp_strm *zstrm);
+#define zcomp_stream_get(...) __acquire_ret(__zcomp_stream_get(__VA_ARGS__), &__ret->lock)
+struct zcomp_strm *__zcomp_stream_get(struct zcomp *comp);
+void zcomp_stream_put(struct zcomp_strm *zstrm)
+ __releases(&zstrm->lock);
int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
const void *src, unsigned int *dst_len);
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index a324ede6206d..e0f716d80369 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -2395,6 +2395,7 @@ static int scan_slots_for_recompress(struct zram *zram, u32 mode, u32 prio_max,
static int recompress_slot(struct zram *zram, u32 index, struct page *page,
u64 *num_recomp_pages, u32 threshold, u32 prio,
u32 prio_max)
+ __no_context_analysis /* too complex for Clang */
{
struct zcomp_strm *zstrm = NULL;
unsigned long handle_old;
^ permalink raw reply related [flat|nested] 51+ messages in thread* [PATCH v2 25/26] rnbd: Enable lock context analysis
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (23 preceding siblings ...)
2026-03-25 21:45 ` [PATCH v2 24/26] zram: " Bart Van Assche
@ 2026-03-25 21:45 ` Bart Van Assche
2026-03-26 6:58 ` Jinpu Wang
2026-03-25 21:45 ` [PATCH v2 26/26] block: Enable lock context analysis for all block drivers Bart Van Assche
2026-03-26 6:23 ` [PATCH v2 00/26] Enable lock context analysis Christoph Hellwig
26 siblings, 1 reply; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:45 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche, Md. Haris Iqbal, Jack Wang, Nathan Chancellor
Let Clang verify lock and unlock calls. Enable lock context analysis in the
Makefile.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/rnbd/Makefile | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/block/rnbd/Makefile b/drivers/block/rnbd/Makefile
index 208e5f865497..42c2cccdb53d 100644
--- a/drivers/block/rnbd/Makefile
+++ b/drivers/block/rnbd/Makefile
@@ -1,5 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
+CONTEXT_ANALYSIS := y
+
ccflags-y := -I$(srctree)/drivers/infiniband/ulp/rtrs
rnbd-client-y := rnbd-clt.o \
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH v2 25/26] rnbd: Enable lock context analysis
2026-03-25 21:45 ` [PATCH v2 25/26] rnbd: " Bart Van Assche
@ 2026-03-26 6:58 ` Jinpu Wang
0 siblings, 0 replies; 51+ messages in thread
From: Jinpu Wang @ 2026-03-26 6:58 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Tejun Heo, Md. Haris Iqbal, Nathan Chancellor
On Wed, Mar 25, 2026 at 10:46 PM Bart Van Assche <bvanassche@acm.org> wrote:
>
> Let Clang verify lock and unlock calls. Enable lock context analysis in the
> Makefile.
>
> Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Acked-by: Jack Wang <jinpu.wang@ionos.com>
>
> ---
> drivers/block/rnbd/Makefile | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/block/rnbd/Makefile b/drivers/block/rnbd/Makefile
> index 208e5f865497..42c2cccdb53d 100644
> --- a/drivers/block/rnbd/Makefile
> +++ b/drivers/block/rnbd/Makefile
> @@ -1,5 +1,7 @@
> # SPDX-License-Identifier: GPL-2.0-or-later
>
> +CONTEXT_ANALYSIS := y
> +
> ccflags-y := -I$(srctree)/drivers/infiniband/ulp/rtrs
>
> rnbd-client-y := rnbd-clt.o \
^ permalink raw reply [flat|nested] 51+ messages in thread
* [PATCH v2 26/26] block: Enable lock context analysis for all block drivers
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (24 preceding siblings ...)
2026-03-25 21:45 ` [PATCH v2 25/26] rnbd: " Bart Van Assche
@ 2026-03-25 21:45 ` Bart Van Assche
2026-03-26 6:23 ` [PATCH v2 00/26] Enable lock context analysis Christoph Hellwig
26 siblings, 0 replies; 51+ messages in thread
From: Bart Van Assche @ 2026-03-25 21:45 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Tejun Heo,
Bart Van Assche
Now that all locking functions in block drivers have been annotated,
enable lock context analysis for all block drivers at the top level of
drivers/block/.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/Makefile | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 2d8096eb8cdf..e17f6381b798 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -6,6 +6,8 @@
# Rewritten to use lists instead of if-statements.
#
+CONTEXT_ANALYSIS := y
+
# needed for trace events
ccflags-y += -I$(src)
^ permalink raw reply related [flat|nested] 51+ messages in thread* Re: [PATCH v2 00/26] Enable lock context analysis
2026-03-25 21:44 [PATCH v2 00/26] Enable lock context analysis Bart Van Assche
` (25 preceding siblings ...)
2026-03-25 21:45 ` [PATCH v2 26/26] block: Enable lock context analysis for all block drivers Bart Van Assche
@ 2026-03-26 6:23 ` Christoph Hellwig
26 siblings, 0 replies; 51+ messages in thread
From: Christoph Hellwig @ 2026-03-26 6:23 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Tejun Heo
Hi Bart,
this is a huge series for very different things. I'd suggest you
submit the core block annotations first, and after that you can handle
drivers indepdently, whіch reduces review load and the amount of spamming
of the list for repeated resends. It should also help you to iterate
faster.
^ permalink raw reply [flat|nested] 51+ messages in thread