From d6496040d904c381d7ecdb113cfcab4964e033c1 Mon Sep 17 00:00:00 2001 From: Tom Caputi Date: Thu, 6 Dec 2018 12:47:23 -0500 Subject: [PATCH] Ensure dsl scan prefetch queue is emptied This patch simply ensures that scn->scn_prefetch_queue is emptied before the kernel module is unloaded and when scanning completes. Reviewed-by: Brian Behlendorf Reviewed-by: Alek Pinchuk Signed-off-by: Tom Caputi Closes #8178 --- module/zfs/dsl_scan.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/module/zfs/dsl_scan.c b/module/zfs/dsl_scan.c index d9d9900a2d..3180ce65ab 100644 --- a/module/zfs/dsl_scan.c +++ b/module/zfs/dsl_scan.c @@ -119,6 +119,7 @@ static scan_cb_t dsl_scan_scrub_cb; static int scan_ds_queue_compare(const void *a, const void *b); static int scan_prefetch_queue_compare(const void *a, const void *b); static void scan_ds_queue_clear(dsl_scan_t *scn); +static void scan_ds_prefetch_queue_clear(dsl_scan_t *scn); static boolean_t scan_ds_queue_contains(dsl_scan_t *scn, uint64_t dsobj, uint64_t *txg); static void scan_ds_queue_insert(dsl_scan_t *scn, uint64_t dsobj, uint64_t txg); @@ -514,8 +515,10 @@ dsl_scan_fini(dsl_pool_t *dp) if (scn->scn_taskq != NULL) taskq_destroy(scn->scn_taskq); + scan_ds_queue_clear(scn); avl_destroy(&scn->scn_queue); + scan_ds_prefetch_queue_clear(scn); avl_destroy(&scn->scn_prefetch_queue); kmem_free(dp->dp_scan, sizeof (dsl_scan_t)); @@ -812,6 +815,7 @@ dsl_scan_done(dsl_scan_t *scn, boolean_t complete, dmu_tx_t *tx) scn->scn_phys.scn_queue_obj = 0; } scan_ds_queue_clear(scn); + scan_ds_prefetch_queue_clear(scn); scn->scn_phys.scn_flags &= ~DSF_SCRUB_PAUSED; @@ -1413,6 +1417,22 @@ scan_prefetch_ctx_add_ref(scan_prefetch_ctx_t *spc, void *tag) zfs_refcount_add(&spc->spc_refcnt, tag); } +static void +scan_ds_prefetch_queue_clear(dsl_scan_t *scn) +{ + spa_t *spa = scn->scn_dp->dp_spa; + void *cookie = NULL; + scan_prefetch_issue_ctx_t *spic = NULL; + + mutex_enter(&spa->spa_scrub_lock); + while ((spic = avl_destroy_nodes(&scn->scn_prefetch_queue, + &cookie)) != NULL) { + scan_prefetch_ctx_rele(spic->spic_spc, scn); + kmem_free(spic, sizeof (scan_prefetch_issue_ctx_t)); + } + mutex_exit(&spa->spa_scrub_lock); +} + static boolean_t dsl_scan_check_prefetch_resume(scan_prefetch_ctx_t *spc, const zbookmark_phys_t *zb)