From d9619546889dfec7b0a8ee45f82671184b75ea0d Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Thu, 1 Feb 2024 11:05:18 +1100 Subject: [PATCH] ddt: only create tables for dedup-capable checksums Most values in zio_checksum can never be used for dedup, partly because the dedup= property only offers a limited list, but also some values (eg ZIO_CHECKSUM_OFF) aren't real and will never be seen. A true flag would be better than a hardcoded list, but thats more cleanup elsewhere than I want to do right now. Reviewed-by: Brian Behlendorf Signed-off-by: Rob Norris Sponsored-by: Klara, Inc. Sponsored-by: iXsystems, Inc. Closes #15887 --- cmd/zdb/zdb.c | 8 +++++++- module/zfs/ddt.c | 21 +++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c index 7f17de03d..4880c8048 100644 --- a/cmd/zdb/zdb.c +++ b/cmd/zdb/zdb.c @@ -1965,6 +1965,8 @@ dump_all_ddts(spa_t *spa) 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++) { @@ -6062,6 +6064,8 @@ zdb_ddt_leak_init(spa_t *spa, zdb_cb_t *zcb) return; ASSERT(ddt_phys_total_refcnt(&dde) > 1); + ddt_t *ddt = spa->spa_ddt[ddb.ddb_checksum]; + VERIFY(ddt); for (p = 0; p < DDT_PHYS_TYPES; p++, ddp++) { if (ddp->ddp_phys_birth == 0) @@ -6076,7 +6080,7 @@ zdb_ddt_leak_init(spa_t *spa, zdb_cb_t *zcb) zcb->zcb_dedup_blocks++; } } - ddt_t *ddt = spa->spa_ddt[ddb.ddb_checksum]; + ddt_enter(ddt); VERIFY(ddt_lookup(ddt, &blk, B_TRUE) != NULL); ddt_exit(ddt); @@ -7949,6 +7953,8 @@ dump_mos_leaks(spa_t *spa) for (uint64_t cksum = 0; cksum < ZIO_CHECKSUM_FUNCTIONS; cksum++) { ddt_t *ddt = spa->spa_ddt[cksum]; + if (!ddt) + continue; mos_obj_refd(ddt->ddt_object[type][class]); } } diff --git a/module/zfs/ddt.c b/module/zfs/ddt.c index 3e278d702..f22c79c50 100644 --- a/module/zfs/ddt.c +++ b/module/zfs/ddt.c @@ -39,6 +39,15 @@ #include #include +/* + * These are the only checksums valid for dedup. They must match the list + * from dedup_table in zfs_prop.c + */ +#define DDT_CHECKSUM_VALID(c) \ + (c == ZIO_CHECKSUM_SHA256 || c == ZIO_CHECKSUM_SHA512 || \ + c == ZIO_CHECKSUM_SKEIN || c == ZIO_CHECKSUM_EDONR || \ + c == ZIO_CHECKSUM_BLAKE3) + static kmem_cache_t *ddt_cache; static kmem_cache_t *ddt_entry_cache; @@ -400,6 +409,7 @@ ddt_phys_total_refcnt(const ddt_entry_t *dde) ddt_t * ddt_select(spa_t *spa, const blkptr_t *bp) { + ASSERT(DDT_CHECKSUM_VALID(BP_GET_CHECKSUM(bp))); return (spa->spa_ddt[BP_GET_CHECKSUM(bp)]); } @@ -629,8 +639,10 @@ ddt_create(spa_t *spa) { spa->spa_dedup_checksum = ZIO_DEDUPCHECKSUM; - for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) - spa->spa_ddt[c] = ddt_table_alloc(spa, c); + for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) { + if (DDT_CHECKSUM_VALID(c)) + spa->spa_ddt[c] = ddt_table_alloc(spa, c); + } } int @@ -648,6 +660,9 @@ ddt_load(spa_t *spa) return (error == ENOENT ? 0 : error); for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) { + if (!DDT_CHECKSUM_VALID(c)) + continue; + ddt_t *ddt = spa->spa_ddt[c]; for (ddt_type_t type = 0; type < DDT_TYPES; type++) { for (ddt_class_t class = 0; class < DDT_CLASSES; @@ -967,6 +982,8 @@ ddt_walk(spa_t *spa, ddt_bookmark_t *ddb, ddt_entry_t *dde) do { do { ddt_t *ddt = spa->spa_ddt[ddb->ddb_checksum]; + if (ddt == NULL) + continue; int error = ENOENT; if (ddt_object_exists(ddt, ddb->ddb_type, ddb->ddb_class)) { -- 2.39.2