* [PATCH 2/3] dm-integrity: always set the io hints
2026-03-25 19:36 [PATCH 1/3] dm-integrity: fix mismatched queue limits Keith Busch
@ 2026-03-25 19:36 ` Keith Busch
2026-03-25 19:36 ` [PATCH 3/3] dm: provide helper to set stacked limits Keith Busch
` (2 subsequent siblings)
3 siblings, 0 replies; 8+ messages in thread
From: Keith Busch @ 2026-03-25 19:36 UTC (permalink / raw)
To: dm-devel; +Cc: mpatocka, snitzer, Keith Busch
From: Keith Busch <kbusch@kernel.org>
Don't depend on the defaults to be what is desired if the integrity
device was set up with 512b sector size. Always set the queue limits to
be at least what the device mapper wants.
Signed-off-by: Keith Busch <kbusch@kernel.org>
---
drivers/md/dm-integrity.c | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index 8dfd498ed1ffd..d64c15c761d0a 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -4046,19 +4046,14 @@ static void dm_integrity_io_hints(struct dm_target *ti, struct queue_limits *lim
{
struct dm_integrity_c *ic = ti->private;
- if (ic->sectors_per_block > 1) {
- limits->logical_block_size =
- max(limits->logical_block_size,
- ic->sectors_per_block << SECTOR_SHIFT);
- limits->physical_block_size =
- max(limits->physical_block_size,
- ic->sectors_per_block << SECTOR_SHIFT);
- limits->io_min =
- max(limits->io_min,
- ic->sectors_per_block << SECTOR_SHIFT);
- limits->dma_alignment = limits->logical_block_size - 1;
- limits->discard_granularity = ic->sectors_per_block << SECTOR_SHIFT;
- }
+ limits->logical_block_size = max(limits->logical_block_size,
+ ic->sectors_per_block << SECTOR_SHIFT);
+ limits->physical_block_size = max(limits->physical_block_size,
+ ic->sectors_per_block << SECTOR_SHIFT);
+ limits->io_min = max(limits->io_min,
+ ic->sectors_per_block << SECTOR_SHIFT);
+ limits->dma_alignment = limits->logical_block_size - 1;
+ limits->discard_granularity = ic->sectors_per_block << SECTOR_SHIFT;
if (!ic->internal_hash) {
struct blk_integrity *bi = &limits->integrity;
--
2.52.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 3/3] dm: provide helper to set stacked limits
2026-03-25 19:36 [PATCH 1/3] dm-integrity: fix mismatched queue limits Keith Busch
2026-03-25 19:36 ` [PATCH 2/3] dm-integrity: always set the io hints Keith Busch
@ 2026-03-25 19:36 ` Keith Busch
2026-03-27 19:41 ` [PATCH 1/3] dm-integrity: fix mismatched queue limits Benjamin Marzinski
2026-03-27 21:25 ` Mikulas Patocka
3 siblings, 0 replies; 8+ messages in thread
From: Keith Busch @ 2026-03-25 19:36 UTC (permalink / raw)
To: dm-devel; +Cc: mpatocka, snitzer, Keith Busch
From: Keith Busch <kbusch@kernel.org>
There are multiple device mappers that set up their stacking limits
exactly the same for the logical, physical and minimum IO queue limits.
Provide a helper for it.
Signed-off-by: Keith Busch <kbusch@kernel.org>
---
drivers/md/dm-crypt.c | 6 +-----
drivers/md/dm-integrity.c | 7 +------
drivers/md/dm-verity-target.c | 8 +-------
drivers/md/dm-writecache.c | 10 +---------
include/linux/device-mapper.h | 7 +++++++
5 files changed, 11 insertions(+), 27 deletions(-)
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 885208a82c55f..60642cee8609d 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -3684,11 +3684,7 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
{
struct crypt_config *cc = ti->private;
- limits->logical_block_size =
- max_t(unsigned int, limits->logical_block_size, cc->sector_size);
- limits->physical_block_size =
- max_t(unsigned int, limits->physical_block_size, cc->sector_size);
- limits->io_min = max_t(unsigned int, limits->io_min, cc->sector_size);
+ dm_stack_bs_limits(limits, cc->sector_size);
limits->dma_alignment = limits->logical_block_size - 1;
/*
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index d64c15c761d0a..65c30dec82220 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -4046,12 +4046,7 @@ static void dm_integrity_io_hints(struct dm_target *ti, struct queue_limits *lim
{
struct dm_integrity_c *ic = ti->private;
- limits->logical_block_size = max(limits->logical_block_size,
- ic->sectors_per_block << SECTOR_SHIFT);
- limits->physical_block_size = max(limits->physical_block_size,
- ic->sectors_per_block << SECTOR_SHIFT);
- limits->io_min = max(limits->io_min,
- ic->sectors_per_block << SECTOR_SHIFT);
+ dm_stack_bs_limits(limits, ic->sectors_per_block << SECTOR_SHIFT);
limits->dma_alignment = limits->logical_block_size - 1;
limits->discard_granularity = ic->sectors_per_block << SECTOR_SHIFT;
diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
index e1d435c79e96c..9a9847f94c460 100644
--- a/drivers/md/dm-verity-target.c
+++ b/drivers/md/dm-verity-target.c
@@ -1011,13 +1011,7 @@ static void verity_io_hints(struct dm_target *ti, struct queue_limits *limits)
{
struct dm_verity *v = ti->private;
- if (limits->logical_block_size < 1 << v->data_dev_block_bits)
- limits->logical_block_size = 1 << v->data_dev_block_bits;
-
- if (limits->physical_block_size < 1 << v->data_dev_block_bits)
- limits->physical_block_size = 1 << v->data_dev_block_bits;
-
- limits->io_min = limits->logical_block_size;
+ dm_stack_bs_limits(limits, 1 << v->data_dev_block_bits);
/*
* Similar to what dm-crypt does, opt dm-verity out of support for
diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
index 98bd945f6da7b..493f5202ad042 100644
--- a/drivers/md/dm-writecache.c
+++ b/drivers/md/dm-writecache.c
@@ -1640,17 +1640,9 @@ static void writecache_io_hints(struct dm_target *ti, struct queue_limits *limit
{
struct dm_writecache *wc = ti->private;
- if (limits->logical_block_size < wc->block_size)
- limits->logical_block_size = wc->block_size;
-
- if (limits->physical_block_size < wc->block_size)
- limits->physical_block_size = wc->block_size;
-
- if (limits->io_min < wc->block_size)
- limits->io_min = wc->block_size;
+ dm_stack_bs_limits(limits, wc->block_size);
}
-
static void writecache_writeback_endio(struct bio *bio)
{
struct writeback_struct *wb = container_of(bio, struct writeback_struct, bio);
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index 38f625af6ab47..cd4faaf5d4275 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -755,4 +755,11 @@ static inline unsigned long to_bytes(sector_t n)
return (n << SECTOR_SHIFT);
}
+static inline void dm_stack_bs_limits(struct queue_limits *limits, unsigned int bs)
+{
+ limits->logical_block_size = max(limits->logical_block_size, bs);
+ limits->physical_block_size = max(limits->physical_block_size, bs);
+ limits->io_min = max(limits->io_min, bs);
+}
+
#endif /* _LINUX_DEVICE_MAPPER_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH 1/3] dm-integrity: fix mismatched queue limits
2026-03-25 19:36 [PATCH 1/3] dm-integrity: fix mismatched queue limits Keith Busch
2026-03-25 19:36 ` [PATCH 2/3] dm-integrity: always set the io hints Keith Busch
2026-03-25 19:36 ` [PATCH 3/3] dm: provide helper to set stacked limits Keith Busch
@ 2026-03-27 19:41 ` Benjamin Marzinski
2026-03-27 20:36 ` Keith Busch
2026-03-27 21:25 ` Mikulas Patocka
3 siblings, 1 reply; 8+ messages in thread
From: Benjamin Marzinski @ 2026-03-27 19:41 UTC (permalink / raw)
To: Keith Busch; +Cc: dm-devel, mpatocka, snitzer, Keith Busch
On Wed, Mar 25, 2026 at 12:36:06PM -0700, Keith Busch wrote:
> From: Keith Busch <kbusch@kernel.org>
>
> A user can integritysetup a device with a backing device using a 4k
> logical block size, but request the dm device use 1k or 2k. This
> mismatch creates an inconsistency such that the dm device would report
> limits for IO that it can't actually execute. Fix this by using the
> backing device's limits if they are larger.
>
> Signed-off-by: Keith Busch <kbusch@kernel.org>
> ---
> drivers/md/dm-integrity.c | 12 +++++++++---
> 1 file changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
> index 06e805902151c..8dfd498ed1ffd 100644
> --- a/drivers/md/dm-integrity.c
> +++ b/drivers/md/dm-integrity.c
> @@ -4047,9 +4047,15 @@ static void dm_integrity_io_hints(struct dm_target *ti, struct queue_limits *lim
> struct dm_integrity_c *ic = ti->private;
>
> if (ic->sectors_per_block > 1) {
> - limits->logical_block_size = ic->sectors_per_block << SECTOR_SHIFT;
> - limits->physical_block_size = ic->sectors_per_block << SECTOR_SHIFT;
> - limits->io_min = ic->sectors_per_block << SECTOR_SHIFT;
> + limits->logical_block_size =
> + max(limits->logical_block_size,
> + ic->sectors_per_block << SECTOR_SHIFT);
> + limits->physical_block_size =
> + max(limits->physical_block_size,
> + ic->sectors_per_block << SECTOR_SHIFT);
> + limits->io_min =
> + max(limits->io_min,
> + ic->sectors_per_block << SECTOR_SHIFT);
> limits->dma_alignment = limits->logical_block_size - 1;
> limits->discard_granularity = ic->sectors_per_block << SECTOR_SHIFT;
Shouldn't this also respect the underlying device's discard_granularity?
-Ben
> }
> --
> 2.52.0
>
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH 1/3] dm-integrity: fix mismatched queue limits
2026-03-27 19:41 ` [PATCH 1/3] dm-integrity: fix mismatched queue limits Benjamin Marzinski
@ 2026-03-27 20:36 ` Keith Busch
2026-03-30 17:41 ` Benjamin Marzinski
0 siblings, 1 reply; 8+ messages in thread
From: Keith Busch @ 2026-03-27 20:36 UTC (permalink / raw)
To: Benjamin Marzinski; +Cc: Keith Busch, dm-devel, mpatocka, snitzer
On Fri, Mar 27, 2026 at 03:41:50PM -0400, Benjamin Marzinski wrote:
> > @@ -4047,9 +4047,15 @@ static void dm_integrity_io_hints(struct dm_target *ti, struct queue_limits *lim
> > struct dm_integrity_c *ic = ti->private;
> >
> > if (ic->sectors_per_block > 1) {
> > - limits->logical_block_size = ic->sectors_per_block << SECTOR_SHIFT;
> > - limits->physical_block_size = ic->sectors_per_block << SECTOR_SHIFT;
> > - limits->io_min = ic->sectors_per_block << SECTOR_SHIFT;
> > + limits->logical_block_size =
> > + max(limits->logical_block_size,
> > + ic->sectors_per_block << SECTOR_SHIFT);
> > + limits->physical_block_size =
> > + max(limits->physical_block_size,
> > + ic->sectors_per_block << SECTOR_SHIFT);
> > + limits->io_min =
> > + max(limits->io_min,
> > + ic->sectors_per_block << SECTOR_SHIFT);
> > limits->dma_alignment = limits->logical_block_size - 1;
> > limits->discard_granularity = ic->sectors_per_block << SECTOR_SHIFT;
>
> Shouldn't this also respect the underlying device's discard_granularity?
It doesn't appear to. I left it unchanged as I'm not very familiar with
this device mapper, so that seemed safer. But I thought it was fine as
is: this dm doesn't appear to forward discards, so the underlying
device's constraints aren't brought into the operation. It looks like it
just sets a "DISCARD_FILLER" pattern into metadata.
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH 1/3] dm-integrity: fix mismatched queue limits
2026-03-27 20:36 ` Keith Busch
@ 2026-03-30 17:41 ` Benjamin Marzinski
2026-03-30 18:16 ` Keith Busch
0 siblings, 1 reply; 8+ messages in thread
From: Benjamin Marzinski @ 2026-03-30 17:41 UTC (permalink / raw)
To: Keith Busch; +Cc: Keith Busch, dm-devel, mpatocka, snitzer
On Fri, Mar 27, 2026 at 02:36:19PM -0600, Keith Busch wrote:
> On Fri, Mar 27, 2026 at 03:41:50PM -0400, Benjamin Marzinski wrote:
> > > @@ -4047,9 +4047,15 @@ static void dm_integrity_io_hints(struct dm_target *ti, struct queue_limits *lim
> > > struct dm_integrity_c *ic = ti->private;
> > >
> > > if (ic->sectors_per_block > 1) {
> > > - limits->logical_block_size = ic->sectors_per_block << SECTOR_SHIFT;
> > > - limits->physical_block_size = ic->sectors_per_block << SECTOR_SHIFT;
> > > - limits->io_min = ic->sectors_per_block << SECTOR_SHIFT;
> > > + limits->logical_block_size =
> > > + max(limits->logical_block_size,
> > > + ic->sectors_per_block << SECTOR_SHIFT);
> > > + limits->physical_block_size =
> > > + max(limits->physical_block_size,
> > > + ic->sectors_per_block << SECTOR_SHIFT);
> > > + limits->io_min =
> > > + max(limits->io_min,
> > > + ic->sectors_per_block << SECTOR_SHIFT);
> > > limits->dma_alignment = limits->logical_block_size - 1;
> > > limits->discard_granularity = ic->sectors_per_block << SECTOR_SHIFT;
> >
> > Shouldn't this also respect the underlying device's discard_granularity?
>
> It doesn't appear to. I left it unchanged as I'm not very familiar with
> this device mapper, so that seemed safer. But I thought it was fine as
> is: this dm doesn't appear to forward discards, so the underlying
> device's constraints aren't brought into the operation. It looks like it
> just sets a "DISCARD_FILLER" pattern into metadata.
If you set allow discards, dm-intergrity should pass them down.
For example:
VALID:
# modprobe scsi_debug dev_size_mb=1024 lbpu=1
# integritysetup format -s 1024 /dev/sda
# integritysetup open --allow-discards /dev/sda integrity-test
# cat /sys/block/sda/queue/discard_granularity
512
# cat /sys/block/dm-1/queue/discard_granularity
1024
# blkdiscard -o 1024 -l 16384 /dev/mapper/integrity-test
# echo $?
0
perf trace:
blkdiscard 11852 [000] 256486.743981: block:block_bio_queue: 253,1 DS 0 + 2 [blkdiscard]
kworker/0:1-eve 11763 [000] 256486.744063: block:block_bio_queue: 8,0 DS 16504 + 2 [kworker/0:1]
kworker/0:1-eve 11763 [000] 256486.744076: block:block_rq_issue: 8,0 DS 1024 () 16504 + 2 0x2,0,4 [kworker/0:1]
swapper 0 [000] 256486.745099: block:block_rq_complete: 8,0 DS () 16504 + 2 0x2,0,4 [0]
swapper 0 [000] 256486.745104: block:block_bio_complete: 253,1 DS 0 + 2 [0]
INVALID:
# modprobe scsi_debug dev_size_mb=1024 lbpu=1 sector_size=4096
# integritysetup format -s 1024 /dev/sda
# integritysetup open --allow-discards /dev/sda integrity-test
# cat /sys/block/sda/queue/discard_granularity
2048
# cat /sys/block/dm-1/queue/discard_granularity
1024
# blkdiscard -o 1024 -l 16384 /dev/mapper/integrity-test
blkdiscard: BLKDISCARD: /dev/mapper/integrity-test ioctl failed: Input/output error
# echo $?
1
perf trace:
blkdiscard 12191 [000] 257234.995337: block:block_bio_queue: 253,1 DS 0 + 2 [blkdiscard]
kworker/0:1-eve 11763 [000] 257235.046620: block:block_bio_queue: 8,0 DS 16504 + 2 [kworker/0:1]
kworker/0:1-eve 11763 [000] 257235.046623: block:block_bio_complete: 8,0 DS 16504 + 2 [-5]
kworker/0:1-eve 11763 [000] 257235.046629: block:block_bio_complete: 253,1 DS 0 + 2 [-5]
-Ben
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH 1/3] dm-integrity: fix mismatched queue limits
2026-03-30 17:41 ` Benjamin Marzinski
@ 2026-03-30 18:16 ` Keith Busch
0 siblings, 0 replies; 8+ messages in thread
From: Keith Busch @ 2026-03-30 18:16 UTC (permalink / raw)
To: Benjamin Marzinski; +Cc: Keith Busch, dm-devel, mpatocka, snitzer
On Mon, Mar 30, 2026 at 01:41:34PM -0400, Benjamin Marzinski wrote:
> INVALID:
> # modprobe scsi_debug dev_size_mb=1024 lbpu=1 sector_size=4096
> # integritysetup format -s 1024 /dev/sda
> # integritysetup open --allow-discards /dev/sda integrity-test
> # cat /sys/block/sda/queue/discard_granularity
> 2048
> # cat /sys/block/dm-1/queue/discard_granularity
> 1024
> # blkdiscard -o 1024 -l 16384 /dev/mapper/integrity-test
This patch fixes that already since it overrides the physical_block_size
to match the backing device's, and blk_validate_limits() will update
dma_granularity to be at least that size as well.
But dm-integrity probably should unconditionally set it to at least the
backing device's too, just in case the backing device wants a larger
granularity than the physical block size.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/3] dm-integrity: fix mismatched queue limits
2026-03-25 19:36 [PATCH 1/3] dm-integrity: fix mismatched queue limits Keith Busch
` (2 preceding siblings ...)
2026-03-27 19:41 ` [PATCH 1/3] dm-integrity: fix mismatched queue limits Benjamin Marzinski
@ 2026-03-27 21:25 ` Mikulas Patocka
3 siblings, 0 replies; 8+ messages in thread
From: Mikulas Patocka @ 2026-03-27 21:25 UTC (permalink / raw)
To: Keith Busch; +Cc: dm-devel, snitzer, Keith Busch
Hi
I accepted all three patches.
Mikulas
On Wed, 25 Mar 2026, Keith Busch wrote:
> From: Keith Busch <kbusch@kernel.org>
>
> A user can integritysetup a device with a backing device using a 4k
> logical block size, but request the dm device use 1k or 2k. This
> mismatch creates an inconsistency such that the dm device would report
> limits for IO that it can't actually execute. Fix this by using the
> backing device's limits if they are larger.
>
> Signed-off-by: Keith Busch <kbusch@kernel.org>
> ---
> drivers/md/dm-integrity.c | 12 +++++++++---
> 1 file changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
> index 06e805902151c..8dfd498ed1ffd 100644
> --- a/drivers/md/dm-integrity.c
> +++ b/drivers/md/dm-integrity.c
> @@ -4047,9 +4047,15 @@ static void dm_integrity_io_hints(struct dm_target *ti, struct queue_limits *lim
> struct dm_integrity_c *ic = ti->private;
>
> if (ic->sectors_per_block > 1) {
> - limits->logical_block_size = ic->sectors_per_block << SECTOR_SHIFT;
> - limits->physical_block_size = ic->sectors_per_block << SECTOR_SHIFT;
> - limits->io_min = ic->sectors_per_block << SECTOR_SHIFT;
> + limits->logical_block_size =
> + max(limits->logical_block_size,
> + ic->sectors_per_block << SECTOR_SHIFT);
> + limits->physical_block_size =
> + max(limits->physical_block_size,
> + ic->sectors_per_block << SECTOR_SHIFT);
> + limits->io_min =
> + max(limits->io_min,
> + ic->sectors_per_block << SECTOR_SHIFT);
> limits->dma_alignment = limits->logical_block_size - 1;
> limits->discard_granularity = ic->sectors_per_block << SECTOR_SHIFT;
> }
> --
> 2.52.0
>
^ permalink raw reply [flat|nested] 8+ messages in thread