From 2505cc72154b11223bf227b5e94057a2c7425b13 Mon Sep 17 00:00:00 2001 From: Fabian Keil Date: Fri, 29 Apr 2016 19:38:53 +0200 Subject: [PATCH 236/257] ZFS: Add a (tunable) lower limit for the dynamic write buffer Default to using 0.5% of the system's physical memory. Obtained from: ElectroBSD --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c | 13 +++++++++++++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c | 1 + sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c | 5 +++++ .../contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h | 1 + 4 files changed, 20 insertions(+) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c index 9c844e30e9e5..61b1bcdffef2 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c @@ -6276,6 +6276,19 @@ arc_init(void) zfs_dirty_data_max = MIN(zfs_dirty_data_max, zfs_dirty_data_max_max); } + /* + * If memory is tight, reduce the dynamic write buffer + * as low as 0.5% of the physical memory. This allows + * a system with 1 GB of physical memory to remain stable + * while building kernels in a loop for days. + * Using 1% (10 MB) proved to be too much. + * + * Systems with 2 GB of physical memory don't seem to + * reach the lower limit while building kernels. + */ + if (zfs_dirty_data_max_min == 0) { + zfs_dirty_data_max_min = ptob(physmem) / 200; + } #ifdef _KERNEL if (TUNABLE_INT_FETCH("vfs.zfs.prefetch_disable", &zfs_prefetch_disable)) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c index 51ded24b981f..7c1e3a6df36a 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c @@ -1394,6 +1394,7 @@ dmu_tx_assign(dmu_tx_t *tx, txg_how_t txg_how) last_max = zfs_dirty_data_max_internal / (1024 * 1024); DTRACE_PROBE1(dmu__tx_dirty, uint64_t, last_max); } + zfs_dirty_data_max_internal = MAX(zfs_dirty_data_max_internal, zfs_dirty_data_max_min); if (zfs_dirty_data_max_internal < zfs_dirty_data_max) { zfs_dynamic_write_buffer_hits++; } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c index d99323fd21a3..b8d742844e37 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c @@ -105,6 +105,7 @@ uint64_t zfs_dirty_data_max; uint64_t zfs_dirty_data_max_internal; uint64_t zfs_dirty_data_max_max = 4ULL * 1024 * 1024 * 1024; +uint64_t zfs_dirty_data_max_min = 0; int zfs_dirty_data_max_percent = 10; /* @@ -154,6 +155,10 @@ SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, dirty_data_max_internal, CTLFLAG_RD, &zfs_dirty_data_max_internal, 0, "The currently active limit of dirty data (may dynamically change)"); +SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, dirty_data_max_min, CTLFLAG_RWTUN, + &zfs_dirty_data_max_min, 0, + "The absolute lower cap on dirty_data_max_internal when auto calculating"); + static int sysctl_zfs_dirty_data_max_percent(SYSCTL_HANDLER_ARGS); SYSCTL_PROC(_vfs_zfs, OID_AUTO, dirty_data_max_percent, CTLTYPE_INT | CTLFLAG_MPSAFE | CTLFLAG_RWTUN, 0, sizeof(int), diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h index ee97b5719cd2..c0444da17104 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h @@ -52,6 +52,7 @@ struct dsl_scan; extern uint64_t zfs_dirty_data_max; extern uint64_t zfs_dirty_data_max_internal; extern uint64_t zfs_dirty_data_max_max; +extern uint64_t zfs_dirty_data_max_min; extern uint64_t zfs_dirty_data_sync; extern int zfs_dirty_data_max_percent; extern int zfs_delay_min_dirty_percent; -- 2.11.0