* [PATCH 08/12] drbd: Split drbd_nl_get_connections_dumpit()
From: Bart Van Assche @ 2026-07-09 21:35 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Marco Elver,
Cc : Christoph Böhmwalder, Bart Van Assche, Philipp Reisner,
Lars Ellenberg
In-Reply-To: <cover.1783632330.git.bvanassche@acm.org>
Move 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);
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/drbd/drbd_nl.c | 98 ++++++++++++++++++++----------------
1 file changed, 55 insertions(+), 43 deletions(-)
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index c44b92856da3..ffcee2e2d1eb 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -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_callback
list_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();
^ permalink raw reply related
* [PATCH 09/12] drbd: Make a mutex_unlock() call unconditional
From: Bart Van Assche @ 2026-07-09 21:35 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Marco Elver,
Cc : Christoph Böhmwalder, Bart Van Assche,
Christoph Hellwig, Philipp Reisner, Lars Ellenberg
In-Reply-To: <cover.1783632330.git.bvanassche@acm.org>
Only jump to the 'out' label if resource is not NULL such that the
mutex_unlock() call past the 'out' label can be made unconditional.
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/drbd/drbd_nl.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index ffcee2e2d1eb..748b1d093f2e 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -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;
^ permalink raw reply related
* [PATCH 04/12] drbd: Remove the 'local' lock context
From: Bart Van Assche @ 2026-07-09 21:35 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Marco Elver,
Cc : Christoph Böhmwalder, Bart Van Assche,
Christoph Hellwig, Philipp Reisner, Lars Ellenberg
In-Reply-To: <cover.1783632330.git.bvanassche@acm.org>
The '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.
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
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(-)
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index 65ea6ec66bfd..1c68f1774e28 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -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);
}
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 49383c309865..4b9d69adb9d4 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1064,18 +1064,14 @@ void conn_md_sync(struct drbd_connection *connection);
void drbd_md_write(struct drbd_device *device, void *buffer);
void drbd_md_sync(struct drbd_device *device);
int drbd_md_read(struct drbd_device *device, struct drbd_backing_dev *bdev);
-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)
- __must_hold(local);
-void drbd_uuid_new_current(struct drbd_device *device) __must_hold(local);
-void drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local);
-void drbd_uuid_move_history(struct drbd_device *device) __must_hold(local);
-void __drbd_uuid_set(struct drbd_device *device, int idx, u64 val)
- __must_hold(local);
-void drbd_md_set_flag(struct drbd_device *device, int flags) __must_hold(local);
-void drbd_md_clear_flag(struct drbd_device *device, int flags)
- __must_hold(local);
+void drbd_uuid_set(struct drbd_device *device, int idx, u64 val);
+void _drbd_uuid_set(struct drbd_device *device, int idx, u64 val);
+void drbd_uuid_new_current(struct drbd_device *device);
+void drbd_uuid_set_bm(struct drbd_device *device, u64 val);
+void drbd_uuid_move_history(struct drbd_device *device);
+void __drbd_uuid_set(struct drbd_device *device, int idx, u64 val);
+void drbd_md_set_flag(struct drbd_device *device, int flags);
+void drbd_md_clear_flag(struct drbd_device *device, int flags);
int drbd_md_test_flag(struct drbd_backing_dev *, int);
void drbd_md_mark_dirty(struct drbd_device *device);
void drbd_queue_bitmap_io(struct drbd_device *device,
@@ -1095,11 +1091,9 @@ int drbd_bitmap_io_from_worker(struct drbd_device *device,
char *why, enum bm_flag flags,
struct drbd_peer_device *peer_device);
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 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
*
@@ -1310,19 +1304,17 @@ void _drbd_bm_set_bits(struct drbd_device *device, const unsigned long s,
int drbd_bm_test_bit(struct drbd_device *device, unsigned long bitnr);
int drbd_bm_e_weight(struct drbd_device *device, unsigned long enr);
int drbd_bm_read(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local);
+ struct drbd_peer_device *peer_device);
void drbd_bm_mark_for_writeout(struct drbd_device *device, int page_nr);
int drbd_bm_write(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local);
-void drbd_bm_reset_al_hints(struct drbd_device *device) __must_hold(local);
-int drbd_bm_write_hinted(struct drbd_device *device) __must_hold(local);
-int drbd_bm_write_lazy(struct drbd_device *device, unsigned upper_idx)
- __must_hold(local);
+ struct drbd_peer_device *peer_device);
+void drbd_bm_reset_al_hints(struct drbd_device *device);
+int drbd_bm_write_hinted(struct drbd_device *device);
+int drbd_bm_write_lazy(struct drbd_device *device, unsigned upper_idx);
int drbd_bm_write_all(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local);
+ struct drbd_peer_device *peer_device);
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);
size_t drbd_bm_words(struct drbd_device *device);
unsigned long drbd_bm_bits(struct drbd_device *device);
sector_t drbd_bm_capacity(struct drbd_device *device);
@@ -1417,8 +1409,7 @@ enum determine_dev_size {
};
enum determine_dev_size drbd_determine_dev_size(struct drbd_device *,
enum dds_flags,
- struct resize_parms *)
- __must_hold(local);
+ struct resize_parms *);
void resync_after_online_grow(struct drbd_device *);
void drbd_reconsider_queue_parameters(struct drbd_device *device,
struct drbd_backing_dev *bdev,
@@ -1502,8 +1493,7 @@ int drbd_submit_peer_request(struct drbd_peer_request *peer_req);
int drbd_free_peer_reqs(struct drbd_device *, struct list_head *);
struct drbd_peer_request *drbd_alloc_peer_req(struct drbd_peer_device *, u64,
sector_t, unsigned int,
- unsigned int, gfp_t)
- __must_hold(local);
+ unsigned int, gfp_t);
void drbd_free_peer_req(struct drbd_device *device,
struct drbd_peer_request *req);
struct page *drbd_alloc_pages(struct drbd_peer_device *, unsigned int, bool);
@@ -1520,7 +1510,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;
@@ -2016,7 +2005,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 dbf6e413db03..d9eb95aa5c44 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -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(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);
@@ -3294,7 +3294,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);
@@ -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);
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index f9ffcd67607b..c44b92856da3 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -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;
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 58b95bf4bdca..4e04ff2dc65d 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -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;
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
* [PATCH 10/12] drbd: Rework locking in drbd_req_state()
From: Bart Van Assche @ 2026-07-09 21:35 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Marco Elver,
Cc : Christoph Böhmwalder, Bart Van Assche, Philipp Reisner,
Lars Ellenberg
In-Reply-To: <cover.1783632330.git.bvanassche@acm.org>
Move 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.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/drbd/drbd_state.c | 47 ++++++++++++++++++++++-----------
1 file changed, 31 insertions(+), 16 deletions(-)
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c
index adcba7f1d8ea..c60c071a666a 100644
--- a/drivers/block/drbd/drbd_state.c
+++ b/drivers/block/drbd/drbd_state.c
@@ -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;
}
^ permalink raw reply related
* [PATCH 11/12] drbd: Annotate drbd_bm_{lock,unlock}()
From: Bart Van Assche @ 2026-07-09 21:35 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Marco Elver,
Cc : Christoph Böhmwalder, Bart Van Assche,
Christoph Hellwig, Philipp Reisner, Lars Ellenberg
In-Reply-To: <cover.1783632330.git.bvanassche@acm.org>
Annotate 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.
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
drivers/block/drbd/drbd_bitmap.c | 6 ++++++
drivers/block/drbd/drbd_int.h | 8 ++++++--
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index e332a96fe90c..d849bd780ca9 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -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 */
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 1f3f2157df8b..7e0e0a0f27ae 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -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;
^ permalink raw reply related
* [PATCH 12/12] drbd: Enable lock context analysis
From: Bart Van Assche @ 2026-07-09 21:35 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Marco Elver,
Cc : Christoph Böhmwalder, Bart Van Assche, Philipp Reisner,
Lars Ellenberg, Nathan Chancellor
In-Reply-To: <cover.1783632330.git.bvanassche@acm.org>
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 <christoph.boehmwalder@linbit.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
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(-)
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 c60c071a666a..416a71d7a61c 100644
--- a/drivers/block/drbd/drbd_state.c
+++ b/drivers/block/drbd/drbd_state.c
@@ -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 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;
^ permalink raw reply related
* [PATCH 01/12] drbd: Remove "extern" from function declarations
From: Bart Van Assche @ 2026-07-09 21:35 UTC (permalink / raw)
To: Jens Axboe
Cc: linux-block, Christoph Hellwig, Marco Elver,
Cc : Christoph Böhmwalder, Bart Van Assche,
Christoph Hellwig, Philipp Reisner, Lars Ellenberg
In-Reply-To: <cover.1783632330.git.bvanassche@acm.org>
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.
Suggested-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
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(-)
diff --git a/drivers/block/drbd/drbd_config.h b/drivers/block/drbd/drbd_config.h
index d215365c6bb1..16a985b30dd3 100644
--- a/drivers/block/drbd/drbd_config.h
+++ b/drivers/block/drbd/drbd_config.h
@@ -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
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 48b45c3142f7..aa39c4d19133 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -109,7 +109,7 @@ extern struct ratelimit_state drbd_ratelimit_state;
extern struct idr drbd_devices; /* RCU, updates: genl_lock() */
extern struct list_head drbd_resources; /* RCU, updates: genl_lock() */
-extern const char *cmdname(enum drbd_packet cmd);
+const char *cmdname(enum drbd_packet cmd);
/* for sending/receiving the bitmap,
* possibly in some encoding scheme */
@@ -129,8 +129,8 @@ struct bm_xfer_ctx {
unsigned bytes[2];
};
-extern void INFO_bm_xfer_stats(struct drbd_peer_device *peer_device,
- const char *direction, struct bm_xfer_ctx *c);
+void INFO_bm_xfer_stats(struct drbd_peer_device *peer_device,
+ const char *direction, struct bm_xfer_ctx *c);
static inline void bm_xfer_ctx_bit_to_word_offset(struct bm_xfer_ctx *c)
{
@@ -151,7 +151,7 @@ static inline void bm_xfer_ctx_bit_to_word_offset(struct bm_xfer_ctx *c)
#endif
}
-extern unsigned int drbd_header_size(struct drbd_connection *connection);
+unsigned int drbd_header_size(struct drbd_connection *connection);
/**********************************************************************/
enum drbd_thread_state {
@@ -195,10 +195,10 @@ struct drbd_device_work {
#include "drbd_interval.h"
-extern int drbd_wait_misc(struct drbd_device *, struct drbd_interval *);
+int drbd_wait_misc(struct drbd_device *, struct drbd_interval *);
-extern void lock_all_resources(void);
-extern void unlock_all_resources(void);
+void lock_all_resources(void);
+void unlock_all_resources(void);
struct drbd_request {
struct drbd_work w;
@@ -559,7 +559,7 @@ struct fifo_buffer {
int total; /* sum of all values */
int values[] __counted_by(size);
};
-extern struct fifo_buffer *fifo_alloc(unsigned int fifo_size);
+struct fifo_buffer *fifo_alloc(unsigned int fifo_size);
/* flag bits per connection */
enum {
@@ -998,93 +998,108 @@ enum dds_flags {
DDSF_NO_RESYNC = 2, /* Do not run a resync for the new space */
};
-extern void drbd_init_set_defaults(struct drbd_device *device);
-extern int drbd_thread_start(struct drbd_thread *thi);
-extern void _drbd_thread_stop(struct drbd_thread *thi, int restart, int wait);
+void drbd_init_set_defaults(struct drbd_device *device);
+int drbd_thread_start(struct drbd_thread *thi);
+void _drbd_thread_stop(struct drbd_thread *thi, int restart, int wait);
#ifdef CONFIG_SMP
-extern void drbd_thread_current_set_cpu(struct drbd_thread *thi);
+void drbd_thread_current_set_cpu(struct drbd_thread *thi);
#else
#define drbd_thread_current_set_cpu(A) ({})
#endif
-extern void tl_release(struct drbd_connection *, unsigned int barrier_nr,
- unsigned int set_size);
-extern void tl_clear(struct drbd_connection *);
-extern void drbd_free_sock(struct drbd_connection *connection);
-extern int drbd_send(struct drbd_connection *connection, struct socket *sock,
- void *buf, size_t size, unsigned msg_flags);
-extern int drbd_send_all(struct drbd_connection *, struct socket *, void *, size_t,
- unsigned);
-
-extern int __drbd_send_protocol(struct drbd_connection *connection, enum drbd_packet cmd);
-extern int drbd_send_protocol(struct drbd_connection *connection);
-extern int drbd_send_uuids(struct drbd_peer_device *);
-extern int drbd_send_uuids_skip_initial_sync(struct drbd_peer_device *);
-extern void drbd_gen_and_send_sync_uuid(struct drbd_peer_device *);
-extern int drbd_send_sizes(struct drbd_peer_device *, int trigger_reply, enum dds_flags flags);
-extern int drbd_send_state(struct drbd_peer_device *, union drbd_state s);
-extern int drbd_send_current_state(struct drbd_peer_device *);
-extern int drbd_send_sync_param(struct drbd_peer_device *);
-extern void drbd_send_b_ack(struct drbd_connection *connection, u32 barrier_nr,
- u32 set_size);
-extern int drbd_send_ack(struct drbd_peer_device *, enum drbd_packet,
- struct drbd_peer_request *);
-extern void drbd_send_ack_rp(struct drbd_peer_device *, enum drbd_packet,
- struct p_block_req *rp);
-extern void drbd_send_ack_dp(struct drbd_peer_device *, enum drbd_packet,
- struct p_data *dp, int data_size);
-extern int drbd_send_ack_ex(struct drbd_peer_device *, enum drbd_packet,
- sector_t sector, int blksize, u64 block_id);
-extern int drbd_send_out_of_sync(struct drbd_peer_device *, struct drbd_request *);
-extern int drbd_send_block(struct drbd_peer_device *, enum drbd_packet,
- struct drbd_peer_request *);
-extern int drbd_send_dblock(struct drbd_peer_device *, struct drbd_request *req);
-extern int drbd_send_drequest(struct drbd_peer_device *, int cmd,
- sector_t sector, int size, u64 block_id);
-extern int drbd_send_drequest_csum(struct drbd_peer_device *, sector_t sector,
- int size, void *digest, int digest_size,
- enum drbd_packet cmd);
-extern int drbd_send_ov_request(struct drbd_peer_device *, sector_t sector, int size);
-
-extern int drbd_send_bitmap(struct drbd_device *device, struct drbd_peer_device *peer_device);
-extern void drbd_send_sr_reply(struct drbd_peer_device *, enum drbd_state_rv retcode);
-extern void conn_send_sr_reply(struct drbd_connection *connection, enum drbd_state_rv retcode);
-extern int drbd_send_rs_deallocated(struct drbd_peer_device *, struct drbd_peer_request *);
-extern void drbd_backing_dev_free(struct drbd_device *device, struct drbd_backing_dev *ldev);
-extern void drbd_device_cleanup(struct drbd_device *device);
-extern void drbd_print_uuids(struct drbd_device *device, const char *text);
-extern void drbd_queue_unplug(struct drbd_device *device);
-
-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 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,
- int (*io_fn)(struct drbd_device *, struct drbd_peer_device *),
- void (*done)(struct drbd_device *, int),
- char *why, enum bm_flag flags,
- struct drbd_peer_device *peer_device);
-extern int drbd_bitmap_io(struct drbd_device *device,
- int (*io_fn)(struct drbd_device *, struct drbd_peer_device *),
- char *why, enum bm_flag flags,
- struct drbd_peer_device *peer_device);
-extern int drbd_bitmap_io_from_worker(struct drbd_device *device,
- int (*io_fn)(struct drbd_device *, struct drbd_peer_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);
-extern int drbd_bmio_clear_n_write(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local);
+void tl_release(struct drbd_connection *, unsigned int barrier_nr,
+ unsigned int set_size);
+void tl_clear(struct drbd_connection *);
+void drbd_free_sock(struct drbd_connection *connection);
+int drbd_send(struct drbd_connection *connection, struct socket *sock,
+ void *buf, size_t size, unsigned msg_flags);
+int drbd_send_all(struct drbd_connection *, struct socket *, void *, size_t,
+ unsigned);
+
+int __drbd_send_protocol(struct drbd_connection *connection,
+ enum drbd_packet cmd);
+int drbd_send_protocol(struct drbd_connection *connection);
+int drbd_send_uuids(struct drbd_peer_device *);
+int drbd_send_uuids_skip_initial_sync(struct drbd_peer_device *);
+void drbd_gen_and_send_sync_uuid(struct drbd_peer_device *);
+int drbd_send_sizes(struct drbd_peer_device *, int trigger_reply,
+ enum dds_flags flags);
+int drbd_send_state(struct drbd_peer_device *, union drbd_state s);
+int drbd_send_current_state(struct drbd_peer_device *);
+int drbd_send_sync_param(struct drbd_peer_device *);
+void drbd_send_b_ack(struct drbd_connection *connection, u32 barrier_nr,
+ u32 set_size);
+int drbd_send_ack(struct drbd_peer_device *, enum drbd_packet,
+ struct drbd_peer_request *);
+void drbd_send_ack_rp(struct drbd_peer_device *, enum drbd_packet,
+ struct p_block_req *rp);
+void drbd_send_ack_dp(struct drbd_peer_device *, enum drbd_packet,
+ struct p_data *dp, int data_size);
+int drbd_send_ack_ex(struct drbd_peer_device *, enum drbd_packet,
+ sector_t sector, int blksize, u64 block_id);
+int drbd_send_out_of_sync(struct drbd_peer_device *, struct drbd_request *);
+int drbd_send_block(struct drbd_peer_device *, enum drbd_packet,
+ struct drbd_peer_request *);
+int drbd_send_dblock(struct drbd_peer_device *, struct drbd_request *req);
+int drbd_send_drequest(struct drbd_peer_device *, int cmd, sector_t sector,
+ int size, u64 block_id);
+int drbd_send_drequest_csum(struct drbd_peer_device *, sector_t sector,
+ int size, void *digest, int digest_size,
+ enum drbd_packet cmd);
+int drbd_send_ov_request(struct drbd_peer_device *, sector_t sector, int size);
+
+int drbd_send_bitmap(struct drbd_device *device,
+ struct drbd_peer_device *peer_device);
+void drbd_send_sr_reply(struct drbd_peer_device *, enum drbd_state_rv retcode);
+void conn_send_sr_reply(struct drbd_connection *connection,
+ enum drbd_state_rv retcode);
+int drbd_send_rs_deallocated(struct drbd_peer_device *,
+ struct drbd_peer_request *);
+void drbd_backing_dev_free(struct drbd_device *device,
+ struct drbd_backing_dev *ldev);
+void drbd_device_cleanup(struct drbd_device *device);
+void drbd_print_uuids(struct drbd_device *device, const char *text);
+void drbd_queue_unplug(struct drbd_device *device);
+
+void conn_md_sync(struct drbd_connection *connection);
+void drbd_md_write(struct drbd_device *device, void *buffer);
+void drbd_md_sync(struct drbd_device *device);
+int drbd_md_read(struct drbd_device *device, struct drbd_backing_dev *bdev);
+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)
+ __must_hold(local);
+void drbd_uuid_new_current(struct drbd_device *device) __must_hold(local);
+void drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local);
+void drbd_uuid_move_history(struct drbd_device *device) __must_hold(local);
+void __drbd_uuid_set(struct drbd_device *device, int idx, u64 val)
+ __must_hold(local);
+void drbd_md_set_flag(struct drbd_device *device, int flags) __must_hold(local);
+void drbd_md_clear_flag(struct drbd_device *device, int flags)
+ __must_hold(local);
+int drbd_md_test_flag(struct drbd_backing_dev *, int);
+void drbd_md_mark_dirty(struct drbd_device *device);
+void drbd_queue_bitmap_io(struct drbd_device *device,
+ int (*io_fn)(struct drbd_device *,
+ struct drbd_peer_device *),
+ void (*done)(struct drbd_device *, int), char *why,
+ enum bm_flag flags,
+ struct drbd_peer_device *peer_device);
+int drbd_bitmap_io(struct drbd_device *device,
+ int (*io_fn)(struct drbd_device *,
+ struct drbd_peer_device *),
+ char *why, enum bm_flag flags,
+ struct drbd_peer_device *peer_device);
+int drbd_bitmap_io_from_worker(struct drbd_device *device,
+ int (*io_fn)(struct drbd_device *,
+ struct drbd_peer_device *),
+ char *why, enum bm_flag flags,
+ struct drbd_peer_device *peer_device);
+int drbd_bmio_set_n_write(struct drbd_device *device,
+ struct drbd_peer_device *peer_device)
+ __must_hold(local);
+int drbd_bmio_clear_n_write(struct drbd_device *device,
+ struct drbd_peer_device *peer_device)
+ __must_hold(local);
/* Meta data layout
*
@@ -1275,56 +1290,62 @@ struct bm_extent {
#define DRBD_MAX_BATCH_BIO_SIZE (AL_UPDATES_PER_TRANSACTION/2*AL_EXTENT_SIZE)
#define DRBD_MAX_BBIO_SECTORS (DRBD_MAX_BATCH_BIO_SIZE >> 9)
-extern int drbd_bm_init(struct drbd_device *device);
-extern int drbd_bm_resize(struct drbd_device *device, sector_t sectors, int set_new_bits);
-extern void drbd_bm_cleanup(struct drbd_device *device);
-extern void drbd_bm_set_all(struct drbd_device *device);
-extern void drbd_bm_clear_all(struct drbd_device *device);
+int drbd_bm_init(struct drbd_device *device);
+int drbd_bm_resize(struct drbd_device *device, sector_t sectors,
+ int set_new_bits);
+void drbd_bm_cleanup(struct drbd_device *device);
+void drbd_bm_set_all(struct drbd_device *device);
+void drbd_bm_clear_all(struct drbd_device *device);
/* set/clear/test only a few bits at a time */
-extern int drbd_bm_set_bits(
- struct drbd_device *device, unsigned long s, unsigned long e);
-extern int drbd_bm_clear_bits(
- struct drbd_device *device, unsigned long s, unsigned long e);
-extern int drbd_bm_count_bits(
- struct drbd_device *device, const unsigned long s, const unsigned long e);
+int drbd_bm_set_bits(struct drbd_device *device, unsigned long s,
+ unsigned long e);
+int drbd_bm_clear_bits(struct drbd_device *device, unsigned long s,
+ unsigned long e);
+int drbd_bm_count_bits(struct drbd_device *device, const unsigned long s,
+ const unsigned long e);
/* bm_set_bits variant for use while holding drbd_bm_lock,
* may process the whole bitmap in one go */
-extern void _drbd_bm_set_bits(struct drbd_device *device,
- const unsigned long s, const unsigned long e);
-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);
-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);
-extern int drbd_bm_write_all(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local);
-extern int drbd_bm_write_copy_pages(struct drbd_device *device,
- struct drbd_peer_device *peer_device) __must_hold(local);
-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);
+void _drbd_bm_set_bits(struct drbd_device *device, const unsigned long s,
+ const unsigned long e);
+int drbd_bm_test_bit(struct drbd_device *device, unsigned long bitnr);
+int drbd_bm_e_weight(struct drbd_device *device, unsigned long enr);
+int drbd_bm_read(struct drbd_device *device,
+ struct drbd_peer_device *peer_device) __must_hold(local);
+void drbd_bm_mark_for_writeout(struct drbd_device *device, int page_nr);
+int drbd_bm_write(struct drbd_device *device,
+ struct drbd_peer_device *peer_device) __must_hold(local);
+void drbd_bm_reset_al_hints(struct drbd_device *device) __must_hold(local);
+int drbd_bm_write_hinted(struct drbd_device *device) __must_hold(local);
+int drbd_bm_write_lazy(struct drbd_device *device, unsigned upper_idx)
+ __must_hold(local);
+int drbd_bm_write_all(struct drbd_device *device,
+ struct drbd_peer_device *peer_device) __must_hold(local);
+int drbd_bm_write_copy_pages(struct drbd_device *device,
+ struct drbd_peer_device *peer_device)
+ __must_hold(local);
+size_t drbd_bm_words(struct drbd_device *device);
+unsigned long drbd_bm_bits(struct drbd_device *device);
+sector_t drbd_bm_capacity(struct drbd_device *device);
#define DRBD_END_OF_BITMAP (~(unsigned long)0)
-extern unsigned long drbd_bm_find_next(struct drbd_device *device, unsigned long bm_fo);
+unsigned long drbd_bm_find_next(struct drbd_device *device,
+ unsigned long bm_fo);
/* bm_find_next variants for use while you hold drbd_bm_lock() */
-extern unsigned long _drbd_bm_find_next(struct drbd_device *device, unsigned long bm_fo);
-extern unsigned long _drbd_bm_find_next_zero(struct drbd_device *device, unsigned long bm_fo);
-extern unsigned long _drbd_bm_total_weight(struct drbd_device *device);
-extern unsigned long drbd_bm_total_weight(struct drbd_device *device);
+unsigned long _drbd_bm_find_next(struct drbd_device *device,
+ unsigned long bm_fo);
+unsigned long _drbd_bm_find_next_zero(struct drbd_device *device,
+ unsigned long bm_fo);
+unsigned long _drbd_bm_total_weight(struct drbd_device *device);
+unsigned long drbd_bm_total_weight(struct drbd_device *device);
/* for receive_bitmap */
-extern void drbd_bm_merge_lel(struct drbd_device *device, size_t offset,
- size_t number, unsigned long *buffer);
+void drbd_bm_merge_lel(struct drbd_device *device, size_t offset, size_t number,
+ unsigned long *buffer);
/* for _drbd_send_bitmap */
-extern void drbd_bm_get_lel(struct drbd_device *device, size_t offset,
- size_t number, unsigned long *buffer);
+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);
+void drbd_bm_lock(struct drbd_device *device, char *why, enum bm_flag flags);
+void drbd_bm_unlock(struct drbd_device *device);
/* drbd_main.c */
extern struct kmem_cache *drbd_request_cache;
@@ -1352,35 +1373,39 @@ extern struct bio_set drbd_io_bio_set;
extern struct mutex resources_mutex;
-extern enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsigned int minor);
-extern void drbd_destroy_device(struct kref *kref);
-extern void drbd_delete_device(struct drbd_device *device);
-
-extern struct drbd_resource *drbd_create_resource(const char *name);
-extern void drbd_free_resource(struct drbd_resource *resource);
-
-extern int set_resource_options(struct drbd_resource *resource, struct res_opts *res_opts);
-extern struct drbd_connection *conn_create(const char *name, struct res_opts *res_opts);
-extern void drbd_destroy_connection(struct kref *kref);
-extern struct drbd_connection *conn_get_by_addrs(void *my_addr, int my_addr_len,
- void *peer_addr, int peer_addr_len);
-extern struct drbd_resource *drbd_find_resource(const char *name);
-extern void drbd_destroy_resource(struct kref *kref);
-extern void conn_free_crypto(struct drbd_connection *connection);
+enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx,
+ unsigned int minor);
+void drbd_destroy_device(struct kref *kref);
+void drbd_delete_device(struct drbd_device *device);
+
+struct drbd_resource *drbd_create_resource(const char *name);
+void drbd_free_resource(struct drbd_resource *resource);
+
+int set_resource_options(struct drbd_resource *resource,
+ struct res_opts *res_opts);
+struct drbd_connection *conn_create(const char *name,
+ struct res_opts *res_opts);
+void drbd_destroy_connection(struct kref *kref);
+struct drbd_connection *conn_get_by_addrs(void *my_addr, int my_addr_len,
+ void *peer_addr, int peer_addr_len);
+struct drbd_resource *drbd_find_resource(const char *name);
+void drbd_destroy_resource(struct kref *kref);
+void conn_free_crypto(struct drbd_connection *connection);
/* drbd_req */
-extern void do_submit(struct work_struct *ws);
-extern void __drbd_make_request(struct drbd_device *, struct bio *);
+void do_submit(struct work_struct *ws);
+void __drbd_make_request(struct drbd_device *, struct bio *);
void drbd_submit_bio(struct bio *bio);
/* drbd_nl.c */
extern struct mutex notification_mutex;
-extern void drbd_suspend_io(struct drbd_device *device);
-extern void drbd_resume_io(struct drbd_device *device);
-extern char *ppsize(char *buf, unsigned long long size);
-extern sector_t drbd_new_dev_size(struct drbd_device *, struct drbd_backing_dev *, sector_t, int);
+void drbd_suspend_io(struct drbd_device *device);
+void drbd_resume_io(struct drbd_device *device);
+char *ppsize(char *buf, unsigned long long size);
+sector_t drbd_new_dev_size(struct drbd_device *, struct drbd_backing_dev *,
+ sector_t, int);
enum determine_dev_size {
DS_ERROR_SHRINK = -3,
DS_ERROR_SPACE_MD = -2,
@@ -1390,41 +1415,46 @@ enum determine_dev_size {
DS_GREW = 2,
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);
-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);
-extern enum drbd_state_rv drbd_set_role(struct drbd_device *device,
- enum drbd_role new_role,
- int force);
-extern bool conn_try_outdate_peer(struct drbd_connection *connection);
-extern void conn_try_outdate_peer_async(struct drbd_connection *connection);
-extern enum drbd_peer_state conn_khelper(struct drbd_connection *connection, char *cmd);
-extern int drbd_khelper(struct drbd_device *device, char *cmd);
+enum determine_dev_size drbd_determine_dev_size(struct drbd_device *,
+ enum dds_flags,
+ struct resize_parms *)
+ __must_hold(local);
+void resync_after_online_grow(struct drbd_device *);
+void drbd_reconsider_queue_parameters(struct drbd_device *device,
+ struct drbd_backing_dev *bdev,
+ struct o_qlim *o);
+enum drbd_state_rv drbd_set_role(struct drbd_device *device,
+ enum drbd_role new_role, int force);
+bool conn_try_outdate_peer(struct drbd_connection *connection);
+void conn_try_outdate_peer_async(struct drbd_connection *connection);
+enum drbd_peer_state conn_khelper(struct drbd_connection *connection,
+ char *cmd);
+int drbd_khelper(struct drbd_device *device, char *cmd);
/* drbd_worker.c */
/* bi_end_io handlers */
-extern void drbd_md_endio(struct bio *bio);
-extern void drbd_peer_request_endio(struct bio *bio);
-extern void drbd_request_endio(struct bio *bio);
-extern int drbd_worker(struct drbd_thread *thi);
+void drbd_md_endio(struct bio *bio);
+void drbd_peer_request_endio(struct bio *bio);
+void drbd_request_endio(struct bio *bio);
+int drbd_worker(struct drbd_thread *thi);
enum drbd_ret_code drbd_resync_after_valid(struct drbd_device *device, int o_minor);
void drbd_resync_after_changed(struct drbd_device *device);
-extern void drbd_start_resync(struct drbd_device *device, enum drbd_conns side);
-extern void resume_next_sg(struct drbd_device *device);
-extern void suspend_other_sg(struct drbd_device *device);
-extern int drbd_resync_finished(struct drbd_peer_device *peer_device);
+void drbd_start_resync(struct drbd_device *device, enum drbd_conns side);
+void resume_next_sg(struct drbd_device *device);
+void suspend_other_sg(struct drbd_device *device);
+int drbd_resync_finished(struct drbd_peer_device *peer_device);
/* maybe rather drbd_main.c ? */
-extern void *drbd_md_get_buffer(struct drbd_device *device, const char *intent);
-extern void drbd_md_put_buffer(struct drbd_device *device);
-extern int drbd_md_sync_page_io(struct drbd_device *device,
- struct drbd_backing_dev *bdev, sector_t sector, enum req_op op);
-extern void drbd_ov_out_of_sync_found(struct drbd_peer_device *peer_device,
- sector_t sector, int size);
-extern void wait_until_done_or_force_detached(struct drbd_device *device,
- struct drbd_backing_dev *bdev, unsigned int *done);
-extern void drbd_rs_controller_reset(struct drbd_peer_device *peer_device);
+void *drbd_md_get_buffer(struct drbd_device *device, const char *intent);
+void drbd_md_put_buffer(struct drbd_device *device);
+int drbd_md_sync_page_io(struct drbd_device *device,
+ struct drbd_backing_dev *bdev, sector_t sector,
+ enum req_op op);
+void drbd_ov_out_of_sync_found(struct drbd_peer_device *peer_device,
+ sector_t sector, int size);
+void wait_until_done_or_force_detached(struct drbd_device *device,
+ struct drbd_backing_dev *bdev,
+ unsigned int *done);
+void drbd_rs_controller_reset(struct drbd_peer_device *peer_device);
static inline void ov_out_of_sync_print(struct drbd_peer_device *peer_device)
{
@@ -1438,48 +1468,48 @@ static inline void ov_out_of_sync_print(struct drbd_peer_device *peer_device)
device->ov_last_oos_size = 0;
}
-
-extern void drbd_csum_bio(struct crypto_shash *, struct bio *, void *);
-extern void drbd_csum_ee(struct crypto_shash *, struct drbd_peer_request *,
- void *);
+void drbd_csum_bio(struct crypto_shash *, struct bio *, void *);
+void drbd_csum_ee(struct crypto_shash *, struct drbd_peer_request *, void *);
/* worker callbacks */
-extern int w_e_end_data_req(struct drbd_work *, int);
-extern int w_e_end_rsdata_req(struct drbd_work *, int);
-extern int w_e_end_csum_rs_req(struct drbd_work *, int);
-extern int w_e_end_ov_reply(struct drbd_work *, int);
-extern int w_e_end_ov_req(struct drbd_work *, int);
-extern int w_ov_finished(struct drbd_work *, int);
-extern int w_resync_timer(struct drbd_work *, int);
-extern int w_send_write_hint(struct drbd_work *, int);
-extern int w_send_dblock(struct drbd_work *, int);
-extern int w_send_read_req(struct drbd_work *, int);
-extern int w_restart_disk_io(struct drbd_work *, int);
-extern int w_send_out_of_sync(struct drbd_work *, int);
-
-extern void resync_timer_fn(struct timer_list *t);
-extern void start_resync_timer_fn(struct timer_list *t);
-
-extern void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req);
+int w_e_end_data_req(struct drbd_work *, int);
+int w_e_end_rsdata_req(struct drbd_work *, int);
+int w_e_end_csum_rs_req(struct drbd_work *, int);
+int w_e_end_ov_reply(struct drbd_work *, int);
+int w_e_end_ov_req(struct drbd_work *, int);
+int w_ov_finished(struct drbd_work *, int);
+int w_resync_timer(struct drbd_work *, int);
+int w_send_write_hint(struct drbd_work *, int);
+int w_send_dblock(struct drbd_work *, int);
+int w_send_read_req(struct drbd_work *, int);
+int w_restart_disk_io(struct drbd_work *, int);
+int w_send_out_of_sync(struct drbd_work *, int);
+
+void resync_timer_fn(struct timer_list *t);
+void start_resync_timer_fn(struct timer_list *t);
+
+void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req);
/* drbd_receiver.c */
-extern int drbd_issue_discard_or_zero_out(struct drbd_device *device,
- sector_t start, unsigned int nr_sectors, int flags);
-extern int drbd_receiver(struct drbd_thread *thi);
-extern int drbd_ack_receiver(struct drbd_thread *thi);
-extern void drbd_send_acks_wf(struct work_struct *ws);
-extern bool drbd_rs_c_min_rate_throttle(struct drbd_device *device);
-extern bool drbd_rs_should_slow_down(struct drbd_peer_device *peer_device, sector_t sector,
- 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,
- sector_t, unsigned int,
- unsigned int,
- gfp_t) __must_hold(local);
-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);
-extern int drbd_connected(struct drbd_peer_device *);
+int drbd_issue_discard_or_zero_out(struct drbd_device *device, sector_t start,
+ unsigned int nr_sectors, int flags);
+int drbd_receiver(struct drbd_thread *thi);
+int drbd_ack_receiver(struct drbd_thread *thi);
+void drbd_send_acks_wf(struct work_struct *ws);
+bool drbd_rs_c_min_rate_throttle(struct drbd_device *device);
+bool drbd_rs_should_slow_down(struct drbd_peer_device *peer_device,
+ sector_t sector, bool throttle_if_app_is_waiting);
+int drbd_submit_peer_request(struct drbd_peer_request *peer_req);
+int drbd_free_peer_reqs(struct drbd_device *, struct list_head *);
+struct drbd_peer_request *drbd_alloc_peer_req(struct drbd_peer_device *, u64,
+ sector_t, unsigned int,
+ unsigned int, gfp_t)
+ __must_hold(local);
+void drbd_free_peer_req(struct drbd_device *device,
+ struct drbd_peer_request *req);
+struct page *drbd_alloc_pages(struct drbd_peer_device *, unsigned int, bool);
+void _drbd_clear_done_ee(struct drbd_device *device,
+ struct list_head *to_be_freed);
+int drbd_connected(struct drbd_peer_device *);
/* sets the number of 512 byte sectors of our virtual device */
void drbd_set_my_capacity(struct drbd_device *device, sector_t size);
@@ -1512,32 +1542,36 @@ extern struct proc_dir_entry *drbd_proc;
int drbd_seq_show(struct seq_file *seq, void *v);
/* drbd_actlog.c */
-extern bool drbd_al_begin_io_prepare(struct drbd_device *device, struct drbd_interval *i);
-extern int drbd_al_begin_io_nonblock(struct drbd_device *device, struct drbd_interval *i);
-extern void drbd_al_begin_io_commit(struct drbd_device *device);
-extern bool drbd_al_begin_io_fastpath(struct drbd_device *device, struct drbd_interval *i);
-extern void drbd_al_begin_io(struct drbd_device *device, struct drbd_interval *i);
-extern void drbd_al_complete_io(struct drbd_device *device, struct drbd_interval *i);
-extern void drbd_rs_complete_io(struct drbd_device *device, sector_t sector);
-extern int drbd_rs_begin_io(struct drbd_device *device, sector_t sector);
-extern int drbd_try_rs_begin_io(struct drbd_peer_device *peer_device, sector_t sector);
-extern void drbd_rs_cancel_all(struct drbd_device *device);
-extern int drbd_rs_del_all(struct drbd_device *device);
-extern void drbd_rs_failed_io(struct drbd_peer_device *peer_device,
- sector_t sector, int size);
-extern void drbd_advance_rs_marks(struct drbd_peer_device *peer_device, unsigned long still_to_go);
+bool drbd_al_begin_io_prepare(struct drbd_device *device,
+ struct drbd_interval *i);
+int drbd_al_begin_io_nonblock(struct drbd_device *device,
+ struct drbd_interval *i);
+void drbd_al_begin_io_commit(struct drbd_device *device);
+bool drbd_al_begin_io_fastpath(struct drbd_device *device,
+ struct drbd_interval *i);
+void drbd_al_begin_io(struct drbd_device *device, struct drbd_interval *i);
+void drbd_al_complete_io(struct drbd_device *device, struct drbd_interval *i);
+void drbd_rs_complete_io(struct drbd_device *device, sector_t sector);
+int drbd_rs_begin_io(struct drbd_device *device, sector_t sector);
+int drbd_try_rs_begin_io(struct drbd_peer_device *peer_device, sector_t sector);
+void drbd_rs_cancel_all(struct drbd_device *device);
+int drbd_rs_del_all(struct drbd_device *device);
+void drbd_rs_failed_io(struct drbd_peer_device *peer_device, sector_t sector,
+ int size);
+void drbd_advance_rs_marks(struct drbd_peer_device *peer_device,
+ unsigned long still_to_go);
enum update_sync_bits_mode { RECORD_RS_FAILED, SET_OUT_OF_SYNC, SET_IN_SYNC };
-extern int __drbd_change_sync(struct drbd_peer_device *peer_device, sector_t sector, int size,
- enum update_sync_bits_mode mode);
+int __drbd_change_sync(struct drbd_peer_device *peer_device, sector_t sector,
+ int size, enum update_sync_bits_mode mode);
#define drbd_set_in_sync(peer_device, sector, size) \
__drbd_change_sync(peer_device, sector, size, SET_IN_SYNC)
#define drbd_set_out_of_sync(peer_device, sector, size) \
__drbd_change_sync(peer_device, sector, size, SET_OUT_OF_SYNC)
#define drbd_rs_failed_io(peer_device, sector, size) \
__drbd_change_sync(peer_device, sector, size, RECORD_RS_FAILED)
-extern void drbd_al_shrink(struct drbd_device *device);
-extern int drbd_al_initialize(struct drbd_device *, void *);
+void drbd_al_shrink(struct drbd_device *device);
+int drbd_al_initialize(struct drbd_device *, void *);
/* drbd_nl.c */
/* state info broadcast */
@@ -1556,28 +1590,20 @@ struct sib_info {
};
void drbd_bcast_event(struct drbd_device *device, const struct sib_info *sib);
-extern int notify_resource_state(struct sk_buff *,
- unsigned int,
- struct drbd_resource *,
- struct resource_info *,
- enum drbd_notification_type);
-extern int notify_device_state(struct sk_buff *,
- unsigned int,
- struct drbd_device *,
- struct device_info *,
- enum drbd_notification_type);
-extern int notify_connection_state(struct sk_buff *,
- unsigned int,
- struct drbd_connection *,
- struct connection_info *,
- enum drbd_notification_type);
-extern int notify_peer_device_state(struct sk_buff *,
- unsigned int,
- struct drbd_peer_device *,
- struct peer_device_info *,
- enum drbd_notification_type);
-extern void notify_helper(enum drbd_notification_type, struct drbd_device *,
- struct drbd_connection *, const char *, int);
+int notify_resource_state(struct sk_buff *, unsigned int,
+ struct drbd_resource *, struct resource_info *,
+ enum drbd_notification_type);
+int notify_device_state(struct sk_buff *, unsigned int, struct drbd_device *,
+ struct device_info *, enum drbd_notification_type);
+int notify_connection_state(struct sk_buff *, unsigned int,
+ struct drbd_connection *, struct connection_info *,
+ enum drbd_notification_type);
+int notify_peer_device_state(struct sk_buff *, unsigned int,
+ struct drbd_peer_device *,
+ struct peer_device_info *,
+ enum drbd_notification_type);
+void notify_helper(enum drbd_notification_type, struct drbd_device *,
+ struct drbd_connection *, const char *, int);
/*
* inline helper functions
@@ -1822,7 +1848,7 @@ drbd_device_post_work(struct drbd_device *device, int work_bit)
}
}
-extern void drbd_flush_workqueue(struct drbd_work_queue *work_queue);
+void drbd_flush_workqueue(struct drbd_work_queue *work_queue);
/* To get the ack_receiver out of the blocking network stack,
* so it can change its sk_rcvtimeo from idle- to ping-timeout,
@@ -1841,19 +1867,19 @@ 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 *,
- enum drbd_packet, unsigned int, void *,
- unsigned int);
-extern 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 *, 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);
-extern int drbd_send_ping(struct drbd_connection *connection);
-extern int drbd_send_ping_ack(struct drbd_connection *connection);
-extern int drbd_send_state_req(struct drbd_peer_device *, union drbd_state, union drbd_state);
-extern int conn_send_state_req(struct drbd_connection *, union drbd_state, union drbd_state);
+int drbd_send_ping(struct drbd_connection *connection);
+int drbd_send_ping_ack(struct drbd_connection *connection);
+int drbd_send_state_req(struct drbd_peer_device *, union drbd_state,
+ union drbd_state);
+int conn_send_state_req(struct drbd_connection *, union drbd_state,
+ union drbd_state);
static inline void drbd_thread_stop(struct drbd_thread *thi)
{
@@ -2023,7 +2049,7 @@ static inline int _get_ldev_if_state(struct drbd_device *device, enum drbd_disk_
return io_allowed;
}
#else
-extern int _get_ldev_if_state(struct drbd_device *device, enum drbd_disk_state mins);
+int _get_ldev_if_state(struct drbd_device *device, enum drbd_disk_state mins);
#endif
/* this throttles on-the-fly application requests
diff --git a/drivers/block/drbd/drbd_interval.h b/drivers/block/drbd/drbd_interval.h
index 5d3213b81eed..255e9d071ae1 100644
--- a/drivers/block/drbd/drbd_interval.h
+++ b/drivers/block/drbd/drbd_interval.h
@@ -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) \
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index 9ae860e7591b..7f24cb8e5429 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -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
diff --git a/drivers/block/drbd/drbd_state.h b/drivers/block/drbd/drbd_state.h
index cbaeb8018dbf..a7e31d092039 100644
--- a/drivers/block/drbd/drbd_state.h
+++ b/drivers/block/drbd/drbd_state.h
@@ -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
diff --git a/drivers/block/drbd/drbd_state_change.h b/drivers/block/drbd/drbd_state_change.h
index a56a57d67686..f58a55014177 100644
--- a/drivers/block/drbd/drbd_state_change.h
+++ b/drivers/block/drbd/drbd_state_change.h
@@ -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 */
^ permalink raw reply related
* [PATCH] drbd: reject data replies with an out-of-range payload size
From: Michael Bommarito @ 2026-07-10 2:28 UTC (permalink / raw)
To: Philipp Reisner, Lars Ellenberg, Christoph Boehmwalder,
Jens Axboe
Cc: drbd-dev, linux-block, linux-kernel
recv_dless_read() receives a P_DATA_REPLY from a peer into the bio of an
outstanding read request. The peer-supplied payload length reaches it as
the signed int data_size, and two peer-controlled inputs can make it
negative. With a negotiated data-integrity-alg the digest length is
subtracted first, so a reply whose payload is smaller than the digest
underflows data_size. With no integrity algorithm (the default) data_size
is assigned from the unsigned h95/h100 wire length and drbdd() never
bounds it for a payload-carrying command, so a length above INT_MAX casts
it negative; this path needs no non-default feature. The bio receive loop
then computes expect = min_t(int, data_size, bv_len), which is negative,
and drbd_recv_all_warn(mapped, expect) receives with a size_t of SIZE_MAX
into the first mapped page.
The sibling receive path read_in_block() is not affected: it uses an
unsigned size and rejects it against DRBD_MAX_BIO_SIZE before receiving.
Reject a data reply whose size is negative after the optional digest
subtraction, covering both triggers.
Impact: a malicious or man-in-the-middle DRBD peer copies attacker-chosen
bytes past a bio page in the receiver, corrupting kernel memory. A node
that reads from its peer (a diskless node, or read-balancing to the peer)
is exposed in the default configuration; data-integrity-alg is not
required.
Fixes: b411b3637fa7 ("The DRBD driver")
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5-5-xhigh
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
Notes:
- Reproduced on mainline f5459048c38a in a virtme-ng KASAN guest driving
the real receiver over a loopback DRBD 8.4 connection with a
man-in-the-middle proxy. Both triggers were confirmed before/after:
(1) with data-integrity-alg=sha256, a P_DATA_REPLY one byte shorter
than the digest; (2) with NO integrity algorithm (default), a
P_DATA_REPLY whose h100 length is rewritten above INT_MAX. Stock
panics with "KASAN: use-after-free in _copy_to_iter" from
receive_DataReply (data_size seen as -1 and -1073741848 respectively);
the patched build rejects both with -EIO and no KASAN. A benign read
control (unmodified replies up to 128 KiB) passes on both stock and
patched. The harness is available on request.
- The sibling receive path read_in_block() is not affected: it uses an
unsigned size and rejects it against DRBD_MAX_BIO_SIZE before
receiving.
- The pending "drbd: rework receiver for DRBD 9 transport and
multi-peer protocol" series keeps the same unguarded subtraction and
signed size in recv_dless_read(), so this check needs to be carried
there too.
drivers/block/drbd/drbd_receiver.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 58b95bf4bdca6..2135c14354a85 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -1810,6 +1810,11 @@ static int recv_dless_read(struct drbd_peer_device *peer_device, struct drbd_req
data_size -= digest_size;
}
+ if (data_size < 0) {
+ drbd_err(peer_device, "Invalid data reply size\n");
+ return -EIO;
+ }
+
/* optimistically update recv_cnt. if receiving fails below,
* we disconnect anyways, and counters will be reset. */
peer_device->device->recv_cnt += data_size>>9;
--
2.53.0
^ permalink raw reply related
* Re: [PATCH] fs: report direct io constraints through file_getattr
From: Christoph Hellwig @ 2026-07-10 4:35 UTC (permalink / raw)
To: Keith Busch
Cc: Christoph Hellwig, Keith Busch, linux-block, linux-ext4,
linux-f2fs-devel, linux-fsdevel, linux-xfs, axboe, jack, brauner,
cem, jaegeuk, aalbersh, tytso
In-Reply-To: <ak-mQqt-a-jy6ZoV@kbusch-mbp>
On Thu, Jul 09, 2026 at 07:46:42AM -0600, Keith Busch wrote:
> On Thu, Jul 09, 2026 at 09:13:52AM +0200, Christoph Hellwig wrote:
> > On Tue, Jul 07, 2026 at 06:18:43PM -0700, Keith Busch wrote:
> >
> > > + fa->fsx_dio_mem_align = bdev_dma_alignment(bdev) + 1;
> > > + fa->fsx_dio_offset_align = bdev_logical_block_size(bdev);
> > > + fa->fsx_dio_read_offset_align = bdev_logical_block_size(bdev);
> > > + fa->fsx_dio_virt_boundary_align = bdev_virt_boundary_alignment(bdev);
> > > + fa->fsx_max_segments = bdev_max_segments(bdev);
> >
> > How is the max_segments value defined in a way that is meaningful to
> > userspace?
>
> It tells you how many sub-sector vectors you can submit in your
> readv/writev before it needs to add up to a logical block size.
>
> Ex: 4k logical block size, 4 byte DMA, 256 max segments. You can define
> 4-byte iov's in your command, but you'll hit the max segment count
> before you have a valid IO if they're all that small.
Ah, makes sense. But besides the missing documentation I think
max_segments is a bit of a misleading name for that.
Something like max_vecs_per_block (although we don't expose blocks
in the UAPI) or max_vecs_per_granularity (I think grammar wants a word
with me for that, though...) might be a bit more suitable.
> > > @@ -145,6 +155,8 @@ static int file_attr_to_fileattr(const struct file_attr *fattr,
> > >
> > > if (fattr->fa_xflags & ~mask)
> > > return -EINVAL;
> > > + if (fattr->fa_pad)
> > > + return -EINVAL;
> >
> > How is this related?
>
> I had to add a padding field to the struct to account for the implicit
> hole in 64-bit and to ensure the struct is the same size for 32-bit.
> It's a reserved field, so we have to ensure the current kernel doesn't
> support any value here in case we define this field for something else
> in the future.
Ah, right.
^ permalink raw reply
page: | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox