From 960a5a557b58d09d43b9e6c361a8f88639d46fcb Mon Sep 17 00:00:00 2001 From: Rich Ercolani <214141+rincebrain@users.noreply.github.com> Date: Tue, 13 Jul 2021 11:47:57 -0400 Subject: [PATCH] Tinker with slop space accounting with dedup * Tinker with slop space accounting with dedup Do not include the deduplicated space usage in the slop space reservation, it leads to surprising outcomes. * Update spa_dedup_dspace sometimes Sometimes, we get into spa_get_slop_space() with spa_dedup_dspace=~0ULL, AKA "unset", while spa_dspace is correctly set. So call the code to update it before we use it if we hit that case. Reviewed-by: Matthew Ahrens Reviewed-by: Mark Maybee Signed-off-by: Rich Ercolani Closes #12271 --- module/zfs/ddt.c | 2 +- module/zfs/spa_misc.c | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/module/zfs/ddt.c b/module/zfs/ddt.c index b94a9f54ec..35c0f2da9a 100644 --- a/module/zfs/ddt.c +++ b/module/zfs/ddt.c @@ -503,7 +503,7 @@ ddt_get_dedup_histogram(spa_t *spa, ddt_histogram_t *ddh) { for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) { ddt_t *ddt = spa->spa_ddt[c]; - for (enum ddt_type type = 0; type < DDT_TYPES; type++) { + for (enum ddt_type type = 0; type < DDT_TYPES && ddt; type++) { for (enum ddt_class class = 0; class < DDT_CLASSES; class++) { ddt_histogram_add(ddh, diff --git a/module/zfs/spa_misc.c b/module/zfs/spa_misc.c index e2523231d2..6ffe11a866 100644 --- a/module/zfs/spa_misc.c +++ b/module/zfs/spa_misc.c @@ -1787,8 +1787,22 @@ spa_get_worst_case_asize(spa_t *spa, uint64_t lsize) uint64_t spa_get_slop_space(spa_t *spa) { - uint64_t space = spa_get_dspace(spa); - uint64_t slop = MIN(space >> spa_slop_shift, spa_max_slop); + uint64_t space = 0; + uint64_t slop = 0; + + /* + * Make sure spa_dedup_dspace has been set. + */ + if (spa->spa_dedup_dspace == ~0ULL) + spa_update_dspace(spa); + + /* + * spa_get_dspace() includes the space only logically "used" by + * deduplicated data, so since it's not useful to reserve more + * space with more deduplicated data, we subtract that out here. + */ + space = spa_get_dspace(spa) - spa->spa_dedup_dspace; + slop = MIN(space >> spa_slop_shift, spa_max_slop); /* * Subtract the embedded log space, but no more than half the (3.2%)