Fix bug caused by rounding in vdev_raidz_asize_to_psize

When an allocation is happening on a raidz vdev, the number of sectors
allocated is rounded up to a multiple of nparity + 1. If this results in
the allocation spilling into an extra row, then the corresponding call
to vdev_raidz_asize_to_psize will incorrectly assume that parity sectors
were allocated for that spilled row, even though no data is stored
there.

If we determine that happened, we need to subtract out those extra
sectors before performing the rest of the capacity calculation.

Sponsored-by: Klara, Inc.
Sponsored-by: Wasabi Technology, Inc.
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Rob Norris <rob.norris@klarasystems.com>
Reviewed-by: Allan Jude <allan@klarasystems.com>
Signed-off-by: Paul Dagnelie <paul.dagnelie@klarasystems.com>
Closes #17490
This commit is contained in:
Paul Dagnelie 2025-06-27 11:54:20 -07:00 committed by GitHub
parent ea076d6921
commit 69ee01aa4b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 9 additions and 0 deletions

View File

@ -2257,6 +2257,14 @@ vdev_raidz_asize_to_psize(vdev_t *vd, uint64_t asize, uint64_t txg)
ASSERT0(asize % (1 << ashift));
psize = (asize >> ashift);
/*
* If the roundup to nparity + 1 caused us to spill into a new row, we
* need to ignore that row entirely (since it can't store data or
* parity).
*/
uint64_t rows = psize / cols;
psize = psize - (rows * cols) <= nparity ? rows * cols : psize;
/* Subtract out parity sectors for each row storing data. */
psize -= nparity * DIV_ROUND_UP(psize, cols);
psize <<= ashift;

View File

@ -3239,6 +3239,7 @@ zio_write_gang_block(zio_t *pio, metaslab_class_t *mc)
uint64_t psize = allocated ? MIN(resid, allocated_size) :
min_size;
ASSERT3U(psize, >=, min_size);
zio_t *cio = zio_write(zio, spa, txg, bp, has_data ?
abd_get_offset(pio->io_abd, pio->io_size - resid) : NULL,