Skip to content

Commit 3f2701b

Browse files
johnpgarrykawasaki
authored andcommitted
block: use chunk_sectors when evaluating stacked atomic write limits
The atomic write unit max value is limited by any stacked device stripe size. It is required that the atomic write unit is a power-of-2 factor of the stripe size. Currently we use io_min limit to hold the stripe size, and check for a io_min <= SECTOR_SIZE when deciding if we have a striped stacked device. Nilay reports that this causes a problem when the physical block size is greater than SECTOR_SIZE [0]. Furthermore, io_min may be mutated when stacking devices, and this makes it a poor candidate to hold the stripe size. Such an example (of when io_min may change) would be when the io_min is less than the physical block size. Use chunk_sectors to hold the stripe size, which is more appropriate. [0] https://lore.kernel.org/linux-block/[email protected]/T/#mecca17129f72811137d3c2f1e477634e77f06781 Reviewed-by: Nilay Shroff <[email protected]> Tested-by: Nilay Shroff <[email protected]> Signed-off-by: John Garry <[email protected]>
1 parent 3eb4178 commit 3f2701b

1 file changed

Lines changed: 33 additions & 23 deletions

File tree

block/blk-settings.c

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -595,41 +595,50 @@ static bool blk_stack_atomic_writes_boundary_head(struct queue_limits *t,
595595
return true;
596596
}
597597

598-
599-
/* Check stacking of first bottom device */
600-
static bool blk_stack_atomic_writes_head(struct queue_limits *t,
601-
struct queue_limits *b)
598+
static void blk_stack_atomic_writes_chunk_sectors(struct queue_limits *t)
602599
{
603-
if (b->atomic_write_hw_boundary &&
604-
!blk_stack_atomic_writes_boundary_head(t, b))
605-
return false;
600+
unsigned int chunk_bytes;
606601

607-
if (t->io_min <= SECTOR_SIZE) {
608-
/* No chunk sectors, so use bottom device values directly */
609-
t->atomic_write_hw_unit_max = b->atomic_write_hw_unit_max;
610-
t->atomic_write_hw_unit_min = b->atomic_write_hw_unit_min;
611-
t->atomic_write_hw_max = b->atomic_write_hw_max;
612-
return true;
613-
}
602+
if (!t->chunk_sectors)
603+
return;
604+
605+
/*
606+
* If chunk sectors is so large that its value in bytes overflows
607+
* UINT_MAX, then just shift it down so it definitely will fit.
608+
* We don't support atomic writes of such a large size anyway.
609+
*/
610+
if (check_shl_overflow(t->chunk_sectors, SECTOR_SHIFT, &chunk_bytes))
611+
chunk_bytes = t->chunk_sectors;
614612

615613
/*
616614
* Find values for limits which work for chunk size.
617615
* b->atomic_write_hw_unit_{min, max} may not be aligned with chunk
618-
* size (t->io_min), as chunk size is not restricted to a power-of-2.
616+
* size, as the chunk size is not restricted to a power-of-2.
619617
* So we need to find highest power-of-2 which works for the chunk
620618
* size.
621-
* As an example scenario, we could have b->unit_max = 16K and
622-
* t->io_min = 24K. For this case, reduce t->unit_max to a value
623-
* aligned with both limits, i.e. 8K in this example.
619+
* As an example scenario, we could have t->unit_max = 16K and
620+
* t->chunk_sectors = 24KB. For this case, reduce t->unit_max to a
621+
* value aligned with both limits, i.e. 8K in this example.
624622
*/
625-
t->atomic_write_hw_unit_max = b->atomic_write_hw_unit_max;
626-
while (t->io_min % t->atomic_write_hw_unit_max)
627-
t->atomic_write_hw_unit_max /= 2;
623+
t->atomic_write_hw_unit_max = min(t->atomic_write_hw_unit_max,
624+
max_pow_of_two_factor(chunk_bytes));
628625

629-
t->atomic_write_hw_unit_min = min(b->atomic_write_hw_unit_min,
626+
t->atomic_write_hw_unit_min = min(t->atomic_write_hw_unit_min,
630627
t->atomic_write_hw_unit_max);
631-
t->atomic_write_hw_max = min(b->atomic_write_hw_max, t->io_min);
628+
t->atomic_write_hw_max = min(t->atomic_write_hw_max, chunk_bytes);
629+
}
630+
631+
/* Check stacking of first bottom device */
632+
static bool blk_stack_atomic_writes_head(struct queue_limits *t,
633+
struct queue_limits *b)
634+
{
635+
if (b->atomic_write_hw_boundary &&
636+
!blk_stack_atomic_writes_boundary_head(t, b))
637+
return false;
632638

639+
t->atomic_write_hw_unit_max = b->atomic_write_hw_unit_max;
640+
t->atomic_write_hw_unit_min = b->atomic_write_hw_unit_min;
641+
t->atomic_write_hw_max = b->atomic_write_hw_max;
633642
return true;
634643
}
635644

@@ -657,6 +666,7 @@ static void blk_stack_atomic_writes_limits(struct queue_limits *t,
657666

658667
if (!blk_stack_atomic_writes_head(t, b))
659668
goto unsupported;
669+
blk_stack_atomic_writes_chunk_sectors(t);
660670
return;
661671

662672
unsupported:

0 commit comments

Comments
 (0)