From 4abc21b28c22d93c06e1e51c1f9019b4fa4e0d51 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Wed, 26 Mar 2025 19:45:34 -0400 Subject: [PATCH] Block remap for cloned blocks on device removal When after device removal we handle block pointers remap, skip blocks that might be cloned. BRTs are indexed by vdev id and offset from block pointer's DVA[0]. So if we start addressing the same block by some different DVA, we won't get the proper reference counter. As result, we might either remap the block twice, that may result in assertion during indirect mapping condense, or free it prematurely, that may result in data overwrite, or free it twice, that may result in assertion in spacemap code. Reviewed-by: Ameer Hamza Reviewed-by: Paul Dagnelie Reviewed-by: Brian Behlendorf Signed-off-by: Alexander Motin Sponsored by: iXsystems, Inc. Closes #15604 Closes #17180 --- module/zfs/metaslab.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/module/zfs/metaslab.c b/module/zfs/metaslab.c index e723d7640..ec25855cd 100644 --- a/module/zfs/metaslab.c +++ b/module/zfs/metaslab.c @@ -28,6 +28,7 @@ */ #include +#include #include #include #include @@ -5536,6 +5537,13 @@ spa_remap_blkptr(spa_t *spa, blkptr_t *bp, spa_remap_cb_t callback, void *arg) if (BP_GET_NDVAS(bp) < 1) return (B_FALSE); + /* + * Cloned blocks can not be remapped since BRT depends on specific + * vdev id and offset in the DVA[0] for its reference counting. + */ + if (!BP_IS_METADATA(bp) && brt_maybe_exists(spa, bp)) + return (B_FALSE); + /* * Note: we only remap dva[0]. If we remapped other dvas, we * would no longer know what their phys birth txg is.