All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 05/14] drbd: Make the lock context annotations compatible with Clang
  2026-03-04 19:48 [PATCH 00/14] Enable lock context analysis Bart Van Assche
@ 2026-03-04 19:48 ` Bart Van Assche
  2026-03-09 10:08   ` Christoph Böhmwalder
  0 siblings, 1 reply; 5+ messages in thread
From: Bart Van Assche @ 2026-03-04 19:48 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Christoph Hellwig, Damien Le Moal, Marco Elver, linux-block,
	Bart Van Assche, Philipp Reisner, Lars Ellenberg,
	Christoph Böhmwalder, 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.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 drivers/block/drbd/drbd_bitmap.c   | 20 +++++++------
 drivers/block/drbd/drbd_int.h      | 46 ++++++++++++++----------------
 drivers/block/drbd/drbd_main.c     | 45 ++++++++++++++++++++++-------
 drivers/block/drbd/drbd_nl.c       |  5 ++--
 drivers/block/drbd/drbd_receiver.c | 20 +++++++------
 drivers/block/drbd/drbd_req.c      |  2 ++
 drivers/block/drbd/drbd_state.c    |  3 ++
 drivers/block/drbd/drbd_worker.c   |  6 ++--
 8 files changed, 91 insertions(+), 56 deletions(-)

diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index 65ea6ec66bfd..eeeeba9840ea 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -122,12 +122,14 @@ 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");
+		__acquire(&b->bm_change);
 		return;
 	}
 
@@ -149,10 +151,12 @@ void drbd_bm_lock(struct drbd_device *device, char *why, enum bm_flag flags)
 }
 
 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");
+		__release(&b->bm_change);
 		return;
 	}
 
@@ -987,7 +991,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 +1064,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 +1219,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 +1232,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 +1244,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 +1254,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 +1271,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 +1280,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..fea8e870781e 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1056,14 +1056,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 +1080,9 @@ 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);
 
 /* Meta data layout
  *
@@ -1292,17 +1292,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);
@@ -1389,7 +1389,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);
@@ -1470,10 +1471,10 @@ extern bool drbd_rs_should_slow_down(struct drbd_peer_device *peer_device, secto
 		bool throttle_if_app_is_waiting);
 extern int drbd_submit_peer_request(struct drbd_peer_request *peer_req);
 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,
+extern struct drbd_peer_request *drbd_alloc_peer_req(struct drbd_peer_device *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 +1489,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;
@@ -1975,8 +1975,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 +1990,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..c014a89e224c 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -589,6 +589,7 @@ static void *__conn_prepare_command(struct drbd_connection *connection,
 }
 
 void *conn_prepare_command(struct drbd_connection *connection, struct drbd_socket *sock)
+	__cond_acquires(true, sock->mutex)
 {
 	void *p;
 
@@ -601,6 +602,7 @@ void *conn_prepare_command(struct drbd_connection *connection, struct drbd_socke
 }
 
 void *drbd_prepare_command(struct drbd_peer_device *peer_device, struct drbd_socket *sock)
+	__cond_acquires(true, sock->mutex)
 {
 	return conn_prepare_command(peer_device->connection, sock);
 }
@@ -646,6 +648,7 @@ static int __conn_send_command(struct drbd_connection *connection, struct drbd_s
 int conn_send_command(struct drbd_connection *connection, struct drbd_socket *sock,
 		      enum drbd_packet cmd, unsigned int header_size,
 		      void *data, unsigned int size)
+	__releases(sock->mutex)
 {
 	int err;
 
@@ -657,6 +660,7 @@ int conn_send_command(struct drbd_connection *connection, struct drbd_socket *so
 int drbd_send_command(struct drbd_peer_device *peer_device, struct drbd_socket *sock,
 		      enum drbd_packet cmd, unsigned int header_size,
 		      void *data, unsigned int size)
+	__releases(sock->mutex)
 {
 	int err;
 
@@ -667,6 +671,7 @@ int drbd_send_command(struct drbd_peer_device *peer_device, struct drbd_socket *
 }
 
 int drbd_send_ping(struct drbd_connection *connection)
+	__cond_acquires(true, connection->meta.mutex)
 {
 	struct drbd_socket *sock;
 
@@ -677,6 +682,7 @@ int drbd_send_ping(struct drbd_connection *connection)
 }
 
 int drbd_send_ping_ack(struct drbd_connection *connection)
+	__cond_acquires(true, connection->meta.mutex)
 {
 	struct drbd_socket *sock;
 
@@ -687,6 +693,7 @@ int drbd_send_ping_ack(struct drbd_connection *connection)
 }
 
 int drbd_send_sync_param(struct drbd_peer_device *peer_device)
+	__cond_acquires(true, peer_device->connection->data.mutex)
 {
 	struct drbd_socket *sock;
 	struct p_rs_param_95 *p;
@@ -800,6 +807,7 @@ int drbd_send_protocol(struct drbd_connection *connection)
 }
 
 static int _drbd_send_uuids(struct drbd_peer_device *peer_device, u64 uuid_flags)
+	__cond_acquires(true, peer_device->connection->data.mutex)
 {
 	struct drbd_device *device = peer_device->device;
 	struct drbd_socket *sock;
@@ -862,6 +870,7 @@ void drbd_print_uuids(struct drbd_device *device, const char *text)
 }
 
 void drbd_gen_and_send_sync_uuid(struct drbd_peer_device *peer_device)
+	__cond_acquires(true, peer_device->connection->data.mutex)
 {
 	struct drbd_device *device = peer_device->device;
 	struct drbd_socket *sock;
@@ -888,6 +897,7 @@ void drbd_gen_and_send_sync_uuid(struct drbd_peer_device *peer_device)
 }
 
 int drbd_send_sizes(struct drbd_peer_device *peer_device, int trigger_reply, enum dds_flags flags)
+	__cond_acquires(true, peer_device->connection->data.mutex)
 {
 	struct drbd_device *device = peer_device->device;
 	struct drbd_socket *sock;
@@ -969,6 +979,7 @@ int drbd_send_sizes(struct drbd_peer_device *peer_device, int trigger_reply, enu
  * @peer_device:	DRBD peer device.
  */
 int drbd_send_current_state(struct drbd_peer_device *peer_device)
+	__cond_acquires(true, peer_device->connection->data.mutex)
 {
 	struct drbd_socket *sock;
 	struct p_state *p;
@@ -992,6 +1003,7 @@ int drbd_send_current_state(struct drbd_peer_device *peer_device)
  * want to send each intermediary state in the order it occurred.
  */
 int drbd_send_state(struct drbd_peer_device *peer_device, union drbd_state state)
+	__cond_acquires(true, peer_device->connection->data.mutex)
 {
 	struct drbd_socket *sock;
 	struct p_state *p;
@@ -1005,6 +1017,7 @@ int drbd_send_state(struct drbd_peer_device *peer_device, union drbd_state state
 }
 
 int drbd_send_state_req(struct drbd_peer_device *peer_device, union drbd_state mask, union drbd_state val)
+	__cond_acquires(true, peer_device->connection->data.mutex)
 {
 	struct drbd_socket *sock;
 	struct p_req_state *p;
@@ -1019,6 +1032,7 @@ int drbd_send_state_req(struct drbd_peer_device *peer_device, union drbd_state m
 }
 
 int conn_send_state_req(struct drbd_connection *connection, union drbd_state mask, union drbd_state val)
+	__cond_acquires(true, connection->data.mutex)
 {
 	enum drbd_packet cmd;
 	struct drbd_socket *sock;
@@ -1035,6 +1049,7 @@ int conn_send_state_req(struct drbd_connection *connection, union drbd_state mas
 }
 
 void drbd_send_sr_reply(struct drbd_peer_device *peer_device, enum drbd_state_rv retcode)
+	__cond_acquires(true, peer_device->connection->data.mutex)
 {
 	struct drbd_socket *sock;
 	struct p_req_state_reply *p;
@@ -1048,6 +1063,7 @@ void drbd_send_sr_reply(struct drbd_peer_device *peer_device, enum drbd_state_rv
 }
 
 void conn_send_sr_reply(struct drbd_connection *connection, enum drbd_state_rv retcode)
+	__cond_acquires(true, connection->data.mutex)
 {
 	struct drbd_socket *sock;
 	struct p_req_state_reply *p;
@@ -1381,6 +1397,7 @@ int drbd_send_ack_ex(struct drbd_peer_device *peer_device, enum drbd_packet cmd,
 
 int drbd_send_rs_deallocated(struct drbd_peer_device *peer_device,
 			     struct drbd_peer_request *peer_req)
+	__cond_acquires(true, peer_device->connection->data.mutex)
 {
 	struct drbd_socket *sock;
 	struct p_block_desc *p;
@@ -1397,6 +1414,7 @@ int drbd_send_rs_deallocated(struct drbd_peer_device *peer_device,
 
 int drbd_send_drequest(struct drbd_peer_device *peer_device, int cmd,
 		       sector_t sector, int size, u64 block_id)
+	__cond_acquires(true, peer_device->connection->data.mutex)
 {
 	struct drbd_socket *sock;
 	struct p_block_req *p;
@@ -1413,6 +1431,7 @@ int drbd_send_drequest(struct drbd_peer_device *peer_device, int cmd,
 
 int drbd_send_drequest_csum(struct drbd_peer_device *peer_device, sector_t sector, int size,
 			    void *digest, int digest_size, enum drbd_packet cmd)
+	__cond_acquires(true, peer_device->connection->data.mutex)
 {
 	struct drbd_socket *sock;
 	struct p_block_req *p;
@@ -1430,6 +1449,7 @@ int drbd_send_drequest_csum(struct drbd_peer_device *peer_device, sector_t secto
 }
 
 int drbd_send_ov_request(struct drbd_peer_device *peer_device, sector_t sector, int size)
+	__cond_acquires(true, peer_device->connection->data.mutex)
 {
 	struct drbd_socket *sock;
 	struct p_block_req *p;
@@ -3282,7 +3302,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 +3310,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 +3325,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 +3333,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 +3352,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 +3374,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 +3407,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 +3434,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 +3561,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 +3569,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);
@@ -3649,6 +3669,7 @@ const char *cmdname(enum drbd_packet cmd)
  *		struct drbd_peer_request
  */
 int drbd_wait_misc(struct drbd_device *device, struct drbd_interval *i)
+	__must_hold(&device->resource->req_lock)
 {
 	struct net_conf *nc;
 	DEFINE_WAIT(wait);
@@ -3678,6 +3699,8 @@ int drbd_wait_misc(struct drbd_device *device, struct drbd_interval *i)
 }
 
 void lock_all_resources(void)
+	__acquires(&resources_mutex)
+	__no_context_analysis /* locking loop */
 {
 	struct drbd_resource *resource;
 	int __maybe_unused i = 0;
@@ -3689,6 +3712,8 @@ void lock_all_resources(void)
 }
 
 void unlock_all_resources(void)
+	__releases(&resources_mutex)
+	__no_context_analysis /* unlock loop */
 {
 	struct drbd_resource *resource;
 
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..9c49b977bc22 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);
 
@@ -733,6 +734,7 @@ int drbd_connected(struct drbd_peer_device *peer_device)
  *  -2 We do not have a network config...
  */
 static int conn_connect(struct drbd_connection *connection)
+	__no_context_analysis /* conditional locking */
 {
 	struct drbd_socket sock, msock;
 	struct drbd_peer_device *peer_device;
@@ -1657,7 +1659,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 +1871,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 +2232,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 +2259,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 +2830,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 +2913,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 +2970,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 +3048,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 +3268,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..ca7e511e83a6 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,7 @@ static void drbd_send_and_submit(struct drbd_device *device, struct drbd_request
 	bool submit_private_bio = false;
 
 	spin_lock_irq(&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..2ab7208cce59 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;
@@ -699,6 +700,7 @@ int drbd_request_detach_interruptible(struct drbd_device *device)
 enum drbd_state_rv
 _drbd_request_state_holding_state_mutex(struct drbd_device *device, union drbd_state mask,
 		    union drbd_state val, enum chg_state_flags f)
+	__must_hold(&device->state_mutex)
 {
 	enum drbd_state_rv rv;
 
@@ -2292,6 +2294,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_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] 5+ messages in thread

* Re: [PATCH 05/14] drbd: Make the lock context annotations compatible with Clang
@ 2026-03-06  4:58 kernel test robot
  0 siblings, 0 replies; 5+ messages in thread
From: kernel test robot @ 2026-03-06  4:58 UTC (permalink / raw)
  To: oe-kbuild; +Cc: lkp, Julia Lawall

BCC: lkp@intel.com
CC: oe-kbuild-all@lists.linux.dev
In-Reply-To: <20260304194843.760669-6-bvanassche@acm.org>
References: <20260304194843.760669-6-bvanassche@acm.org>
TO: Bart Van Assche <bvanassche@acm.org>
TO: Jens Axboe <axboe@kernel.dk>
CC: Christoph Hellwig <hch@lst.de>
CC: Damien Le Moal <dlemoal@kernel.org>
CC: Marco Elver <elver@google.com>
CC: linux-block@vger.kernel.org
CC: Bart Van Assche <bvanassche@acm.org>
CC: Philipp Reisner <philipp.reisner@linbit.com>
CC: Lars Ellenberg <lars.ellenberg@linbit.com>
CC: "Christoph Böhmwalder" <christoph.boehmwalder@linbit.com>
CC: Nathan Chancellor <nathan@kernel.org>

Hi Bart,

kernel test robot noticed the following build warnings:

[auto build test WARNING on axboe/for-next]
[also build test WARNING on bpf-next/net bpf-next/master bpf/master linus/master v7.0-rc2 next-20260305]
[cannot apply to ceph-client/testing ceph-client/for-linus hch-configfs/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Bart-Van-Assche/drbd-Balance-RCU-calls-in-drbd_adm_dump_devices/20260305-035510
base:   https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux.git for-next
patch link:    https://lore.kernel.org/r/20260304194843.760669-6-bvanassche%40acm.org
patch subject: [PATCH 05/14] drbd: Make the lock context annotations compatible with Clang
:::::: branch date: 33 hours ago
:::::: commit date: 33 hours ago
config: openrisc-randconfig-r053-20260306 (https://download.01.org/0day-ci/archive/20260306/202603061238.WbZr6WGt-lkp@intel.com/config)
compiler: or1k-linux-gcc (GCC) 15.2.0

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Julia Lawall <julia.lawall@inria.fr>
| Closes: https://lore.kernel.org/r/202603061238.WbZr6WGt-lkp@intel.com/

cocci warnings: (new ones prefixed by >>)
>> drivers/block/drbd/drbd_bitmap.c:132:16-25: ERROR: b is NULL but dereferenced.
   drivers/block/drbd/drbd_bitmap.c:159:16-25: ERROR: b is NULL but dereferenced.

vim +132 drivers/block/drbd/drbd_bitmap.c

b411b3637fa71fc Philipp Reisner     2009-09-25  123  
b30ab7913b0a7b1 Andreas Gruenbacher 2011-07-03  124  void drbd_bm_lock(struct drbd_device *device, char *why, enum bm_flag flags)
9c640e625a48df2 Bart Van Assche     2026-03-04  125  	__acquires(&device->bitmap->bm_change)
b411b3637fa71fc Philipp Reisner     2009-09-25  126  {
b30ab7913b0a7b1 Andreas Gruenbacher 2011-07-03  127  	struct drbd_bitmap *b = device->bitmap;
b411b3637fa71fc Philipp Reisner     2009-09-25  128  	int trylock_failed;
b411b3637fa71fc Philipp Reisner     2009-09-25  129  
b411b3637fa71fc Philipp Reisner     2009-09-25  130  	if (!b) {
d01801710265cfb Andreas Gruenbacher 2011-07-03  131  		drbd_err(device, "FIXME no bitmap in drbd_bm_lock!?\n");
9c640e625a48df2 Bart Van Assche     2026-03-04 @132  		__acquire(&b->bm_change);
b411b3637fa71fc Philipp Reisner     2009-09-25  133  		return;
b411b3637fa71fc Philipp Reisner     2009-09-25  134  	}
b411b3637fa71fc Philipp Reisner     2009-09-25  135  
8a03ae2a5baed3d Thomas Gleixner     2010-01-29  136  	trylock_failed = !mutex_trylock(&b->bm_change);
b411b3637fa71fc Philipp Reisner     2009-09-25  137  
b411b3637fa71fc Philipp Reisner     2009-09-25  138  	if (trylock_failed) {
c60b0251d9d3501 Andreas Gruenbacher 2011-08-10  139  		drbd_warn(device, "%s[%d] going to '%s' but bitmap already locked for '%s' by %s[%d]\n",
c60b0251d9d3501 Andreas Gruenbacher 2011-08-10  140  			  current->comm, task_pid_nr(current),
b411b3637fa71fc Philipp Reisner     2009-09-25  141  			  why, b->bm_why ?: "?",
c60b0251d9d3501 Andreas Gruenbacher 2011-08-10  142  			  b->bm_task->comm, task_pid_nr(b->bm_task));
8a03ae2a5baed3d Thomas Gleixner     2010-01-29  143  		mutex_lock(&b->bm_change);
b411b3637fa71fc Philipp Reisner     2009-09-25  144  	}
20ceb2b22edaf51 Lars Ellenberg      2011-01-21  145  	if (BM_LOCKED_MASK & b->bm_flags)
d01801710265cfb Andreas Gruenbacher 2011-07-03  146  		drbd_err(device, "FIXME bitmap already locked in bm_lock\n");
20ceb2b22edaf51 Lars Ellenberg      2011-01-21  147  	b->bm_flags |= flags & BM_LOCKED_MASK;
b411b3637fa71fc Philipp Reisner     2009-09-25  148  
b411b3637fa71fc Philipp Reisner     2009-09-25  149  	b->bm_why  = why;
b411b3637fa71fc Philipp Reisner     2009-09-25  150  	b->bm_task = current;
b411b3637fa71fc Philipp Reisner     2009-09-25  151  }
b411b3637fa71fc Philipp Reisner     2009-09-25  152  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 05/14] drbd: Make the lock context annotations compatible with Clang
  2026-03-04 19:48 ` [PATCH 05/14] drbd: Make the lock context annotations compatible with Clang Bart Van Assche
@ 2026-03-09 10:08   ` Christoph Böhmwalder
  2026-03-09 23:15     ` Bart Van Assche
  0 siblings, 1 reply; 5+ messages in thread
From: Christoph Böhmwalder @ 2026-03-09 10:08 UTC (permalink / raw)
  To: Bart Van Assche, Jens Axboe
  Cc: Christoph Hellwig, Damien Le Moal, Marco Elver, linux-block,
	Philipp Reisner, Lars Ellenberg, Nathan Chancellor

Am 04.03.26 um 20:48 schrieb Bart Van Assche:
> 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.
> 
> Signed-off-by: Bart Van Assche <bvanassche@acm.org>
> ---
>  drivers/block/drbd/drbd_bitmap.c   | 20 +++++++------
>  drivers/block/drbd/drbd_int.h      | 46 ++++++++++++++----------------
>  drivers/block/drbd/drbd_main.c     | 45 ++++++++++++++++++++++-------
>  drivers/block/drbd/drbd_nl.c       |  5 ++--
>  drivers/block/drbd/drbd_receiver.c | 20 +++++++------
>  drivers/block/drbd/drbd_req.c      |  2 ++
>  drivers/block/drbd/drbd_state.c    |  3 ++
>  drivers/block/drbd/drbd_worker.c   |  6 ++--
>  8 files changed, 91 insertions(+), 56 deletions(-)
[...]
>  
>  void drbd_send_sr_reply(struct drbd_peer_device *peer_device, enum drbd_state_rv retcode)
> +	__cond_acquires(true, peer_device->connection->data.mutex)
>  {
>  	struct drbd_socket *sock;
>  	struct p_req_state_reply *p;
> @@ -1048,6 +1063,7 @@ void drbd_send_sr_reply(struct drbd_peer_device *peer_device, enum drbd_state_rv
>  }
>  
>  void conn_send_sr_reply(struct drbd_connection *connection, enum drbd_state_rv retcode)
> +	__cond_acquires(true, connection->data.mutex)
>  {
>  	struct drbd_socket *sock;
>  	struct p_req_state_reply *p;

These are marked as acquiring connection->data.mutex, but actually use
connection->meta later. So the annotation should reference meta.mutex.

Also, I think the annotations on drbd_send_* are wrong. These functions
have no path where they return without releasing the mutex, but these
annotations would tell clang that they hold the mutex on non-zero return.

Regards,
Christoph

-- 
Christoph Böhmwalder
LINBIT | Keeping the Digital World Running
DRBD HA —  Disaster Recovery — Software defined Storage


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 05/14] drbd: Make the lock context annotations compatible with Clang
  2026-03-09 10:08   ` Christoph Böhmwalder
@ 2026-03-09 23:15     ` Bart Van Assche
  2026-03-11 20:42       ` Christoph Böhmwalder
  0 siblings, 1 reply; 5+ messages in thread
From: Bart Van Assche @ 2026-03-09 23:15 UTC (permalink / raw)
  To: Christoph Böhmwalder, Jens Axboe
  Cc: Christoph Hellwig, Damien Le Moal, Marco Elver, linux-block,
	Philipp Reisner, Lars Ellenberg, Nathan Chancellor

On 3/9/26 3:08 AM, Christoph Böhmwalder wrote:
> These are marked as acquiring connection->data.mutex, but actually use
> connection->meta later. So the annotation should reference meta.mutex.
> 
> Also, I think the annotations on drbd_send_* are wrong. These functions
> have no path where they return without releasing the mutex, but these
> annotations would tell clang that they hold the mutex on non-zero return.

Thanks for the feedback. Does the patch below look better? Compared to
the previous version, all lock context annotations (except for static
functions) have been moved from .c into .h files. Lock context aliases
have been introduced if the synchronization object is not visible in the
.h file. Two function declarations have been moved from before to after
the struct drbd_device definition.

Thanks,

Bart.


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] 5+ messages in thread

* Re: [PATCH 05/14] drbd: Make the lock context annotations compatible with Clang
  2026-03-09 23:15     ` Bart Van Assche
@ 2026-03-11 20:42       ` Christoph Böhmwalder
  0 siblings, 0 replies; 5+ messages in thread
From: Christoph Böhmwalder @ 2026-03-11 20:42 UTC (permalink / raw)
  To: Bart Van Assche, Jens Axboe
  Cc: Christoph Hellwig, Damien Le Moal, Marco Elver, linux-block,
	Philipp Reisner, Lars Ellenberg, Nathan Chancellor



Am 10.03.26 um 00:15 schrieb Bart Van Assche:
> On 3/9/26 3:08 AM, Christoph Böhmwalder wrote:
>> These are marked as acquiring connection->data.mutex, but actually use
>> connection->meta later. So the annotation should reference meta.mutex.
>>
>> Also, I think the annotations on drbd_send_* are wrong. These functions
>> have no path where they return without releasing the mutex, but these
>> annotations would tell clang that they hold the mutex on non-zero return.
> 
> Thanks for the feedback. Does the patch below look better? Compared to
> the previous version, all lock context annotations (except for static
> functions) have been moved from .c into .h files. Lock context aliases
> have been introduced if the synchronization object is not visible in the
> .h file. Two function declarations have been moved from before to after
> the struct drbd_device definition.
> 
> Thanks,
> 
> Bart.
> 

Yes, looks better now, and I can confirm that no warnings remain (after
the other DRBD patch in this series).

Reviewed-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>

-- 
Christoph Böhmwalder
LINBIT | Keeping the Digital World Running
DRBD HA —  Disaster Recovery — Software defined Storage


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-03-11 20:42 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-06  4:58 [PATCH 05/14] drbd: Make the lock context annotations compatible with Clang kernel test robot
  -- strict thread matches above, loose matches on Subject: below --
2026-03-04 19:48 [PATCH 00/14] Enable lock context analysis Bart Van Assche
2026-03-04 19:48 ` [PATCH 05/14] drbd: Make the lock context annotations compatible with Clang Bart Van Assche
2026-03-09 10:08   ` Christoph Böhmwalder
2026-03-09 23:15     ` Bart Van Assche
2026-03-11 20:42       ` Christoph Böhmwalder

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.