From 0dd9a7f286c9ef36b78a82f9259050251e9fd32d 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. Reviewed-by: Brian Behlendorf Signed-off-by: Rob Norris Sponsored-by: Klara, Inc. Sponsored-by: iXsystems, Inc. Closes #15887 --- 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 4ef6c3a07e3b..af5365a1d114 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,