Set spa_final_txg in spa_unload()

I've noticed that after some dedup tests system reboot ends up in
assertion about ms_defer tree not free.  It seems to be caused by
DDT flushing still freeing some blocks while ZFS trying to reach
a final steady state due to spa_final_txg, while being set by
spa_export_common() on pool export, is not set when spa_unload()
is called by spa_evict_all() on system reboot/shutdown.  Setting
spa_final_txg in spa_unload() fixes this issue.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Rob Norris <rob.norris@klarasystems.com>
Reviewed-by: Paul Dagnelie <pcd@delphix.com>
Signed-off-by:	Alexander Motin <mav@FreeBSD.org>
Sponsored by:	iXsystems, Inc.
Closes #17395
This commit is contained in:
Alexander Motin 2025-05-30 14:44:45 -04:00 committed by GitHub
parent f5a6dd8b70
commit 008c9666ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1683,6 +1683,7 @@ spa_activate(spa_t *spa, spa_mode_t mode)
ASSERT(spa->spa_state == POOL_STATE_UNINITIALIZED); ASSERT(spa->spa_state == POOL_STATE_UNINITIALIZED);
spa->spa_state = POOL_STATE_ACTIVE; spa->spa_state = POOL_STATE_ACTIVE;
spa->spa_final_txg = UINT64_MAX;
spa->spa_mode = mode; spa->spa_mode = mode;
spa->spa_read_spacemaps = spa_mode_readable_spacemaps; spa->spa_read_spacemaps = spa_mode_readable_spacemaps;
@ -2085,6 +2086,11 @@ spa_unload(spa_t *spa)
vdev_rebuild_stop_all(spa); vdev_rebuild_stop_all(spa);
l2arc_spa_rebuild_stop(spa); l2arc_spa_rebuild_stop(spa);
} }
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
spa->spa_final_txg = spa_last_synced_txg(spa) +
TXG_DEFER_SIZE + 1;
spa_config_exit(spa, SCL_ALL, FTAG);
} }
/* /*