From 9b8ccbd2cbf55636d6b9835d49723b075fb4e641 Mon Sep 17 00:00:00 2001 From: Andriy Tkachuk Date: Tue, 31 Mar 2026 23:41:03 +0100 Subject: [PATCH] draid: fix import failure after disks replacements Currently, it's possible that draid vdev asize would decrease after disks replacements when the disk size is a little less than all other disks in the pool. In such situations, import would fail on this check in vdev_open(): /* * Make sure the allocatable size hasn't shrunk too much. */ if (asize < vd->vdev_min_asize) { vdev_set_state(vd, B_TRUE, VDEV_STATE_CANT_OPEN, VDEV_AUX_BAD_LABEL); return (SET_ERROR(EINVAL)); } Solution: fix vdev_draid_min_asize() so that it would round up the required minimal disk capacity to the VDEV_DRAID_ROWHEIGHT. This would refuse replacements with the disks whose size is less than minimally required to avoid draid asize decrement. Note: we also use VDEV_DRAID_ROWHEIGHT in vdev_draid_open() when calculating asize, and thats why we need to round up min_size at vdev_draid_min_asize() to avoid asize drops. Reviewed-by: Brian Behlendorf Signed-off-by: Andriy Tkachuk Closes #18380 --- module/zfs/vdev_draid.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/module/zfs/vdev_draid.c b/module/zfs/vdev_draid.c index 9e02d8682..8c132fb5a 100644 --- a/module/zfs/vdev_draid.c +++ b/module/zfs/vdev_draid.c @@ -1161,7 +1161,7 @@ vdev_draid_get_astart(vdev_t *vd, const uint64_t start) /* * Allocatable space for dRAID is (children - nspares) * sizeof(smallest child) * rounded down to the last full slice. So each child must provide at least - * 1 / (children - nspares) of its asize. + * 1 / (children - nspares) of its asize rounded up to VDEV_DRAID_ROWHEIGHT. */ static uint64_t vdev_draid_min_asize(vdev_t *vd) @@ -1171,7 +1171,9 @@ vdev_draid_min_asize(vdev_t *vd) ASSERT3P(vd->vdev_ops, ==, &vdev_draid_ops); return (VDEV_DRAID_REFLOW_RESERVE + - (vd->vdev_min_asize + vdc->vdc_ndisks - 1) / (vdc->vdc_ndisks)); + ((vd->vdev_min_asize + vdc->vdc_ndisks - 1) / (vdc->vdc_ndisks) + + VDEV_DRAID_ROWHEIGHT - 1) / VDEV_DRAID_ROWHEIGHT * + VDEV_DRAID_ROWHEIGHT); } /*