* drbd atomic queue limits conversion
@ 2024-03-05 13:40 Christoph Hellwig
2024-03-05 13:40 ` [PATCH 1/7] drbd: pass the max_hw_sectors limit to blk_alloc_disk Christoph Hellwig
` (14 more replies)
0 siblings, 15 replies; 17+ messages in thread
From: Christoph Hellwig @ 2024-03-05 13:40 UTC (permalink / raw)
To: Philipp Reisner, Lars Ellenberg, Christoph Böhmwalder,
Jens Axboe
Cc: drbd-dev, linux-block
Hi Jens,
this is a standalone resend of the drbd queue limits conversion.
Philipp said Linbit has reviewed and tested it, and they'll hopefully
provide the formal tags for that in a bit.
Diffstat:
drbd_main.c | 13 ++-
drbd_nl.c | 210 ++++++++++++++++++++++++++++--------------------------------
2 files changed, 110 insertions(+), 113 deletions(-)
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 1/7] drbd: pass the max_hw_sectors limit to blk_alloc_disk
2024-03-05 13:40 drbd atomic queue limits conversion Christoph Hellwig
@ 2024-03-05 13:40 ` Christoph Hellwig
2024-03-05 13:40 ` [PATCH 2/7] drbd: refactor drbd_reconsider_queue_parameters Christoph Hellwig
` (13 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Christoph Hellwig @ 2024-03-05 13:40 UTC (permalink / raw)
To: Philipp Reisner, Lars Ellenberg, Christoph Böhmwalder,
Jens Axboe
Cc: drbd-dev, linux-block
Pass a queue_limits structure with the max_hw_sectors limit to
blk_alloc_disk instead of updating the limit on the allocated gendisk.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/block/drbd/drbd_main.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index cea1e537fd56c1..113b441d4d3670 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -2690,6 +2690,14 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
int id;
int vnr = adm_ctx->volume;
enum drbd_ret_code err = ERR_NOMEM;
+ struct queue_limits lim = {
+ /*
+ * Setting the max_hw_sectors to an odd value of 8kibyte here.
+ * This triggers a max_bio_size message upon first attach or
+ * connect.
+ */
+ .max_hw_sectors = DRBD_MAX_BIO_SIZE_SAFE >> 8,
+ };
device = minor_to_device(minor);
if (device)
@@ -2708,7 +2716,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
drbd_init_set_defaults(device);
- disk = blk_alloc_disk(NULL, NUMA_NO_NODE);
+ disk = blk_alloc_disk(&lim, NUMA_NO_NODE);
if (IS_ERR(disk)) {
err = PTR_ERR(disk);
goto out_no_disk;
@@ -2729,9 +2737,6 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, disk->queue);
blk_queue_write_cache(disk->queue, true, true);
- /* Setting the max_hw_sectors to an odd value of 8kibyte here
- This triggers a max_bio_size message upon first attach or connect */
- blk_queue_max_hw_sectors(disk->queue, DRBD_MAX_BIO_SIZE_SAFE >> 8);
device->md_io.page = alloc_page(GFP_KERNEL);
if (!device->md_io.page)
--
2.39.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 2/7] drbd: refactor drbd_reconsider_queue_parameters
2024-03-05 13:40 drbd atomic queue limits conversion Christoph Hellwig
2024-03-05 13:40 ` [PATCH 1/7] drbd: pass the max_hw_sectors limit to blk_alloc_disk Christoph Hellwig
@ 2024-03-05 13:40 ` Christoph Hellwig
2024-03-05 13:40 ` [PATCH 3/7] drbd: refactor the backing dev max_segments calculation Christoph Hellwig
` (12 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Christoph Hellwig @ 2024-03-05 13:40 UTC (permalink / raw)
To: Philipp Reisner, Lars Ellenberg, Christoph Böhmwalder,
Jens Axboe
Cc: drbd-dev, linux-block
Split out a drbd_max_peer_bio_size helper for the peer I/O size,
and condense the various checks to a nested min3(..., max())) instead
of using a lot of local variables.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/block/drbd/drbd_nl.c | 84 +++++++++++++++++++++---------------
1 file changed, 49 insertions(+), 35 deletions(-)
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 43747a1aae4353..9135001a8e572d 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1189,6 +1189,33 @@ static int drbd_check_al_size(struct drbd_device *device, struct disk_conf *dc)
return 0;
}
+static unsigned int drbd_max_peer_bio_size(struct drbd_device *device)
+{
+ /*
+ * We may ignore peer limits if the peer is modern enough. From 8.3.8
+ * onwards the peer can use multiple BIOs for a single peer_request.
+ */
+ if (device->state.conn < C_WF_REPORT_PARAMS)
+ return device->peer_max_bio_size;
+
+ if (first_peer_device(device)->connection->agreed_pro_version < 94)
+ return min(device->peer_max_bio_size, DRBD_MAX_SIZE_H80_PACKET);
+
+ /*
+ * Correct old drbd (up to 8.3.7) if it believes it can do more than
+ * 32KiB.
+ */
+ if (first_peer_device(device)->connection->agreed_pro_version == 94)
+ return DRBD_MAX_SIZE_H80_PACKET;
+
+ /*
+ * drbd 8.3.8 onwards, before 8.4.0
+ */
+ if (first_peer_device(device)->connection->agreed_pro_version < 100)
+ return DRBD_MAX_BIO_SIZE_P95;
+ return DRBD_MAX_BIO_SIZE;
+}
+
static void blk_queue_discard_granularity(struct request_queue *q, unsigned int granularity)
{
q->limits.discard_granularity = granularity;
@@ -1303,48 +1330,35 @@ static void drbd_setup_queue_param(struct drbd_device *device, struct drbd_backi
fixup_discard_support(device, q);
}
-void drbd_reconsider_queue_parameters(struct drbd_device *device, struct drbd_backing_dev *bdev, struct o_qlim *o)
+void drbd_reconsider_queue_parameters(struct drbd_device *device,
+ struct drbd_backing_dev *bdev, struct o_qlim *o)
{
- unsigned int now, new, local, peer;
-
- now = queue_max_hw_sectors(device->rq_queue) << 9;
- local = device->local_max_bio_size; /* Eventually last known value, from volatile memory */
- peer = device->peer_max_bio_size; /* Eventually last known value, from meta data */
+ unsigned int now = queue_max_hw_sectors(device->rq_queue) <<
+ SECTOR_SHIFT;
+ unsigned int new;
if (bdev) {
- local = queue_max_hw_sectors(bdev->backing_bdev->bd_disk->queue) << 9;
- device->local_max_bio_size = local;
- }
- local = min(local, DRBD_MAX_BIO_SIZE);
-
- /* We may ignore peer limits if the peer is modern enough.
- Because new from 8.3.8 onwards the peer can use multiple
- BIOs for a single peer_request */
- if (device->state.conn >= C_WF_REPORT_PARAMS) {
- if (first_peer_device(device)->connection->agreed_pro_version < 94)
- peer = min(device->peer_max_bio_size, DRBD_MAX_SIZE_H80_PACKET);
- /* Correct old drbd (up to 8.3.7) if it believes it can do more than 32KiB */
- else if (first_peer_device(device)->connection->agreed_pro_version == 94)
- peer = DRBD_MAX_SIZE_H80_PACKET;
- else if (first_peer_device(device)->connection->agreed_pro_version < 100)
- peer = DRBD_MAX_BIO_SIZE_P95; /* drbd 8.3.8 onwards, before 8.4.0 */
- else
- peer = DRBD_MAX_BIO_SIZE;
+ struct request_queue *b = bdev->backing_bdev->bd_disk->queue;
- /* We may later detach and re-attach on a disconnected Primary.
- * Avoid this setting to jump back in that case.
- * We want to store what we know the peer DRBD can handle,
- * not what the peer IO backend can handle. */
- if (peer > device->peer_max_bio_size)
- device->peer_max_bio_size = peer;
+ device->local_max_bio_size =
+ queue_max_hw_sectors(b) << SECTOR_SHIFT;
}
- new = min(local, peer);
- if (device->state.role == R_PRIMARY && new < now)
- drbd_err(device, "ASSERT FAILED new < now; (%u < %u)\n", new, now);
-
- if (new != now)
+ /*
+ * We may later detach and re-attach on a disconnected Primary. Avoid
+ * decreasing the value in this case.
+ *
+ * We want to store what we know the peer DRBD can handle, not what the
+ * peer IO backend can handle.
+ */
+ new = min3(DRBD_MAX_BIO_SIZE, device->local_max_bio_size,
+ max(drbd_max_peer_bio_size(device), device->peer_max_bio_size));
+ if (new != now) {
+ if (device->state.role == R_PRIMARY && new < now)
+ drbd_err(device, "ASSERT FAILED new < now; (%u < %u)\n",
+ new, now);
drbd_info(device, "max BIO size = %u\n", new);
+ }
drbd_setup_queue_param(device, bdev, new, o);
}
--
2.39.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 3/7] drbd: refactor the backing dev max_segments calculation
2024-03-05 13:40 drbd atomic queue limits conversion Christoph Hellwig
2024-03-05 13:40 ` [PATCH 1/7] drbd: pass the max_hw_sectors limit to blk_alloc_disk Christoph Hellwig
2024-03-05 13:40 ` [PATCH 2/7] drbd: refactor drbd_reconsider_queue_parameters Christoph Hellwig
@ 2024-03-05 13:40 ` Christoph Hellwig
2024-03-05 13:40 ` [PATCH 4/7] drbd: merge drbd_setup_queue_param into drbd_reconsider_queue_parameters Christoph Hellwig
` (11 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Christoph Hellwig @ 2024-03-05 13:40 UTC (permalink / raw)
To: Philipp Reisner, Lars Ellenberg, Christoph Böhmwalder,
Jens Axboe
Cc: drbd-dev, linux-block
Factor out a drbd_backing_dev_max_segments helper that checks the
backing device limitation.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/block/drbd/drbd_nl.c | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 9135001a8e572d..0326b7322ceb48 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1295,30 +1295,39 @@ static void fixup_discard_support(struct drbd_device *device, struct request_que
}
}
+/* This is the workaround for "bio would need to, but cannot, be split" */
+static unsigned int drbd_backing_dev_max_segments(struct drbd_device *device)
+{
+ unsigned int max_segments;
+
+ rcu_read_lock();
+ max_segments = rcu_dereference(device->ldev->disk_conf)->max_bio_bvecs;
+ rcu_read_unlock();
+
+ if (!max_segments)
+ return BLK_MAX_SEGMENTS;
+ return max_segments;
+}
+
static void drbd_setup_queue_param(struct drbd_device *device, struct drbd_backing_dev *bdev,
unsigned int max_bio_size, struct o_qlim *o)
{
struct request_queue * const q = device->rq_queue;
unsigned int max_hw_sectors = max_bio_size >> 9;
- unsigned int max_segments = 0;
+ unsigned int max_segments = BLK_MAX_SEGMENTS;
struct request_queue *b = NULL;
- struct disk_conf *dc;
if (bdev) {
b = bdev->backing_bdev->bd_disk->queue;
max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9);
- rcu_read_lock();
- dc = rcu_dereference(device->ldev->disk_conf);
- max_segments = dc->max_bio_bvecs;
- rcu_read_unlock();
+ max_segments = drbd_backing_dev_max_segments(device);
blk_set_stacking_limits(&q->limits);
}
blk_queue_max_hw_sectors(q, max_hw_sectors);
- /* This is the workaround for "bio would need to, but cannot, be split" */
- blk_queue_max_segments(q, max_segments ? max_segments : BLK_MAX_SEGMENTS);
+ blk_queue_max_segments(q, max_segments);
blk_queue_segment_boundary(q, PAGE_SIZE-1);
decide_on_discard_support(device, bdev);
--
2.39.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 4/7] drbd: merge drbd_setup_queue_param into drbd_reconsider_queue_parameters
2024-03-05 13:40 drbd atomic queue limits conversion Christoph Hellwig
` (2 preceding siblings ...)
2024-03-05 13:40 ` [PATCH 3/7] drbd: refactor the backing dev max_segments calculation Christoph Hellwig
@ 2024-03-05 13:40 ` Christoph Hellwig
2024-03-05 13:40 ` [PATCH 5/7] drbd: don't set max_write_zeroes_sectors in decide_on_discard_support Christoph Hellwig
` (10 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Christoph Hellwig @ 2024-03-05 13:40 UTC (permalink / raw)
To: Philipp Reisner, Lars Ellenberg, Christoph Böhmwalder,
Jens Axboe
Cc: drbd-dev, linux-block
drbd_setup_queue_param is only called by drbd_reconsider_queue_parameters
and there is no really clear boundary of responsibilities between the
two.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/block/drbd/drbd_nl.c | 56 ++++++++++++++----------------------
1 file changed, 22 insertions(+), 34 deletions(-)
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 0326b7322ceb48..0f40fdee089971 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1309,45 +1309,16 @@ static unsigned int drbd_backing_dev_max_segments(struct drbd_device *device)
return max_segments;
}
-static void drbd_setup_queue_param(struct drbd_device *device, struct drbd_backing_dev *bdev,
- unsigned int max_bio_size, struct o_qlim *o)
-{
- struct request_queue * const q = device->rq_queue;
- unsigned int max_hw_sectors = max_bio_size >> 9;
- unsigned int max_segments = BLK_MAX_SEGMENTS;
- struct request_queue *b = NULL;
-
- if (bdev) {
- b = bdev->backing_bdev->bd_disk->queue;
-
- max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9);
- max_segments = drbd_backing_dev_max_segments(device);
-
- blk_set_stacking_limits(&q->limits);
- }
-
- blk_queue_max_hw_sectors(q, max_hw_sectors);
- blk_queue_max_segments(q, max_segments);
- blk_queue_segment_boundary(q, PAGE_SIZE-1);
- decide_on_discard_support(device, bdev);
-
- if (b) {
- blk_stack_limits(&q->limits, &b->limits, 0);
- disk_update_readahead(device->vdisk);
- }
- fixup_write_zeroes(device, q);
- fixup_discard_support(device, q);
-}
-
void drbd_reconsider_queue_parameters(struct drbd_device *device,
struct drbd_backing_dev *bdev, struct o_qlim *o)
{
- unsigned int now = queue_max_hw_sectors(device->rq_queue) <<
- SECTOR_SHIFT;
+ struct request_queue * const q = device->rq_queue;
+ unsigned int now = queue_max_hw_sectors(q) << 9;
+ struct request_queue *b = NULL;
unsigned int new;
if (bdev) {
- struct request_queue *b = bdev->backing_bdev->bd_disk->queue;
+ b = bdev->backing_bdev->bd_disk->queue;
device->local_max_bio_size =
queue_max_hw_sectors(b) << SECTOR_SHIFT;
@@ -1369,7 +1340,24 @@ void drbd_reconsider_queue_parameters(struct drbd_device *device,
drbd_info(device, "max BIO size = %u\n", new);
}
- drbd_setup_queue_param(device, bdev, new, o);
+ if (bdev) {
+ blk_set_stacking_limits(&q->limits);
+ blk_queue_max_segments(q,
+ drbd_backing_dev_max_segments(device));
+ } else {
+ blk_queue_max_segments(q, BLK_MAX_SEGMENTS);
+ }
+
+ blk_queue_max_hw_sectors(q, new >> SECTOR_SHIFT);
+ blk_queue_segment_boundary(q, PAGE_SIZE - 1);
+ decide_on_discard_support(device, bdev);
+
+ if (bdev) {
+ blk_stack_limits(&q->limits, &b->limits, 0);
+ disk_update_readahead(device->vdisk);
+ }
+ fixup_write_zeroes(device, q);
+ fixup_discard_support(device, q);
}
/* Starts the worker thread */
--
2.39.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 5/7] drbd: don't set max_write_zeroes_sectors in decide_on_discard_support
2024-03-05 13:40 drbd atomic queue limits conversion Christoph Hellwig
` (3 preceding siblings ...)
2024-03-05 13:40 ` [PATCH 4/7] drbd: merge drbd_setup_queue_param into drbd_reconsider_queue_parameters Christoph Hellwig
@ 2024-03-05 13:40 ` Christoph Hellwig
2024-03-05 13:40 ` [PATCH 6/7] drbd: split out a drbd_discard_supported helper Christoph Hellwig
` (9 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Christoph Hellwig @ 2024-03-05 13:40 UTC (permalink / raw)
To: Philipp Reisner, Lars Ellenberg, Christoph Böhmwalder,
Jens Axboe
Cc: drbd-dev, linux-block
fixup_write_zeroes always overrides the max_write_zeroes_sectors value
a little further down the callchain, so don't bother to setup a limit
in decide_on_discard_support.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/block/drbd/drbd_nl.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 0f40fdee089971..a79b7fe5335de4 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1260,7 +1260,6 @@ static void decide_on_discard_support(struct drbd_device *device,
blk_queue_discard_granularity(q, 512);
max_discard_sectors = drbd_max_discard_sectors(connection);
blk_queue_max_discard_sectors(q, max_discard_sectors);
- blk_queue_max_write_zeroes_sectors(q, max_discard_sectors);
return;
not_supported:
--
2.39.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 6/7] drbd: split out a drbd_discard_supported helper
2024-03-05 13:40 drbd atomic queue limits conversion Christoph Hellwig
` (4 preceding siblings ...)
2024-03-05 13:40 ` [PATCH 5/7] drbd: don't set max_write_zeroes_sectors in decide_on_discard_support Christoph Hellwig
@ 2024-03-05 13:40 ` Christoph Hellwig
2024-03-05 13:40 ` [PATCH 7/7] drbd: atomically update queue limits in drbd_reconsider_queue_parameters Christoph Hellwig
` (8 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Christoph Hellwig @ 2024-03-05 13:40 UTC (permalink / raw)
To: Philipp Reisner, Lars Ellenberg, Christoph Böhmwalder,
Jens Axboe
Cc: drbd-dev, linux-block
Add a helper to check if discard is supported for a given connection /
backing device combination.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/block/drbd/drbd_nl.c | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index a79b7fe5335de4..94ed2b3ea6361d 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1231,24 +1231,33 @@ static unsigned int drbd_max_discard_sectors(struct drbd_connection *connection)
return AL_EXTENT_SIZE >> 9;
}
-static void decide_on_discard_support(struct drbd_device *device,
+static bool drbd_discard_supported(struct drbd_connection *connection,
struct drbd_backing_dev *bdev)
{
- struct drbd_connection *connection =
- first_peer_device(device)->connection;
- struct request_queue *q = device->rq_queue;
- unsigned int max_discard_sectors;
-
if (bdev && !bdev_max_discard_sectors(bdev->backing_bdev))
- goto not_supported;
+ return false;
if (connection->cstate >= C_CONNECTED &&
!(connection->agreed_features & DRBD_FF_TRIM)) {
drbd_info(connection,
"peer DRBD too old, does not support TRIM: disabling discards\n");
- goto not_supported;
+ return false;
}
+ return true;
+}
+
+static void decide_on_discard_support(struct drbd_device *device,
+ struct drbd_backing_dev *bdev)
+{
+ struct drbd_connection *connection =
+ first_peer_device(device)->connection;
+ struct request_queue *q = device->rq_queue;
+ unsigned int max_discard_sectors;
+
+ if (!drbd_discard_supported(connection, bdev))
+ goto not_supported;
+
/*
* We don't care for the granularity, really.
*
--
2.39.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 7/7] drbd: atomically update queue limits in drbd_reconsider_queue_parameters
2024-03-05 13:40 drbd atomic queue limits conversion Christoph Hellwig
` (5 preceding siblings ...)
2024-03-05 13:40 ` [PATCH 6/7] drbd: split out a drbd_discard_supported helper Christoph Hellwig
@ 2024-03-05 13:40 ` Christoph Hellwig
2024-03-06 14:03 ` [PATCH 0/7] drbd atomic queue limits conversion Philipp Reisner
` (7 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Christoph Hellwig @ 2024-03-05 13:40 UTC (permalink / raw)
To: Philipp Reisner, Lars Ellenberg, Christoph Böhmwalder,
Jens Axboe
Cc: drbd-dev, linux-block
Switch drbd_reconsider_queue_parameters to set up the queue parameters
in an on-stack queue_limits structure and apply the atomically. Remove
various helpers that have become so trivial that they can be folded into
drbd_reconsider_queue_parameters.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/block/drbd/drbd_nl.c | 119 ++++++++++++++---------------------
1 file changed, 46 insertions(+), 73 deletions(-)
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 94ed2b3ea6361d..fbd92803dc1da4 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1216,11 +1216,6 @@ static unsigned int drbd_max_peer_bio_size(struct drbd_device *device)
return DRBD_MAX_BIO_SIZE;
}
-static void blk_queue_discard_granularity(struct request_queue *q, unsigned int granularity)
-{
- q->limits.discard_granularity = granularity;
-}
-
static unsigned int drbd_max_discard_sectors(struct drbd_connection *connection)
{
/* when we introduced REQ_WRITE_SAME support, we also bumped
@@ -1247,62 +1242,6 @@ static bool drbd_discard_supported(struct drbd_connection *connection,
return true;
}
-static void decide_on_discard_support(struct drbd_device *device,
- struct drbd_backing_dev *bdev)
-{
- struct drbd_connection *connection =
- first_peer_device(device)->connection;
- struct request_queue *q = device->rq_queue;
- unsigned int max_discard_sectors;
-
- if (!drbd_discard_supported(connection, bdev))
- goto not_supported;
-
- /*
- * We don't care for the granularity, really.
- *
- * Stacking limits below should fix it for the local device. Whether or
- * not it is a suitable granularity on the remote device is not our
- * problem, really. If you care, you need to use devices with similar
- * topology on all peers.
- */
- blk_queue_discard_granularity(q, 512);
- max_discard_sectors = drbd_max_discard_sectors(connection);
- blk_queue_max_discard_sectors(q, max_discard_sectors);
- return;
-
-not_supported:
- blk_queue_discard_granularity(q, 0);
- blk_queue_max_discard_sectors(q, 0);
-}
-
-static void fixup_write_zeroes(struct drbd_device *device, struct request_queue *q)
-{
- /* Fixup max_write_zeroes_sectors after blk_stack_limits():
- * if we can handle "zeroes" efficiently on the protocol,
- * we want to do that, even if our backend does not announce
- * max_write_zeroes_sectors itself. */
- struct drbd_connection *connection = first_peer_device(device)->connection;
- /* If the peer announces WZEROES support, use it. Otherwise, rather
- * send explicit zeroes than rely on some discard-zeroes-data magic. */
- if (connection->agreed_features & DRBD_FF_WZEROES)
- q->limits.max_write_zeroes_sectors = DRBD_MAX_BBIO_SECTORS;
- else
- q->limits.max_write_zeroes_sectors = 0;
-}
-
-static void fixup_discard_support(struct drbd_device *device, struct request_queue *q)
-{
- unsigned int max_discard = device->rq_queue->limits.max_discard_sectors;
- unsigned int discard_granularity =
- device->rq_queue->limits.discard_granularity >> SECTOR_SHIFT;
-
- if (discard_granularity > max_discard) {
- blk_queue_discard_granularity(q, 0);
- blk_queue_max_discard_sectors(q, 0);
- }
-}
-
/* This is the workaround for "bio would need to, but cannot, be split" */
static unsigned int drbd_backing_dev_max_segments(struct drbd_device *device)
{
@@ -1320,8 +1259,11 @@ static unsigned int drbd_backing_dev_max_segments(struct drbd_device *device)
void drbd_reconsider_queue_parameters(struct drbd_device *device,
struct drbd_backing_dev *bdev, struct o_qlim *o)
{
+ struct drbd_connection *connection =
+ first_peer_device(device)->connection;
struct request_queue * const q = device->rq_queue;
unsigned int now = queue_max_hw_sectors(q) << 9;
+ struct queue_limits lim;
struct request_queue *b = NULL;
unsigned int new;
@@ -1348,24 +1290,55 @@ void drbd_reconsider_queue_parameters(struct drbd_device *device,
drbd_info(device, "max BIO size = %u\n", new);
}
+ lim = queue_limits_start_update(q);
if (bdev) {
- blk_set_stacking_limits(&q->limits);
- blk_queue_max_segments(q,
- drbd_backing_dev_max_segments(device));
+ blk_set_stacking_limits(&lim);
+ lim.max_segments = drbd_backing_dev_max_segments(device);
} else {
- blk_queue_max_segments(q, BLK_MAX_SEGMENTS);
+ lim.max_segments = BLK_MAX_SEGMENTS;
}
- blk_queue_max_hw_sectors(q, new >> SECTOR_SHIFT);
- blk_queue_segment_boundary(q, PAGE_SIZE - 1);
- decide_on_discard_support(device, bdev);
+ lim.max_hw_sectors = new >> SECTOR_SHIFT;
+ lim.seg_boundary_mask = PAGE_SIZE - 1;
- if (bdev) {
- blk_stack_limits(&q->limits, &b->limits, 0);
- disk_update_readahead(device->vdisk);
+ /*
+ * We don't care for the granularity, really.
+ *
+ * Stacking limits below should fix it for the local device. Whether or
+ * not it is a suitable granularity on the remote device is not our
+ * problem, really. If you care, you need to use devices with similar
+ * topology on all peers.
+ */
+ if (drbd_discard_supported(connection, bdev)) {
+ lim.discard_granularity = 512;
+ lim.max_hw_discard_sectors =
+ drbd_max_discard_sectors(connection);
+ } else {
+ lim.discard_granularity = 0;
+ lim.max_hw_discard_sectors = 0;
}
- fixup_write_zeroes(device, q);
- fixup_discard_support(device, q);
+
+ if (bdev)
+ blk_stack_limits(&lim, &b->limits, 0);
+
+ /*
+ * If we can handle "zeroes" efficiently on the protocol, we want to do
+ * that, even if our backend does not announce max_write_zeroes_sectors
+ * itself.
+ */
+ if (connection->agreed_features & DRBD_FF_WZEROES)
+ lim.max_write_zeroes_sectors = DRBD_MAX_BBIO_SECTORS;
+ else
+ lim.max_write_zeroes_sectors = 0;
+
+ if ((lim.discard_granularity >> SECTOR_SHIFT) >
+ lim.max_hw_discard_sectors) {
+ lim.discard_granularity = 0;
+ lim.max_hw_discard_sectors = 0;
+ }
+
+ if (queue_limits_commit_update(q, &lim))
+ drbd_err(device, "setting new queue limits failed\n");
}
/* Starts the worker thread */
--
2.39.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 0/7] drbd atomic queue limits conversion
2024-03-05 13:40 drbd atomic queue limits conversion Christoph Hellwig
` (6 preceding siblings ...)
2024-03-05 13:40 ` [PATCH 7/7] drbd: atomically update queue limits in drbd_reconsider_queue_parameters Christoph Hellwig
@ 2024-03-06 14:03 ` Philipp Reisner
2024-03-06 15:35 ` Jens Axboe
2024-03-06 14:03 ` [PATCH 1/7] drbd: pass the max_hw_sectors limit to blk_alloc_disk Philipp Reisner
` (6 subsequent siblings)
14 siblings, 1 reply; 17+ messages in thread
From: Philipp Reisner @ 2024-03-06 14:03 UTC (permalink / raw)
To: Jens Axboe; +Cc: drbd-dev, linux-block, Christoph Hellwig, Philipp Reisner
Hello Jens,
Here, with the Reviewed-by and Tested-by trailers.
Christoph Hellwig (7):
drbd: pass the max_hw_sectors limit to blk_alloc_disk
drbd: refactor drbd_reconsider_queue_parameters
drbd: refactor the backing dev max_segments calculation
drbd: merge drbd_setup_queue_param into
drbd_reconsider_queue_parameters
drbd: don't set max_write_zeroes_sectors in decide_on_discard_support
drbd: split out a drbd_discard_supported helper
drbd: atomically update queue limits in
drbd_reconsider_queue_parameters
drivers/block/drbd/drbd_main.c | 13 +-
drivers/block/drbd/drbd_nl.c | 210 ++++++++++++++++-----------------
2 files changed, 110 insertions(+), 113 deletions(-)
--
2.40.1
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 1/7] drbd: pass the max_hw_sectors limit to blk_alloc_disk
2024-03-05 13:40 drbd atomic queue limits conversion Christoph Hellwig
` (7 preceding siblings ...)
2024-03-06 14:03 ` [PATCH 0/7] drbd atomic queue limits conversion Philipp Reisner
@ 2024-03-06 14:03 ` Philipp Reisner
2024-03-06 14:03 ` [PATCH 2/7] drbd: refactor drbd_reconsider_queue_parameters Philipp Reisner
` (5 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2024-03-06 14:03 UTC (permalink / raw)
To: Jens Axboe
Cc: drbd-dev, linux-block, Christoph Hellwig, Philipp Reisner,
Lars Ellenberg, Christoph Böhmwalder
From: Christoph Hellwig <hch@lst.de>
Pass a queue_limits structure with the max_hw_sectors limit to
blk_alloc_disk instead of updating the limit on the allocated gendisk.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Philipp Reisner <philipp.reisner@linbit.com>
Reviewed-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Tested-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
---
drivers/block/drbd/drbd_main.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index cea1e537fd56..113b441d4d36 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -2690,6 +2690,14 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
int id;
int vnr = adm_ctx->volume;
enum drbd_ret_code err = ERR_NOMEM;
+ struct queue_limits lim = {
+ /*
+ * Setting the max_hw_sectors to an odd value of 8kibyte here.
+ * This triggers a max_bio_size message upon first attach or
+ * connect.
+ */
+ .max_hw_sectors = DRBD_MAX_BIO_SIZE_SAFE >> 8,
+ };
device = minor_to_device(minor);
if (device)
@@ -2708,7 +2716,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
drbd_init_set_defaults(device);
- disk = blk_alloc_disk(NULL, NUMA_NO_NODE);
+ disk = blk_alloc_disk(&lim, NUMA_NO_NODE);
if (IS_ERR(disk)) {
err = PTR_ERR(disk);
goto out_no_disk;
@@ -2729,9 +2737,6 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, disk->queue);
blk_queue_write_cache(disk->queue, true, true);
- /* Setting the max_hw_sectors to an odd value of 8kibyte here
- This triggers a max_bio_size message upon first attach or connect */
- blk_queue_max_hw_sectors(disk->queue, DRBD_MAX_BIO_SIZE_SAFE >> 8);
device->md_io.page = alloc_page(GFP_KERNEL);
if (!device->md_io.page)
--
2.40.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 2/7] drbd: refactor drbd_reconsider_queue_parameters
2024-03-05 13:40 drbd atomic queue limits conversion Christoph Hellwig
` (8 preceding siblings ...)
2024-03-06 14:03 ` [PATCH 1/7] drbd: pass the max_hw_sectors limit to blk_alloc_disk Philipp Reisner
@ 2024-03-06 14:03 ` Philipp Reisner
2024-03-06 14:03 ` [PATCH 3/7] drbd: refactor the backing dev max_segments calculation Philipp Reisner
` (4 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2024-03-06 14:03 UTC (permalink / raw)
To: Jens Axboe
Cc: drbd-dev, linux-block, Christoph Hellwig, Philipp Reisner,
Lars Ellenberg, Christoph Böhmwalder
From: Christoph Hellwig <hch@lst.de>
Split out a drbd_max_peer_bio_size helper for the peer I/O size,
and condense the various checks to a nested min3(..., max())) instead
of using a lot of local variables.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Philipp Reisner <philipp.reisner@linbit.com>
Reviewed-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Tested-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
---
drivers/block/drbd/drbd_nl.c | 84 +++++++++++++++++++++---------------
1 file changed, 49 insertions(+), 35 deletions(-)
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 43747a1aae43..9135001a8e57 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1189,6 +1189,33 @@ static int drbd_check_al_size(struct drbd_device *device, struct disk_conf *dc)
return 0;
}
+static unsigned int drbd_max_peer_bio_size(struct drbd_device *device)
+{
+ /*
+ * We may ignore peer limits if the peer is modern enough. From 8.3.8
+ * onwards the peer can use multiple BIOs for a single peer_request.
+ */
+ if (device->state.conn < C_WF_REPORT_PARAMS)
+ return device->peer_max_bio_size;
+
+ if (first_peer_device(device)->connection->agreed_pro_version < 94)
+ return min(device->peer_max_bio_size, DRBD_MAX_SIZE_H80_PACKET);
+
+ /*
+ * Correct old drbd (up to 8.3.7) if it believes it can do more than
+ * 32KiB.
+ */
+ if (first_peer_device(device)->connection->agreed_pro_version == 94)
+ return DRBD_MAX_SIZE_H80_PACKET;
+
+ /*
+ * drbd 8.3.8 onwards, before 8.4.0
+ */
+ if (first_peer_device(device)->connection->agreed_pro_version < 100)
+ return DRBD_MAX_BIO_SIZE_P95;
+ return DRBD_MAX_BIO_SIZE;
+}
+
static void blk_queue_discard_granularity(struct request_queue *q, unsigned int granularity)
{
q->limits.discard_granularity = granularity;
@@ -1303,48 +1330,35 @@ static void drbd_setup_queue_param(struct drbd_device *device, struct drbd_backi
fixup_discard_support(device, q);
}
-void drbd_reconsider_queue_parameters(struct drbd_device *device, struct drbd_backing_dev *bdev, struct o_qlim *o)
+void drbd_reconsider_queue_parameters(struct drbd_device *device,
+ struct drbd_backing_dev *bdev, struct o_qlim *o)
{
- unsigned int now, new, local, peer;
-
- now = queue_max_hw_sectors(device->rq_queue) << 9;
- local = device->local_max_bio_size; /* Eventually last known value, from volatile memory */
- peer = device->peer_max_bio_size; /* Eventually last known value, from meta data */
+ unsigned int now = queue_max_hw_sectors(device->rq_queue) <<
+ SECTOR_SHIFT;
+ unsigned int new;
if (bdev) {
- local = queue_max_hw_sectors(bdev->backing_bdev->bd_disk->queue) << 9;
- device->local_max_bio_size = local;
- }
- local = min(local, DRBD_MAX_BIO_SIZE);
-
- /* We may ignore peer limits if the peer is modern enough.
- Because new from 8.3.8 onwards the peer can use multiple
- BIOs for a single peer_request */
- if (device->state.conn >= C_WF_REPORT_PARAMS) {
- if (first_peer_device(device)->connection->agreed_pro_version < 94)
- peer = min(device->peer_max_bio_size, DRBD_MAX_SIZE_H80_PACKET);
- /* Correct old drbd (up to 8.3.7) if it believes it can do more than 32KiB */
- else if (first_peer_device(device)->connection->agreed_pro_version == 94)
- peer = DRBD_MAX_SIZE_H80_PACKET;
- else if (first_peer_device(device)->connection->agreed_pro_version < 100)
- peer = DRBD_MAX_BIO_SIZE_P95; /* drbd 8.3.8 onwards, before 8.4.0 */
- else
- peer = DRBD_MAX_BIO_SIZE;
+ struct request_queue *b = bdev->backing_bdev->bd_disk->queue;
- /* We may later detach and re-attach on a disconnected Primary.
- * Avoid this setting to jump back in that case.
- * We want to store what we know the peer DRBD can handle,
- * not what the peer IO backend can handle. */
- if (peer > device->peer_max_bio_size)
- device->peer_max_bio_size = peer;
+ device->local_max_bio_size =
+ queue_max_hw_sectors(b) << SECTOR_SHIFT;
}
- new = min(local, peer);
- if (device->state.role == R_PRIMARY && new < now)
- drbd_err(device, "ASSERT FAILED new < now; (%u < %u)\n", new, now);
-
- if (new != now)
+ /*
+ * We may later detach and re-attach on a disconnected Primary. Avoid
+ * decreasing the value in this case.
+ *
+ * We want to store what we know the peer DRBD can handle, not what the
+ * peer IO backend can handle.
+ */
+ new = min3(DRBD_MAX_BIO_SIZE, device->local_max_bio_size,
+ max(drbd_max_peer_bio_size(device), device->peer_max_bio_size));
+ if (new != now) {
+ if (device->state.role == R_PRIMARY && new < now)
+ drbd_err(device, "ASSERT FAILED new < now; (%u < %u)\n",
+ new, now);
drbd_info(device, "max BIO size = %u\n", new);
+ }
drbd_setup_queue_param(device, bdev, new, o);
}
--
2.40.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 3/7] drbd: refactor the backing dev max_segments calculation
2024-03-05 13:40 drbd atomic queue limits conversion Christoph Hellwig
` (9 preceding siblings ...)
2024-03-06 14:03 ` [PATCH 2/7] drbd: refactor drbd_reconsider_queue_parameters Philipp Reisner
@ 2024-03-06 14:03 ` Philipp Reisner
2024-03-06 14:03 ` [PATCH 4/7] drbd: merge drbd_setup_queue_param into drbd_reconsider_queue_parameters Philipp Reisner
` (3 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2024-03-06 14:03 UTC (permalink / raw)
To: Jens Axboe
Cc: drbd-dev, linux-block, Christoph Hellwig, Philipp Reisner,
Lars Ellenberg, Christoph Böhmwalder
From: Christoph Hellwig <hch@lst.de>
Factor out a drbd_backing_dev_max_segments helper that checks the
backing device limitation.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Philipp Reisner <philipp.reisner@linbit.com>
Reviewed-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Tested-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
---
drivers/block/drbd/drbd_nl.c | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 9135001a8e57..0326b7322ceb 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1295,30 +1295,39 @@ static void fixup_discard_support(struct drbd_device *device, struct request_que
}
}
+/* This is the workaround for "bio would need to, but cannot, be split" */
+static unsigned int drbd_backing_dev_max_segments(struct drbd_device *device)
+{
+ unsigned int max_segments;
+
+ rcu_read_lock();
+ max_segments = rcu_dereference(device->ldev->disk_conf)->max_bio_bvecs;
+ rcu_read_unlock();
+
+ if (!max_segments)
+ return BLK_MAX_SEGMENTS;
+ return max_segments;
+}
+
static void drbd_setup_queue_param(struct drbd_device *device, struct drbd_backing_dev *bdev,
unsigned int max_bio_size, struct o_qlim *o)
{
struct request_queue * const q = device->rq_queue;
unsigned int max_hw_sectors = max_bio_size >> 9;
- unsigned int max_segments = 0;
+ unsigned int max_segments = BLK_MAX_SEGMENTS;
struct request_queue *b = NULL;
- struct disk_conf *dc;
if (bdev) {
b = bdev->backing_bdev->bd_disk->queue;
max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9);
- rcu_read_lock();
- dc = rcu_dereference(device->ldev->disk_conf);
- max_segments = dc->max_bio_bvecs;
- rcu_read_unlock();
+ max_segments = drbd_backing_dev_max_segments(device);
blk_set_stacking_limits(&q->limits);
}
blk_queue_max_hw_sectors(q, max_hw_sectors);
- /* This is the workaround for "bio would need to, but cannot, be split" */
- blk_queue_max_segments(q, max_segments ? max_segments : BLK_MAX_SEGMENTS);
+ blk_queue_max_segments(q, max_segments);
blk_queue_segment_boundary(q, PAGE_SIZE-1);
decide_on_discard_support(device, bdev);
--
2.40.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 4/7] drbd: merge drbd_setup_queue_param into drbd_reconsider_queue_parameters
2024-03-05 13:40 drbd atomic queue limits conversion Christoph Hellwig
` (10 preceding siblings ...)
2024-03-06 14:03 ` [PATCH 3/7] drbd: refactor the backing dev max_segments calculation Philipp Reisner
@ 2024-03-06 14:03 ` Philipp Reisner
2024-03-06 14:03 ` [PATCH 5/7] drbd: don't set max_write_zeroes_sectors in decide_on_discard_support Philipp Reisner
` (2 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2024-03-06 14:03 UTC (permalink / raw)
To: Jens Axboe
Cc: drbd-dev, linux-block, Christoph Hellwig, Philipp Reisner,
Lars Ellenberg, Christoph Böhmwalder
From: Christoph Hellwig <hch@lst.de>
drbd_setup_queue_param is only called by drbd_reconsider_queue_parameters
and there is no really clear boundary of responsibilities between the
two.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Philipp Reisner <philipp.reisner@linbit.com>
Reviewed-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Tested-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
---
drivers/block/drbd/drbd_nl.c | 56 ++++++++++++++----------------------
1 file changed, 22 insertions(+), 34 deletions(-)
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 0326b7322ceb..0f40fdee0899 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1309,45 +1309,16 @@ static unsigned int drbd_backing_dev_max_segments(struct drbd_device *device)
return max_segments;
}
-static void drbd_setup_queue_param(struct drbd_device *device, struct drbd_backing_dev *bdev,
- unsigned int max_bio_size, struct o_qlim *o)
-{
- struct request_queue * const q = device->rq_queue;
- unsigned int max_hw_sectors = max_bio_size >> 9;
- unsigned int max_segments = BLK_MAX_SEGMENTS;
- struct request_queue *b = NULL;
-
- if (bdev) {
- b = bdev->backing_bdev->bd_disk->queue;
-
- max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9);
- max_segments = drbd_backing_dev_max_segments(device);
-
- blk_set_stacking_limits(&q->limits);
- }
-
- blk_queue_max_hw_sectors(q, max_hw_sectors);
- blk_queue_max_segments(q, max_segments);
- blk_queue_segment_boundary(q, PAGE_SIZE-1);
- decide_on_discard_support(device, bdev);
-
- if (b) {
- blk_stack_limits(&q->limits, &b->limits, 0);
- disk_update_readahead(device->vdisk);
- }
- fixup_write_zeroes(device, q);
- fixup_discard_support(device, q);
-}
-
void drbd_reconsider_queue_parameters(struct drbd_device *device,
struct drbd_backing_dev *bdev, struct o_qlim *o)
{
- unsigned int now = queue_max_hw_sectors(device->rq_queue) <<
- SECTOR_SHIFT;
+ struct request_queue * const q = device->rq_queue;
+ unsigned int now = queue_max_hw_sectors(q) << 9;
+ struct request_queue *b = NULL;
unsigned int new;
if (bdev) {
- struct request_queue *b = bdev->backing_bdev->bd_disk->queue;
+ b = bdev->backing_bdev->bd_disk->queue;
device->local_max_bio_size =
queue_max_hw_sectors(b) << SECTOR_SHIFT;
@@ -1369,7 +1340,24 @@ void drbd_reconsider_queue_parameters(struct drbd_device *device,
drbd_info(device, "max BIO size = %u\n", new);
}
- drbd_setup_queue_param(device, bdev, new, o);
+ if (bdev) {
+ blk_set_stacking_limits(&q->limits);
+ blk_queue_max_segments(q,
+ drbd_backing_dev_max_segments(device));
+ } else {
+ blk_queue_max_segments(q, BLK_MAX_SEGMENTS);
+ }
+
+ blk_queue_max_hw_sectors(q, new >> SECTOR_SHIFT);
+ blk_queue_segment_boundary(q, PAGE_SIZE - 1);
+ decide_on_discard_support(device, bdev);
+
+ if (bdev) {
+ blk_stack_limits(&q->limits, &b->limits, 0);
+ disk_update_readahead(device->vdisk);
+ }
+ fixup_write_zeroes(device, q);
+ fixup_discard_support(device, q);
}
/* Starts the worker thread */
--
2.40.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 5/7] drbd: don't set max_write_zeroes_sectors in decide_on_discard_support
2024-03-05 13:40 drbd atomic queue limits conversion Christoph Hellwig
` (11 preceding siblings ...)
2024-03-06 14:03 ` [PATCH 4/7] drbd: merge drbd_setup_queue_param into drbd_reconsider_queue_parameters Philipp Reisner
@ 2024-03-06 14:03 ` Philipp Reisner
2024-03-06 14:03 ` [PATCH 6/7] drbd: split out a drbd_discard_supported helper Philipp Reisner
2024-03-06 14:03 ` [PATCH 7/7] drbd: atomically update queue limits in drbd_reconsider_queue_parameters Philipp Reisner
14 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2024-03-06 14:03 UTC (permalink / raw)
To: Jens Axboe
Cc: drbd-dev, linux-block, Christoph Hellwig, Philipp Reisner,
Lars Ellenberg, Christoph Böhmwalder
From: Christoph Hellwig <hch@lst.de>
fixup_write_zeroes always overrides the max_write_zeroes_sectors value
a little further down the callchain, so don't bother to setup a limit
in decide_on_discard_support.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Philipp Reisner <philipp.reisner@linbit.com>
Reviewed-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Tested-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
---
drivers/block/drbd/drbd_nl.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 0f40fdee0899..a79b7fe5335d 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1260,7 +1260,6 @@ static void decide_on_discard_support(struct drbd_device *device,
blk_queue_discard_granularity(q, 512);
max_discard_sectors = drbd_max_discard_sectors(connection);
blk_queue_max_discard_sectors(q, max_discard_sectors);
- blk_queue_max_write_zeroes_sectors(q, max_discard_sectors);
return;
not_supported:
--
2.40.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 6/7] drbd: split out a drbd_discard_supported helper
2024-03-05 13:40 drbd atomic queue limits conversion Christoph Hellwig
` (12 preceding siblings ...)
2024-03-06 14:03 ` [PATCH 5/7] drbd: don't set max_write_zeroes_sectors in decide_on_discard_support Philipp Reisner
@ 2024-03-06 14:03 ` Philipp Reisner
2024-03-06 14:03 ` [PATCH 7/7] drbd: atomically update queue limits in drbd_reconsider_queue_parameters Philipp Reisner
14 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2024-03-06 14:03 UTC (permalink / raw)
To: Jens Axboe
Cc: drbd-dev, linux-block, Christoph Hellwig, Philipp Reisner,
Lars Ellenberg, Christoph Böhmwalder
From: Christoph Hellwig <hch@lst.de>
Add a helper to check if discard is supported for a given connection /
backing device combination.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Philipp Reisner <philipp.reisner@linbit.com>
Reviewed-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Tested-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
---
drivers/block/drbd/drbd_nl.c | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index a79b7fe5335d..94ed2b3ea636 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1231,24 +1231,33 @@ static unsigned int drbd_max_discard_sectors(struct drbd_connection *connection)
return AL_EXTENT_SIZE >> 9;
}
-static void decide_on_discard_support(struct drbd_device *device,
+static bool drbd_discard_supported(struct drbd_connection *connection,
struct drbd_backing_dev *bdev)
{
- struct drbd_connection *connection =
- first_peer_device(device)->connection;
- struct request_queue *q = device->rq_queue;
- unsigned int max_discard_sectors;
-
if (bdev && !bdev_max_discard_sectors(bdev->backing_bdev))
- goto not_supported;
+ return false;
if (connection->cstate >= C_CONNECTED &&
!(connection->agreed_features & DRBD_FF_TRIM)) {
drbd_info(connection,
"peer DRBD too old, does not support TRIM: disabling discards\n");
- goto not_supported;
+ return false;
}
+ return true;
+}
+
+static void decide_on_discard_support(struct drbd_device *device,
+ struct drbd_backing_dev *bdev)
+{
+ struct drbd_connection *connection =
+ first_peer_device(device)->connection;
+ struct request_queue *q = device->rq_queue;
+ unsigned int max_discard_sectors;
+
+ if (!drbd_discard_supported(connection, bdev))
+ goto not_supported;
+
/*
* We don't care for the granularity, really.
*
--
2.40.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 7/7] drbd: atomically update queue limits in drbd_reconsider_queue_parameters
2024-03-05 13:40 drbd atomic queue limits conversion Christoph Hellwig
` (13 preceding siblings ...)
2024-03-06 14:03 ` [PATCH 6/7] drbd: split out a drbd_discard_supported helper Philipp Reisner
@ 2024-03-06 14:03 ` Philipp Reisner
14 siblings, 0 replies; 17+ messages in thread
From: Philipp Reisner @ 2024-03-06 14:03 UTC (permalink / raw)
To: Jens Axboe
Cc: drbd-dev, linux-block, Christoph Hellwig, Philipp Reisner,
Lars Ellenberg, Christoph Böhmwalder
From: Christoph Hellwig <hch@lst.de>
Switch drbd_reconsider_queue_parameters to set up the queue parameters
in an on-stack queue_limits structure and apply the atomically. Remove
various helpers that have become so trivial that they can be folded into
drbd_reconsider_queue_parameters.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Philipp Reisner <philipp.reisner@linbit.com>
Reviewed-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Tested-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
---
drivers/block/drbd/drbd_nl.c | 119 ++++++++++++++---------------------
1 file changed, 46 insertions(+), 73 deletions(-)
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 94ed2b3ea636..fbd92803dc1d 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1216,11 +1216,6 @@ static unsigned int drbd_max_peer_bio_size(struct drbd_device *device)
return DRBD_MAX_BIO_SIZE;
}
-static void blk_queue_discard_granularity(struct request_queue *q, unsigned int granularity)
-{
- q->limits.discard_granularity = granularity;
-}
-
static unsigned int drbd_max_discard_sectors(struct drbd_connection *connection)
{
/* when we introduced REQ_WRITE_SAME support, we also bumped
@@ -1247,62 +1242,6 @@ static bool drbd_discard_supported(struct drbd_connection *connection,
return true;
}
-static void decide_on_discard_support(struct drbd_device *device,
- struct drbd_backing_dev *bdev)
-{
- struct drbd_connection *connection =
- first_peer_device(device)->connection;
- struct request_queue *q = device->rq_queue;
- unsigned int max_discard_sectors;
-
- if (!drbd_discard_supported(connection, bdev))
- goto not_supported;
-
- /*
- * We don't care for the granularity, really.
- *
- * Stacking limits below should fix it for the local device. Whether or
- * not it is a suitable granularity on the remote device is not our
- * problem, really. If you care, you need to use devices with similar
- * topology on all peers.
- */
- blk_queue_discard_granularity(q, 512);
- max_discard_sectors = drbd_max_discard_sectors(connection);
- blk_queue_max_discard_sectors(q, max_discard_sectors);
- return;
-
-not_supported:
- blk_queue_discard_granularity(q, 0);
- blk_queue_max_discard_sectors(q, 0);
-}
-
-static void fixup_write_zeroes(struct drbd_device *device, struct request_queue *q)
-{
- /* Fixup max_write_zeroes_sectors after blk_stack_limits():
- * if we can handle "zeroes" efficiently on the protocol,
- * we want to do that, even if our backend does not announce
- * max_write_zeroes_sectors itself. */
- struct drbd_connection *connection = first_peer_device(device)->connection;
- /* If the peer announces WZEROES support, use it. Otherwise, rather
- * send explicit zeroes than rely on some discard-zeroes-data magic. */
- if (connection->agreed_features & DRBD_FF_WZEROES)
- q->limits.max_write_zeroes_sectors = DRBD_MAX_BBIO_SECTORS;
- else
- q->limits.max_write_zeroes_sectors = 0;
-}
-
-static void fixup_discard_support(struct drbd_device *device, struct request_queue *q)
-{
- unsigned int max_discard = device->rq_queue->limits.max_discard_sectors;
- unsigned int discard_granularity =
- device->rq_queue->limits.discard_granularity >> SECTOR_SHIFT;
-
- if (discard_granularity > max_discard) {
- blk_queue_discard_granularity(q, 0);
- blk_queue_max_discard_sectors(q, 0);
- }
-}
-
/* This is the workaround for "bio would need to, but cannot, be split" */
static unsigned int drbd_backing_dev_max_segments(struct drbd_device *device)
{
@@ -1320,8 +1259,11 @@ static unsigned int drbd_backing_dev_max_segments(struct drbd_device *device)
void drbd_reconsider_queue_parameters(struct drbd_device *device,
struct drbd_backing_dev *bdev, struct o_qlim *o)
{
+ struct drbd_connection *connection =
+ first_peer_device(device)->connection;
struct request_queue * const q = device->rq_queue;
unsigned int now = queue_max_hw_sectors(q) << 9;
+ struct queue_limits lim;
struct request_queue *b = NULL;
unsigned int new;
@@ -1348,24 +1290,55 @@ void drbd_reconsider_queue_parameters(struct drbd_device *device,
drbd_info(device, "max BIO size = %u\n", new);
}
+ lim = queue_limits_start_update(q);
if (bdev) {
- blk_set_stacking_limits(&q->limits);
- blk_queue_max_segments(q,
- drbd_backing_dev_max_segments(device));
+ blk_set_stacking_limits(&lim);
+ lim.max_segments = drbd_backing_dev_max_segments(device);
} else {
- blk_queue_max_segments(q, BLK_MAX_SEGMENTS);
+ lim.max_segments = BLK_MAX_SEGMENTS;
}
- blk_queue_max_hw_sectors(q, new >> SECTOR_SHIFT);
- blk_queue_segment_boundary(q, PAGE_SIZE - 1);
- decide_on_discard_support(device, bdev);
+ lim.max_hw_sectors = new >> SECTOR_SHIFT;
+ lim.seg_boundary_mask = PAGE_SIZE - 1;
- if (bdev) {
- blk_stack_limits(&q->limits, &b->limits, 0);
- disk_update_readahead(device->vdisk);
+ /*
+ * We don't care for the granularity, really.
+ *
+ * Stacking limits below should fix it for the local device. Whether or
+ * not it is a suitable granularity on the remote device is not our
+ * problem, really. If you care, you need to use devices with similar
+ * topology on all peers.
+ */
+ if (drbd_discard_supported(connection, bdev)) {
+ lim.discard_granularity = 512;
+ lim.max_hw_discard_sectors =
+ drbd_max_discard_sectors(connection);
+ } else {
+ lim.discard_granularity = 0;
+ lim.max_hw_discard_sectors = 0;
}
- fixup_write_zeroes(device, q);
- fixup_discard_support(device, q);
+
+ if (bdev)
+ blk_stack_limits(&lim, &b->limits, 0);
+
+ /*
+ * If we can handle "zeroes" efficiently on the protocol, we want to do
+ * that, even if our backend does not announce max_write_zeroes_sectors
+ * itself.
+ */
+ if (connection->agreed_features & DRBD_FF_WZEROES)
+ lim.max_write_zeroes_sectors = DRBD_MAX_BBIO_SECTORS;
+ else
+ lim.max_write_zeroes_sectors = 0;
+
+ if ((lim.discard_granularity >> SECTOR_SHIFT) >
+ lim.max_hw_discard_sectors) {
+ lim.discard_granularity = 0;
+ lim.max_hw_discard_sectors = 0;
+ }
+
+ if (queue_limits_commit_update(q, &lim))
+ drbd_err(device, "setting new queue limits failed\n");
}
/* Starts the worker thread */
--
2.40.1
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 0/7] drbd atomic queue limits conversion
2024-03-06 14:03 ` [PATCH 0/7] drbd atomic queue limits conversion Philipp Reisner
@ 2024-03-06 15:35 ` Jens Axboe
0 siblings, 0 replies; 17+ messages in thread
From: Jens Axboe @ 2024-03-06 15:35 UTC (permalink / raw)
To: Philipp Reisner; +Cc: drbd-dev, linux-block, Christoph Hellwig
On Wed, 06 Mar 2024 15:03:25 +0100, Philipp Reisner wrote:
> Here, with the Reviewed-by and Tested-by trailers.
>
> Christoph Hellwig (7):
> drbd: pass the max_hw_sectors limit to blk_alloc_disk
> drbd: refactor drbd_reconsider_queue_parameters
> drbd: refactor the backing dev max_segments calculation
> drbd: merge drbd_setup_queue_param into
> drbd_reconsider_queue_parameters
> drbd: don't set max_write_zeroes_sectors in decide_on_discard_support
> drbd: split out a drbd_discard_supported helper
> drbd: atomically update queue limits in
> drbd_reconsider_queue_parameters
>
> [...]
Applied, thanks!
[1/7] drbd: pass the max_hw_sectors limit to blk_alloc_disk
commit: aa067325c05dc3a3aac588f40cacf8418f916cee
[2/7] drbd: refactor drbd_reconsider_queue_parameters
commit: 342d81fde24152adf9747e6e126c8c3179d1a54c
[3/7] drbd: refactor the backing dev max_segments calculation
commit: 2828908d5cc8396e7c91d04d67e03ed834234bcd
[4/7] drbd: merge drbd_setup_queue_param into drbd_reconsider_queue_parameters
commit: e16344e506314e35b1a5a8ccd7b88f4b1844ebb0
[5/7] drbd: don't set max_write_zeroes_sectors in decide_on_discard_support
commit: e3992e02c970f6eb803b98b9f733cad40f190161
[6/7] drbd: split out a drbd_discard_supported helper
commit: 5eaee6e9c8f9940ecee93678972774fb8dd450d5
[7/7] drbd: atomically update queue limits in drbd_reconsider_queue_parameters
commit: e6dfe748f09e37f77437bd337f891f5b57d5d5a2
Best regards,
--
Jens Axboe
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2024-03-06 15:35 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-05 13:40 drbd atomic queue limits conversion Christoph Hellwig
2024-03-05 13:40 ` [PATCH 1/7] drbd: pass the max_hw_sectors limit to blk_alloc_disk Christoph Hellwig
2024-03-05 13:40 ` [PATCH 2/7] drbd: refactor drbd_reconsider_queue_parameters Christoph Hellwig
2024-03-05 13:40 ` [PATCH 3/7] drbd: refactor the backing dev max_segments calculation Christoph Hellwig
2024-03-05 13:40 ` [PATCH 4/7] drbd: merge drbd_setup_queue_param into drbd_reconsider_queue_parameters Christoph Hellwig
2024-03-05 13:40 ` [PATCH 5/7] drbd: don't set max_write_zeroes_sectors in decide_on_discard_support Christoph Hellwig
2024-03-05 13:40 ` [PATCH 6/7] drbd: split out a drbd_discard_supported helper Christoph Hellwig
2024-03-05 13:40 ` [PATCH 7/7] drbd: atomically update queue limits in drbd_reconsider_queue_parameters Christoph Hellwig
2024-03-06 14:03 ` [PATCH 0/7] drbd atomic queue limits conversion Philipp Reisner
2024-03-06 15:35 ` Jens Axboe
2024-03-06 14:03 ` [PATCH 1/7] drbd: pass the max_hw_sectors limit to blk_alloc_disk Philipp Reisner
2024-03-06 14:03 ` [PATCH 2/7] drbd: refactor drbd_reconsider_queue_parameters Philipp Reisner
2024-03-06 14:03 ` [PATCH 3/7] drbd: refactor the backing dev max_segments calculation Philipp Reisner
2024-03-06 14:03 ` [PATCH 4/7] drbd: merge drbd_setup_queue_param into drbd_reconsider_queue_parameters Philipp Reisner
2024-03-06 14:03 ` [PATCH 5/7] drbd: don't set max_write_zeroes_sectors in decide_on_discard_support Philipp Reisner
2024-03-06 14:03 ` [PATCH 6/7] drbd: split out a drbd_discard_supported helper Philipp Reisner
2024-03-06 14:03 ` [PATCH 7/7] drbd: atomically update queue limits in drbd_reconsider_queue_parameters Philipp Reisner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).