summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPrakash Surya <prakash.surya@delphix.com>2021-02-24 09:52:43 -0800
committerTony Hutter <hutter2@llnl.gov>2021-09-22 15:19:08 -0700
commit61ae6c99f711a0e64779ac85ffbeaf50f920a7cc (patch)
tree84d460f0585ef9a539b38a254fc43eb2310a9758
parente9353bc2ef27c300281574453e0cf5189a375680 (diff)
Add upper bound for slop space calculation
This change modifies the behavior of how we determine how much slop space to use in the pool, such that now it has an upper limit. The default upper limit is 128G, but is configurable via a tunable. (Backporting note: Snipped out the embedded_log portion of the changes.) Reviewed-by: Matthew Ahrens <mahrens@delphix.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Prakash Surya <prakash.surya@delphix.com> Closes #11023
-rw-r--r--include/sys/dsl_synctask.h9
-rw-r--r--module/zfs/spa_misc.c32
2 files changed, 27 insertions, 14 deletions
diff --git a/include/sys/dsl_synctask.h b/include/sys/dsl_synctask.h
index 0bb602e8f..5a5b30641 100644
--- a/include/sys/dsl_synctask.h
+++ b/include/sys/dsl_synctask.h
@@ -41,10 +41,11 @@ typedef void (dsl_sigfunc_t)(void *, dmu_tx_t *);
typedef enum zfs_space_check {
/*
- * Normal space check: if there is less than 3.2% free space,
- * the operation will fail. Operations which are logically
- * creating things should use this (e.g. "zfs create", "zfs snapshot").
- * User writes (via the ZPL / ZVOL) also fail at this point.
+ * Normal space check: if there is less than 3.2% free space (bounded
+ * by spa_max_slop), the operation will fail. Operations which are
+ * logically creating things should use this (e.g. "zfs create", "zfs
+ * snapshot"). User writes (via the ZPL / ZVOL) also fail at this
+ * point.
*/
ZFS_SPACE_CHECK_NORMAL,
diff --git a/module/zfs/spa_misc.c b/module/zfs/spa_misc.c
index dc5d5be2d..eff8c716d 100644
--- a/module/zfs/spa_misc.c
+++ b/module/zfs/spa_misc.c
@@ -347,10 +347,10 @@ int spa_asize_inflation = 24;
/*
* Normally, we don't allow the last 3.2% (1/(2^spa_slop_shift)) of space in
- * the pool to be consumed. This ensures that we don't run the pool
- * completely out of space, due to unaccounted changes (e.g. to the MOS).
- * It also limits the worst-case time to allocate space. If we have
- * less than this amount of free space, most ZPL operations (e.g. write,
+ * the pool to be consumed (bounded by spa_max_slop). This ensures that we
+ * don't run the pool completely out of space, due to unaccounted changes (e.g.
+ * to the MOS). It also limits the worst-case time to allocate space. If we
+ * have less than this amount of free space, most ZPL operations (e.g. write,
* create) will return ENOSPC.
*
* Certain operations (e.g. file removal, most administrative actions) can
@@ -374,10 +374,15 @@ int spa_asize_inflation = 24;
* 3.2%, in an effort to have it be at least spa_min_slop (128MB),
* but we never allow it to be more than half the pool size.
*
+ * Further, on very large pools, the slop space will be smaller than
+ * 3.2%, to avoid reserving much more space than we actually need; bounded
+ * by spa_max_slop (128GB).
+ *
* See also the comments in zfs_space_check_t.
*/
int spa_slop_shift = 5;
-uint64_t spa_min_slop = 128 * 1024 * 1024;
+uint64_t spa_min_slop = 128ULL * 1024 * 1024;
+uint64_t spa_max_slop = 128ULL * 1024 * 1024 * 1024;
int spa_allocators = 4;
@@ -1775,17 +1780,24 @@ spa_get_worst_case_asize(spa_t *spa, uint64_t lsize)
}
/*
- * Return the amount of slop space in bytes. It is 1/32 of the pool (3.2%),
- * or at least 128MB, unless that would cause it to be more than half the
- * pool size.
+ * Return the amount of slop space in bytes. It is typically 1/32 of the pool
+ * (3.2%). On very small pools, it may be slightly larger than this. On very
+ * large pools, it will be capped to the value of spa_max_slop.
*
- * See the comment above spa_slop_shift for details.
+ * See the comment above spa_slop_shift for more details.
*/
uint64_t
spa_get_slop_space(spa_t *spa)
{
uint64_t space = spa_get_dspace(spa);
- return (MAX(space >> spa_slop_shift, MIN(space >> 1, spa_min_slop)));
+ uint64_t slop = MIN(space >> spa_slop_shift, spa_max_slop);
+
+ /*
+ * Slop space should be at least spa_min_slop, but no more than half
+ * the entire pool.
+ */
+ slop = MAX(slop, MIN(space >> 1, spa_min_slop));
+ return (slop);
}
uint64_t