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 <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Nick Price <[email protected]>
Closes #18693
This commit is contained in:
Nick Price authored and GitHub committed 2026-06-22 15:44:20 -07:00
1 parent 14c2857366
commit 0483a8e0c0
1 file changed
+4 -3
+4 -3
View File
@@ -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);