From 69ee01aa4b106dd57016b0d756201ecf7c211d46 Mon Sep 17 00:00:00 2001 From: Paul Dagnelie Date: Fri, 27 Jun 2025 11:54:20 -0700 Subject: [PATCH] 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 Reviewed-by: Rob Norris Reviewed-by: Allan Jude Signed-off-by: Paul Dagnelie Closes #17490 --- module/zfs/vdev_raidz.c | 8 ++++++++ module/zfs/zio.c | 1 + 2 files changed, 9 insertions(+) diff --git a/module/zfs/vdev_raidz.c b/module/zfs/vdev_raidz.c index 5941e645e..71c4bfbda 100644 --- a/module/zfs/vdev_raidz.c +++ b/module/zfs/vdev_raidz.c @@ -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; diff --git a/module/zfs/zio.c b/module/zfs/zio.c index 9d80062e5..6d7bce8b0 100644 --- a/module/zfs/zio.c +++ b/module/zfs/zio.c @@ -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,