From 33bbc2fad0996d7fd48d7098f05f194177deeaea Mon Sep 17 00:00:00 2001 From: Pavel Snajdr Date: Tue, 23 Jan 2024 18:17:31 +0100 Subject: [PATCH] Don't defer resilver when progress is below 12.5% Do a restart from the beginning instead. The original rationale for deferring additional resilvers, when there is already one in progress, was to help achieving data redundancy sooner for the data that gets scanned at the end of the resilver. But in case the admin wants to attach multiple disks to a single vdev, it wasn't immediately obvious the admin is supposed to run `zpool resilver` afterwards to reset the deferred resilvers and start a new one from scratch. Signed-off-by: Pavel Snajdr --- module/zfs/dsl_scan.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/module/zfs/dsl_scan.c b/module/zfs/dsl_scan.c index d04149f560a4..6003269a9231 100644 --- a/module/zfs/dsl_scan.c +++ b/module/zfs/dsl_scan.c @@ -4260,6 +4260,8 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx) dsl_scan_t *scn = dp->dp_scan; spa_t *spa = dp->dp_spa; state_sync_type_t sync_type = SYNC_OPTIONAL; + uint64_t to_issue, issued; + int restart_early; if (spa->spa_resilver_deferred && !spa_feature_is_active(dp->dp_spa, SPA_FEATURE_RESILVER_DEFER)) @@ -4270,9 +4272,23 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx) * that we can restart an old-style scan while the pool is being * imported (see dsl_scan_init). We also restart scans if there * is a deferred resilver and the user has manually disabled - * deferred resilvers via the tunable. + * deferred resilvers via the tunable, or if the curent scan progress + * is below 12.5%. */ - if (dsl_scan_restarting(scn, tx) || + + /* + * Taken from spa_misc.c spa_scan_get_stats(): + */ + to_issue = scn->scn_phys.scn_to_examine - scn->scn_phys.scn_skipped; + issued = scn->scn_issued_before_pass + spa->spa_scan_pass_issued; + /* + * Make sure we're not in a restart loop and check the 12.5% threshold + */ + restart_early = spa->spa_resilver_deferred && + !dsl_scan_restarting(scn, tx) && + (issued < (to_issue >> 3)); + + if (dsl_scan_restarting(scn, tx) || restart_early || (spa->spa_resilver_deferred && zfs_resilver_disable_defer)) { pool_scan_func_t func = POOL_SCAN_SCRUB; dsl_scan_done(scn, B_FALSE, tx);