1222 * during a scrub, but of course it can so we must account for changes
1223 * in a block's replication class.
1224 *
1225 * Here's an example of what can occur:
1226 *
1227 * If a block has refcnt > 1 during the DDT scrub phase, but has refcnt == 1
1228 * when visited during the top-down scrub phase, it will be scrubbed twice.
1229 * This negates our scrub optimization, but is otherwise harmless.
1230 *
1231 * If a block has refcnt == 1 during the DDT scrub phase, but has refcnt > 1
1232 * on each visit during the top-down scrub phase, it will never be scrubbed.
1233 * To catch this, ddt_sync_entry() notifies the scrub code whenever a block's
1234 * reference class transitions to a higher level (i.e DDT_CLASS_UNIQUE to
1235 * DDT_CLASS_DUPLICATE); if it transitions from refcnt == 1 to refcnt > 1
1236 * while a scrub is in progress, it scrubs the block right then.
1237 */
1238 static void
1239 dsl_scan_ddt(dsl_scan_t *scn, dmu_tx_t *tx)
1240 {
1241 ddt_bookmark_t *ddb = &scn->scn_phys.scn_ddt_bookmark;
1242 ddt_entry_t dde = { 0 };
1243 int error;
1244 uint64_t n = 0;
1245
1246 while ((error = ddt_walk(scn->scn_dp->dp_spa, ddb, &dde)) == 0) {
1247 ddt_t *ddt;
1248
1249 if (ddb->ddb_class > scn->scn_phys.scn_ddt_class_max)
1250 break;
1251 dprintf("visiting ddb=%llu/%llu/%llu/%llx\n",
1252 (longlong_t)ddb->ddb_class,
1253 (longlong_t)ddb->ddb_type,
1254 (longlong_t)ddb->ddb_checksum,
1255 (longlong_t)ddb->ddb_cursor);
1256
1257 /* There should be no pending changes to the dedup table */
1258 ddt = scn->scn_dp->dp_spa->spa_ddt[ddb->ddb_checksum];
1259 ASSERT(avl_first(&ddt->ddt_tree) == NULL);
1260
1261 dsl_scan_ddt_entry(scn, ddb->ddb_checksum, &dde, tx);
1262 n++;
|
1222 * during a scrub, but of course it can so we must account for changes
1223 * in a block's replication class.
1224 *
1225 * Here's an example of what can occur:
1226 *
1227 * If a block has refcnt > 1 during the DDT scrub phase, but has refcnt == 1
1228 * when visited during the top-down scrub phase, it will be scrubbed twice.
1229 * This negates our scrub optimization, but is otherwise harmless.
1230 *
1231 * If a block has refcnt == 1 during the DDT scrub phase, but has refcnt > 1
1232 * on each visit during the top-down scrub phase, it will never be scrubbed.
1233 * To catch this, ddt_sync_entry() notifies the scrub code whenever a block's
1234 * reference class transitions to a higher level (i.e DDT_CLASS_UNIQUE to
1235 * DDT_CLASS_DUPLICATE); if it transitions from refcnt == 1 to refcnt > 1
1236 * while a scrub is in progress, it scrubs the block right then.
1237 */
1238 static void
1239 dsl_scan_ddt(dsl_scan_t *scn, dmu_tx_t *tx)
1240 {
1241 ddt_bookmark_t *ddb = &scn->scn_phys.scn_ddt_bookmark;
1242 ddt_entry_t dde = { .dde_loaded = 0 };
1243 int error;
1244 uint64_t n = 0;
1245
1246 while ((error = ddt_walk(scn->scn_dp->dp_spa, ddb, &dde)) == 0) {
1247 ddt_t *ddt;
1248
1249 if (ddb->ddb_class > scn->scn_phys.scn_ddt_class_max)
1250 break;
1251 dprintf("visiting ddb=%llu/%llu/%llu/%llx\n",
1252 (longlong_t)ddb->ddb_class,
1253 (longlong_t)ddb->ddb_type,
1254 (longlong_t)ddb->ddb_checksum,
1255 (longlong_t)ddb->ddb_cursor);
1256
1257 /* There should be no pending changes to the dedup table */
1258 ddt = scn->scn_dp->dp_spa->spa_ddt[ddb->ddb_checksum];
1259 ASSERT(avl_first(&ddt->ddt_tree) == NULL);
1260
1261 dsl_scan_ddt_entry(scn, ddb->ddb_checksum, &dde, tx);
1262 n++;
|