Skip to content

Commit ce06c8f

Browse files
behlendorfdefaziogiancarlo
authored andcommitted
Increase default zfs_scan_vdev_limit to 16MB
For HDD based pools the default zfs_scan_vdev_limit of 4M per-vdev can significantly limit the maximum scrub performance. Increasing the default to 16M can double the scrub speed from 80 MB/s per disk to 160 MB/s per disk. This does increase the memory footprint during scrub/resilver but given the performance win this is a reasonable trade off. Memory usage is capped at 1/4 of arc_c_max. Note that number of outstanding I/Os has not changed and is still limited by zfs_vdev_scrub_max_active. Reviewed-by: Akash B <[email protected]> Reviewed-by: Tony Nguyen <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes openzfs#14428 Conflicts: man/man4/zfs.4 module/zfs/dsl_scan.c
1 parent 56fcfd3 commit ce06c8f

File tree

2 files changed

+17
-13
lines changed

2 files changed

+17
-13
lines changed

man/man4/zfs.4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1846,7 +1846,7 @@ When disabled, the memory limit may be exceeded by fast disks.
18461846
Freezes a scrub/resilver in progress without actually pausing it.
18471847
Intended for testing/debugging.
18481848
.
1849-
.It Sy zfs_scan_vdev_limit Ns = Ns Sy 4194304 Ns B Po 4MB Pc Pq int
1849+
.It Sy zfs_scan_vdev_limit Ns = Ns Sy 16777216 Ns B Po 16 MiB Pc Pq int
18501850
Maximum amount of data that can be concurrently issued at once for scrubs and
18511851
resilvers per leaf device, given in bytes.
18521852
.

module/zfs/dsl_scan.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <sys/dmu_tx.h>
3838
#include <sys/dmu_objset.h>
3939
#include <sys/arc.h>
40+
#include <sys/arc_impl.h>
4041
#include <sys/zap.h>
4142
#include <sys/zio.h>
4243
#include <sys/zfs_context.h>
@@ -126,7 +127,7 @@ static boolean_t scan_ds_queue_contains(dsl_scan_t *scn, uint64_t dsobj,
126127
static void scan_ds_queue_insert(dsl_scan_t *scn, uint64_t dsobj, uint64_t txg);
127128
static void scan_ds_queue_remove(dsl_scan_t *scn, uint64_t dsobj);
128129
static void scan_ds_queue_sync(dsl_scan_t *scn, dmu_tx_t *tx);
129-
static uint64_t dsl_scan_count_data_disks(vdev_t *vd);
130+
static uint64_t dsl_scan_count_data_disks(spa_t *spa);
130131

131132
extern int zfs_vdev_async_write_active_min_dirty_percent;
132133
static int zfs_scan_blkstats = 0;
@@ -156,7 +157,7 @@ int zfs_scan_strict_mem_lim = B_FALSE;
156157
* overload the drives with I/O, since that is protected by
157158
* zfs_vdev_scrub_max_active.
158159
*/
159-
unsigned long zfs_scan_vdev_limit = 4 << 20;
160+
unsigned long zfs_scan_vdev_limit = 16 << 20;
160161

161162
int zfs_scan_issue_strategy = 0;
162163
int zfs_scan_legacy = B_FALSE; /* don't queue & sort zios, go direct */
@@ -459,11 +460,12 @@ dsl_scan_init(dsl_pool_t *dp, uint64_t txg)
459460

460461
/*
461462
* Calculate the max number of in-flight bytes for pool-wide
462-
* scanning operations (minimum 1MB). Limits for the issuing
463-
* phase are done per top-level vdev and are handled separately.
463+
* scanning operations (minimum 1MB, maximum 1/4 of arc_c_max).
464+
* Limits for the issuing phase are done per top-level vdev and
465+
* are handled separately.
464466
*/
465-
scn->scn_maxinflight_bytes = MAX(zfs_scan_vdev_limit *
466-
dsl_scan_count_data_disks(spa->spa_root_vdev), 1ULL << 20);
467+
scn->scn_maxinflight_bytes = MIN(arc_c_max / 4, MAX(1ULL << 20,
468+
zfs_scan_vdev_limit * dsl_scan_count_data_disks(spa)));
467469

468470
avl_create(&scn->scn_queue, scan_ds_queue_compare, sizeof (scan_ds_t),
469471
offsetof(scan_ds_t, sds_node));
@@ -2794,8 +2796,9 @@ dsl_scan_visit(dsl_scan_t *scn, dmu_tx_t *tx)
27942796
}
27952797

27962798
static uint64_t
2797-
dsl_scan_count_data_disks(vdev_t *rvd)
2799+
dsl_scan_count_data_disks(spa_t *spa)
27982800
{
2801+
vdev_t *rvd = spa->spa_root_vdev;
27992802
uint64_t i, leaves = 0;
28002803

28012804
for (i = 0; i < rvd->vdev_children; i++) {
@@ -3700,12 +3703,13 @@ dsl_scan_sync(dsl_pool_t *dp, dmu_tx_t *tx)
37003703
taskqid_t prefetch_tqid;
37013704

37023705
/*
3703-
* Recalculate the max number of in-flight bytes for pool-wide
3704-
* scanning operations (minimum 1MB). Limits for the issuing
3705-
* phase are done per top-level vdev and are handled separately.
3706+
* Calculate the max number of in-flight bytes for pool-wide
3707+
* scanning operations (minimum 1MB, maximum 1/4 of arc_c_max).
3708+
* Limits for the issuing phase are done per top-level vdev and
3709+
* are handled separately.
37063710
*/
3707-
scn->scn_maxinflight_bytes = MAX(zfs_scan_vdev_limit *
3708-
dsl_scan_count_data_disks(spa->spa_root_vdev), 1ULL << 20);
3711+
scn->scn_maxinflight_bytes = MIN(arc_c_max / 4, MAX(1ULL << 20,
3712+
zfs_scan_vdev_limit * dsl_scan_count_data_disks(spa)));
37093713

37103714
if (scnp->scn_ddt_bookmark.ddb_class <=
37113715
scnp->scn_ddt_class_max) {

0 commit comments

Comments
 (0)