* [PATCH v2 00/12] Enable lock context analysis
@ 2026-03-16 20:08 Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 01/12] drbd: Balance RCU calls in drbd_adm_dump_devices() Bart Van Assche
` (12 more replies)
0 siblings, 13 replies; 22+ messages in thread
From: Bart Van Assche @ 2026-03-16 20:08 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Bart Van Assche
Hi Jens,
During the most recent merge window the following patch series has been merged:
[PATCH v5 00/36] Compiler-Based Context- and Locking-Analysis
(https://lore.kernel.org/lkml/20251219154418.3592607-1-elver@google.com/). That
patch series drops support for verifying lock context annotations with sparse
and introduces support for verifying lock context annotations with Clang. The
support in Clang for lock context annotation and verification is better than
that in sparse. As an example, __cond_acquires() and __guarded_by() are
supported by Clang but not by sparse. Hence this patch series that enables lock
context analysis for the block layer core and all block drivers.
The first patch in this series fixes a bug discovered in DRBD while enabling
lock context analysis.
Please consider this patch series for the upstream kernel.
Thanks,
Bart.
Changes compared to v1:
- Dropped the blk-ioc and rnbd patches.
- Fixed the DRBD and ublk patches.
Bart Van Assche (12):
drbd: Balance RCU calls in drbd_adm_dump_devices()
block: Make the lock context annotations compatible with Clang
aoe: Add a lock context annotation
drbd: Make the lock context annotations compatible with Clang
loop: Add lock context annotations
nbd: Add lock context annotations
null_blk: Add more lock context annotations
rbd: Add lock context annotations
ublk: Fix the lock context annotations
zloop: Add a lock context annotations
zram: Add lock context annotations
block: Enable lock context analysis for all block drivers
block/Makefile | 2 +
block/bdev.c | 8 ++-
block/blk-cgroup.c | 7 ++-
block/blk-crypto-profile.c | 2 +
block/blk-iocost.c | 2 +
block/blk-mq-debugfs.c | 12 ++--
block/blk-zoned.c | 1 +
block/blk.h | 4 ++
block/ioctl.c | 1 +
block/kyber-iosched.c | 4 +-
block/mq-deadline.c | 8 +--
drivers/block/Makefile | 2 +
drivers/block/aoe/Makefile | 2 +
drivers/block/aoe/aoecmd.c | 1 +
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 | 13 +++--
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 +-
drivers/block/loop.c | 4 ++
drivers/block/mtip32xx/Makefile | 2 +
drivers/block/nbd.c | 3 +
drivers/block/null_blk/Makefile | 2 +
drivers/block/null_blk/main.c | 7 ++-
drivers/block/null_blk/zoned.c | 2 +
drivers/block/rbd.c | 7 +++
drivers/block/rnbd/Makefile | 2 +
drivers/block/ublk_drv.c | 4 ++
drivers/block/xen-blkback/Makefile | 3 +
drivers/block/zloop.c | 1 +
drivers/block/zram/Makefile | 2 +
drivers/block/zram/zcomp.c | 3 +-
drivers/block/zram/zcomp.h | 6 +-
drivers/block/zram/zram_drv.c | 1 +
include/linux/backing-dev.h | 2 +
include/linux/blkdev.h | 9 ++-
include/linux/bpf.h | 1 +
42 files changed, 236 insertions(+), 97 deletions(-)
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v2 01/12] drbd: Balance RCU calls in drbd_adm_dump_devices()
2026-03-16 20:08 [PATCH v2 00/12] Enable lock context analysis Bart Van Assche
@ 2026-03-16 20:08 ` Bart Van Assche
2026-03-16 20:08 ` [PATCH v2] powerpc/powermac: Remove pmac_low_i2c_{lock,unlock}() Bart Van Assche
` (11 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Bart Van Assche @ 2026-03-16 20:08 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, 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. Compile-tested only.
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 e201f0087a0f..728ecc431b38 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -3378,8 +3378,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;
}
}
@@ -3628,8 +3630,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] 22+ messages in thread
* [PATCH v2] powerpc/powermac: Remove pmac_low_i2c_{lock,unlock}()
2026-03-16 20:08 [PATCH v2 00/12] Enable lock context analysis Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 01/12] drbd: Balance RCU calls in drbd_adm_dump_devices() Bart Van Assche
@ 2026-03-16 20:08 ` Bart Van Assche
2026-03-16 20:12 ` Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 02/12] block: Make the lock context annotations compatible with Clang Bart Van Assche
` (10 subsequent siblings)
12 siblings, 1 reply; 22+ messages in thread
From: Bart Van Assche @ 2026-03-16 20:08 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Bart Van Assche,
Christophe Leroy (CS GROUP), Madhavan Srinivasan,
Michael Ellerman, Thomas Gleixner, Ingo Molnar, Kees Cook
Commit a28d3af2a26c ("[PATCH] 2/5 powerpc: Rework PowerMac i2c part 2")
removed the last calls to the pmac_low_i2c_{lock,unlock}() functions.
Hence, remove these two functions.
Reviewed-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
Changes compared to v1: corrected the description of the history of the removed
functions and added Christophe's Reviewed-by tag.
arch/powerpc/include/asm/pmac_low_i2c.h | 4 ---
arch/powerpc/platforms/powermac/low_i2c.c | 34 -----------------------
2 files changed, 38 deletions(-)
diff --git a/arch/powerpc/include/asm/pmac_low_i2c.h b/arch/powerpc/include/asm/pmac_low_i2c.h
index 21bd7297c87f..fead8fae08ab 100644
--- a/arch/powerpc/include/asm/pmac_low_i2c.h
+++ b/arch/powerpc/include/asm/pmac_low_i2c.h
@@ -79,10 +79,6 @@ extern int pmac_i2c_match_adapter(struct device_node *dev,
struct i2c_adapter *adapter);
-/* (legacy) Locking functions exposed to i2c-keywest */
-extern int pmac_low_i2c_lock(struct device_node *np);
-extern int pmac_low_i2c_unlock(struct device_node *np);
-
/* Access functions for platform code */
extern int pmac_i2c_open(struct pmac_i2c_bus *bus, int polled);
extern void pmac_i2c_close(struct pmac_i2c_bus *bus);
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 73b7f4e8c047..da72a30ab865 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -1058,40 +1058,6 @@ int pmac_i2c_match_adapter(struct device_node *dev, struct i2c_adapter *adapter)
}
EXPORT_SYMBOL_GPL(pmac_i2c_match_adapter);
-int pmac_low_i2c_lock(struct device_node *np)
-{
- struct pmac_i2c_bus *bus, *found = NULL;
-
- list_for_each_entry(bus, &pmac_i2c_busses, link) {
- if (np == bus->controller) {
- found = bus;
- break;
- }
- }
- if (!found)
- return -ENODEV;
- return pmac_i2c_open(bus, 0);
-}
-EXPORT_SYMBOL_GPL(pmac_low_i2c_lock);
-
-int pmac_low_i2c_unlock(struct device_node *np)
-{
- struct pmac_i2c_bus *bus, *found = NULL;
-
- list_for_each_entry(bus, &pmac_i2c_busses, link) {
- if (np == bus->controller) {
- found = bus;
- break;
- }
- }
- if (!found)
- return -ENODEV;
- pmac_i2c_close(bus);
- return 0;
-}
-EXPORT_SYMBOL_GPL(pmac_low_i2c_unlock);
-
-
int pmac_i2c_open(struct pmac_i2c_bus *bus, int polled)
{
int rc;
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 02/12] block: Make the lock context annotations compatible with Clang
2026-03-16 20:08 [PATCH v2 00/12] Enable lock context analysis Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 01/12] drbd: Balance RCU calls in drbd_adm_dump_devices() Bart Van Assche
2026-03-16 20:08 ` [PATCH v2] powerpc/powermac: Remove pmac_low_i2c_{lock,unlock}() Bart Van Assche
@ 2026-03-16 20:08 ` Bart Van Assche
2026-03-17 14:04 ` Christoph Hellwig
2026-03-16 20:08 ` [PATCH v2 03/12] aoe: Add a lock context annotation Bart Van Assche
` (9 subsequent siblings)
12 siblings, 1 reply; 22+ messages in thread
From: Bart Van Assche @ 2026-03-16 20:08 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Bart Van Assche,
Tejun Heo, Josef Bacik, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Nathan Chancellor, Christian Brauner,
Joanne Koong, David Hildenbrand, Andreas Gruenbacher,
Mateusz Guzik
Clang is more strict than sparse with regard to lock context annotation
checking. Hence this patch that makes the lock context annotations
compatible with Clang. __release() annotations have been added below
invocations of indirect calls that unlock a mutex because Clang does not
support annotating function pointers with __releases().
Enable context analysis in the block layer Makefile.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
block/Makefile | 2 ++
block/bdev.c | 8 ++++++--
block/blk-cgroup.c | 7 ++++---
block/blk-crypto-profile.c | 2 ++
block/blk-iocost.c | 2 ++
block/blk-mq-debugfs.c | 12 ++++++------
block/blk-zoned.c | 1 +
block/blk.h | 4 ++++
block/ioctl.c | 1 +
block/kyber-iosched.c | 4 ++--
block/mq-deadline.c | 8 ++++----
include/linux/backing-dev.h | 2 ++
include/linux/blkdev.h | 9 ++++++---
include/linux/bpf.h | 1 +
14 files changed, 43 insertions(+), 20 deletions(-)
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 \
diff --git a/block/bdev.c b/block/bdev.c
index ed022f8c48c7..212e5c44a29a 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -313,6 +313,7 @@ int bdev_freeze(struct block_device *bdev)
if (bdev->bd_holder_ops && bdev->bd_holder_ops->freeze) {
error = bdev->bd_holder_ops->freeze(bdev);
lockdep_assert_not_held(&bdev->bd_holder_lock);
+ __release(&bdev->bd_holder_lock); /* blk_holder_ops::freeze() */
} else {
mutex_unlock(&bdev->bd_holder_lock);
error = sync_blockdev(bdev);
@@ -356,6 +357,7 @@ int bdev_thaw(struct block_device *bdev)
if (bdev->bd_holder_ops && bdev->bd_holder_ops->thaw) {
error = bdev->bd_holder_ops->thaw(bdev);
lockdep_assert_not_held(&bdev->bd_holder_lock);
+ __release(&bdev->bd_holder_lock); /* blk_holder_ops::freeze() */
} else {
mutex_unlock(&bdev->bd_holder_lock);
}
@@ -1254,9 +1256,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 {
+ /* blk_holder_ops::mark_dead() */
+ __release(&bdev->bd_holder_lock);
+ } else {
mutex_unlock(&bdev->bd_holder_lock);
sync_blockdev(bdev);
}
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 2d7b18eb7291..447259e76751 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -777,6 +777,7 @@ EXPORT_SYMBOL_GPL(blkg_conf_init);
* of @ctx->input. Returns -errno on error.
*/
int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx)
+ __no_context_analysis /* conditional locking */
{
char *input = ctx->input;
unsigned int major, minor;
@@ -822,6 +823,7 @@ int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx)
* for restoring the memalloc scope.
*/
unsigned long __must_check blkg_conf_open_bdev_frozen(struct blkg_conf_ctx *ctx)
+ __no_context_analysis /* see blkg_conf_open_bdev() */
{
int ret;
unsigned long memflags;
@@ -863,7 +865,7 @@ unsigned long __must_check 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)
- __acquires(&bdev->bd_queue->queue_lock)
+ __cond_acquires(0, &ctx->bdev->bd_disk->queue->queue_lock)
{
struct gendisk *disk;
struct request_queue *q;
@@ -977,8 +979,7 @@ EXPORT_SYMBOL_GPL(blkg_conf_prep);
* 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)
+ __no_context_analysis /* conditional unlocking */
{
if (ctx->blkg) {
spin_unlock_irq(&bdev_get_queue(ctx->bdev)->queue_lock);
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)
diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index d145db61e5c3..081054ca8111 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -728,6 +728,7 @@ static void iocg_commit_bio(struct ioc_gq *iocg, struct bio *bio,
}
static void iocg_lock(struct ioc_gq *iocg, bool lock_ioc, unsigned long *flags)
+ __no_context_analysis /* conditional locking */
{
if (lock_ioc) {
spin_lock_irqsave(&iocg->ioc->lock, *flags);
@@ -738,6 +739,7 @@ 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)
+ __no_context_analysis /* conditional locking */
{
if (unlock_ioc) {
spin_unlock(&iocg->waitq.lock);
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-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;
diff --git a/block/blk.h b/block/blk.h
index c5b2115b9ea4..7a4d8d047905 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -738,16 +738,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();
@@ -757,6 +760,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);
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;
diff --git a/block/kyber-iosched.c b/block/kyber-iosched.c
index b84163d1f851..874791838cbc 100644
--- a/block/kyber-iosched.c
+++ b/block/kyber-iosched.c
@@ -894,7 +894,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(((struct kyber_hctx_data *)((struct blk_mq_hw_ctx *)m->private)->sched_data)->lock) \
{ \
struct blk_mq_hw_ctx *hctx = m->private; \
struct kyber_hctx_data *khd = hctx->sched_data; \
@@ -913,7 +913,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(((struct kyber_hctx_data *)((struct blk_mq_hw_ctx *)m->private)->sched_data)->lock) \
{ \
struct blk_mq_hw_ctx *hctx = m->private; \
struct kyber_hctx_data *khd = hctx->sched_data; \
diff --git a/block/mq-deadline.c b/block/mq-deadline.c
index 95917a88976f..b812708a86ee 100644
--- a/block/mq-deadline.c
+++ b/block/mq-deadline.c
@@ -798,7 +798,7 @@ static const struct elv_fs_entry deadline_attrs[] = {
#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(&((struct deadline_data *)((struct request_queue *)m->private)->elevator->elevator_data)->lock) \
{ \
struct request_queue *q = m->private; \
struct deadline_data *dd = q->elevator->elevator_data; \
@@ -819,7 +819,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(&((struct deadline_data *)((struct request_queue *)m->private)->elevator->elevator_data)->lock) \
{ \
struct request_queue *q = m->private; \
struct deadline_data *dd = q->elevator->elevator_data; \
@@ -921,7 +921,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(&((struct deadline_data *)((struct request_queue *)m->private)->elevator->elevator_data)->lock)
{
struct request_queue *q = m->private;
struct deadline_data *dd = q->elevator->elevator_data;
@@ -939,7 +939,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(&((struct deadline_data *)((struct request_queue *)m->private)->elevator->elevator_data)->lock)
{
struct request_queue *q = m->private;
struct deadline_data *dd = q->elevator->elevator_data;
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index 0c8342747cab..34571d8b9dce 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -273,6 +273,7 @@ static inline struct bdi_writeback *inode_to_wb_wbc(
*/
static inline struct bdi_writeback *
unlocked_inode_to_wb_begin(struct inode *inode, struct wb_lock_cookie *cookie)
+ __no_context_analysis /* conditional locking */
{
rcu_read_lock();
@@ -300,6 +301,7 @@ unlocked_inode_to_wb_begin(struct inode *inode, struct wb_lock_cookie *cookie)
*/
static inline void unlocked_inode_to_wb_end(struct inode *inode,
struct wb_lock_cookie *cookie)
+ __no_context_analysis /* conditional locking */
{
if (unlikely(cookie->locked))
xa_unlock_irqrestore(&inode->i_mapping->i_pages, cookie->flags);
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);
}
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 05b34a6355b0..a3277bcf8d1d 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -2489,6 +2489,7 @@ bpf_prog_run_array(const struct bpf_prog_array *array,
static __always_inline u32
bpf_prog_run_array_uprobe(const struct bpf_prog_array *array,
const void *ctx, bpf_prog_run_fn run_prog)
+ __no_context_analysis /* conditional locking */
{
const struct bpf_prog_array_item *item;
const struct bpf_prog *prog;
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 03/12] aoe: Add a lock context annotation
2026-03-16 20:08 [PATCH v2 00/12] Enable lock context analysis Bart Van Assche
` (2 preceding siblings ...)
2026-03-16 20:08 ` [PATCH v2 02/12] block: Make the lock context annotations compatible with Clang Bart Van Assche
@ 2026-03-16 20:08 ` Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 04/12] drbd: Make the lock context annotations compatible with Clang Bart Van Assche
` (8 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Bart Van Assche @ 2026-03-16 20:08 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Bart Van Assche,
Justin Sanders
Prepare for enabling lock context analysis by adding __must_hold() where
appropriate.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/aoe/aoecmd.c | 1 +
1 file changed, 1 insertion(+)
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] 22+ messages in thread
* [PATCH v2 04/12] drbd: Make the lock context annotations compatible with Clang
2026-03-16 20:08 [PATCH v2 00/12] Enable lock context analysis Bart Van Assche
` (3 preceding siblings ...)
2026-03-16 20:08 ` [PATCH v2 03/12] aoe: Add a lock context annotation Bart Van Assche
@ 2026-03-16 20:08 ` Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 05/12] loop: Add lock context annotations Bart Van Assche
` (7 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Bart Van Assche @ 2026-03-16 20:08 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, 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 prepares for enabling lock context analysis.
Reviewed-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
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 +-
9 files changed, 135 insertions(+), 70 deletions(-)
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 728ecc431b38..cf505b31d040 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -927,7 +927,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;
@@ -3025,7 +3025,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;
@@ -3453,6 +3453,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] 22+ messages in thread
* [PATCH v2 05/12] loop: Add lock context annotations
2026-03-16 20:08 [PATCH v2 00/12] Enable lock context analysis Bart Van Assche
` (4 preceding siblings ...)
2026-03-16 20:08 ` [PATCH v2 04/12] drbd: Make the lock context annotations compatible with Clang Bart Van Assche
@ 2026-03-16 20:08 ` Bart Van Assche
2026-03-17 14:05 ` Christoph Hellwig
2026-03-16 20:08 ` [PATCH v2 06/12] nbd: " Bart Van Assche
` (6 subsequent siblings)
12 siblings, 1 reply; 22+ messages in thread
From: Bart Van Assche @ 2026-03-16 20:08 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Bart Van Assche,
Nathan Chancellor
Prepare for enabling lock context analysis by adding lock context
annotations that are compatible with Clang.
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] 22+ messages in thread
* [PATCH v2 06/12] nbd: Add lock context annotations
2026-03-16 20:08 [PATCH v2 00/12] Enable lock context analysis Bart Van Assche
` (5 preceding siblings ...)
2026-03-16 20:08 ` [PATCH v2 05/12] loop: Add lock context annotations Bart Van Assche
@ 2026-03-16 20:08 ` Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 07/12] null_blk: Add more " Bart Van Assche
` (5 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Bart Van Assche @ 2026-03-16 20:08 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Bart Van Assche,
Josef Bacik, Nathan Chancellor
Prepare for enabling lock context analysis by adding those lock context
annotations that are required by Clang.
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] 22+ messages in thread
* [PATCH v2 07/12] null_blk: Add more lock context annotations
2026-03-16 20:08 [PATCH v2 00/12] Enable lock context analysis Bart Van Assche
` (6 preceding siblings ...)
2026-03-16 20:08 ` [PATCH v2 06/12] nbd: " Bart Van Assche
@ 2026-03-16 20:08 ` Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 08/12] rbd: Add " Bart Van Assche
` (4 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Bart Van Assche @ 2026-03-16 20:08 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Bart Van Assche,
Nathan Chancellor, Keith Busch, Johannes Thumshirn,
Chaitanya Kulkarni, Genjian Zhang, Nilay Shroff,
Christophe JAILLET, Kees Cook
Prepare for enabling lock context analysis by adding the lock context
annotations that are required by Clang.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/null_blk/main.c | 7 +++++--
drivers/block/null_blk/zoned.c | 2 ++
2 files changed, 7 insertions(+), 2 deletions(-)
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] 22+ messages in thread
* [PATCH v2 08/12] rbd: Add lock context annotations
2026-03-16 20:08 [PATCH v2 00/12] Enable lock context analysis Bart Van Assche
` (7 preceding siblings ...)
2026-03-16 20:08 ` [PATCH v2 07/12] null_blk: Add more " Bart Van Assche
@ 2026-03-16 20:08 ` Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 09/12] ublk: Fix the " Bart Van Assche
` (3 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Bart Van Assche @ 2026-03-16 20:08 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Bart Van Assche,
Ilya Dryomov, Nathan Chancellor
Prepare for enabling lock context analysis by adding the lock context
annotations that are required by Clang.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/rbd.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index e7da06200c1e..595e4ba720ec 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,8 @@ static ssize_t do_rbd_add(const char *buf, size_t count)
if (rc < 0)
goto err_out_rbd_dev;
+ __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] 22+ messages in thread
* [PATCH v2 09/12] ublk: Fix the lock context annotations
2026-03-16 20:08 [PATCH v2 00/12] Enable lock context analysis Bart Van Assche
` (8 preceding siblings ...)
2026-03-16 20:08 ` [PATCH v2 08/12] rbd: Add " Bart Van Assche
@ 2026-03-16 20:08 ` Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 10/12] zloop: Add a " Bart Van Assche
` (2 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: Bart Van Assche @ 2026-03-16 20:08 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Bart Van Assche,
Ming Lei, Nathan Chancellor
Add the lock context annotations that are required by Clang. This patch
prepares for enabling 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 9e1ebb8e80da..626269636ebb 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);
}
@@ -3160,6 +3162,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))
@@ -3581,6 +3584,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] 22+ messages in thread
* [PATCH v2 10/12] zloop: Add a lock context annotations
2026-03-16 20:08 [PATCH v2 00/12] Enable lock context analysis Bart Van Assche
` (9 preceding siblings ...)
2026-03-16 20:08 ` [PATCH v2 09/12] ublk: Fix the " Bart Van Assche
@ 2026-03-16 20:08 ` Bart Van Assche
2026-03-17 14:07 ` Christoph Hellwig
2026-03-16 20:08 ` [PATCH v2 11/12] zram: Add " Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 12/12] block: Enable lock context analysis for all block drivers Bart Van Assche
12 siblings, 1 reply; 22+ messages in thread
From: Bart Van Assche @ 2026-03-16 20:08 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Bart Van Assche,
Nathan Chancellor
Prepare for enabling lock context analysis by adding a lock context
annotation that is required for Clang.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/zloop.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/block/zloop.c b/drivers/block/zloop.c
index 51c043342127..b3654fd814c7 100644
--- a/drivers/block/zloop.c
+++ b/drivers/block/zloop.c
@@ -379,6 +379,7 @@ static void zloop_rw_complete(struct kiocb *iocb, long ret)
}
static void zloop_rw(struct zloop_cmd *cmd)
+ __no_context_analysis /* conditional locking */
{
struct request *rq = blk_mq_rq_from_pdu(cmd);
struct zloop_device *zlo = rq->q->queuedata;
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 11/12] zram: Add lock context annotations
2026-03-16 20:08 [PATCH v2 00/12] Enable lock context analysis Bart Van Assche
` (10 preceding siblings ...)
2026-03-16 20:08 ` [PATCH v2 10/12] zloop: Add a " Bart Van Assche
@ 2026-03-16 20:08 ` Bart Van Assche
2026-03-17 14:08 ` Christoph Hellwig
2026-03-16 20:08 ` [PATCH v2 12/12] block: Enable lock context analysis for all block drivers Bart Van Assche
12 siblings, 1 reply; 22+ messages in thread
From: Bart Van Assche @ 2026-03-16 20:08 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Bart Van Assche,
Sergey Senozhatsky, Minchan Kim, Nathan Chancellor
Prepare for enabling lock context analysis by adding the lock context
annotations that are required by Clang.
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/zram/zcomp.c | 3 ++-
drivers/block/zram/zcomp.h | 6 ++++--
drivers/block/zram/zram_drv.c | 1 +
3 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index a771a8ecc540..c5dc9bb7046d 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 /* acquire related to return value */
{
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] 22+ messages in thread
* [PATCH v2 12/12] block: Enable lock context analysis for all block drivers
2026-03-16 20:08 [PATCH v2 00/12] Enable lock context analysis Bart Van Assche
` (11 preceding siblings ...)
2026-03-16 20:08 ` [PATCH v2 11/12] zram: Add " Bart Van Assche
@ 2026-03-16 20:08 ` Bart Van Assche
2026-03-17 14:08 ` Christoph Hellwig
12 siblings, 1 reply; 22+ messages in thread
From: Bart Van Assche @ 2026-03-16 20:08 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal, Bart Van Assche,
Sergey Senozhatsky, Justin Sanders, Philipp Reisner,
Lars Ellenberg, Christoph Böhmwalder, Md. Haris Iqbal,
Jack Wang, Roger Pau Monné, Minchan Kim
Now that all locking functions in block drivers have been annotated,
enable lock context analysis for all block drivers.
Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org> # zram
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/Makefile | 2 ++
drivers/block/aoe/Makefile | 2 ++
drivers/block/drbd/Makefile | 3 +++
drivers/block/mtip32xx/Makefile | 2 ++
drivers/block/null_blk/Makefile | 2 ++
drivers/block/rnbd/Makefile | 2 ++
drivers/block/xen-blkback/Makefile | 3 +++
drivers/block/zram/Makefile | 2 ++
8 files changed, 18 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)
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/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/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
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/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 \
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
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
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH v2] powerpc/powermac: Remove pmac_low_i2c_{lock,unlock}()
2026-03-16 20:08 ` [PATCH v2] powerpc/powermac: Remove pmac_low_i2c_{lock,unlock}() Bart Van Assche
@ 2026-03-16 20:12 ` Bart Van Assche
0 siblings, 0 replies; 22+ messages in thread
From: Bart Van Assche @ 2026-03-16 20:12 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Damien Le Moal,
Christophe Leroy (CS GROUP), Madhavan Srinivasan,
Michael Ellerman, Thomas Gleixner, Ingo Molnar, Kees Cook
On 3/16/26 1:08 PM, Bart Van Assche wrote:
> Commit a28d3af2a26c ("[PATCH] 2/5 powerpc: Rework PowerMac i2c part 2")
> removed the last calls to the pmac_low_i2c_{lock,unlock}() functions.
> Hence, remove these two functions.
This patch is a duplicate of https://lore.kernel.org/
all/20260316174747.3871924-1-bvanassche@acm.org/ and does not belong in
this series so please ignore it.
Thanks,
Bart.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 02/12] block: Make the lock context annotations compatible with Clang
2026-03-16 20:08 ` [PATCH v2 02/12] block: Make the lock context annotations compatible with Clang Bart Van Assche
@ 2026-03-17 14:04 ` Christoph Hellwig
2026-03-17 16:36 ` Bart Van Assche
0 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2026-03-17 14:04 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Tejun Heo, Josef Bacik, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Nathan Chancellor, Christian Brauner,
Joanne Koong, David Hildenbrand, Andreas Gruenbacher,
Mateusz Guzik
On Mon, Mar 16, 2026 at 01:08:39PM -0700, Bart Van Assche wrote:
> Clang is more strict than sparse with regard to lock context annotation
> checking. Hence this patch that makes the lock context annotations
> compatible with Clang.
Does it break sparse in the way? If so we'll need to find out a way
to disable the sparse lock annotations conditionally as there are
other warnings we only get from spare. Most importantly the __bitwise
warnings for endianess and the address spaces for user/mmio pointers.
All these are arguably more important than the lock annotations.
(If only the compilers could pick these up natively...)
> __release() annotations have been added below
> invocations of indirect calls that unlock a mutex because Clang does not
> support annotating function pointers with __releases().
Please split this up into a patch per area and document what you're
doing in each area in the commit log.
> if (bdev->bd_holder_ops && bdev->bd_holder_ops->freeze) {
> error = bdev->bd_holder_ops->freeze(bdev);
> lockdep_assert_not_held(&bdev->bd_holder_lock);
> + __release(&bdev->bd_holder_lock); /* blk_holder_ops::freeze() */
I have no idea what this comment is supposed to mean.
> } else {
> mutex_unlock(&bdev->bd_holder_lock);
> error = sync_blockdev(bdev);
> @@ -356,6 +357,7 @@ int bdev_thaw(struct block_device *bdev)
> if (bdev->bd_holder_ops && bdev->bd_holder_ops->thaw) {
> error = bdev->bd_holder_ops->thaw(bdev);
> lockdep_assert_not_held(&bdev->bd_holder_lock);
> + __release(&bdev->bd_holder_lock); /* blk_holder_ops::freeze() */
Same.
> - 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 {
> + /* blk_holder_ops::mark_dead() */
Same.
> int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx)
> + __no_context_analysis /* conditional locking */
Please always try to refactor code to avoid the conditional locking
first, and only if that doesn't work it go for this, explaining why
you had to do that in the commit message.
> static void *kyber_##name##_rqs_start(struct seq_file *m, loff_t *pos) \
> - __acquires(&khd->lock) \
> + __acquires(((struct kyber_hctx_data *)((struct blk_mq_hw_ctx *)m->private)->sched_data)->lock) \
> { \
Urrg. Is there some way to make this less ugly? A macro?
Same for all the other crazy cast+dereference instances.
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
This isn't block layer code at all.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 05/12] loop: Add lock context annotations
2026-03-16 20:08 ` [PATCH v2 05/12] loop: Add lock context annotations Bart Van Assche
@ 2026-03-17 14:05 ` Christoph Hellwig
0 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2026-03-17 14:05 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Nathan Chancellor
On Mon, Mar 16, 2026 at 01:08:42PM -0700, Bart Van Assche wrote:
> Prepare for enabling lock context analysis by adding lock context
> annotations that are compatible with Clang.
>
> 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 */
Same comment as for the first patch, please try to sort these things
out instead of using the big hammer without much of an explanation.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 10/12] zloop: Add a lock context annotations
2026-03-16 20:08 ` [PATCH v2 10/12] zloop: Add a " Bart Van Assche
@ 2026-03-17 14:07 ` Christoph Hellwig
0 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2026-03-17 14:07 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Nathan Chancellor
On Mon, Mar 16, 2026 at 01:08:47PM -0700, Bart Van Assche wrote:
> Prepare for enabling lock context analysis by adding a lock context
> annotation that is required for Clang.
No, it's not required. You just disable warnings. Anyway, the
conditional locking is fixed by a patch I have in my pipeline.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 11/12] zram: Add lock context annotations
2026-03-16 20:08 ` [PATCH v2 11/12] zram: Add " Bart Van Assche
@ 2026-03-17 14:08 ` Christoph Hellwig
2026-03-17 16:24 ` Bart Van Assche
0 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2026-03-17 14:08 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Sergey Senozhatsky, Minchan Kim, Nathan Chancellor
> -struct zcomp_strm *zcomp_stream_get(struct zcomp *comp)
> +struct zcomp_strm *__zcomp_stream_get(struct zcomp *comp)
> + __no_context_analysis /* acquire related to return value */
Which should be supported by the latest version of the annotations.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 12/12] block: Enable lock context analysis for all block drivers
2026-03-16 20:08 ` [PATCH v2 12/12] block: Enable lock context analysis for all block drivers Bart Van Assche
@ 2026-03-17 14:08 ` Christoph Hellwig
0 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2026-03-17 14:08 UTC (permalink / raw)
To: Bart Van Assche
Cc: Jens Axboe, linux-block, Christoph Hellwig, Damien Le Moal,
Sergey Senozhatsky, Justin Sanders, Philipp Reisner,
Lars Ellenberg, Christoph Böhmwalder, Md. Haris Iqbal,
Jack Wang, Roger Pau Monné, Minchan Kim
On Mon, Mar 16, 2026 at 01:08:49PM -0700, Bart Van Assche wrote:
> Now that all locking functions in block drivers have been annotated,
> enable lock context analysis for all block drivers.
Please group the enablement with the drivers that your convert on a
per-subdirectory basis.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 11/12] zram: Add lock context annotations
2026-03-17 14:08 ` Christoph Hellwig
@ 2026-03-17 16:24 ` Bart Van Assche
0 siblings, 0 replies; 22+ messages in thread
From: Bart Van Assche @ 2026-03-17 16:24 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jens Axboe, linux-block, Damien Le Moal, Sergey Senozhatsky,
Minchan Kim, Nathan Chancellor
On 3/17/26 7:08 AM, Christoph Hellwig wrote:
>> -struct zcomp_strm *zcomp_stream_get(struct zcomp *comp)
>> +struct zcomp_strm *__zcomp_stream_get(struct zcomp *comp)
>> + __no_context_analysis /* acquire related to return value */
>
> Which should be supported by the latest version of the annotations.
Unfortunately not. If I annotate __zcomp_stream_get() with
__acquires(&raw_cpu_ptr(comp->stream)->lock), the following error
messages appear:
drivers/block/zram/zcomp.c:131:1: error: mutex 'tcp_ptr__.lock' is still
held at
the end of function [-Werror,-Wthread-safety-analysis]
131 | }
| ^
drivers/block/zram/zcomp.c:126:3: note: mutex acquired here
126 | mutex_lock(&zstrm->lock);
| ^
drivers/block/zram/zcomp.c:131:1: error: expecting mutex
'tcp_ptr__.lock' to be
held at the end of function [-Werror,-Wthread-safety-analysis]
131 | }
| ^
drivers/block/zram/zcomp.c:110:20: note: mutex acquired here
110 | struct zcomp_strm *__zcomp_stream_get(struct zcomp *comp)
| ^
2 errors generated.
raw_cpu_ptr() has been defined as follows:
#define raw_cpu_ptr(ptr) \
({ \
__verify_pcpu_ptr(ptr); \
arch_raw_cpu_ptr(ptr); \
})
If I replace arch_raw_cpu_ptr(ptr) with 0 in the above macro (which is
incorrect), the compiler errors shown above disappear. So there must be
something in the x86 definition of arch_raw_cpu_ptr() that makes the
Clang alias analysis fail (this_cpu_off is a per-cpu variable):
#define arch_raw_cpu_ptr(_ptr) \
({ \
unsigned long tcp_ptr__ = raw_cpu_read_long(this_cpu_off); \
\
tcp_ptr__ += (__force unsigned long)(_ptr); \
(TYPEOF_UNQUAL(*(_ptr)) __force __kernel *)tcp_ptr__; \
})
Thanks,
Bart.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2 02/12] block: Make the lock context annotations compatible with Clang
2026-03-17 14:04 ` Christoph Hellwig
@ 2026-03-17 16:36 ` Bart Van Assche
0 siblings, 0 replies; 22+ messages in thread
From: Bart Van Assche @ 2026-03-17 16:36 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jens Axboe, linux-block, Damien Le Moal, Tejun Heo, Josef Bacik,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Nathan Chancellor, Christian Brauner, Joanne Koong,
David Hildenbrand, Andreas Gruenbacher, Mateusz Guzik
On 3/17/26 7:04 AM, Christoph Hellwig wrote:
> On Mon, Mar 16, 2026 at 01:08:39PM -0700, Bart Van Assche wrote:
>> Clang is more strict than sparse with regard to lock context annotation
>> checking. Hence this patch that makes the lock context annotations
>> compatible with Clang.
>
> Does it break sparse in the way? If so we'll need to find out a way
> to disable the sparse lock annotations conditionally as there are
> other warnings we only get from spare. Most importantly the __bitwise
> warnings for endianess and the address spaces for user/mmio pointers.
> All these are arguably more important than the lock annotations.
> (If only the compilers could pick these up natively...)
Agreed that the __bitwise annotations and sparse support for these
annotations are important. The following patch has been queued by Peter
Zijlstra to restore support for analyzing the kernel with sparse:
"[PATCH] include/linux/local_lock_internal.h: Make this header file
again compatible with sparse"
(https://lore.kernel.org/all/20260311231455.1961413-1-bvanassche@acm.org/)
From that patch:
-----------------------------------------------------------------------
--- a/include/linux/local_lock_internal.h
+++ b/include/linux/local_lock_internal.h
@@ -315,7 +315,7 @@ do { \
#endif /* CONFIG_PREEMPT_RT */
-#if defined(WARN_CONTEXT_ANALYSIS)
+#if defined(WARN_CONTEXT_ANALYSIS) && !defined(__CHECKER__)
/*
* Because the compiler only knows about the base per-CPU variable,
use this
* helper function to make the compiler think we lock/unlock the @base
variable,
-----------------------------------------------------------------------
Note: lock context annotations are ignored if the kernel is analyzed
with sparse. See also commit 5b63d0ae94cc ("compiler-context-analysis:
Remove Sparse support").
Thanks,
Bart.
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2026-03-17 16:36 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-16 20:08 [PATCH v2 00/12] Enable lock context analysis Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 01/12] drbd: Balance RCU calls in drbd_adm_dump_devices() Bart Van Assche
2026-03-16 20:08 ` [PATCH v2] powerpc/powermac: Remove pmac_low_i2c_{lock,unlock}() Bart Van Assche
2026-03-16 20:12 ` Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 02/12] block: Make the lock context annotations compatible with Clang Bart Van Assche
2026-03-17 14:04 ` Christoph Hellwig
2026-03-17 16:36 ` Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 03/12] aoe: Add a lock context annotation Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 04/12] drbd: Make the lock context annotations compatible with Clang Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 05/12] loop: Add lock context annotations Bart Van Assche
2026-03-17 14:05 ` Christoph Hellwig
2026-03-16 20:08 ` [PATCH v2 06/12] nbd: " Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 07/12] null_blk: Add more " Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 08/12] rbd: Add " Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 09/12] ublk: Fix the " Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 10/12] zloop: Add a " Bart Van Assche
2026-03-17 14:07 ` Christoph Hellwig
2026-03-16 20:08 ` [PATCH v2 11/12] zram: Add " Bart Van Assche
2026-03-17 14:08 ` Christoph Hellwig
2026-03-17 16:24 ` Bart Van Assche
2026-03-16 20:08 ` [PATCH v2 12/12] block: Enable lock context analysis for all block drivers Bart Van Assche
2026-03-17 14:08 ` Christoph Hellwig
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox