Clang performs more strict checking of lock context annotations than sparse. This patch makes the DRBD lock context annotations compatible with Clang and enables lock context analysis in the Makefile. Cc: Christoph Böhmwalder Signed-off-by: Bart Van Assche --- drivers/block/drbd/Makefile | 3 +++ drivers/block/drbd/drbd_int.h | 27 ++++++++++++++++++--------- drivers/block/drbd/drbd_main.c | 2 ++ drivers/block/drbd/drbd_receiver.c | 6 ++++++ drivers/block/drbd/drbd_req.c | 1 + drivers/block/drbd/drbd_state.c | 2 ++ drivers/block/drbd/drbd_state.h | 4 ++-- 7 files changed, 34 insertions(+), 11 deletions(-) diff --git a/drivers/block/drbd/Makefile b/drivers/block/drbd/Makefile index 5faaa8a8e7f0..cae65578001b 100644 --- a/drivers/block/drbd/Makefile +++ b/drivers/block/drbd/Makefile @@ -1,4 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only + +CONTEXT_ANALYSIS := y + drbd-y := drbd_buildtag.o drbd_bitmap.o drbd_proc.o drbd-y += drbd_worker.o drbd_receiver.o drbd_req.o drbd_actlog.o drbd-y += drbd_main.o drbd_strings.o drbd_nl.o diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 7e0e0a0f27ae..73ceaab3842d 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -197,8 +197,8 @@ struct drbd_device_work { extern struct mutex resources_mutex; -void lock_all_resources(void); -void unlock_all_resources(void); +void lock_all_resources(void) __acquires(&resources_mutex); +void unlock_all_resources(void) __releases(&resources_mutex); struct drbd_request { struct drbd_work w; @@ -1094,7 +1094,8 @@ int drbd_bmio_set_n_write(struct drbd_device *device, struct drbd_peer_device *peer_device); int drbd_bmio_clear_n_write(struct drbd_device *device, struct drbd_peer_device *peer_device); -int drbd_wait_misc(struct drbd_device *device, struct drbd_interval *i); +int drbd_wait_misc(struct drbd_device *device, struct drbd_interval *i) + __must_hold(&device->resource->req_lock); /* Meta data layout * @@ -1859,12 +1860,20 @@ static inline void request_ping(struct drbd_connection *connection) wake_ack_receiver(connection); } -void *conn_prepare_command(struct drbd_connection *, struct drbd_socket *); -void *drbd_prepare_command(struct drbd_peer_device *, struct drbd_socket *); -int conn_send_command(struct drbd_connection *, struct drbd_socket *, - enum drbd_packet, unsigned int, void *, unsigned int); -int drbd_send_command(struct drbd_peer_device *, struct drbd_socket *, - enum drbd_packet, unsigned int, void *, unsigned int); +void *conn_prepare_command(struct drbd_connection *connection, + struct drbd_socket *sock) + __cond_acquires(true, &sock->mutex); +void *drbd_prepare_command(struct drbd_peer_device *peer_device, struct drbd_socket *sock) + __cond_acquires(true, &sock->mutex); +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 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 drbd_send_ping(struct drbd_connection *connection); int drbd_send_ping_ack(struct drbd_connection *connection); diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index d9eb95aa5c44..6f3c04252b5d 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -3659,6 +3659,7 @@ int drbd_wait_misc(struct drbd_device *device, struct drbd_interval *i) } void lock_all_resources(void) + __context_unsafe(locking loop) { struct drbd_resource *resource; int __maybe_unused i = 0; @@ -3670,6 +3671,7 @@ void lock_all_resources(void) } void unlock_all_resources(void) + __context_unsafe(locking loop) { struct drbd_resource *resource; diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 4e04ff2dc65d..b4a350cd03b0 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -288,6 +288,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); @@ -897,6 +898,8 @@ static int conn_connect(struct drbd_connection *connection) if (drbd_send_protocol(connection) == -EOPNOTSUPP) return -1; + /* context_unsafe() because of two locking loops */ + context_unsafe( /* Prevent a race between resync-handshake and * being promoted to Primary. * @@ -914,6 +917,7 @@ static int conn_connect(struct drbd_connection *connection) 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) { @@ -2231,6 +2235,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; @@ -2257,6 +2262,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); diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index a851e43c94a8..1cc455846f92 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -953,6 +953,7 @@ static bool remote_due_to_read_balancing(struct drbd_device *device, sector_t se */ static void complete_conflicting_writes(struct drbd_resource *resource, struct drbd_request *req) + __must_hold(&resource->req_lock) { DEFINE_WAIT(wait); struct drbd_device *device = req->device; diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c index 171c6488283d..a48b2c1b5f15 100644 --- a/drivers/block/drbd/drbd_state.c +++ b/drivers/block/drbd/drbd_state.c @@ -713,6 +713,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; @@ -2306,6 +2307,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) + __context_unsafe(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 a7e31d092039..a22ee1916051 100644 --- a/drivers/block/drbd/drbd_state.h +++ b/drivers/block/drbd/drbd_state.h @@ -121,8 +121,8 @@ enum drbd_state_rv _drbd_request_state(struct drbd_device *, union drbd_state, union drbd_state, enum chg_state_flags); enum drbd_state_rv -_drbd_request_state_holding_state_mutex(struct drbd_device *, union drbd_state, - union drbd_state, enum chg_state_flags); +_drbd_request_state_holding_state_mutex(struct drbd_device *device, union drbd_state mask, + union drbd_state val, enum chg_state_flags f); enum drbd_state_rv _drbd_set_state(struct drbd_device *, union drbd_state, enum chg_state_flags,