From 510b56df55e84613683b105f2aec28a0f5f979b9 Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Thu, 15 Jun 2023 16:10:00 +1000 Subject: [PATCH] ddt: ensure ddt objects exist before trying to get stats from them ddt_get_dedup_histogram() was actually checking it, just in an extremely cursed way. ddt_get_dedup_object_stats() wasn't, but wasn't being called from a dangerous place so no one noticed. These checks are necessary, because spa_ddt[] is not populated until spa_load(), but the spa can exist before that, while being created, and as vdevs and metaslabs are initialised the space accounting functions will be called to update pool space counts. Probably the whole create path doesn't need to go asking for space accounting from metadata subsystems until after the pool is created. This will at least catch misuse. Signed-off-by: Rob Norris Sponsored-by: Klara, Inc. Sponsored-by: iXsystems, Inc. --- module/zfs/ddt_stats.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/module/zfs/ddt_stats.c b/module/zfs/ddt_stats.c index 4ef6c3a07e..af5365a1d1 100644 --- a/module/zfs/ddt_stats.c +++ b/module/zfs/ddt_stats.c @@ -132,6 +132,9 @@ ddt_get_dedup_object_stats(spa_t *spa, ddt_object_t *ddo_total) /* Sum the statistics we cached in ddt_object_sync(). */ for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) { ddt_t *ddt = spa->spa_ddt[c]; + if (!ddt) + continue; + for (ddt_type_t type = 0; type < DDT_TYPES; type++) { for (ddt_class_t class = 0; class < DDT_CLASSES; class++) { @@ -156,7 +159,10 @@ 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 (ddt_type_t type = 0; type < DDT_TYPES && ddt; type++) { + if (!ddt) + continue; + + for (ddt_type_t type = 0; type < DDT_TYPES; type++) { for (ddt_class_t class = 0; class < DDT_CLASSES; class++) { ddt_histogram_add(ddh,