From 0483a8e0c0cb28cc215dfafaa2ff1d79f5bd1860 Mon Sep 17 00:00:00 2001 From: Nick Price Date: Mon, 22 Jun 2026 15:44:20 -0700 Subject: [PATCH] Clean up embedded slog metaslab across txgs On a read-write import, metaslab_set_fragmentation() can dirty a metaslab via vdev_dirty() while still in the txg==0 load path when its space map has an unexpected bonus size (e.g. a makefs-created pool whose space-map dnodes use the boot loader's 24-byte space_map_phys_t with nblkptr=3, giving db_size=64). If that metaslab is then selected as the embedded slog, vdev_metaslab_init() only removed it from vdev_ms_list when txg != 0, so the txg==0 case left it queued and metaslab_fini() tripped VERIFY(!txg_list_member(&vd->vdev_ms_list, msp, t)). Remove slog_ms from the dirty list for every TXG_SIZE slot before metaslab_fini() so the cleanup is correct regardless of txg. Reported on FreeBSD as PR 281520: External-issue: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=281520 Reviewed-by: Alexander Motin Reviewed-by: Brian Behlendorf Signed-off-by: Nick Price Closes #18693 --- module/zfs/vdev.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/module/zfs/vdev.c b/module/zfs/vdev.c index d22d6990c3c9..d028268ea372 100644 --- a/module/zfs/vdev.c +++ b/module/zfs/vdev.c @@ -1739,11 +1739,12 @@ vdev_metaslab_init(vdev_t *vd, uint64_t txg) /* * The metaslab was marked as dirty at the end of * metaslab_init(). Remove it from the dirty list so that we - * can uninitialize and reinitialize it to the new class. + * can uninitialize and reinitialize it to the new class. It + * may be dirty in any txg slot, so clear them all. */ - if (txg != 0) { + for (int t = 0; t < TXG_SIZE; t++) { (void) txg_list_remove_this(&vd->vdev_ms_list, - slog_ms, txg); + slog_ms, t); } uint64_t sm_obj = space_map_object(slog_ms->ms_sm); metaslab_fini(slog_ms);