drbd: Enable lock context analysis
Subsystems (2)
cover drbd: Enable lock context analysis
Hi Jens,
This patch series enables compile-time lock context analysis for DRBD. The goal of this series is to allow the compiler to statically verify that locks are acquired and released correctly, helping to prevent deadlocks and race conditions. This version addresses feedback received on the v1 series, improves the annotations, and refactors some conditional locking paths to use the modern cleanup.h guard infrastructure.
Changes since v1:
- Extracted the DRBD patches from a larger series. See also "[PATCH 00/27] Enable lock context analysis in drivers/block/"
(https://lore.kernel.org/all/[email protected]/).
- Fixed the indentation of the arguments of drbd_nl_put_dump_connections_result().
- Combined the two drbd_req_state() patches into a single patch.
Please consider these patches for the next merge window.
Thanks,
Bart.
Bart Van Assche (12):
drbd: Remove "extern" from function declarations
drbd: Retain one _get_ldev_if_state() implementation
drbd: Remove the get_ldev_if_state() macro
drbd: Remove the 'local' lock context
drbd: Simplify the bitmap locking functions.
drbd: Move two declarations
drbd: Pass 'resource' directly to complete_conflicting_writes()
drbd: Split drbd_nl_get_connections_dumpit()
drbd: Make a mutex_unlock() call unconditional
drbd: Rework locking in drbd_req_state()
drbd: Annotate drbd_bm_{lock,unlock}()
drbd: Enable lock context analysis
drivers/block/drbd/Makefile | 3 + drivers/block/drbd/drbd_bitmap.c | 43 +- drivers/block/drbd/drbd_config.h | 2 +- drivers/block/drbd/drbd_int.h | 594 +++++++++++++------------ drivers/block/drbd/drbd_interval.h | 11 +- drivers/block/drbd/drbd_main.c | 41 +- drivers/block/drbd/drbd_nl.c | 117 ++--- drivers/block/drbd/drbd_receiver.c | 27 +- drivers/block/drbd/drbd_req.c | 10 +- drivers/block/drbd/drbd_req.h | 24 +- drivers/block/drbd/drbd_state.c | 49 +- drivers/block/drbd/drbd_state.h | 35 +- drivers/block/drbd/drbd_state_change.h | 32 +- drivers/block/drbd/drbd_worker.c | 6 +- 14 files changed, 508 insertions(+), 486 deletions(-)
PATCH 1/12 drbd: Remove "extern" from function declarations
The "extern" keyword is superfluous when declaring a function. Remove that keyword from function declarations to improve consistency with the rest of the kernel source code.
--- drivers/block/drbd/drbd_config.h | 2 +- drivers/block/drbd/drbd_int.h | 576 +++++++++++++------------ drivers/block/drbd/drbd_interval.h | 11 +- drivers/block/drbd/drbd_req.h | 24 +- drivers/block/drbd/drbd_state.h | 35 +- drivers/block/drbd/drbd_state_change.h | 32 +- 6 files changed, 346 insertions(+), 334 deletions(-)
drivers/block/drbd/drbd_config.h +1 -1
@@ -7,7 +7,7 @@#ifndef DRBD_CONFIG_H #define DRBD_CONFIG_H -extern const char *drbd_buildtag (void ); +const char *drbd_buildtag (void );#define REL_VERSION "8.4.11"#define PRO_VERSION_MIN 86
drivers/block/drbd/drbd_int.h +301 -275
706 lines not on this page · raw message
drivers/block/drbd/drbd_interval.h +5 -6
@@ -29,13 +29,12 @@ static inline bool drbd_interval_empty(struct drbd_interval *i)return RB_EMPTY_NODE (&i->rb); } -extern bool drbd_insert_interval (struct rb_root *,struct drbd_interval *); -extern bool drbd_contains_interval (struct rb_root *,sector_t , -struct drbd_interval *); -extern void drbd_remove_interval (struct rb_root *,struct drbd_interval *); -extern struct drbd_interval *drbd_find_overlap (struct rb_root *,sector_t , +bool drbd_insert_interval (struct rb_root *,struct drbd_interval *); +bool drbd_contains_interval (struct rb_root *,sector_t ,struct drbd_interval *); +void drbd_remove_interval (struct rb_root *,struct drbd_interval *); +struct drbd_interval *drbd_find_overlap (struct rb_root *,sector_t ,unsigned int ); -extern struct drbd_interval *drbd_next_overlap (struct drbd_interval *,sector_t , +struct drbd_interval *drbd_next_overlap (struct drbd_interval *,sector_t ,unsigned int );#define drbd_for_each_overlap (i, root, sector, size) \
drivers/block/drbd/drbd_req.h +11 -13
@@ -264,20 +264,18 @@ struct bio_and_error {int error; }; -extern void start_new_tl_epoch (struct drbd_connection *connection); -extern void drbd_req_destroy (struct kref *kref); -extern int __req_mod (struct drbd_request *req,enum drbd_req_event what, -struct drbd_peer_device *peer_device, -struct bio_and_error *m); -extern void complete_master_bio (struct drbd_device *device, -struct bio_and_error *m); -extern void request_timer_fn (struct timer_list *t); -extern void tl_restart (struct drbd_connection *connection,enum drbd_req_event what); -extern void _tl_restart (struct drbd_connection *connection,enum drbd_req_event what); -extern void tl_abort_disk_io (struct drbd_device *device); +void start_new_tl_epoch (struct drbd_connection *connection); +void drbd_req_destroy (struct kref *kref); +int __req_mod (struct drbd_request *req,enum drbd_req_event what, +struct drbd_peer_device *peer_device,struct bio_and_error *m); +void complete_master_bio (struct drbd_device *device,struct bio_and_error *m); +void request_timer_fn (struct timer_list *t); +void tl_restart (struct drbd_connection *connection,enum drbd_req_event what); +void _tl_restart (struct drbd_connection *connection,enum drbd_req_event what); +void tl_abort_disk_io (struct drbd_device *device);/* this is in drbd_main.c */ -extern void drbd_restart_request (struct drbd_request *req); +void drbd_restart_request (struct drbd_request *req);/* use this if you don't want to deal with calling complete_master_bio() * outside the spinlock, e.g. when walking some list on cleanup. */
@@ -319,6 +317,6 @@ static inline int req_mod(struct drbd_request *req, return rv; } -extern bool drbd_should_do_remote (union drbd_dev_state ); +bool drbd_should_do_remote (union drbd_dev_state );#endif
drivers/block/drbd/drbd_state.h +16 -19
@@ -112,26 +112,23 @@ union drbd_dev_state {unsigned int i; }; -extern enum drbd_state_rv drbd_change_state (struct drbd_device *device, -enum chg_state_flags f, -union drbd_state mask, -union drbd_state val); -extern void drbd_force_state (struct drbd_device *,union drbd_state , -union drbd_state ); -extern enum drbd_state_rv _drbd_request_state (struct drbd_device *, -union drbd_state , -union drbd_state , -enum chg_state_flags ); - -extern enum drbd_state_rv +enum drbd_state_rv drbd_change_state (struct drbd_device *device, +enum chg_state_flags f, +union drbd_state mask, +union drbd_state val); +void drbd_force_state (struct drbd_device *,union drbd_state ,union drbd_state ); +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 ); -extern enum drbd_state_rv _drbd_set_state (struct drbd_device *,union drbd_state , -enum chg_state_flags , -struct completion *done); -extern void print_st_err (struct drbd_device *,union drbd_state , -union drbd_state ,enum drbd_state_rv ); +enum drbd_state_rv _drbd_set_state (struct drbd_device *,union drbd_state , +enum chg_state_flags , +struct completion *done); +void print_st_err (struct drbd_device *,union drbd_state ,union drbd_state , +enum drbd_state_rv ); enum drbd_state_rv _conn_request_state(struct drbd_connection *connection, union drbd_state mask, union drbd_state val,
@@ -141,8 +138,8 @@ enum drbd_state_rv conn_request_state(struct drbd_connection *connection, union drbd_state mask, union drbd_state val, enum chg_state_flags flags); -extern void drbd_resume_al (struct drbd_device *device); -extern bool conn_all_vols_unconf (struct drbd_connection *connection); +void drbd_resume_al (struct drbd_device *device); +bool conn_all_vols_unconf (struct drbd_connection *connection);/** * drbd_request_state() - Request a state change
drivers/block/drbd/drbd_state_change.h +12 -20
@@ -40,25 +40,17 @@ struct drbd_state_change { struct drbd_peer_device_state_change *peer_devices; }; -extern struct drbd_state_change *remember_old_state (struct drbd_resource *,gfp_t ); -extern void copy_old_to_new_state_change (struct drbd_state_change *); -extern void forget_state_change (struct drbd_state_change *); - -extern int notify_resource_state_change (struct sk_buff *, -unsigned int , -void *, -enum drbd_notification_type type); -extern int notify_connection_state_change (struct sk_buff *, -unsigned int , -void *, -enum drbd_notification_type type); -extern int notify_device_state_change (struct sk_buff *, -unsigned int , -void *, -enum drbd_notification_type type); -extern int notify_peer_device_state_change (struct sk_buff *, -unsigned int , -void *, -enum drbd_notification_type type); +struct drbd_state_change *remember_old_state (struct drbd_resource *,gfp_t ); +void copy_old_to_new_state_change (struct drbd_state_change *); +void forget_state_change (struct drbd_state_change *); + +int notify_resource_state_change (struct sk_buff *,unsigned int ,void *, +enum drbd_notification_type type); +int notify_connection_state_change (struct sk_buff *,unsigned int ,void *, +enum drbd_notification_type type); +int notify_device_state_change (struct sk_buff *,unsigned int ,void *, +enum drbd_notification_type type); +int notify_peer_device_state_change (struct sk_buff *,unsigned int ,void *, +enum drbd_notification_type type);#endif /* DRBD_STATE_CHANGE_H */
PATCH 2/12 drbd: Retain one _get_ldev_if_state() implementation
In reply to Bart Van AsscheThere are two slightly different _get_ldev_if_state() implementations in the DRBD source code. Keep the version that is used. This does not affect C=1 / C=2 builds because lock context checking is performed by Clang instead of sparse since commit 5b63d0ae94cc ("compiler-context-
analysis: Remove Sparse support").
--- drivers/block/drbd/drbd_int.h | 7 ++----- drivers/block/drbd/drbd_main.c | 19 ------------------- 2 files changed, 2 insertions(+), 24 deletions(-)
drivers/block/drbd/drbd_int.h +2 -5
@@ -2033,8 +2033,8 @@ static inline void put_ldev(struct drbd_device *device) } } -#ifndef __CHECKER__ -static inline int _get_ldev_if_state (struct drbd_device *device,enum drbd_disk_state mins) +static inline int _get_ldev_if_state (struct drbd_device *device, +enum drbd_disk_state mins) {int io_allowed;
@@ -2048,9 +2048,6 @@ static inline int _get_ldev_if_state(struct drbd_device *device, enum drbd_disk_put_ldev (device);return io_allowed; } -#else -int _get_ldev_if_state (struct drbd_device *device,enum drbd_disk_state mins); -#endif /* this throttles on-the-fly application requests * according to max_buffers settings;
drivers/block/drbd/drbd_main.c +0 -19
@@ -128,25 +128,6 @@ static const struct block_device_operations drbd_ops = { .release = drbd_release, }; -#ifdef __CHECKER__ -/* When checking with sparse, and this is an inline function, sparse will -give tons of false positives. When this is a real functions sparse works. -*/ -int _get_ldev_if_state (struct drbd_device *device,enum drbd_disk_state mins) -{ -int io_allowed; - -atomic_inc (&device->local_cnt); - io_allowed = (device->state.disk >= mins); -if (!io_allowed) { -if (atomic_dec_and_test (&device->local_cnt)) -wake_up (&device->misc_wait); - } -return io_allowed; -} - -#endif -/** * tl_release() - mark as BARRIER_ACKED all requests in the corresponding transfer log epoch * @connection: DRBD connection.
PATCH 3/12 drbd: Remove the get_ldev_if_state() macro
In reply to Bart Van AsscheThe get_ldev_if_state() macro has been introduced because sparse does not support something like __cond_acquires(). Remove this macro and rename _get_ldev_if_state() into get_ldev_if_state().
--- drivers/block/drbd/drbd_int.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
drivers/block/drbd/drbd_int.h +2 -5
@@ -2002,9 +2002,6 @@ 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)#define get_ldev (_device) get_ldev_if_state(_device, D_INCONSISTENT)static inline void put_ldev (struct drbd_device *device)
@@ -2033,8 +2030,8 @@ static inline void put_ldev(struct drbd_device *device) } } -static inline int _get_ldev_if_state (struct drbd_device *device, -enum drbd_disk_state mins) +static inline int get_ldev_if_state (struct drbd_device *device, +enum drbd_disk_state mins) {int io_allowed;
PATCH 4/12 drbd: Remove the 'local' lock context
In reply to Bart Van AsscheThe 'local' lock context represents code sections between get_ldev() and put_ldev() calls. Between these two calls the device->ldev pointer is valid. Since there are multiple functions with unpaired get_ldev() / put_ldev() calls, remove this lock context.
--- drivers/block/drbd/drbd_bitmap.c | 17 +++++----- drivers/block/drbd/drbd_int.h | 50 ++++++++++++------------------ drivers/block/drbd/drbd_main.c | 20 ++++++------ drivers/block/drbd/drbd_nl.c | 7 +++-- drivers/block/drbd/drbd_receiver.c | 21 +++++++------ drivers/block/drbd/drbd_worker.c | 6 ++-- 6 files changed, 55 insertions(+), 66 deletions(-)
drivers/block/drbd/drbd_bitmap.c +9 -8
@@ -987,7 +987,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 +1060,8 @@ 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 +1216,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 +1229,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 +1241,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 +1251,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 +1268,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 +1277,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 ); }
drivers/block/drbd/drbd_int.h +19 -31
97 lines not on this page · raw message
drivers/block/drbd/drbd_main.c +10 -10
@@ -3263,7 +3263,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;
@@ -3271,7 +3271,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 )
@@ -3286,7 +3286,7 @@ void __drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(ldrbd_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);
@@ -3294,7 +3294,7 @@ void _drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(lospin_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);
@@ -3313,7 +3313,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;
@@ -3335,7 +3335,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);
@@ -3368,7 +3368,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 ;
@@ -3395,7 +3395,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);
@@ -3522,7 +3522,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);
@@ -3530,7 +3530,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);
drivers/block/drbd/drbd_nl.c +4 -3
@@ -968,8 +968,9 @@ void drbd_resume_io(struct drbd_device *device)* Returns 0 on success, negative return values indicate errors. * 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) +enum determine_dev_size 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;
@@ -3097,7 +3098,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;
drivers/block/drbd/drbd_receiver.c +11 -10
@@ -174,8 +174,9 @@ You must not have the req_lock:* w_same: payload_size == logical_block_size * 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) +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) {struct drbd_device *device = peer_device->device;struct drbd_peer_request *peer_req;
@@ -1657,7 +1658,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);
@@ -1868,8 +1869,8 @@ static int e_end_resync_block(struct drbd_work *w, int unused)return err; } -static int recv_resync_read (struct drbd_peer_device *peer_device,sector_t sector, -struct packet_info *pi)__releases (local) +static int recv_resync_read (struct drbd_peer_device *peer_device, +sector_t sector,struct packet_info *pi) {struct drbd_device *device = peer_device->device;struct drbd_peer_request *peer_req;
@@ -2826,7 +2827,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 +2910,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 +2967,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 +3045,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 +3265,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 ;
drivers/block/drbd/drbd_worker.c +2 -4
@@ -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);
PATCH 5/12 drbd: Simplify the bitmap locking functions.
In reply to Bart Van AsscheCall mutex_lock() instead of mutex_trylock() followed by mutex_lock(). Remove the code that depends on device->bitmap == NULL because this can't happen. All drbd_bm_{lock,unlock}() callers guarantee that the device->bitmap pointer is valid.
--- drivers/block/drbd/drbd_bitmap.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-)
drivers/block/drbd/drbd_bitmap.c +1 -19
@@ -124,22 +124,8 @@ 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) {struct drbd_bitmap *b = device->bitmap; -int trylock_failed; -if (!b) { -drbd_err (device,"FIXME no bitmap in drbd_bm_lock!?\n" ); -return ; - } - - trylock_failed = !mutex_trylock (&b->bm_change); - -if (trylock_failed) { -drbd_warn (device,"%s[%d] going to '%s' but bitmap already locked for '%s' by %s[%d]\n" , - current->comm,task_pid_nr (current), - why, b->bm_why ?:"?" , - b->bm_task->comm,task_pid_nr (b->bm_task)); -mutex_lock (&b->bm_change); - } +mutex_lock (&b->bm_change);if (BM_LOCKED_MASK & b->bm_flags)drbd_err (device,"FIXME bitmap already locked in bm_lock\n" ); b->bm_flags |= flags &BM_LOCKED_MASK ;
@@ -151,10 +137,6 @@ void drbd_bm_lock(struct drbd_device *device, char *why, enum bm_flag flags)void drbd_bm_unlock (struct drbd_device *device) {struct drbd_bitmap *b = device->bitmap; -if (!b) { -drbd_err (device,"FIXME no bitmap in drbd_bm_unlock!?\n" ); -return ; - }if (!(BM_LOCKED_MASK & device->bitmap->bm_flags))drbd_err (device,"FIXME bitmap not locked in bm_unlock\n" );
PATCH 6/12 drbd: Move two declarations
In reply to Bart Van AsscheMove the resources_mutex declaration in front of the functions that acquire and release this mutex. Move the drbd_wait_misc() declaration past the struct drbd_device definition. This patch prepares for adding lock context annotations.
--- drivers/block/drbd/drbd_int.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/block/drbd/drbd_int.h +2 -3
@@ -195,7 +195,7 @@ struct drbd_device_work {#include "drbd_interval.h" -int drbd_wait_misc (struct drbd_device *,struct drbd_interval *); +extern struct mutex resources_mutex;void lock_all_resources (void );void unlock_all_resources (void );
@@ -1094,6 +1094,7 @@ 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);/* Meta data layout *
@@ -1363,8 +1364,6 @@ extern struct bio_set drbd_md_io_bio_set;/* And a bio_set for cloning */ extern struct bio_set drbd_io_bio_set; -extern struct mutex resources_mutex; -enum drbd_ret_code drbd_create_device (struct drbd_config_context *adm_ctx,unsigned int minor);void drbd_destroy_device (struct kref *kref);
PATCH 7/12 drbd: Pass 'resource' directly to complete_conflicting_writes()
In reply to Bart Van AsschePrepare for adding lock context annotations. Without this change, an __assume_ctx_lock() statement would have to be added.
--- drivers/block/drbd/drbd_req.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/block/drbd/drbd_req.c +5 -4
@@ -951,7 +951,8 @@ 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) +static void complete_conflicting_writes (struct drbd_resource *resource, +struct drbd_request *req) {DEFINE_WAIT (wait);struct drbd_device *device = req->device;
@@ -974,9 +975,9 @@ static void complete_conflicting_writes(struct drbd_request *req)/* Indicate to wake up device->misc_wait on progress. */ prepare_to_wait (&device->misc_wait, &wait,TASK_UNINTERRUPTIBLE ); i->waiting = true; -spin_unlock_irq (&device->resource->req_lock); +spin_unlock_irq (&resource->req_lock);schedule (); -spin_lock_irq (&device->resource->req_lock); +spin_lock_irq (&resource->req_lock); }finish_wait (&device->misc_wait, &wait); }
@@ -1329,7 +1330,7 @@ static void drbd_send_and_submit(struct drbd_device *device, struct drbd_request/* This may temporarily give up the req_lock, * but will re-aquire it before it returns here. * Needs to be before the check on drbd_suspended() */ -complete_conflicting_writes (req); +complete_conflicting_writes (resource, req);/* no more giving up req_lock from now on! */ /* check for congestion, and potentially stop sending
PATCH 8/12 drbd: Split drbd_nl_get_connections_dumpit()
In reply to Bart Van AsscheMove the code between the 'put_result' and 'out' labels into a new function. Prepare for making the following code unconditional:
if (resource) mutex_unlock(&resource->conf_update);
--- drivers/block/drbd/drbd_nl.c | 98 ++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 43 deletions(-)
drivers/block/drbd/drbd_nl.c +55 -43
@@ -3529,15 +3529,56 @@ int drbd_adm_dump_connections_done(struct netlink_callback *cb)enum {SINGLE_RESOURCE ,ITERATE_RESOURCES }; +static int drbd_nl_put_dump_connections_result ( +struct sk_buff *skb,struct netlink_callback *cb, +struct drbd_resource *resource, +struct drbd_connection *connection,enum drbd_ret_code retcode) +{ +struct drbd_genlmsghdr *dh; + + dh =genlmsg_put (skb,NETLINK_CB (cb->skb).portid, cb->nlh->nlmsg_seq, + &drbd_nl_family,NLM_F_MULTI , +DRBD_ADM_GET_CONNECTIONS ); +if (!dh) +return -ENOMEM ; + dh->ret_code = retcode; + dh->minor =-1U ; +if (retcode ==NO_ERROR ) { +struct connection_statistics connection_statistics; +struct connection_info connection_info; +struct net_conf *net_conf; +int err; + + err =nla_put_drbd_cfg_context (skb, resource, connection,NULL ); +if (err) +return err; + net_conf =rcu_dereference (connection->net_conf); +if (net_conf) { + err =net_conf_to_skb (skb, net_conf); +if (err) +return err; + } +connection_to_info (&connection_info, connection); + err =connection_info_to_skb (skb, &connection_info); +if (err) +return err; + connection_statistics.conn_congested = +test_bit (NET_CONGESTED , &connection->flags); + err =connection_statistics_to_skb (skb, &connection_statistics); +if (err) +return err; + cb->args[2 ] = (long )connection; + } +genlmsg_end (skb, dh); +return 0 ; +} +int drbd_nl_get_connections_dumpit (struct sk_buff *skb,struct netlink_callback *cb) {struct nlattr *resource_filter;struct drbd_resource *resource =NULL , *next_resource;struct drbd_connection *connection; -int err =0 , retcode; -struct drbd_genlmsghdr *dh; -struct connection_info connection_info; -struct connection_statistics connection_statistics; +int err =0 ;rcu_read_lock (); resource = (struct drbd_resource *)cb->args[0 ];
@@ -3545,10 +3586,13 @@ int drbd_nl_get_connections_dumpit(struct sk_buff *skb, struct netlink_callback resource_filter =find_cfg_context_attr (cb->nlh,DRBD_A_DRBD_CFG_CONTEXT_CTX_RESOURCE_NAME );if (resource_filter) { - retcode =ERR_RES_NOT_KNOWN ; resource =drbd_find_resource (nla_data (resource_filter)); -if (!resource) - goto put_result; +if (!resource) { + err =drbd_nl_put_dump_connections_result ( + skb, cb, resource,NULL , +ERR_RES_NOT_KNOWN ); + goto out; + } cb->args[0 ] = (long )resource; cb->args[1 ] =SINGLE_RESOURCE ; }
@@ -3579,8 +3623,9 @@ int drbd_nl_get_connections_dumpit(struct sk_buff *skb, struct netlink_callbacklist_for_each_entry_continue_rcu (connection, &resource->connections, connections) {if (!has_net_conf (connection))continue ; - retcode =NO_ERROR ; - goto put_result;/* only one iteration */ + err =drbd_nl_put_dump_connections_result (skb, cb, resource, + connection,NO_ERROR ); + goto out;/* only one iteration */ } no_more_connections:
@@ -3603,41 +3648,8 @@ int drbd_nl_get_connections_dumpit(struct sk_buff *skb, struct netlink_callback cb->args[2 ] =0 ; goto next_resource; } - goto out;/* no more resources */ - -put_result: - dh =genlmsg_put (skb,NETLINK_CB (cb->skb).portid, - cb->nlh->nlmsg_seq, &drbd_nl_family, -NLM_F_MULTI ,DRBD_ADM_GET_CONNECTIONS ); - err = -ENOMEM ; -if (!dh) - goto out; - dh->ret_code = retcode; - dh->minor =-1U ; -if (retcode ==NO_ERROR ) { -struct net_conf *net_conf; - err =nla_put_drbd_cfg_context (skb, resource, connection,NULL ); -if (err) - goto out; - net_conf =rcu_dereference (connection->net_conf); -if (net_conf) { - err =net_conf_to_skb (skb, net_conf); -if (err) - goto out; - } -connection_to_info (&connection_info, connection); - err =connection_info_to_skb (skb, &connection_info); -if (err) - goto out; - connection_statistics.conn_congested =test_bit (NET_CONGESTED , &connection->flags); - err =connection_statistics_to_skb (skb, &connection_statistics); -if (err) - goto out; - cb->args[2 ] = (long )connection; - } -genlmsg_end (skb, dh); - err =0 ; +/* no more resources */ out:rcu_read_unlock ();
PATCH 9/12 drbd: Make a mutex_unlock() call unconditional
In reply to Bart Van AsscheOnly jump to the 'out' label if resource is not NULL such that the mutex_unlock() call past the 'out' label can be made unconditional.
--- drivers/block/drbd/drbd_nl.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
drivers/block/drbd/drbd_nl.c +9 -5
@@ -3591,15 +3591,18 @@ int drbd_nl_get_connections_dumpit(struct sk_buff *skb, struct netlink_callback err =drbd_nl_put_dump_connections_result ( skb, cb, resource,NULL ,ERR_RES_NOT_KNOWN ); - goto out; +rcu_read_unlock (); + goto ret; } cb->args[0 ] = (long )resource; cb->args[1 ] =SINGLE_RESOURCE ; } }if (!resource) { -if (list_empty (&drbd_resources)) - goto out; +if (list_empty (&drbd_resources)) { +rcu_read_unlock (); + goto ret; + } resource = list_first_entry(&drbd_resources, struct drbd_resource, resources);kref_get (&resource->kref); cb->args[0 ] = (long )resource;
@@ -3653,8 +3656,9 @@ int drbd_nl_get_connections_dumpit(struct sk_buff *skb, struct netlink_callback out:rcu_read_unlock (); -if (resource) -mutex_unlock (&resource->conf_update); +mutex_unlock (&resource->conf_update); + +ret:if (err)return err;return skb->len;
PATCH 10/12 drbd: Rework locking in drbd_req_state()
In reply to Bart Van AsscheMove all code except a mutex_lock() and a mutex_unlock() call from drbd_req_state() into the new function __drbd_req_state(). Rework locking in drbd_req_state() such that the mutex_lock() and mutex_unlock() calls occur in the same branch of an if-condition.
--- drivers/block/drbd/drbd_state.c | 47 ++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 16 deletions(-)
drivers/block/drbd/drbd_state.c +31 -16
@@ -549,19 +549,10 @@ _req_st_cond(struct drbd_device *device, union drbd_state mask,return rv; } -/** -* drbd_req_state() - Perform an eventually cluster wide state change -* @device: DRBD device. -* @mask: mask of state bits to change. -* @val: value of new state bits. -* @f: flags -* -* Should not be called directly, use drbd_request_state() or -* _drbd_request_state(). -*/ -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) +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) {struct completion done;unsigned long flags;
@@ -571,8 +562,6 @@ drbd_req_state(struct drbd_device *device, union drbd_state mask,init_completion (&done); -if (f &CS_SERIALIZE ) -mutex_lock (device->state_mutex);if (f &CS_INHIBIT_MD_IO ) buffer =drbd_md_get_buffer (device, __func__);
@@ -629,8 +618,34 @@ drbd_req_state(struct drbd_device *device, union drbd_state mask, abort:if (buffer)drbd_md_put_buffer (device); -if (f &CS_SERIALIZE ) + +return rv; +} + +/** +* drbd_req_state() - Perform an eventually cluster wide state change +* @device: DRBD device. +* @mask: mask of state bits to change. +* @val: value of new state bits. +* @f: flags +* +* Should not be called directly, use drbd_request_state() or +* _drbd_request_state(). +*/ +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) +{ +enum drbd_state_rv rv; + +if (f &CS_SERIALIZE ) { +mutex_lock (device->state_mutex); + rv =__drbd_req_state (device, mask, val, f);mutex_unlock (device->state_mutex); + }else { + rv =__drbd_req_state (device, mask, val, f); + }return rv; }
PATCH 11/12 drbd: Annotate drbd_bm_{lock,unlock}()
In reply to Bart Van AsscheAnnotate the bitmap locking functions. Introduce a new token context lock because the struct drbd_device definition is not visible from the drbd_int.h header file. Annotate the declarations of bitmap locking functions with only the token context lock. Annotate the definitions of the bitmap locking functions with both the token context lock and the actual mutex.
--- drivers/block/drbd/drbd_bitmap.c | 6 ++++++ drivers/block/drbd/drbd_int.h | 8 ++++++-- 2 files changed, 12 insertions(+), 2 deletions(-)
drivers/block/drbd/drbd_bitmap.c +6 -0
@@ -122,9 +122,12 @@ 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 (drbd_dev_bm_lock) + __acquires(&device->bitmap->bm_change) {struct drbd_bitmap *b = device->bitmap; +__acquire (drbd_dev_bm_lock);mutex_lock (&b->bm_change);if (BM_LOCKED_MASK & b->bm_flags)drbd_err (device,"FIXME bitmap already locked in bm_lock\n" );
@@ -135,6 +138,8 @@ void drbd_bm_lock(struct drbd_device *device, char *why, enum bm_flag flags) }void drbd_bm_unlock (struct drbd_device *device) +__releases (drbd_dev_bm_lock) + __releases(&device->bitmap->bm_change) {struct drbd_bitmap *b = device->bitmap;
@@ -145,6 +150,7 @@ void drbd_bm_unlock(struct drbd_device *device) b->bm_why =NULL ; b->bm_task =NULL ;mutex_unlock (&b->bm_change); +__release (drbd_dev_bm_lock); }/* we store some "meta" info about our pages in page->private */
drivers/block/drbd/drbd_int.h +6 -2
@@ -1337,8 +1337,12 @@ void drbd_bm_merge_lel(struct drbd_device *device, size_t offset, size_t number,void drbd_bm_get_lel (struct drbd_device *device,size_t offset,size_t number,unsigned long *buffer); -void drbd_bm_lock (struct drbd_device *device,char *why,enum bm_flag flags); -void drbd_bm_unlock (struct drbd_device *device); +token_context_lock (drbd_dev_bm_lock); + +void drbd_bm_lock(struct drbd_device *device, char *why, enum bm_flag flags) + __acquires(drbd_dev_bm_lock); +void drbd_bm_unlock(struct drbd_device *device) + __releases(drbd_dev_bm_lock);/* drbd_main.c */ extern struct kmem_cache *drbd_request_cache;
PATCH 12/12 drbd: Enable lock context analysis
In reply to Bart Van AsscheClang 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.
--- 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 ++ 6 files changed, 32 insertions(+), 9 deletions(-)
drivers/block/drbd/Makefile +3 -0
@@ -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
drivers/block/drbd/drbd_int.h +18 -9
@@ -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);
drivers/block/drbd/drbd_main.c +2 -0
@@ -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;
drivers/block/drbd/drbd_receiver.c +6 -0
@@ -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);
drivers/block/drbd/drbd_req.c +1 -0
@@ -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;
drivers/block/drbd/drbd_state.c +2 -0
@@ -714,6 +714,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;
@@ -2307,6 +2308,7 @@ _conn_rq_cond(struct drbd_connection *connection, union drbd_state mask, union denum 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;
Quoted 6 lines · Bart Van Assche
This patch series enables compile-time lock context analysis for DRBD. The goal of this series is to allow the compiler to statically verify that locks are acquired and released correctly, helping to prevent deadlocks and race conditions. This version addresses feedback received on the v1 series, improves the annotations, and refactors some conditional locking paths to use the modern
cleanup.hguard infrastructure.
Christoph Böhmwalder, are you the right person to help with reviewing this patch series?
Thanks,
Bart.