]>
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>
35 ddt_stat_generate(ddt_t
*ddt
, ddt_entry_t
*dde
, ddt_stat_t
*dds
)
37 spa_t
*spa
= ddt
->ddt_spa
;
38 ddt_phys_t
*ddp
= dde
->dde_phys
;
39 ddt_key_t
*ddk
= &dde
->dde_key
;
40 uint64_t lsize
= DDK_GET_LSIZE(ddk
);
41 uint64_t psize
= DDK_GET_PSIZE(ddk
);
43 memset(dds
, 0, sizeof (*dds
));
45 for (int p
= 0; p
< DDT_PHYS_TYPES
; p
++, ddp
++) {
47 uint64_t refcnt
= ddp
->ddp_refcnt
;
49 if (ddp
->ddp_phys_birth
== 0)
52 int ndvas
= DDK_GET_CRYPT(&dde
->dde_key
) ?
53 SPA_DVAS_PER_BP
- 1 : SPA_DVAS_PER_BP
;
54 for (int d
= 0; d
< ndvas
; d
++)
55 dsize
+= dva_get_dsize_sync(spa
, &ddp
->ddp_dva
[d
]);
58 dds
->dds_lsize
+= lsize
;
59 dds
->dds_psize
+= psize
;
60 dds
->dds_dsize
+= dsize
;
62 dds
->dds_ref_blocks
+= refcnt
;
63 dds
->dds_ref_lsize
+= lsize
* refcnt
;
64 dds
->dds_ref_psize
+= psize
* refcnt
;
65 dds
->dds_ref_dsize
+= dsize
* refcnt
;
70 ddt_stat_add(ddt_stat_t
*dst
, const ddt_stat_t
*src
, uint64_t neg
)
72 const uint64_t *s
= (const uint64_t *)src
;
73 uint64_t *d
= (uint64_t *)dst
;
74 uint64_t *d_end
= (uint64_t *)(dst
+ 1);
76 ASSERT(neg
== 0 || neg
== -1ULL); /* add or subtract */
78 for (int i
= 0; i
< d_end
- d
; i
++)
79 d
[i
] += (s
[i
] ^ neg
) - neg
;
83 ddt_stat_update(ddt_t
*ddt
, ddt_entry_t
*dde
, uint64_t neg
)
89 ddt_stat_generate(ddt
, dde
, &dds
);
91 bucket
= highbit64(dds
.dds_ref_blocks
) - 1;
92 ASSERT3U(bucket
, >=, 0);
94 ddh
= &ddt
->ddt_histogram
[dde
->dde_type
][dde
->dde_class
];
96 ddt_stat_add(&ddh
->ddh_stat
[bucket
], &dds
, neg
);
100 ddt_histogram_add(ddt_histogram_t
*dst
, const ddt_histogram_t
*src
)
102 for (int h
= 0; h
< 64; h
++)
103 ddt_stat_add(&dst
->ddh_stat
[h
], &src
->ddh_stat
[h
], 0);
107 ddt_histogram_stat(ddt_stat_t
*dds
, const ddt_histogram_t
*ddh
)
109 memset(dds
, 0, sizeof (*dds
));
111 for (int h
= 0; h
< 64; h
++)
112 ddt_stat_add(dds
, &ddh
->ddh_stat
[h
], 0);
116 ddt_histogram_empty(const ddt_histogram_t
*ddh
)
118 const uint64_t *s
= (const uint64_t *)ddh
;
119 const uint64_t *s_end
= (const uint64_t *)(ddh
+ 1);
129 ddt_get_dedup_object_stats(spa_t
*spa
, ddt_object_t
*ddo_total
)
131 /* Sum the statistics we cached in ddt_object_sync(). */
132 for (enum zio_checksum c
= 0; c
< ZIO_CHECKSUM_FUNCTIONS
; c
++) {
133 ddt_t
*ddt
= spa
->spa_ddt
[c
];
134 for (enum ddt_type type
= 0; type
< DDT_TYPES
; type
++) {
135 for (enum ddt_class
class = 0; class < DDT_CLASSES
;
138 &ddt
->ddt_object_stats
[type
][class];
139 ddo_total
->ddo_count
+= ddo
->ddo_count
;
140 ddo_total
->ddo_dspace
+= ddo
->ddo_dspace
;
141 ddo_total
->ddo_mspace
+= ddo
->ddo_mspace
;
146 /* ... and compute the averages. */
147 if (ddo_total
->ddo_count
!= 0) {
148 ddo_total
->ddo_dspace
/= ddo_total
->ddo_count
;
149 ddo_total
->ddo_mspace
/= ddo_total
->ddo_count
;
154 ddt_get_dedup_histogram(spa_t
*spa
, ddt_histogram_t
*ddh
)
156 for (enum zio_checksum c
= 0; c
< ZIO_CHECKSUM_FUNCTIONS
; c
++) {
157 ddt_t
*ddt
= spa
->spa_ddt
[c
];
158 for (enum ddt_type type
= 0; type
< DDT_TYPES
&& ddt
; type
++) {
159 for (enum ddt_class
class = 0; class < DDT_CLASSES
;
161 ddt_histogram_add(ddh
,
162 &ddt
->ddt_histogram_cache
[type
][class]);
169 ddt_get_dedup_stats(spa_t
*spa
, ddt_stat_t
*dds_total
)
171 ddt_histogram_t
*ddh_total
;
173 ddh_total
= kmem_zalloc(sizeof (ddt_histogram_t
), KM_SLEEP
);
174 ddt_get_dedup_histogram(spa
, ddh_total
);
175 ddt_histogram_stat(dds_total
, ddh_total
);
176 kmem_free(ddh_total
, sizeof (ddt_histogram_t
));
180 ddt_get_dedup_dspace(spa_t
*spa
)
182 ddt_stat_t dds_total
;
184 if (spa
->spa_dedup_dspace
!= ~0ULL)
185 return (spa
->spa_dedup_dspace
);
187 memset(&dds_total
, 0, sizeof (ddt_stat_t
));
189 /* Calculate and cache the stats */
190 ddt_get_dedup_stats(spa
, &dds_total
);
191 spa
->spa_dedup_dspace
= dds_total
.dds_ref_dsize
- dds_total
.dds_dsize
;
192 return (spa
->spa_dedup_dspace
);
196 ddt_get_pool_dedup_ratio(spa_t
*spa
)
198 ddt_stat_t dds_total
= { 0 };
200 ddt_get_dedup_stats(spa
, &dds_total
);
201 if (dds_total
.dds_dsize
== 0)
204 return (dds_total
.dds_ref_dsize
* 100 / dds_total
.dds_dsize
);