Mercurial > illumos > illumos-gate
changeset 11938:6f4775397a5e
6909931 dedup stats are computed incorrectly
author | George Wilson <George.Wilson@Sun.COM> |
---|---|
date | Tue, 16 Mar 2010 09:59:42 -0700 |
parents | ee1b786b1783 |
children | 99d25c90b354 |
files | usr/src/uts/common/fs/zfs/ddt.c usr/src/uts/common/fs/zfs/sys/ddt.h |
diffstat | 2 files changed, 54 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/ddt.c Tue Mar 16 10:49:14 2010 -0600 +++ b/usr/src/uts/common/fs/zfs/ddt.c Tue Mar 16 09:59:42 2010 -0700 @@ -87,6 +87,7 @@ VERIFY(zap_remove(os, DMU_POOL_DIRECTORY_OBJECT, name, tx) == 0); VERIFY(zap_remove(os, spa->spa_ddt_stat_object, name, tx) == 0); VERIFY(ddt_ops[type]->ddt_op_destroy(os, *objectp, tx) == 0); + bzero(&ddt->ddt_object_stats[type][class], sizeof (ddt_object_t)); *objectp = 0; } @@ -94,6 +95,8 @@ static int ddt_object_load(ddt_t *ddt, enum ddt_type type, enum ddt_class class) { + ddt_object_t *ddo = &ddt->ddt_object_stats[type][class]; + dmu_object_info_t doi; char name[DDT_NAMELEN]; int error; @@ -109,6 +112,15 @@ sizeof (uint64_t), sizeof (ddt_histogram_t) / sizeof (uint64_t), &ddt->ddt_histogram[type][class]); + /* + * Seed the cached statistics. + */ + VERIFY(ddt_object_info(ddt, type, class, &doi) == 0); + + ddo->ddo_count = ddt_object_count(ddt, type, class); + ddo->ddo_dspace = doi.doi_physical_blocks_512 << 9; + ddo->ddo_mspace = doi.doi_fill_count * doi.doi_data_block_size; + ASSERT(error == 0); return (error); } @@ -117,6 +129,8 @@ ddt_object_sync(ddt_t *ddt, enum ddt_type type, enum ddt_class class, dmu_tx_t *tx) { + ddt_object_t *ddo = &ddt->ddt_object_stats[type][class]; + dmu_object_info_t doi; char name[DDT_NAMELEN]; ddt_object_name(ddt, type, class, name); @@ -124,6 +138,15 @@ VERIFY(zap_update(ddt->ddt_os, ddt->ddt_spa->spa_ddt_stat_object, name, sizeof (uint64_t), sizeof (ddt_histogram_t) / sizeof (uint64_t), &ddt->ddt_histogram[type][class], tx) == 0); + + /* + * Cache DDT statistics; this is the only time they'll change. + */ + VERIFY(ddt_object_info(ddt, type, class, &doi) == 0); + + ddo->ddo_count = ddt_object_count(ddt, type, class); + ddo->ddo_dspace = doi.doi_physical_blocks_512 << 9; + ddo->ddo_mspace = doi.doi_fill_count * doi.doi_data_block_size; } static int @@ -400,31 +423,31 @@ } void -ddt_get_dedup_object_stats(spa_t *spa, ddt_object_t *ddo) +ddt_get_dedup_object_stats(spa_t *spa, ddt_object_t *ddo_total) { - dmu_object_info_t doi; - uint64_t count; - int error; - + /* 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]; for (enum ddt_type type = 0; type < DDT_TYPES; type++) { for (enum ddt_class class = 0; class < DDT_CLASSES; class++) { - error = ddt_object_info(ddt, type, class, &doi); - if (error == ENOENT) - continue; - ASSERT3U(error, ==, 0); - - count = ddt_object_count(ddt, type, class); - ddo->ddo_count += count; - ddo->ddo_dspace += - (doi.doi_physical_blocks_512 << 9) / count; - ddo->ddo_mspace += doi.doi_fill_count * - doi.doi_data_block_size / count; + ddt_object_t *ddo = + &ddt->ddt_object_stats[type][class]; + ddo_total->ddo_count += ddo->ddo_count; + ddo_total->ddo_dspace += ddo->ddo_dspace; + ddo_total->ddo_mspace += ddo->ddo_mspace; } } } + + /* ... and compute the averages. */ + if (ddo_total->ddo_count != 0) { + ddo_total->ddo_dspace /= ddo_total->ddo_count; + ddo_total->ddo_mspace /= ddo_total->ddo_count; + } else { + ASSERT(ddo_total->ddo_dspace == 0); + ASSERT(ddo_total->ddo_mspace == 0); + } } void @@ -436,7 +459,7 @@ for (enum ddt_class class = 0; class < DDT_CLASSES; class++) { ddt_histogram_add(ddh, - &ddt->ddt_histogram[type][class]); + &ddt->ddt_histogram_cache[type][class]); } } } @@ -761,15 +784,21 @@ return (error == ENOENT ? 0 : error); 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_class class = 0; class < DDT_CLASSES; class++) { - ddt_t *ddt = spa->spa_ddt[c]; error = ddt_object_load(ddt, type, class); if (error != 0 && error != ENOENT) return (error); } } + + /* + * Seed the cached histograms. + */ + bcopy(ddt->ddt_histogram, &ddt->ddt_histogram_cache, + sizeof (ddt->ddt_histogram)); } return (0); @@ -1009,6 +1038,9 @@ ddt_object_destroy(ddt, type, class, tx); } } + + bcopy(ddt->ddt_histogram, &ddt->ddt_histogram_cache, + sizeof (ddt->ddt_histogram)); } void
--- a/usr/src/uts/common/fs/zfs/sys/ddt.h Tue Mar 16 10:49:14 2010 -0600 +++ b/usr/src/uts/common/fs/zfs/sys/ddt.h Tue Mar 16 09:59:42 2010 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -101,7 +101,7 @@ DDT_PHYS_DOUBLE = 2, DDT_PHYS_TRIPLE = 3, DDT_PHYS_TYPES -} ddt_phys_type_t; +}; /* * In-core ddt entry @@ -132,6 +132,8 @@ uint64_t ddt_stat_object; uint64_t ddt_object[DDT_TYPES][DDT_CLASSES]; ddt_histogram_t ddt_histogram[DDT_TYPES][DDT_CLASSES]; + ddt_histogram_t ddt_histogram_cache[DDT_TYPES][DDT_CLASSES]; + ddt_object_t ddt_object_stats[DDT_TYPES][DDT_CLASSES]; avl_node_t ddt_node; };