xref: /freebsd/sys/contrib/openzfs/module/zfs/ddt_stats.c (revision 61145dc2b94f12f6a47344fb9aac702321880e43)
1*61145dc2SMartin Matuska // SPDX-License-Identifier: CDDL-1.0
24fefe1b7SMartin Matuska /*
34fefe1b7SMartin Matuska  * CDDL HEADER START
44fefe1b7SMartin Matuska  *
54fefe1b7SMartin Matuska  * The contents of this file are subject to the terms of the
64fefe1b7SMartin Matuska  * Common Development and Distribution License (the "License").
74fefe1b7SMartin Matuska  * You may not use this file except in compliance with the License.
84fefe1b7SMartin Matuska  *
94fefe1b7SMartin Matuska  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
104fefe1b7SMartin Matuska  * or https://opensource.org/licenses/CDDL-1.0.
114fefe1b7SMartin Matuska  * See the License for the specific language governing permissions
124fefe1b7SMartin Matuska  * and limitations under the License.
134fefe1b7SMartin Matuska  *
144fefe1b7SMartin Matuska  * When distributing Covered Code, include this CDDL HEADER in each
154fefe1b7SMartin Matuska  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
164fefe1b7SMartin Matuska  * If applicable, add the following below this CDDL HEADER, with the
174fefe1b7SMartin Matuska  * fields enclosed by brackets "[]" replaced with your own identifying
184fefe1b7SMartin Matuska  * information: Portions Copyright [yyyy] [name of copyright owner]
194fefe1b7SMartin Matuska  *
204fefe1b7SMartin Matuska  * CDDL HEADER END
214fefe1b7SMartin Matuska  */
224fefe1b7SMartin Matuska 
234fefe1b7SMartin Matuska /*
244fefe1b7SMartin Matuska  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
254fefe1b7SMartin Matuska  * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
264fefe1b7SMartin Matuska  * Copyright (c) 2022 by Pawel Jakub Dawidek
274fefe1b7SMartin Matuska  * Copyright (c) 2023, Klara Inc.
284fefe1b7SMartin Matuska  */
294fefe1b7SMartin Matuska 
304fefe1b7SMartin Matuska #include <sys/zfs_context.h>
314fefe1b7SMartin Matuska #include <sys/spa.h>
324fefe1b7SMartin Matuska #include <sys/spa_impl.h>
334fefe1b7SMartin Matuska #include <sys/ddt.h>
344fefe1b7SMartin Matuska #include <sys/ddt_impl.h>
354fefe1b7SMartin Matuska 
364fefe1b7SMartin Matuska static void
ddt_stat_generate(ddt_t * ddt,const ddt_lightweight_entry_t * ddlwe,ddt_stat_t * dds)37e2df9bb4SMartin Matuska ddt_stat_generate(ddt_t *ddt, const ddt_lightweight_entry_t *ddlwe,
38e2df9bb4SMartin Matuska     ddt_stat_t *dds)
394fefe1b7SMartin Matuska {
404fefe1b7SMartin Matuska 	spa_t *spa = ddt->ddt_spa;
41e2df9bb4SMartin Matuska 	uint64_t lsize = DDK_GET_LSIZE(&ddlwe->ddlwe_key);
42e2df9bb4SMartin Matuska 	uint64_t psize = DDK_GET_PSIZE(&ddlwe->ddlwe_key);
434fefe1b7SMartin Matuska 
444fefe1b7SMartin Matuska 	memset(dds, 0, sizeof (*dds));
454fefe1b7SMartin Matuska 
46e2df9bb4SMartin Matuska 	for (int p = 0; p < DDT_NPHYS(ddt); p++) {
47e2df9bb4SMartin Matuska 		const ddt_univ_phys_t *ddp = &ddlwe->ddlwe_phys;
48e2df9bb4SMartin Matuska 		ddt_phys_variant_t v = DDT_PHYS_VARIANT(ddt, p);
494fefe1b7SMartin Matuska 
50e2df9bb4SMartin Matuska 		if (ddt_phys_birth(ddp, v) == 0)
514fefe1b7SMartin Matuska 			continue;
524fefe1b7SMartin Matuska 
53e2df9bb4SMartin Matuska 		int ndvas = ddt_phys_dva_count(ddp, v,
54e2df9bb4SMartin Matuska 		    DDK_GET_CRYPT(&ddlwe->ddlwe_key));
55e2df9bb4SMartin Matuska 		const dva_t *dvas = (ddt->ddt_flags & DDT_FLAG_FLAT) ?
56e2df9bb4SMartin Matuska 		    ddp->ddp_flat.ddp_dva : ddp->ddp_trad[p].ddp_dva;
57e2df9bb4SMartin Matuska 
58e2df9bb4SMartin Matuska 		uint64_t dsize = 0;
594fefe1b7SMartin Matuska 		for (int d = 0; d < ndvas; d++)
60e2df9bb4SMartin Matuska 			dsize += dva_get_dsize_sync(spa, &dvas[d]);
61e2df9bb4SMartin Matuska 
62e2df9bb4SMartin Matuska 		uint64_t refcnt = ddt_phys_refcnt(ddp, v);
634fefe1b7SMartin Matuska 
644fefe1b7SMartin Matuska 		dds->dds_blocks += 1;
654fefe1b7SMartin Matuska 		dds->dds_lsize += lsize;
664fefe1b7SMartin Matuska 		dds->dds_psize += psize;
674fefe1b7SMartin Matuska 		dds->dds_dsize += dsize;
684fefe1b7SMartin Matuska 
694fefe1b7SMartin Matuska 		dds->dds_ref_blocks += refcnt;
704fefe1b7SMartin Matuska 		dds->dds_ref_lsize += lsize * refcnt;
714fefe1b7SMartin Matuska 		dds->dds_ref_psize += psize * refcnt;
724fefe1b7SMartin Matuska 		dds->dds_ref_dsize += dsize * refcnt;
734fefe1b7SMartin Matuska 	}
744fefe1b7SMartin Matuska }
754fefe1b7SMartin Matuska 
76e2df9bb4SMartin Matuska static void
ddt_stat_add(ddt_stat_t * dst,const ddt_stat_t * src)77e2df9bb4SMartin Matuska ddt_stat_add(ddt_stat_t *dst, const ddt_stat_t *src)
784fefe1b7SMartin Matuska {
79e2df9bb4SMartin Matuska 	dst->dds_blocks		+= src->dds_blocks;
80e2df9bb4SMartin Matuska 	dst->dds_lsize		+= src->dds_lsize;
81e2df9bb4SMartin Matuska 	dst->dds_psize		+= src->dds_psize;
82e2df9bb4SMartin Matuska 	dst->dds_dsize		+= src->dds_dsize;
83e2df9bb4SMartin Matuska 	dst->dds_ref_blocks	+= src->dds_ref_blocks;
84e2df9bb4SMartin Matuska 	dst->dds_ref_lsize	+= src->dds_ref_lsize;
85e2df9bb4SMartin Matuska 	dst->dds_ref_psize	+= src->dds_ref_psize;
86e2df9bb4SMartin Matuska 	dst->dds_ref_dsize	+= src->dds_ref_dsize;
87e2df9bb4SMartin Matuska }
884fefe1b7SMartin Matuska 
89e2df9bb4SMartin Matuska static void
ddt_stat_sub(ddt_stat_t * dst,const ddt_stat_t * src)90e2df9bb4SMartin Matuska ddt_stat_sub(ddt_stat_t *dst, const ddt_stat_t *src)
91e2df9bb4SMartin Matuska {
92e2df9bb4SMartin Matuska 	/* This caught more during development than you might expect... */
93e2df9bb4SMartin Matuska 	ASSERT3U(dst->dds_blocks, >=, src->dds_blocks);
94e2df9bb4SMartin Matuska 	ASSERT3U(dst->dds_lsize, >=, src->dds_lsize);
95e2df9bb4SMartin Matuska 	ASSERT3U(dst->dds_psize, >=, src->dds_psize);
96e2df9bb4SMartin Matuska 	ASSERT3U(dst->dds_dsize, >=, src->dds_dsize);
97e2df9bb4SMartin Matuska 	ASSERT3U(dst->dds_ref_blocks, >=, src->dds_ref_blocks);
98e2df9bb4SMartin Matuska 	ASSERT3U(dst->dds_ref_lsize, >=, src->dds_ref_lsize);
99e2df9bb4SMartin Matuska 	ASSERT3U(dst->dds_ref_psize, >=, src->dds_ref_psize);
100e2df9bb4SMartin Matuska 	ASSERT3U(dst->dds_ref_dsize, >=, src->dds_ref_dsize);
1014fefe1b7SMartin Matuska 
102e2df9bb4SMartin Matuska 	dst->dds_blocks		-= src->dds_blocks;
103e2df9bb4SMartin Matuska 	dst->dds_lsize		-= src->dds_lsize;
104e2df9bb4SMartin Matuska 	dst->dds_psize		-= src->dds_psize;
105e2df9bb4SMartin Matuska 	dst->dds_dsize		-= src->dds_dsize;
106e2df9bb4SMartin Matuska 	dst->dds_ref_blocks	-= src->dds_ref_blocks;
107e2df9bb4SMartin Matuska 	dst->dds_ref_lsize	-= src->dds_ref_lsize;
108e2df9bb4SMartin Matuska 	dst->dds_ref_psize	-= src->dds_ref_psize;
109e2df9bb4SMartin Matuska 	dst->dds_ref_dsize	-= src->dds_ref_dsize;
1104fefe1b7SMartin Matuska }
1114fefe1b7SMartin Matuska 
1124fefe1b7SMartin Matuska void
ddt_histogram_add_entry(ddt_t * ddt,ddt_histogram_t * ddh,const ddt_lightweight_entry_t * ddlwe)113e2df9bb4SMartin Matuska ddt_histogram_add_entry(ddt_t *ddt, ddt_histogram_t *ddh,
114e2df9bb4SMartin Matuska     const ddt_lightweight_entry_t *ddlwe)
1154fefe1b7SMartin Matuska {
1164fefe1b7SMartin Matuska 	ddt_stat_t dds;
1174fefe1b7SMartin Matuska 	int bucket;
1184fefe1b7SMartin Matuska 
119e2df9bb4SMartin Matuska 	ddt_stat_generate(ddt, ddlwe, &dds);
1204fefe1b7SMartin Matuska 
1214fefe1b7SMartin Matuska 	bucket = highbit64(dds.dds_ref_blocks) - 1;
122e2df9bb4SMartin Matuska 	if (bucket < 0)
123e2df9bb4SMartin Matuska 		return;
1244fefe1b7SMartin Matuska 
125e2df9bb4SMartin Matuska 	ddt_stat_add(&ddh->ddh_stat[bucket], &dds);
126e2df9bb4SMartin Matuska }
1274fefe1b7SMartin Matuska 
128e2df9bb4SMartin Matuska void
ddt_histogram_sub_entry(ddt_t * ddt,ddt_histogram_t * ddh,const ddt_lightweight_entry_t * ddlwe)129e2df9bb4SMartin Matuska ddt_histogram_sub_entry(ddt_t *ddt, ddt_histogram_t *ddh,
130e2df9bb4SMartin Matuska     const ddt_lightweight_entry_t *ddlwe)
131e2df9bb4SMartin Matuska {
132e2df9bb4SMartin Matuska 	ddt_stat_t dds;
133e2df9bb4SMartin Matuska 	int bucket;
134e2df9bb4SMartin Matuska 
135e2df9bb4SMartin Matuska 	ddt_stat_generate(ddt, ddlwe, &dds);
136e2df9bb4SMartin Matuska 
137e2df9bb4SMartin Matuska 	bucket = highbit64(dds.dds_ref_blocks) - 1;
138e2df9bb4SMartin Matuska 	if (bucket < 0)
139e2df9bb4SMartin Matuska 		return;
140e2df9bb4SMartin Matuska 
141e2df9bb4SMartin Matuska 	ddt_stat_sub(&ddh->ddh_stat[bucket], &dds);
1424fefe1b7SMartin Matuska }
1434fefe1b7SMartin Matuska 
1444fefe1b7SMartin Matuska void
ddt_histogram_add(ddt_histogram_t * dst,const ddt_histogram_t * src)1454fefe1b7SMartin Matuska ddt_histogram_add(ddt_histogram_t *dst, const ddt_histogram_t *src)
1464fefe1b7SMartin Matuska {
1474fefe1b7SMartin Matuska 	for (int h = 0; h < 64; h++)
148e2df9bb4SMartin Matuska 		ddt_stat_add(&dst->ddh_stat[h], &src->ddh_stat[h]);
1494fefe1b7SMartin Matuska }
1504fefe1b7SMartin Matuska 
1514fefe1b7SMartin Matuska void
ddt_histogram_total(ddt_stat_t * dds,const ddt_histogram_t * ddh)152e2df9bb4SMartin Matuska ddt_histogram_total(ddt_stat_t *dds, const ddt_histogram_t *ddh)
1534fefe1b7SMartin Matuska {
1544fefe1b7SMartin Matuska 	memset(dds, 0, sizeof (*dds));
1554fefe1b7SMartin Matuska 
1564fefe1b7SMartin Matuska 	for (int h = 0; h < 64; h++)
157e2df9bb4SMartin Matuska 		ddt_stat_add(dds, &ddh->ddh_stat[h]);
1584fefe1b7SMartin Matuska }
1594fefe1b7SMartin Matuska 
1604fefe1b7SMartin Matuska boolean_t
ddt_histogram_empty(const ddt_histogram_t * ddh)1614fefe1b7SMartin Matuska ddt_histogram_empty(const ddt_histogram_t *ddh)
1624fefe1b7SMartin Matuska {
163e2df9bb4SMartin Matuska 	for (int h = 0; h < 64; h++) {
164e2df9bb4SMartin Matuska 		const ddt_stat_t *dds = &ddh->ddh_stat[h];
1654fefe1b7SMartin Matuska 
166e2df9bb4SMartin Matuska 		if (dds->dds_blocks == 0 &&
167e2df9bb4SMartin Matuska 		    dds->dds_lsize == 0 &&
168e2df9bb4SMartin Matuska 		    dds->dds_psize == 0 &&
169e2df9bb4SMartin Matuska 		    dds->dds_dsize == 0 &&
170e2df9bb4SMartin Matuska 		    dds->dds_ref_blocks == 0 &&
171e2df9bb4SMartin Matuska 		    dds->dds_ref_lsize == 0 &&
172e2df9bb4SMartin Matuska 		    dds->dds_ref_psize == 0 &&
173e2df9bb4SMartin Matuska 		    dds->dds_ref_dsize == 0)
174e2df9bb4SMartin Matuska 			continue;
175e2df9bb4SMartin Matuska 
1764fefe1b7SMartin Matuska 		return (B_FALSE);
177e2df9bb4SMartin Matuska 	}
1784fefe1b7SMartin Matuska 
1794fefe1b7SMartin Matuska 	return (B_TRUE);
1804fefe1b7SMartin Matuska }
1814fefe1b7SMartin Matuska 
1824fefe1b7SMartin Matuska void
ddt_get_dedup_object_stats(spa_t * spa,ddt_object_t * ddo_total)1834fefe1b7SMartin Matuska ddt_get_dedup_object_stats(spa_t *spa, ddt_object_t *ddo_total)
1844fefe1b7SMartin Matuska {
185ce4dcb97SMartin Matuska 	memset(ddo_total, 0, sizeof (*ddo_total));
186ce4dcb97SMartin Matuska 
1874fefe1b7SMartin Matuska 	for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) {
1884fefe1b7SMartin Matuska 		ddt_t *ddt = spa->spa_ddt[c];
1894fefe1b7SMartin Matuska 		if (!ddt)
1904fefe1b7SMartin Matuska 			continue;
1914fefe1b7SMartin Matuska 
1924fefe1b7SMartin Matuska 		for (ddt_type_t type = 0; type < DDT_TYPES; type++) {
1934fefe1b7SMartin Matuska 			for (ddt_class_t class = 0; class < DDT_CLASSES;
1944fefe1b7SMartin Matuska 			    class++) {
195ce4dcb97SMartin Matuska 				dmu_object_info_t doi;
196ce4dcb97SMartin Matuska 				uint64_t cnt;
197ce4dcb97SMartin Matuska 				int err;
198ce4dcb97SMartin Matuska 
199ce4dcb97SMartin Matuska 				/*
200ce4dcb97SMartin Matuska 				 * These stats were originally calculated
201ce4dcb97SMartin Matuska 				 * during ddt_object_load().
202ce4dcb97SMartin Matuska 				 */
203ce4dcb97SMartin Matuska 
204ce4dcb97SMartin Matuska 				err = ddt_object_info(ddt, type, class, &doi);
205ce4dcb97SMartin Matuska 				if (err != 0)
206ce4dcb97SMartin Matuska 					continue;
207ce4dcb97SMartin Matuska 
208ce4dcb97SMartin Matuska 				err = ddt_object_count(ddt, type, class, &cnt);
209ce4dcb97SMartin Matuska 				if (err != 0)
210ce4dcb97SMartin Matuska 					continue;
211ce4dcb97SMartin Matuska 
2124fefe1b7SMartin Matuska 				ddt_object_t *ddo =
2134fefe1b7SMartin Matuska 				    &ddt->ddt_object_stats[type][class];
214ce4dcb97SMartin Matuska 
215ce4dcb97SMartin Matuska 				ddo->ddo_count = cnt;
216ce4dcb97SMartin Matuska 				ddo->ddo_dspace =
217ce4dcb97SMartin Matuska 				    doi.doi_physical_blocks_512 << 9;
218ce4dcb97SMartin Matuska 				ddo->ddo_mspace = doi.doi_fill_count *
219ce4dcb97SMartin Matuska 				    doi.doi_data_block_size;
220ce4dcb97SMartin Matuska 
2214fefe1b7SMartin Matuska 				ddo_total->ddo_count += ddo->ddo_count;
2224fefe1b7SMartin Matuska 				ddo_total->ddo_dspace += ddo->ddo_dspace;
2234fefe1b7SMartin Matuska 				ddo_total->ddo_mspace += ddo->ddo_mspace;
2244fefe1b7SMartin Matuska 			}
2254fefe1b7SMartin Matuska 		}
226e2df9bb4SMartin Matuska 
227e2df9bb4SMartin Matuska 		ddt_object_t *ddo = &ddt->ddt_log_stats;
228e2df9bb4SMartin Matuska 		ddo_total->ddo_count += ddo->ddo_count;
229e2df9bb4SMartin Matuska 		ddo_total->ddo_dspace += ddo->ddo_dspace;
230e2df9bb4SMartin Matuska 		ddo_total->ddo_mspace += ddo->ddo_mspace;
2314fefe1b7SMartin Matuska 	}
2324fefe1b7SMartin Matuska 
233ce4dcb97SMartin Matuska 	/*
234ce4dcb97SMartin Matuska 	 * This returns raw counts (not averages). One of the consumers,
235ce4dcb97SMartin Matuska 	 * print_dedup_stats(), historically has expected raw counts.
236ce4dcb97SMartin Matuska 	 */
237ce4dcb97SMartin Matuska 
238ce4dcb97SMartin Matuska 	spa->spa_dedup_dsize = ddo_total->ddo_dspace;
2394fefe1b7SMartin Matuska }
240ce4dcb97SMartin Matuska 
241ce4dcb97SMartin Matuska uint64_t
ddt_get_ddt_dsize(spa_t * spa)242ce4dcb97SMartin Matuska ddt_get_ddt_dsize(spa_t *spa)
243ce4dcb97SMartin Matuska {
244ce4dcb97SMartin Matuska 	ddt_object_t ddo_total;
245ce4dcb97SMartin Matuska 
246ce4dcb97SMartin Matuska 	/* recalculate after each txg sync */
247ce4dcb97SMartin Matuska 	if (spa->spa_dedup_dsize == ~0ULL)
248ce4dcb97SMartin Matuska 		ddt_get_dedup_object_stats(spa, &ddo_total);
249ce4dcb97SMartin Matuska 
250ce4dcb97SMartin Matuska 	return (spa->spa_dedup_dsize);
2514fefe1b7SMartin Matuska }
2524fefe1b7SMartin Matuska 
2534fefe1b7SMartin Matuska void
ddt_get_dedup_histogram(spa_t * spa,ddt_histogram_t * ddh)2544fefe1b7SMartin Matuska ddt_get_dedup_histogram(spa_t *spa, ddt_histogram_t *ddh)
2554fefe1b7SMartin Matuska {
2564fefe1b7SMartin Matuska 	for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) {
2574fefe1b7SMartin Matuska 		ddt_t *ddt = spa->spa_ddt[c];
2584fefe1b7SMartin Matuska 		if (!ddt)
2594fefe1b7SMartin Matuska 			continue;
2604fefe1b7SMartin Matuska 
2614fefe1b7SMartin Matuska 		for (ddt_type_t type = 0; type < DDT_TYPES; type++) {
2624fefe1b7SMartin Matuska 			for (ddt_class_t class = 0; class < DDT_CLASSES;
2634fefe1b7SMartin Matuska 			    class++) {
2644fefe1b7SMartin Matuska 				ddt_histogram_add(ddh,
2654fefe1b7SMartin Matuska 				    &ddt->ddt_histogram_cache[type][class]);
2664fefe1b7SMartin Matuska 			}
2674fefe1b7SMartin Matuska 		}
268e2df9bb4SMartin Matuska 
269e2df9bb4SMartin Matuska 		ddt_histogram_add(ddh, &ddt->ddt_log_histogram);
2704fefe1b7SMartin Matuska 	}
2714fefe1b7SMartin Matuska }
2724fefe1b7SMartin Matuska 
2734fefe1b7SMartin Matuska void
ddt_get_dedup_stats(spa_t * spa,ddt_stat_t * dds_total)2744fefe1b7SMartin Matuska ddt_get_dedup_stats(spa_t *spa, ddt_stat_t *dds_total)
2754fefe1b7SMartin Matuska {
2764fefe1b7SMartin Matuska 	ddt_histogram_t *ddh_total;
2774fefe1b7SMartin Matuska 
2784fefe1b7SMartin Matuska 	ddh_total = kmem_zalloc(sizeof (ddt_histogram_t), KM_SLEEP);
2794fefe1b7SMartin Matuska 	ddt_get_dedup_histogram(spa, ddh_total);
280e2df9bb4SMartin Matuska 	ddt_histogram_total(dds_total, ddh_total);
2814fefe1b7SMartin Matuska 	kmem_free(ddh_total, sizeof (ddt_histogram_t));
2824fefe1b7SMartin Matuska }
2834fefe1b7SMartin Matuska 
2844fefe1b7SMartin Matuska uint64_t
ddt_get_dedup_dspace(spa_t * spa)2854fefe1b7SMartin Matuska ddt_get_dedup_dspace(spa_t *spa)
2864fefe1b7SMartin Matuska {
2874fefe1b7SMartin Matuska 	ddt_stat_t dds_total;
2884fefe1b7SMartin Matuska 
2894fefe1b7SMartin Matuska 	if (spa->spa_dedup_dspace != ~0ULL)
2904fefe1b7SMartin Matuska 		return (spa->spa_dedup_dspace);
2914fefe1b7SMartin Matuska 
2924fefe1b7SMartin Matuska 	memset(&dds_total, 0, sizeof (ddt_stat_t));
2934fefe1b7SMartin Matuska 
2944fefe1b7SMartin Matuska 	/* Calculate and cache the stats */
2954fefe1b7SMartin Matuska 	ddt_get_dedup_stats(spa, &dds_total);
2964fefe1b7SMartin Matuska 	spa->spa_dedup_dspace = dds_total.dds_ref_dsize - dds_total.dds_dsize;
2974fefe1b7SMartin Matuska 	return (spa->spa_dedup_dspace);
2984fefe1b7SMartin Matuska }
2994fefe1b7SMartin Matuska 
3004fefe1b7SMartin Matuska uint64_t
ddt_get_pool_dedup_ratio(spa_t * spa)3014fefe1b7SMartin Matuska ddt_get_pool_dedup_ratio(spa_t *spa)
3024fefe1b7SMartin Matuska {
3034fefe1b7SMartin Matuska 	ddt_stat_t dds_total = { 0 };
3044fefe1b7SMartin Matuska 
3054fefe1b7SMartin Matuska 	ddt_get_dedup_stats(spa, &dds_total);
3064fefe1b7SMartin Matuska 	if (dds_total.dds_dsize == 0)
3074fefe1b7SMartin Matuska 		return (100);
3084fefe1b7SMartin Matuska 
3094fefe1b7SMartin Matuska 	return (dds_total.dds_ref_dsize * 100 / dds_total.dds_dsize);
3104fefe1b7SMartin Matuska }
311ce4dcb97SMartin Matuska 
312ce4dcb97SMartin Matuska int
ddt_get_pool_dedup_cached(spa_t * spa,uint64_t * psize)313ce4dcb97SMartin Matuska ddt_get_pool_dedup_cached(spa_t *spa, uint64_t *psize)
314ce4dcb97SMartin Matuska {
315ce4dcb97SMartin Matuska 	uint64_t l1sz, l1tot, l2sz, l2tot;
316ce4dcb97SMartin Matuska 	int err = 0;
317ce4dcb97SMartin Matuska 
318ce4dcb97SMartin Matuska 	l1tot = l2tot = 0;
319ce4dcb97SMartin Matuska 	*psize = 0;
320ce4dcb97SMartin Matuska 	for (enum zio_checksum c = 0; c < ZIO_CHECKSUM_FUNCTIONS; c++) {
321ce4dcb97SMartin Matuska 		ddt_t *ddt = spa->spa_ddt[c];
322ce4dcb97SMartin Matuska 		if (ddt == NULL)
323ce4dcb97SMartin Matuska 			continue;
324ce4dcb97SMartin Matuska 		for (ddt_type_t type = 0; type < DDT_TYPES; type++) {
325ce4dcb97SMartin Matuska 			for (ddt_class_t class = 0; class < DDT_CLASSES;
326ce4dcb97SMartin Matuska 			    class++) {
327ce4dcb97SMartin Matuska 				err = dmu_object_cached_size(ddt->ddt_os,
328ce4dcb97SMartin Matuska 				    ddt->ddt_object[type][class], &l1sz, &l2sz);
329ce4dcb97SMartin Matuska 				if (err != 0)
330ce4dcb97SMartin Matuska 					return (err);
331ce4dcb97SMartin Matuska 				l1tot += l1sz;
332ce4dcb97SMartin Matuska 				l2tot += l2sz;
333ce4dcb97SMartin Matuska 			}
334ce4dcb97SMartin Matuska 		}
335ce4dcb97SMartin Matuska 	}
336ce4dcb97SMartin Matuska 
337ce4dcb97SMartin Matuska 	*psize = l1tot + l2tot;
338ce4dcb97SMartin Matuska 	return (err);
339ce4dcb97SMartin Matuska }
340