Skip to content

Commit 1567a9b

Browse files
author
Ryan Moeller
committed
Add zpool properties for allocation class space
The existing zpool properties accounting pool space (size, allocated, fragmentation, expandsize, free, capacity) are based on the normal metaslab class or are cumulative properties of all classes combined. Add properties reporting the space accounting metrics for each metaslab class individually. Update ZTS to recognize the new properties and validate reported values. Sponsored-by: Klara, Inc. Signed-off-by: Ryan Moeller <ryan.moeller@klarasystems.com>
1 parent 4e13844 commit 1567a9b

File tree

13 files changed

+797
-32
lines changed

13 files changed

+797
-32
lines changed

cmd/zpool/zpool_main.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6954,7 +6954,19 @@ collect_vdev_prop(zpool_prop_t prop, uint64_t value, const char *str,
69546954

69556955
switch (prop) {
69566956
case ZPOOL_PROP_SIZE:
6957+
case ZPOOL_PROP_NORMAL_SIZE:
6958+
case ZPOOL_PROP_SPECIAL_SIZE:
6959+
case ZPOOL_PROP_DEDUP_SIZE:
6960+
case ZPOOL_PROP_LOG_SIZE:
6961+
case ZPOOL_PROP_ELOG_SIZE:
6962+
case ZPOOL_PROP_SELOG_SIZE:
69576963
case ZPOOL_PROP_EXPANDSZ:
6964+
case ZPOOL_PROP_NORMAL_EXPANDSZ:
6965+
case ZPOOL_PROP_SPECIAL_EXPANDSZ:
6966+
case ZPOOL_PROP_DEDUP_EXPANDSZ:
6967+
case ZPOOL_PROP_LOG_EXPANDSZ:
6968+
case ZPOOL_PROP_ELOG_EXPANDSZ:
6969+
case ZPOOL_PROP_SELOG_EXPANDSZ:
69586970
case ZPOOL_PROP_CHECKPOINT:
69596971
case ZPOOL_PROP_DEDUPRATIO:
69606972
case ZPOOL_PROP_DEDUPCACHED:
@@ -6965,6 +6977,12 @@ collect_vdev_prop(zpool_prop_t prop, uint64_t value, const char *str,
69656977
format);
69666978
break;
69676979
case ZPOOL_PROP_FRAGMENTATION:
6980+
case ZPOOL_PROP_NORMAL_FRAGMENTATION:
6981+
case ZPOOL_PROP_SPECIAL_FRAGMENTATION:
6982+
case ZPOOL_PROP_DEDUP_FRAGMENTATION:
6983+
case ZPOOL_PROP_LOG_FRAGMENTATION:
6984+
case ZPOOL_PROP_ELOG_FRAGMENTATION:
6985+
case ZPOOL_PROP_SELOG_FRAGMENTATION:
69686986
if (value == ZFS_FRAG_INVALID) {
69696987
(void) strlcpy(propval, "-", sizeof (propval));
69706988
} else if (format == ZFS_NICENUM_RAW) {
@@ -6976,6 +6994,12 @@ collect_vdev_prop(zpool_prop_t prop, uint64_t value, const char *str,
69766994
}
69776995
break;
69786996
case ZPOOL_PROP_CAPACITY:
6997+
case ZPOOL_PROP_NORMAL_CAPACITY:
6998+
case ZPOOL_PROP_SPECIAL_CAPACITY:
6999+
case ZPOOL_PROP_DEDUP_CAPACITY:
7000+
case ZPOOL_PROP_LOG_CAPACITY:
7001+
case ZPOOL_PROP_ELOG_CAPACITY:
7002+
case ZPOOL_PROP_SELOG_CAPACITY:
69797003
/* capacity value is in parts-per-10,000 (aka permyriad) */
69807004
if (format == ZFS_NICENUM_RAW)
69817005
(void) snprintf(propval, sizeof (propval), "%llu",

include/sys/fs/zfs.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,73 @@ typedef enum {
273273
ZPOOL_PROP_DEDUP_TABLE_QUOTA,
274274
ZPOOL_PROP_DEDUPCACHED,
275275
ZPOOL_PROP_LAST_SCRUBBED_TXG,
276+
ZPOOL_PROP_NORMAL_SIZE,
277+
ZPOOL_PROP_NORMAL_CAPACITY,
278+
ZPOOL_PROP_NORMAL_FREE,
279+
ZPOOL_PROP_NORMAL_ALLOCATED,
280+
ZPOOL_PROP_NORMAL_AVAILABLE,
281+
ZPOOL_PROP_NORMAL_EXPANDSZ,
282+
ZPOOL_PROP_NORMAL_FRAGMENTATION,
283+
ZPOOL_PROP_SPECIAL_SIZE,
284+
ZPOOL_PROP_SPECIAL_CAPACITY,
285+
ZPOOL_PROP_SPECIAL_FREE,
286+
ZPOOL_PROP_SPECIAL_ALLOCATED,
287+
ZPOOL_PROP_SPECIAL_AVAILABLE,
288+
ZPOOL_PROP_SPECIAL_EXPANDSZ,
289+
ZPOOL_PROP_SPECIAL_FRAGMENTATION,
290+
ZPOOL_PROP_DEDUP_SIZE,
291+
ZPOOL_PROP_DEDUP_CAPACITY,
292+
ZPOOL_PROP_DEDUP_FREE,
293+
ZPOOL_PROP_DEDUP_ALLOCATED,
294+
ZPOOL_PROP_DEDUP_AVAILABLE,
295+
ZPOOL_PROP_DEDUP_EXPANDSZ,
296+
ZPOOL_PROP_DEDUP_FRAGMENTATION,
297+
ZPOOL_PROP_LOG_SIZE,
298+
ZPOOL_PROP_LOG_CAPACITY,
299+
ZPOOL_PROP_LOG_FREE,
300+
ZPOOL_PROP_LOG_ALLOCATED,
301+
ZPOOL_PROP_LOG_AVAILABLE,
302+
ZPOOL_PROP_LOG_EXPANDSZ,
303+
ZPOOL_PROP_LOG_FRAGMENTATION,
304+
ZPOOL_PROP_ELOG_SIZE,
305+
ZPOOL_PROP_ELOG_CAPACITY,
306+
ZPOOL_PROP_ELOG_FREE,
307+
ZPOOL_PROP_ELOG_ALLOCATED,
308+
ZPOOL_PROP_ELOG_AVAILABLE,
309+
ZPOOL_PROP_ELOG_EXPANDSZ,
310+
ZPOOL_PROP_ELOG_FRAGMENTATION,
311+
ZPOOL_PROP_SELOG_SIZE,
312+
ZPOOL_PROP_SELOG_CAPACITY,
313+
ZPOOL_PROP_SELOG_FREE,
314+
ZPOOL_PROP_SELOG_ALLOCATED,
315+
ZPOOL_PROP_SELOG_AVAILABLE,
316+
ZPOOL_PROP_SELOG_EXPANDSZ,
317+
ZPOOL_PROP_SELOG_FRAGMENTATION,
276318
ZPOOL_NUM_PROPS
277319
} zpool_prop_t;
278320

321+
/* Offsets for metaslab class properties. */
322+
typedef enum {
323+
ZPOOL_MC_PROP_SIZE,
324+
ZPOOL_MC_PROP_CAPACITY,
325+
ZPOOL_MC_PROP_FREE,
326+
ZPOOL_MC_PROP_ALLOCATED,
327+
ZPOOL_MC_PROP_AVAILABLE,
328+
ZPOOL_MC_PROP_EXPANDSZ,
329+
ZPOOL_MC_PROP_FRAGMENTATION,
330+
ZPOOL_NUM_MC_PROPS
331+
} zpool_mc_prop_t;
332+
333+
/* Offsets for metaslab class property groups. */
334+
typedef enum {
335+
ZPOOL_MC_PROPS_NORMAL = ZPOOL_PROP_NORMAL_SIZE,
336+
ZPOOL_MC_PROPS_SPECIAL = ZPOOL_PROP_SPECIAL_SIZE,
337+
ZPOOL_MC_PROPS_DEDUP = ZPOOL_PROP_DEDUP_SIZE,
338+
ZPOOL_MC_PROPS_LOG = ZPOOL_PROP_LOG_SIZE,
339+
ZPOOL_MC_PROPS_ELOG = ZPOOL_PROP_ELOG_SIZE,
340+
ZPOOL_MC_PROPS_SELOG = ZPOOL_PROP_SELOG_SIZE,
341+
} zpool_mc_props_t;
342+
279343
/* Small enough to not hog a whole line of printout in zpool(8). */
280344
#define ZPROP_MAX_COMMENT 32
281345
#define ZPROP_BOOLEAN_NA 2

lib/libzfs/libzfs_pool.c

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,8 +370,32 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
370370
zfs_fallthrough;
371371

372372
case ZPOOL_PROP_SIZE:
373+
case ZPOOL_PROP_NORMAL_SIZE:
374+
case ZPOOL_PROP_SPECIAL_SIZE:
375+
case ZPOOL_PROP_DEDUP_SIZE:
376+
case ZPOOL_PROP_LOG_SIZE:
377+
case ZPOOL_PROP_ELOG_SIZE:
378+
case ZPOOL_PROP_SELOG_SIZE:
373379
case ZPOOL_PROP_ALLOCATED:
380+
case ZPOOL_PROP_NORMAL_ALLOCATED:
381+
case ZPOOL_PROP_SPECIAL_ALLOCATED:
382+
case ZPOOL_PROP_DEDUP_ALLOCATED:
383+
case ZPOOL_PROP_LOG_ALLOCATED:
384+
case ZPOOL_PROP_ELOG_ALLOCATED:
385+
case ZPOOL_PROP_SELOG_ALLOCATED:
386+
case ZPOOL_PROP_NORMAL_AVAILABLE:
387+
case ZPOOL_PROP_SPECIAL_AVAILABLE:
388+
case ZPOOL_PROP_DEDUP_AVAILABLE:
389+
case ZPOOL_PROP_LOG_AVAILABLE:
390+
case ZPOOL_PROP_ELOG_AVAILABLE:
391+
case ZPOOL_PROP_SELOG_AVAILABLE:
374392
case ZPOOL_PROP_FREE:
393+
case ZPOOL_PROP_NORMAL_FREE:
394+
case ZPOOL_PROP_SPECIAL_FREE:
395+
case ZPOOL_PROP_DEDUP_FREE:
396+
case ZPOOL_PROP_LOG_FREE:
397+
case ZPOOL_PROP_ELOG_FREE:
398+
case ZPOOL_PROP_SELOG_FREE:
375399
case ZPOOL_PROP_FREEING:
376400
case ZPOOL_PROP_LEAKED:
377401
case ZPOOL_PROP_ASHIFT:
@@ -389,6 +413,12 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
389413
break;
390414

391415
case ZPOOL_PROP_EXPANDSZ:
416+
case ZPOOL_PROP_NORMAL_EXPANDSZ:
417+
case ZPOOL_PROP_SPECIAL_EXPANDSZ:
418+
case ZPOOL_PROP_DEDUP_EXPANDSZ:
419+
case ZPOOL_PROP_LOG_EXPANDSZ:
420+
case ZPOOL_PROP_ELOG_EXPANDSZ:
421+
case ZPOOL_PROP_SELOG_EXPANDSZ:
392422
case ZPOOL_PROP_CHECKPOINT:
393423
if (intval == 0) {
394424
(void) strlcpy(buf, "-", len);
@@ -401,6 +431,12 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
401431
break;
402432

403433
case ZPOOL_PROP_CAPACITY:
434+
case ZPOOL_PROP_NORMAL_CAPACITY:
435+
case ZPOOL_PROP_SPECIAL_CAPACITY:
436+
case ZPOOL_PROP_DEDUP_CAPACITY:
437+
case ZPOOL_PROP_LOG_CAPACITY:
438+
case ZPOOL_PROP_ELOG_CAPACITY:
439+
case ZPOOL_PROP_SELOG_CAPACITY:
404440
if (literal) {
405441
(void) snprintf(buf, len, "%llu",
406442
(u_longlong_t)intval);
@@ -411,7 +447,13 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
411447
break;
412448

413449
case ZPOOL_PROP_FRAGMENTATION:
414-
if (intval == UINT64_MAX) {
450+
case ZPOOL_PROP_NORMAL_FRAGMENTATION:
451+
case ZPOOL_PROP_SPECIAL_FRAGMENTATION:
452+
case ZPOOL_PROP_DEDUP_FRAGMENTATION:
453+
case ZPOOL_PROP_LOG_FRAGMENTATION:
454+
case ZPOOL_PROP_ELOG_FRAGMENTATION:
455+
case ZPOOL_PROP_SELOG_FRAGMENTATION:
456+
if (intval == ZFS_FRAG_INVALID) {
415457
(void) strlcpy(buf, "-", len);
416458
} else if (literal) {
417459
(void) snprintf(buf, len, "%llu",

man/man7/zpoolprops.7

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@
2727
.\" Copyright 2017 Nexenta Systems, Inc.
2828
.\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
2929
.\" Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
30-
.\" Copyright (c) 2023, Klara Inc.
30+
.\" Copyright (c) 2023, 2026, Klara Inc.
3131
.\"
32-
.Dd December 4, 2024
32+
.Dd January 31, 2026
3333
.Dt ZPOOLPROPS 7
3434
.Os
3535
.
@@ -49,7 +49,7 @@ For more information about user properties, see the
4949
section.
5050
.Pp
5151
The following are read-only properties:
52-
.Bl -tag -width "unsupported@guid"
52+
.Bl -tag -width "last_scrubbed_txg"
5353
.It Sy allocated
5454
Amount of storage used within the pool.
5555
See
@@ -186,6 +186,96 @@ For non-full pools of a reasonable size, these effects should be invisible.
186186
For small pools, or pools that are close to being completely full, these
187187
discrepancies may become more noticeable.
188188
.Pp
189+
The following properties are read-only metrics for allocation classes:
190+
.Bl -ohang
191+
.It Xo Sy dedup_allocated , dedup_available , dedup_capacity ,
192+
.Sy dedup_expandsize , dedup_fragmentation , dedup_free
193+
.Xc
194+
.Bd -ragged -offset Ds -compact
195+
Space usage properties of the pool's
196+
.Sy dedup
197+
metaslab allocator class.
198+
.Ed
199+
.It Xo Sy embedded_log_allocated , embedded_log_available ,
200+
.Sy embedded_log_capacity , embedded_log_expandsize ,
201+
.Sy embedded_log_fragmentation , embedded_log_free
202+
.Xc
203+
.Bd -ragged -offset Ds -compact
204+
Space usage properties of the pool's
205+
.Sy embedded_log
206+
metaslab allocator class.
207+
.Ed
208+
.It Xo Sy log_allocated , log_available , log_capacity , log_expandsize ,
209+
.Sy log_fragmentation , log_free
210+
.Xc
211+
.Bd -ragged -offset Ds -compact
212+
Space usage properties of the pool's
213+
.Sy log
214+
metaslab allocator class.
215+
.Ed
216+
.It Xo Sy normal_allocated , normal_available , normal_capacity ,
217+
.Sy normal_expandsize , normal_fragmentation , normal_free
218+
.Xc
219+
.Bd -ragged -offset Ds -compact
220+
Space usage properties of the pool's
221+
.Sy normal
222+
metaslab allocator class.
223+
.Ed
224+
.It Xo Sy special_allocated , special_available , special_capacity ,
225+
.Sy special_expandsize , special_fragmentation , special_free
226+
.Xc
227+
.Bd -ragged -offset Ds -compact
228+
Space usage properties of the pool's
229+
.Sy special
230+
metaslab allocator class.
231+
.Ed
232+
.It Xo Sy special_embedded_log_allocated , special_embedded_log_available ,
233+
.Sy special_embedded_log_capacity , special_embedded_log_expandsize ,
234+
.Sy special_embedded_log_fragmentation , special_embedded_log_free
235+
.Xc
236+
.Bd -ragged -offset Ds -compact
237+
Space usage properties of the pool's
238+
.Sy special_embedded_log
239+
metaslab allocator class.
240+
.Ed
241+
.El
242+
.Pp
243+
Each allocation class is described by these values:
244+
.Bl -tag -width "fragmentation"
245+
.It Sy allocated
246+
Amount of storage used within the allocation class.
247+
.It Sy available
248+
Estimate of free space available in the allocation class, adjusted for raidz
249+
parity overhead.
250+
The adjustment assumes a fixed 128KiB record size to compute a data-to-parity
251+
ratio.
252+
.Sy available
253+
is a heuristic for allocation and should not be interpreted as an exact measure
254+
of usable space.
255+
Actual usable space depends on a variety of factors such as dataset record size
256+
and compression.
257+
.It Sy capacity
258+
Percentage of allocation class space used.
259+
.It Sy expandsize
260+
Amount of uninitialized space within the allocation class that can be used to
261+
increase the capacity of the allocator.
262+
See the pool-wide
263+
.Sy expandsize
264+
property.
265+
.It Sy fragmentation
266+
The amount of fragmentation in the allocation class.
267+
See the pool-wide
268+
.Sy fragmentation
269+
property.
270+
.It Sy free
271+
The amount of free space available in the allocation class.
272+
This value is not adjusted for factors such as dataset record size, compression,
273+
or raidz parity overhead.
274+
See the pool-wide
275+
.Sy free
276+
property.
277+
.El
278+
.Pp
189279
The following property can be set at creation time and import time:
190280
.Bl -tag -width Ds
191281
.It Sy altroot

module/zcommon/zpool_prop.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,31 @@ zpool_prop_get_table(void)
5050
return (zpool_prop_table);
5151
}
5252

53+
#define zpool_mc_props_init(uclass, lclass, sfeatures) ({ \
54+
zpool_mc_props_t mcp = ZPOOL_MC_PROPS_##uclass; \
55+
zprop_register_number(mcp + ZPOOL_MC_PROP_SIZE, \
56+
#lclass "_size", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \
57+
#uclass "_SIZE", B_FALSE, sfeatures); \
58+
zprop_register_number(mcp + ZPOOL_MC_PROP_CAPACITY, \
59+
#lclass "_capacity", 0, PROP_READONLY, ZFS_TYPE_POOL, "<percent>", \
60+
#uclass "_CAP", B_FALSE, sfeatures); \
61+
zprop_register_number(mcp + ZPOOL_MC_PROP_FREE, \
62+
#lclass "_free", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \
63+
#uclass "_FREE", B_FALSE, sfeatures); \
64+
zprop_register_number(mcp + ZPOOL_MC_PROP_ALLOCATED, \
65+
#lclass "_allocated", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \
66+
#uclass "_ALLOC", B_FALSE, sfeatures); \
67+
zprop_register_number(mcp + ZPOOL_MC_PROP_AVAILABLE, \
68+
#lclass "_available", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \
69+
#uclass "_AVAIL", B_FALSE, sfeatures); \
70+
zprop_register_number(mcp + ZPOOL_MC_PROP_EXPANDSZ, \
71+
#lclass "_expandsize", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \
72+
#uclass "_EXPANDSZ", B_FALSE, sfeatures); \
73+
zprop_register_number(mcp + ZPOOL_MC_PROP_FRAGMENTATION, \
74+
#lclass "_fragmentation", 0, PROP_READONLY, ZFS_TYPE_POOL, \
75+
"<percent>", #uclass "_FRAG", B_FALSE, sfeatures); \
76+
})
77+
5378
void
5479
zpool_prop_init(void)
5580
{
@@ -133,6 +158,13 @@ zpool_prop_init(void)
133158
"last_scrubbed_txg", 0, PROP_READONLY, ZFS_TYPE_POOL, "<txg>",
134159
"LAST_SCRUBBED_TXG", B_FALSE, sfeatures);
135160

161+
zpool_mc_props_init(NORMAL, normal, sfeatures);
162+
zpool_mc_props_init(SPECIAL, special, sfeatures);
163+
zpool_mc_props_init(DEDUP, dedup, sfeatures);
164+
zpool_mc_props_init(LOG, log, sfeatures);
165+
zpool_mc_props_init(ELOG, embedded_log, sfeatures);
166+
zpool_mc_props_init(SELOG, special_embedded_log, sfeatures);
167+
136168
/* default number properties */
137169
zprop_register_number(ZPOOL_PROP_VERSION, "version", SPA_VERSION,
138170
PROP_DEFAULT, ZFS_TYPE_POOL, "<version>", "VERSION", B_FALSE,

module/zfs/metaslab.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,10 @@ metaslab_class_fragmentation(metaslab_class_t *mc)
805805
{
806806
vdev_t *rvd = mc->mc_spa->spa_root_vdev;
807807
uint64_t fragmentation = 0;
808+
uint64_t space = metaslab_class_get_space(mc);
809+
810+
if (space == 0)
811+
return (ZFS_FRAG_INVALID);
808812

809813
spa_config_enter(mc->mc_spa, SCL_VDEV, FTAG, RW_READER);
810814

@@ -837,7 +841,7 @@ metaslab_class_fragmentation(metaslab_class_t *mc)
837841
fragmentation += mg->mg_fragmentation *
838842
metaslab_group_get_space(mg);
839843
}
840-
fragmentation /= metaslab_class_get_space(mc);
844+
fragmentation /= space;
841845

842846
ASSERT3U(fragmentation, <=, 100);
843847
spa_config_exit(mc->mc_spa, SCL_VDEV, FTAG);

0 commit comments

Comments
 (0)