diff --git a/include/sys/dsl_scan.h b/include/sys/dsl_scan.h index 032f7f3e2..bcb896da3 100644 --- a/include/sys/dsl_scan.h +++ b/include/sys/dsl_scan.h @@ -138,6 +138,7 @@ typedef struct dsl_scan { /* per txg statistics */ uint64_t scn_visited_this_txg; /* total bps visited this txg */ + uint64_t scn_dedup_frees_this_txg; /* dedup bps freed this txg */ uint64_t scn_holes_this_txg; uint64_t scn_lt_min_this_txg; uint64_t scn_gt_max_this_txg; diff --git a/man/man5/zfs-module-parameters.5 b/man/man5/zfs-module-parameters.5 index 6c0fc0dab..311d898ff 100644 --- a/man/man5/zfs-module-parameters.5 +++ b/man/man5/zfs-module-parameters.5 @@ -1642,6 +1642,17 @@ Default value: \fB1\fR. .RS 12n Maximum number of blocks freed in a single txg. .sp +Default value: \fBULONG_MAX\fR (unlimited). +.RE + +.sp +.ne 2 +.na +\fBzfs_max_async_dedup_frees\fR (ulong) +.ad +.RS 12n +Maximum number of dedup blocks freed in a single txg. +.sp Default value: \fB100,000\fR. .RE diff --git a/module/zfs/dsl_scan.c b/module/zfs/dsl_scan.c index 1c31261bf..3579f71d7 100644 --- a/module/zfs/dsl_scan.c +++ b/module/zfs/dsl_scan.c @@ -175,7 +175,9 @@ int zfs_no_scrub_io = B_FALSE; /* set to disable scrub i/o */ int zfs_no_scrub_prefetch = B_FALSE; /* set to disable scrub prefetch */ enum ddt_class zfs_scrub_ddt_class_max = DDT_CLASS_DUPLICATE; /* max number of blocks to free in a single TXG */ -unsigned long zfs_async_block_max_blocks = 100000; +unsigned long zfs_async_block_max_blocks = ULONG_MAX; +/* max number of dedup blocks to free in a single TXG */ +unsigned long zfs_max_async_dedup_frees = 100000; int zfs_resilver_disable_defer = 0; /* set to disable resilver deferring */ @@ -3101,6 +3103,11 @@ dsl_scan_async_block_should_pause(dsl_scan_t *scn) return (B_TRUE); } + if (zfs_max_async_dedup_frees != 0 && + scn->scn_dedup_frees_this_txg >= zfs_max_async_dedup_frees) { + return (B_TRUE); + } + elapsed_nanosecs = gethrtime() - scn->scn_sync_start_time; return (elapsed_nanosecs / NANOSEC > zfs_txg_timeout || (NSEC2MSEC(elapsed_nanosecs) > scn->scn_async_block_min_time_ms && @@ -3125,6 +3132,8 @@ dsl_scan_free_block_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx) -bp_get_dsize_sync(scn->scn_dp->dp_spa, bp), -BP_GET_PSIZE(bp), -BP_GET_UCSIZE(bp), tx); scn->scn_visited_this_txg++; + if (BP_GET_DEDUP(bp)) + scn->scn_dedup_frees_this_txg++; return (0); } @@ -3365,6 +3374,7 @@ dsl_process_async_destroys(dsl_pool_t *dp, dmu_tx_t *tx) NSEC2MSEC(gethrtime() - scn->scn_sync_start_time), (longlong_t)tx->tx_txg, err); scn->scn_visited_this_txg = 0; + scn->scn_dedup_frees_this_txg = 0; /* * Write out changes to the DDT that may be required as a @@ -3493,6 +3503,7 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx) /* reset scan statistics */ scn->scn_visited_this_txg = 0; + scn->scn_dedup_frees_this_txg = 0; scn->scn_holes_this_txg = 0; scn->scn_lt_min_this_txg = 0; scn->scn_gt_max_this_txg = 0; @@ -4327,6 +4338,9 @@ ZFS_MODULE_PARAM(zfs, zfs_, no_scrub_prefetch, INT, ZMOD_RW, ZFS_MODULE_PARAM(zfs, zfs_, async_block_max_blocks, ULONG, ZMOD_RW, "Max number of blocks freed in one txg"); +ZFS_MODULE_PARAM(zfs, zfs_, max_async_dedup_frees, ULONG, ZMOD_RW, + "Max number of dedup blocks freed in one txg"); + ZFS_MODULE_PARAM(zfs, zfs_, free_bpobj_enabled, INT, ZMOD_RW, "Enable processing of the free_bpobj");