]>
git.proxmox.com Git - mirror_zfs.git/blob - module/zfs/ddt_stats.c
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
, ddt_entry_t
*dde
, ddt_stat_t
*dds
)
38 spa_t
*spa
= ddt
->ddt_spa
;
39 ddt_phys_t
*ddp
= dde
->dde_phys
;
40 ddt_key_t
*ddk
= &dde
->dde_key
;
41 uint64_t lsize
= DDK_GET_LSIZE(ddk
);
42 uint64_t psize
= DDK_GET_PSIZE(ddk
);
44 memset(dds
, 0, sizeof (*dds
));
46 for (int p
= 0; p
< DDT_PHYS_TYPES
; p
++, ddp
++) {
48 uint64_t refcnt
= ddp
->ddp_refcnt
;
50 if (ddp
->ddp_phys_birth
== 0)
53 int ndvas
= DDK_GET_CRYPT(&dde
->dde_key
) ?
54 SPA_DVAS_PER_BP
- 1 : SPA_DVAS_PER_BP
;
55 for (int d
= 0; d
< ndvas
; d
++)
56 dsize
+= dva_get_dsize_sync(spa
, &ddp
->ddp_dva
[d
]);
59 dds
->dds_lsize
+= lsize
;
60 dds
->dds_psize
+= psize
;
61 dds
->dds_dsize
+= dsize
;
63 dds
->dds_ref_blocks
+= refcnt
;
64 dds
->dds_ref_lsize
+= lsize
* refcnt
;
65 dds
->dds_ref_psize
+= psize
* refcnt
;
66 dds
->dds_ref_dsize
+= dsize
* refcnt
;
71 ddt_stat_add(ddt_stat_t
*dst
, const ddt_stat_t
*src
, uint64_t neg
)
73 const uint64_t *s
= (const uint64_t *)src
;
74 uint64_t *d
= (uint64_t *)dst
;
75 uint64_t *d_end
= (uint64_t *)(dst
+ 1);
77 ASSERT(neg
== 0 || neg
== -1ULL); /* add or subtract */
79 for (int i
= 0; i
< d_end
- d
; i
++)
80 d
[i
] += (s
[i
] ^ neg
) - neg
;
84 ddt_stat_update(ddt_t
*ddt
, ddt_entry_t
*dde
, uint64_t neg
)
90 ddt_stat_generate(ddt
, dde
, &dds
);
92 bucket
= highbit64(dds
.dds_ref_blocks
) - 1;
93 ASSERT3U(bucket
, >=, 0);
95 ddh
= &ddt
->ddt_histogram
[dde
->dde_type
][dde
->dde_class
];
97 ddt_stat_add(&ddh
->ddh_stat
[bucket
], &dds
, neg
);
101 ddt_histogram_add(ddt_histogram_t
*dst
, const ddt_histogram_t
*src
)
103 for (int h
= 0; h
< 64; h
++)
104 ddt_stat_add(&dst
->ddh_stat
[h
], &src
->ddh_stat
[h
], 0);
108 ddt_histogram_stat(ddt_stat_t
*dds
, const ddt_histogram_t
*ddh
)
110 memset(dds
, 0, sizeof (*dds
));
112 for (int h
= 0; h
< 64; h
++)
113 ddt_stat_add(dds
, &ddh
->ddh_stat
[h
], 0);
117 ddt_histogram_empty(const ddt_histogram_t
*ddh
)
119 const uint64_t *s
= (const uint64_t *)ddh
;
120 const uint64_t *s_end
= (const uint64_t *)(ddh
+ 1);
130 ddt_get_dedup_object_stats(spa_t
*spa
, ddt_object_t
*ddo_total
)
132 /* Sum the statistics we cached in ddt_object_sync(). */
133 for (enum zio_checksum c
= 0; c
< ZIO_CHECKSUM_FUNCTIONS
; c
++) {
134 ddt_t
*ddt
= spa
->spa_ddt
[c
];
138 for (ddt_type_t type
= 0; type
< DDT_TYPES
; type
++) {
139 for (ddt_class_t
class = 0; class < DDT_CLASSES
;
142 &ddt
->ddt_object_stats
[type
][class];
143 ddo_total
->ddo_count
+= ddo
->ddo_count
;
144 ddo_total
->ddo_dspace
+= ddo
->ddo_dspace
;
145 ddo_total
->ddo_mspace
+= ddo
->ddo_mspace
;
150 /* ... and compute the averages. */
151 if (ddo_total
->ddo_count
!= 0) {
152 ddo_total
->ddo_dspace
/= ddo_total
->ddo_count
;
153 ddo_total
->ddo_mspace
/= ddo_total
->ddo_count
;
158 ddt_get_dedup_histogram(spa_t
*spa
, ddt_histogram_t
*ddh
)
160 for (enum zio_checksum c
= 0; c
< ZIO_CHECKSUM_FUNCTIONS
; c
++) {
161 ddt_t
*ddt
= spa
->spa_ddt
[c
];
165 for (ddt_type_t type
= 0; type
< DDT_TYPES
; type
++) {
166 for (ddt_class_t
class = 0; class < DDT_CLASSES
;
168 ddt_histogram_add(ddh
,
169 &ddt
->ddt_histogram_cache
[type
][class]);
176 ddt_get_dedup_stats(spa_t
*spa
, ddt_stat_t
*dds_total
)
178 ddt_histogram_t
*ddh_total
;
180 ddh_total
= kmem_zalloc(sizeof (ddt_histogram_t
), KM_SLEEP
);
181 ddt_get_dedup_histogram(spa
, ddh_total
);
182 ddt_histogram_stat(dds_total
, ddh_total
);
183 kmem_free(ddh_total
, sizeof (ddt_histogram_t
));
187 ddt_get_dedup_dspace(spa_t
*spa
)
189 ddt_stat_t dds_total
;
191 if (spa
->spa_dedup_dspace
!= ~0ULL)
192 return (spa
->spa_dedup_dspace
);
194 memset(&dds_total
, 0, sizeof (ddt_stat_t
));
196 /* Calculate and cache the stats */
197 ddt_get_dedup_stats(spa
, &dds_total
);
198 spa
->spa_dedup_dspace
= dds_total
.dds_ref_dsize
- dds_total
.dds_dsize
;
199 return (spa
->spa_dedup_dspace
);
203 ddt_get_pool_dedup_ratio(spa_t
*spa
)
205 ddt_stat_t dds_total
= { 0 };
207 ddt_get_dedup_stats(spa
, &dds_total
);
208 if (dds_total
.dds_dsize
== 0)
211 return (dds_total
.dds_ref_dsize
* 100 / dds_total
.dds_dsize
);