L2ARC: Stop rebuild before setting spa_final_txg

Without doing that there is a race window on export when history
log write by completed rebuild dirties transaction beyond final,
triggering assertion.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: George Amanakis <gamanakis@gmail.com>
Signed-off-by: Alexander Motin <mav@FreeBSD.org>
Sponsored by: iXsystems, Inc.
Closes #16714
Closes #16782
This commit is contained in:
Alexander Motin 2024-11-20 09:11:51 -05:00 committed by GitHub
parent 534688948c
commit 0ca82c5680
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 35 additions and 3 deletions

View File

@ -347,6 +347,7 @@ void l2arc_fini(void);
void l2arc_start(void);
void l2arc_stop(void);
void l2arc_spa_rebuild_start(spa_t *spa);
void l2arc_spa_rebuild_stop(spa_t *spa);
#ifndef _KERNEL
extern boolean_t arc_watch;

View File

@ -9846,6 +9846,37 @@ l2arc_spa_rebuild_start(spa_t *spa)
}
}
void
l2arc_spa_rebuild_stop(spa_t *spa)
{
ASSERT(MUTEX_HELD(&spa_namespace_lock) ||
spa->spa_export_thread == curthread);
for (int i = 0; i < spa->spa_l2cache.sav_count; i++) {
l2arc_dev_t *dev =
l2arc_vdev_get(spa->spa_l2cache.sav_vdevs[i]);
if (dev == NULL)
continue;
mutex_enter(&l2arc_rebuild_thr_lock);
dev->l2ad_rebuild_cancel = B_TRUE;
mutex_exit(&l2arc_rebuild_thr_lock);
}
for (int i = 0; i < spa->spa_l2cache.sav_count; i++) {
l2arc_dev_t *dev =
l2arc_vdev_get(spa->spa_l2cache.sav_vdevs[i]);
if (dev == NULL)
continue;
mutex_enter(&l2arc_rebuild_thr_lock);
if (dev->l2ad_rebuild_began == B_TRUE) {
while (dev->l2ad_rebuild == B_TRUE) {
cv_wait(&l2arc_rebuild_thr_cv,
&l2arc_rebuild_thr_lock);
}
}
mutex_exit(&l2arc_rebuild_thr_lock);
}
}
/*
* Main entry point for L2ARC rebuilding.
*/
@ -9854,12 +9885,12 @@ l2arc_dev_rebuild_thread(void *arg)
{
l2arc_dev_t *dev = arg;
VERIFY(!dev->l2ad_rebuild_cancel);
VERIFY(dev->l2ad_rebuild);
(void) l2arc_rebuild(dev);
mutex_enter(&l2arc_rebuild_thr_lock);
dev->l2ad_rebuild_began = B_FALSE;
dev->l2ad_rebuild = B_FALSE;
cv_signal(&l2arc_rebuild_thr_cv);
mutex_exit(&l2arc_rebuild_thr_lock);
thread_exit();
@ -10010,8 +10041,6 @@ l2arc_rebuild(l2arc_dev_t *dev)
for (;;) {
mutex_enter(&l2arc_rebuild_thr_lock);
if (dev->l2ad_rebuild_cancel) {
dev->l2ad_rebuild = B_FALSE;
cv_signal(&l2arc_rebuild_thr_cv);
mutex_exit(&l2arc_rebuild_thr_lock);
err = SET_ERROR(ECANCELED);
goto out;

View File

@ -2081,6 +2081,7 @@ spa_unload(spa_t *spa)
vdev_trim_stop_all(root_vdev, VDEV_TRIM_ACTIVE);
vdev_autotrim_stop_all(spa);
vdev_rebuild_stop_all(spa);
l2arc_spa_rebuild_stop(spa);
}
}
@ -7115,6 +7116,7 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
vdev_trim_stop_all(rvd, VDEV_TRIM_ACTIVE);
vdev_autotrim_stop_all(spa);
vdev_rebuild_stop_all(spa);
l2arc_spa_rebuild_stop(spa);
/*
* We want this to be reflected on every label,