4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or https://opensource.org/licenses/CDDL-1.0.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
25 * Copyright (c) 2022 by Pawel Jakub Dawidek
26 * Copyright (c) 2023, Klara Inc.
29 #include <sys/zfs_context.h>
31 #include <sys/spa_impl.h>
33 #include <sys/ddt_impl.h>
36 ddt_stat_generate(ddt_t
*ddt
, const ddt_lightweight_entry_t
*ddlwe
,
39 spa_t
*spa
= ddt
->ddt_spa
;
40 uint64_t lsize
= DDK_GET_LSIZE(&ddlwe
->ddlwe_key
);
41 uint64_t psize
= DDK_GET_PSIZE(&ddlwe
->ddlwe_key
);
43 memset(dds
, 0, sizeof (*dds
));
45 for (int p
= 0; p
< DDT_NPHYS(ddt
); p
++) {
46 const ddt_univ_phys_t
*ddp
= &ddlwe
->ddlwe_phys
;
47 ddt_phys_variant_t v
= DDT_PHYS_VARIANT(ddt
, p
);
49 if (ddt_phys_birth(ddp
, v
) == 0)
52 int ndvas
= ddt_phys_dva_count(ddp
, v
,
53 DDK_GET_CRYPT(&ddlwe
->ddlwe_key
));
54 const dva_t
*dvas
= (ddt
->ddt_flags
& DDT_FLAG_FLAT
) ?
55 ddp
->ddp_flat
.ddp_dva
: ddp
->ddp_trad
[p
].ddp_dva
;
58 for (int d
= 0; d
< ndvas
; d
++)
59 dsize
+= dva_get_dsize_sync(spa
, &dvas
[d
]);
61 uint64_t refcnt
= ddt_phys_refcnt(ddp
, v
);
64 dds
->dds_lsize
+= lsize
;
65 dds
->dds_psize
+= psize
;
66 dds
->dds_dsize
+= dsize
;
68 dds
->dds_ref_blocks
+= refcnt
;
69 dds
->dds_ref_lsize
+= lsize
* refcnt
;
70 dds
->dds_ref_psize
+= psize
* refcnt
;
71 dds
->dds_ref_dsize
+= dsize
* refcnt
;
76 ddt_stat_add(ddt_stat_t
*dst
, const ddt_stat_t
*src
)
78 dst
->dds_blocks
+= src
->dds_blocks
;
79 dst
->dds_lsize
+= src
->dds_lsize
;
80 dst
->dds_psize
+= src
->dds_psize
;
81 dst
->dds_dsize
+= src
->dds_dsize
;
82 dst
->dds_ref_blocks
+= src
->dds_ref_blocks
;
83 dst
->dds_ref_lsize
+= src
->dds_ref_lsize
;
84 dst
->dds_ref_psize
+= src
->dds_ref_psize
;
85 dst
->dds_ref_dsize
+= src
->dds_ref_dsize
;
89 ddt_stat_sub(ddt_stat_t
*dst
, const ddt_stat_t
*src
)
91 /* This caught more during development than you might expect... */
92 ASSERT3U(dst
->dds_blocks
, >=, src
->dds_blocks
);
93 ASSERT3U(dst
->dds_lsize
, >=, src
->dds_lsize
);
94 ASSERT3U(dst
->dds_psize
, >=, src
->dds_psize
);
95 ASSERT3U(dst
->dds_dsize
, >=, src
->dds_dsize
);
96 ASSERT3U(dst
->dds_ref_blocks
, >=, src
->dds_ref_blocks
);
97 ASSERT3U(dst
->dds_ref_lsize
, >=, src
->dds_ref_lsize
);
98 ASSERT3U(dst
->dds_ref_psize
, >=, src
->dds_ref_psize
);
99 ASSERT3U(dst
->dds_ref_dsize
, >=, src
->dds_ref_dsize
);
101 dst
->dds_blocks
-= src
->dds_blocks
;
102 dst
->dds_lsize
-= src
->dds_lsize
;
103 dst
->dds_psize
-= src
->dds_psize
;
104 dst
->dds_dsize
-= src
->dds_dsize
;
105 dst
->dds_ref_blocks
-= src
->dds_ref_blocks
;
106 dst
->dds_ref_lsize
-= src
->dds_ref_lsize
;
107 dst
->dds_ref_psize
-= src
->dds_ref_psize
;
108 dst
->dds_ref_dsize
-= src
->dds_ref_dsize
;
112 ddt_histogram_add_entry(ddt_t
*ddt
, ddt_histogram_t
*ddh
,
113 const ddt_lightweight_entry_t
*ddlwe
)
118 ddt_stat_generate(ddt
, ddlwe
, &dds
);
120 bucket
= highbit64(dds
.dds_ref_blocks
) - 1;
124 ddt_stat_add(&ddh
->ddh_stat
[bucket
], &dds
);
128 ddt_histogram_sub_entry(ddt_t
*ddt
, ddt_histogram_t
*ddh
,
129 const ddt_lightweight_entry_t
*ddlwe
)
134 ddt_stat_generate(ddt
, ddlwe
, &dds
);
136 bucket
= highbit64(dds
.dds_ref_blocks
) - 1;
140 ddt_stat_sub(&ddh
->ddh_stat
[bucket
], &dds
);
144 ddt_histogram_add(ddt_histogram_t
*dst
, const ddt_histogram_t
*src
)
146 for (int h
= 0; h
< 64; h
++)
147 ddt_stat_add(&dst
->ddh_stat
[h
], &src
->ddh_stat
[h
]);
151 ddt_histogram_total(ddt_stat_t
*dds
, const ddt_histogram_t
*ddh
)
153 memset(dds
, 0, sizeof (*dds
));
155 for (int h
= 0; h
< 64; h
++)
156 ddt_stat_add(dds
, &ddh
->ddh_stat
[h
]);
160 ddt_histogram_empty(const ddt_histogram_t
*ddh
)
162 for (int h
= 0; h
< 64; h
++) {
163 const ddt_stat_t
*dds
= &ddh
->ddh_stat
[h
];
165 if (dds
->dds_blocks
== 0 &&
166 dds
->dds_lsize
== 0 &&
167 dds
->dds_psize
== 0 &&
168 dds
->dds_dsize
== 0 &&
169 dds
->dds_ref_blocks
== 0 &&
170 dds
->dds_ref_lsize
== 0 &&
171 dds
->dds_ref_psize
== 0 &&
172 dds
->dds_ref_dsize
== 0)
182 ddt_get_dedup_object_stats(spa_t
*spa
, ddt_object_t
*ddo_total
)
184 memset(ddo_total
, 0, sizeof (*ddo_total
));
186 for (enum zio_checksum c
= 0; c
< ZIO_CHECKSUM_FUNCTIONS
; c
++) {
187 ddt_t
*ddt
= spa
->spa_ddt
[c
];
191 for (ddt_type_t type
= 0; type
< DDT_TYPES
; type
++) {
192 for (ddt_class_t
class = 0; class < DDT_CLASSES
;
194 dmu_object_info_t doi
;
199 * These stats were originally calculated
200 * during ddt_object_load().
203 err
= ddt_object_info(ddt
, type
, class, &doi
);
207 err
= ddt_object_count(ddt
, type
, class, &cnt
);
212 &ddt
->ddt_object_stats
[type
][class];
214 ddo
->ddo_count
= cnt
;
216 doi
.doi_physical_blocks_512
<< 9;
217 ddo
->ddo_mspace
= doi
.doi_fill_count
*
218 doi
.doi_data_block_size
;
220 ddo_total
->ddo_count
+= ddo
->ddo_count
;
221 ddo_total
->ddo_dspace
+= ddo
->ddo_dspace
;
222 ddo_total
->ddo_mspace
+= ddo
->ddo_mspace
;
226 ddt_object_t
*ddo
= &ddt
->ddt_log_stats
;
227 ddo_total
->ddo_count
+= ddo
->ddo_count
;
228 ddo_total
->ddo_dspace
+= ddo
->ddo_dspace
;
229 ddo_total
->ddo_mspace
+= ddo
->ddo_mspace
;
233 * This returns raw counts (not averages). One of the consumers,
234 * print_dedup_stats(), historically has expected raw counts.
237 spa
->spa_dedup_dsize
= ddo_total
->ddo_dspace
;
241 ddt_get_ddt_dsize(spa_t
*spa
)
243 ddt_object_t ddo_total
;
245 /* recalculate after each txg sync */
246 if (spa
->spa_dedup_dsize
== ~0ULL)
247 ddt_get_dedup_object_stats(spa
, &ddo_total
);
249 return (spa
->spa_dedup_dsize
);
253 ddt_get_dedup_histogram(spa_t
*spa
, ddt_histogram_t
*ddh
)
255 for (enum zio_checksum c
= 0; c
< ZIO_CHECKSUM_FUNCTIONS
; c
++) {
256 ddt_t
*ddt
= spa
->spa_ddt
[c
];
260 for (ddt_type_t type
= 0; type
< DDT_TYPES
; type
++) {
261 for (ddt_class_t
class = 0; class < DDT_CLASSES
;
263 ddt_histogram_add(ddh
,
264 &ddt
->ddt_histogram_cache
[type
][class]);
268 ddt_histogram_add(ddh
, &ddt
->ddt_log_histogram
);
273 ddt_get_dedup_stats(spa_t
*spa
, ddt_stat_t
*dds_total
)
275 ddt_histogram_t
*ddh_total
;
277 ddh_total
= kmem_zalloc(sizeof (ddt_histogram_t
), KM_SLEEP
);
278 ddt_get_dedup_histogram(spa
, ddh_total
);
279 ddt_histogram_total(dds_total
, ddh_total
);
280 kmem_free(ddh_total
, sizeof (ddt_histogram_t
));
284 ddt_get_dedup_dspace(spa_t
*spa
)
286 ddt_stat_t dds_total
;
288 if (spa
->spa_dedup_dspace
!= ~0ULL)
289 return (spa
->spa_dedup_dspace
);
291 memset(&dds_total
, 0, sizeof (ddt_stat_t
));
293 /* Calculate and cache the stats */
294 ddt_get_dedup_stats(spa
, &dds_total
);
295 spa
->spa_dedup_dspace
= dds_total
.dds_ref_dsize
- dds_total
.dds_dsize
;
296 return (spa
->spa_dedup_dspace
);
300 ddt_get_pool_dedup_ratio(spa_t
*spa
)
302 ddt_stat_t dds_total
= { 0 };
304 ddt_get_dedup_stats(spa
, &dds_total
);
305 if (dds_total
.dds_dsize
== 0)
308 return (dds_total
.dds_ref_dsize
* 100 / dds_total
.dds_dsize
);
312 ddt_get_pool_dedup_cached(spa_t
*spa
, uint64_t *psize
)
314 uint64_t l1sz
, l1tot
, l2sz
, l2tot
;
319 for (enum zio_checksum c
= 0; c
< ZIO_CHECKSUM_FUNCTIONS
; c
++) {
320 ddt_t
*ddt
= spa
->spa_ddt
[c
];
323 for (ddt_type_t type
= 0; type
< DDT_TYPES
; type
++) {
324 for (ddt_class_t
class = 0; class < DDT_CLASSES
;
326 err
= dmu_object_cached_size(ddt
->ddt_os
,
327 ddt
->ddt_object
[type
][class], &l1sz
, &l2sz
);
336 *psize
= l1tot
+ l2tot
;