]> granicus.if.org Git - zfs/commitdiff
Ensure dsl scan prefetch queue is emptied
authorTom Caputi <tcaputi@datto.com>
Thu, 6 Dec 2018 17:47:23 +0000 (12:47 -0500)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 6 Dec 2018 17:47:23 +0000 (09:47 -0800)
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 <behlendorf1@llnl.gov>
Reviewed-by: Alek Pinchuk <apinchuk@datto.com>
Signed-off-by: Tom Caputi <tcaputi@datto.com>
Closes #8178

module/zfs/dsl_scan.c

index d9d9900a2d03a6ab5aca4767a1322fdc6f3a9b61..3180ce65abee7690232cad17e94bd624849fa90b 100644 (file)
@@ -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)