summaryrefslogtreecommitdiffstats
path: root/module/zfs/dsl_scrub.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/dsl_scrub.c')
-rw-r--r--module/zfs/dsl_scrub.c61
1 files changed, 32 insertions, 29 deletions
diff --git a/module/zfs/dsl_scrub.c b/module/zfs/dsl_scrub.c
index 950a91f78..dbdfe8c75 100644
--- a/module/zfs/dsl_scrub.c
+++ b/module/zfs/dsl_scrub.c
@@ -391,7 +391,7 @@ traverse_zil(dsl_pool_t *dp, zil_header_t *zh)
* We only want to visit blocks that have been claimed but not yet
* replayed (or, in read-only mode, blocks that *would* be claimed).
*/
- if (claim_txg == 0 && (spa_mode & FWRITE))
+ if (claim_txg == 0 && spa_writeable(dp->dp_spa))
return;
zilog = zil_alloc(dp->dp_meta_objset, zh);
@@ -409,9 +409,6 @@ scrub_visitbp(dsl_pool_t *dp, dnode_phys_t *dnp,
int err;
arc_buf_t *buf = NULL;
- if (bp->blk_birth == 0)
- return;
-
if (bp->blk_birth <= dp->dp_scrub_min_txg)
return;
@@ -740,6 +737,7 @@ enqueue_cb(spa_t *spa, uint64_t dsobj, const char *dsname, void *arg)
void
dsl_pool_scrub_sync(dsl_pool_t *dp, dmu_tx_t *tx)
{
+ spa_t *spa = dp->dp_spa;
zap_cursor_t zc;
zap_attribute_t za;
boolean_t complete = B_TRUE;
@@ -747,8 +745,10 @@ dsl_pool_scrub_sync(dsl_pool_t *dp, dmu_tx_t *tx)
if (dp->dp_scrub_func == SCRUB_FUNC_NONE)
return;
- /* If the spa is not fully loaded, don't bother. */
- if (dp->dp_spa->spa_load_state != SPA_LOAD_NONE)
+ /*
+ * If the pool is not loaded, or is trying to unload, leave it alone.
+ */
+ if (spa->spa_load_state != SPA_LOAD_NONE || spa_shutting_down(spa))
return;
if (dp->dp_scrub_restart) {
@@ -757,13 +757,13 @@ dsl_pool_scrub_sync(dsl_pool_t *dp, dmu_tx_t *tx)
dsl_pool_scrub_setup_sync(dp, &func, kcred, tx);
}
- if (dp->dp_spa->spa_root_vdev->vdev_stat.vs_scrub_type == 0) {
+ if (spa->spa_root_vdev->vdev_stat.vs_scrub_type == 0) {
/*
* We must have resumed after rebooting; reset the vdev
* stats to know that we're doing a scrub (although it
* will think we're just starting now).
*/
- vdev_scrub_stat_update(dp->dp_spa->spa_root_vdev,
+ vdev_scrub_stat_update(spa->spa_root_vdev,
dp->dp_scrub_min_txg ? POOL_SCRUB_RESILVER :
POOL_SCRUB_EVERYTHING, B_FALSE);
}
@@ -771,7 +771,7 @@ dsl_pool_scrub_sync(dsl_pool_t *dp, dmu_tx_t *tx)
dp->dp_scrub_pausing = B_FALSE;
dp->dp_scrub_start_time = lbolt64;
dp->dp_scrub_isresilver = (dp->dp_scrub_min_txg != 0);
- dp->dp_spa->spa_scrub_active = B_TRUE;
+ spa->spa_scrub_active = B_TRUE;
if (dp->dp_scrub_bookmark.zb_objset == 0) {
/* First do the MOS & ORIGIN */
@@ -779,8 +779,8 @@ dsl_pool_scrub_sync(dsl_pool_t *dp, dmu_tx_t *tx)
if (dp->dp_scrub_pausing)
goto out;
- if (spa_version(dp->dp_spa) < SPA_VERSION_DSL_SCRUB) {
- VERIFY(0 == dmu_objset_find_spa(dp->dp_spa,
+ if (spa_version(spa) < SPA_VERSION_DSL_SCRUB) {
+ VERIFY(0 == dmu_objset_find_spa(spa,
NULL, enqueue_cb, tx, DS_FIND_CHILDREN));
} else {
scrub_visitds(dp, dp->dp_origin_snap->ds_object, tx);
@@ -830,15 +830,13 @@ out:
VERIFY(0 == zap_update(dp->dp_meta_objset,
DMU_POOL_DIRECTORY_OBJECT,
DMU_POOL_SCRUB_ERRORS, sizeof (uint64_t), 1,
- &dp->dp_spa->spa_scrub_errors, tx));
+ &spa->spa_scrub_errors, tx));
/* XXX this is scrub-clean specific */
- mutex_enter(&dp->dp_spa->spa_scrub_lock);
- while (dp->dp_spa->spa_scrub_inflight > 0) {
- cv_wait(&dp->dp_spa->spa_scrub_io_cv,
- &dp->dp_spa->spa_scrub_lock);
- }
- mutex_exit(&dp->dp_spa->spa_scrub_lock);
+ mutex_enter(&spa->spa_scrub_lock);
+ while (spa->spa_scrub_inflight > 0)
+ cv_wait(&spa->spa_scrub_io_cv, &spa->spa_scrub_lock);
+ mutex_exit(&spa->spa_scrub_lock);
}
void
@@ -920,13 +918,17 @@ static int
dsl_pool_scrub_clean_cb(dsl_pool_t *dp,
const blkptr_t *bp, const zbookmark_t *zb)
{
- size_t size = BP_GET_LSIZE(bp);
- int d;
+ size_t size = BP_GET_PSIZE(bp);
spa_t *spa = dp->dp_spa;
boolean_t needs_io;
- int zio_flags = ZIO_FLAG_SCRUB_THREAD | ZIO_FLAG_CANFAIL;
+ int zio_flags = ZIO_FLAG_SCRUB_THREAD | ZIO_FLAG_RAW | ZIO_FLAG_CANFAIL;
int zio_priority;
+ ASSERT(bp->blk_birth > dp->dp_scrub_min_txg);
+
+ if (bp->blk_birth >= dp->dp_scrub_max_txg)
+ return (0);
+
count_block(dp->dp_blkstats, bp);
if (dp->dp_scrub_isresilver == 0) {
@@ -945,7 +947,7 @@ dsl_pool_scrub_clean_cb(dsl_pool_t *dp,
if (zb->zb_level == -1 && BP_GET_TYPE(bp) != DMU_OT_OBJSET)
zio_flags |= ZIO_FLAG_SPECULATIVE;
- for (d = 0; d < BP_GET_NDVAS(bp); d++) {
+ for (int d = 0; d < BP_GET_NDVAS(bp); d++) {
vdev_t *vd = vdev_lookup_top(spa,
DVA_GET_VDEV(&bp->blk_dva[d]));
@@ -963,16 +965,17 @@ dsl_pool_scrub_clean_cb(dsl_pool_t *dp,
if (DVA_GET_GANG(&bp->blk_dva[d])) {
/*
* Gang members may be spread across multiple
- * vdevs, so the best we can do is look at the
- * pool-wide DTL.
+ * vdevs, so the best estimate we have is the
+ * scrub range, which has already been checked.
* XXX -- it would be better to change our
- * allocation policy to ensure that this can't
- * happen.
+ * allocation policy to ensure that all
+ * gang members reside on the same vdev.
*/
- vd = spa->spa_root_vdev;
+ needs_io = B_TRUE;
+ } else {
+ needs_io = vdev_dtl_contains(vd, DTL_PARTIAL,
+ bp->blk_birth, 1);
}
- needs_io = vdev_dtl_contains(&vd->vdev_dtl_map,
- bp->blk_birth, 1);
}
}