* block: zero logical block size leads to infinite loop in set_init_blocksize()
@ 2026-09-03 17:41 Maks
2026-09-03 17:55 ` Keith Busch
0 siblings, 1 reply; 5+ messages in thread
From: Maks @ 2026-09-03 17:41 UTC (permalink / raw)
To: linux-block; +Cc: Jens Axboe
Hi,
I hit a soft lockup in set_init_blocksize() with a block device whose
logical_block_size was zero.
I understand that logical_block_size == 0 violates the block layer
contract and that the driver which allowed this value needs to be fixed.
However, the generic block code currently turns this invariant violation
into a non-terminating loop:
while (bsize < PAGE_SIZE) {
if (size & bsize)
break;
bsize <<= 1;
}
With bsize == 0, the value never changes.
In my case this resulted in:
watchdog: BUG: soft lockup - CPU#0 stuck for 26s! [(udev-worker):...]
RIP: set_init_blocksize+0x28/0x60
Call Trace:
blkdev_get_whole+...
bdev_open+...
Is this considered acceptable behavior for a broken driver, or should
the generic block layer defensively detect this case and fail the open
instead of spinning indefinitely?
If adding such a check is considered worthwhile, I can prepare a patch.
Thanks,
Maks
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: block: zero logical block size leads to infinite loop in set_init_blocksize()
2026-09-03 17:41 block: zero logical block size leads to infinite loop in set_init_blocksize() Maks
@ 2026-09-03 17:55 ` Keith Busch
2026-09-03 18:50 ` Maksim Ivanov
2026-09-09 19:11 ` Maks
0 siblings, 2 replies; 5+ messages in thread
From: Keith Busch @ 2026-09-03 17:55 UTC (permalink / raw)
To: Maks; +Cc: linux-block, Jens Axboe
On Thu, Sep 03, 2026 at 08:41:24PM +0300, Maks wrote:
> Hi,
>
> I hit a soft lockup in set_init_blocksize() with a block device whose
> logical_block_size was zero.
>
> I understand that logical_block_size == 0 violates the block layer
> contract and that the driver which allowed this value needs to be fixed.
>
> However, the generic block code currently turns this invariant violation
> into a non-terminating loop:
>
> while (bsize < PAGE_SIZE) {
> if (size & bsize)
> break;
> bsize <<= 1;
> }
>
> With bsize == 0, the value never changes.
How did you manage to get a block_device created, but bypassed the check
and override for a zero logical block size in blk_validate_limits()? Is
your driver writing over the limits outside the API's update path?
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: block: zero logical block size leads to infinite loop in set_init_blocksize()
2026-09-03 17:55 ` Keith Busch
@ 2026-09-03 18:50 ` Maksim Ivanov
2026-09-09 19:11 ` Maks
1 sibling, 0 replies; 5+ messages in thread
From: Maksim Ivanov @ 2026-09-03 18:50 UTC (permalink / raw)
To: Keith Busch; +Cc: linux-block, Jens Axboe
> Is your driver writing over the limits outside the API's update path?
Yes, it does update the queue limits directly:
volume->queue->limits = limits;
There is no blk_validate_limits() call on this path, so this bypasses the
normal queue limits validation.
чт, 3 сент. 2026 г. в 20:55, Keith Busch <kbusch@kernel.org>:
>
> On Thu, Sep 03, 2026 at 08:41:24PM +0300, Maks wrote:
> > Hi,
> >
> > I hit a soft lockup in set_init_blocksize() with a block device whose
> > logical_block_size was zero.
> >
> > I understand that logical_block_size == 0 violates the block layer
> > contract and that the driver which allowed this value needs to be fixed.
> >
> > However, the generic block code currently turns this invariant violation
> > into a non-terminating loop:
> >
> > while (bsize < PAGE_SIZE) {
> > if (size & bsize)
> > break;
> > bsize <<= 1;
> > }
> >
> > With bsize == 0, the value never changes.
>
> How did you manage to get a block_device created, but bypassed the check
> and override for a zero logical block size in blk_validate_limits()? Is
> your driver writing over the limits outside the API's update path?
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: block: zero logical block size leads to infinite loop in set_init_blocksize()
2026-09-03 17:55 ` Keith Busch
2026-09-03 18:50 ` Maksim Ivanov
@ 2026-09-09 19:11 ` Maks
2026-09-09 19:51 ` Keith Busch
1 sibling, 1 reply; 5+ messages in thread
From: Maks @ 2026-09-09 19:11 UTC (permalink / raw)
To: Keith Busch; +Cc: linux-block, Jens Axboe
Hi,
> How did you manage to get a block_device created, but bypassed the check
> and override for a zero logical block size in blk_validate_limits()? Is
> your driver writing over the limits outside the API's update path?
Yes, it does update the queue limits directly:
volume->queue->limits = limits;
There is no blk_validate_limits() call on this path, so this bypasses the
normal queue limits validation.
Given that the driver is clearly bypassing the normal queue limits
validation, would a defensive check in set_init_blocksize() still be
considered worthwhile to avoid the infinite loop in this case?
If so, I can prepare and send a patch.
Thanks,
Maks
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: block: zero logical block size leads to infinite loop in set_init_blocksize()
2026-09-09 19:11 ` Maks
@ 2026-09-09 19:51 ` Keith Busch
0 siblings, 0 replies; 5+ messages in thread
From: Keith Busch @ 2026-09-09 19:51 UTC (permalink / raw)
To: Maks; +Cc: linux-block, Jens Axboe
On Wed, Sep 09, 2026 at 10:11:07PM +0300, Maks wrote:
> Hi,
>
> > How did you manage to get a block_device created, but bypassed the check
> > and override for a zero logical block size in blk_validate_limits()? Is
> > your driver writing over the limits outside the API's update path?
>
> Yes, it does update the queue limits directly:
>
> volume->queue->limits = limits;
>
> There is no blk_validate_limits() call on this path, so this bypasses the
> normal queue limits validation.
>
> Given that the driver is clearly bypassing the normal queue limits
> validation, would a defensive check in set_init_blocksize() still be
> considered worthwhile to avoid the infinite loop in this case?
There's just a lot more places than set_init_blocksize() that assumes
bdev_logical_block_size() returns a validated value. If you've a driver
bypassing the API's that manage this field, then there's many other
functions that also won't work correctly.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-09-09 19:51 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-03 17:41 block: zero logical block size leads to infinite loop in set_init_blocksize() Maks
2026-09-03 17:55 ` Keith Busch
2026-09-03 18:50 ` Maksim Ivanov
2026-09-09 19:11 ` Maks
2026-09-09 19:51 ` Keith Busch
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox