Linux block layer
 help / color / mirror / Atom feed
* 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