mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-03-11 12:56:21 +03:00
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 several classes combined. Add properties reporting the space accounting metrics for each metaslab class individually. Also introduce pool-wide AVAIL, USABLE, and USED properties reporting values corresponding to FREE, SIZE, and ALLOC deflated for raidz. Update ZTS to recognize the new properties and validate reported values. While in zpool_get_parsable.cfg, add "fragmentation" to the list of parsable properties. Sponsored-by: Klara, Inc. Reviewed-by: Alexander Motin <alexander.motin@TrueNAS.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Ameer Hamza <ahamza@ixsystems.com> Signed-off-by: Ryan Moeller <ryan.moeller@klarasystems.com> Cloes #18238
This commit is contained in:
parent
6ba3f915d0
commit
ac0fd40c8c
@ -6960,7 +6960,19 @@ collect_vdev_prop(zpool_prop_t prop, uint64_t value, const char *str,
|
||||
|
||||
switch (prop) {
|
||||
case ZPOOL_PROP_SIZE:
|
||||
case ZPOOL_PROP_NORMAL_SIZE:
|
||||
case ZPOOL_PROP_SPECIAL_SIZE:
|
||||
case ZPOOL_PROP_DEDUP_SIZE:
|
||||
case ZPOOL_PROP_LOG_SIZE:
|
||||
case ZPOOL_PROP_ELOG_SIZE:
|
||||
case ZPOOL_PROP_SELOG_SIZE:
|
||||
case ZPOOL_PROP_EXPANDSZ:
|
||||
case ZPOOL_PROP_NORMAL_EXPANDSZ:
|
||||
case ZPOOL_PROP_SPECIAL_EXPANDSZ:
|
||||
case ZPOOL_PROP_DEDUP_EXPANDSZ:
|
||||
case ZPOOL_PROP_LOG_EXPANDSZ:
|
||||
case ZPOOL_PROP_ELOG_EXPANDSZ:
|
||||
case ZPOOL_PROP_SELOG_EXPANDSZ:
|
||||
case ZPOOL_PROP_CHECKPOINT:
|
||||
case ZPOOL_PROP_DEDUPRATIO:
|
||||
case ZPOOL_PROP_DEDUPCACHED:
|
||||
@ -6971,6 +6983,12 @@ collect_vdev_prop(zpool_prop_t prop, uint64_t value, const char *str,
|
||||
format);
|
||||
break;
|
||||
case ZPOOL_PROP_FRAGMENTATION:
|
||||
case ZPOOL_PROP_NORMAL_FRAGMENTATION:
|
||||
case ZPOOL_PROP_SPECIAL_FRAGMENTATION:
|
||||
case ZPOOL_PROP_DEDUP_FRAGMENTATION:
|
||||
case ZPOOL_PROP_LOG_FRAGMENTATION:
|
||||
case ZPOOL_PROP_ELOG_FRAGMENTATION:
|
||||
case ZPOOL_PROP_SELOG_FRAGMENTATION:
|
||||
if (value == ZFS_FRAG_INVALID) {
|
||||
(void) strlcpy(propval, "-", sizeof (propval));
|
||||
} else if (format == ZFS_NICENUM_RAW) {
|
||||
@ -6982,6 +7000,12 @@ collect_vdev_prop(zpool_prop_t prop, uint64_t value, const char *str,
|
||||
}
|
||||
break;
|
||||
case ZPOOL_PROP_CAPACITY:
|
||||
case ZPOOL_PROP_NORMAL_CAPACITY:
|
||||
case ZPOOL_PROP_SPECIAL_CAPACITY:
|
||||
case ZPOOL_PROP_DEDUP_CAPACITY:
|
||||
case ZPOOL_PROP_LOG_CAPACITY:
|
||||
case ZPOOL_PROP_ELOG_CAPACITY:
|
||||
case ZPOOL_PROP_SELOG_CAPACITY:
|
||||
/* capacity value is in parts-per-10,000 (aka permyriad) */
|
||||
if (format == ZFS_NICENUM_RAW)
|
||||
(void) snprintf(propval, sizeof (propval), "%llu",
|
||||
|
||||
@ -275,9 +275,90 @@ typedef enum {
|
||||
ZPOOL_PROP_LAST_SCRUBBED_TXG,
|
||||
ZPOOL_PROP_DEDUPUSED,
|
||||
ZPOOL_PROP_DEDUPSAVED,
|
||||
ZPOOL_PROP_AVAILABLE,
|
||||
ZPOOL_PROP_USABLE,
|
||||
ZPOOL_PROP_USED,
|
||||
ZPOOL_PROP_NORMAL_SIZE,
|
||||
ZPOOL_PROP_NORMAL_CAPACITY,
|
||||
ZPOOL_PROP_NORMAL_FREE,
|
||||
ZPOOL_PROP_NORMAL_ALLOCATED,
|
||||
ZPOOL_PROP_NORMAL_AVAILABLE,
|
||||
ZPOOL_PROP_NORMAL_USABLE,
|
||||
ZPOOL_PROP_NORMAL_USED,
|
||||
ZPOOL_PROP_NORMAL_EXPANDSZ,
|
||||
ZPOOL_PROP_NORMAL_FRAGMENTATION,
|
||||
ZPOOL_PROP_SPECIAL_SIZE,
|
||||
ZPOOL_PROP_SPECIAL_CAPACITY,
|
||||
ZPOOL_PROP_SPECIAL_FREE,
|
||||
ZPOOL_PROP_SPECIAL_ALLOCATED,
|
||||
ZPOOL_PROP_SPECIAL_AVAILABLE,
|
||||
ZPOOL_PROP_SPECIAL_USABLE,
|
||||
ZPOOL_PROP_SPECIAL_USED,
|
||||
ZPOOL_PROP_SPECIAL_EXPANDSZ,
|
||||
ZPOOL_PROP_SPECIAL_FRAGMENTATION,
|
||||
ZPOOL_PROP_DEDUP_SIZE,
|
||||
ZPOOL_PROP_DEDUP_CAPACITY,
|
||||
ZPOOL_PROP_DEDUP_FREE,
|
||||
ZPOOL_PROP_DEDUP_ALLOCATED,
|
||||
ZPOOL_PROP_DEDUP_AVAILABLE,
|
||||
ZPOOL_PROP_DEDUP_USABLE,
|
||||
ZPOOL_PROP_DEDUP_USED,
|
||||
ZPOOL_PROP_DEDUP_EXPANDSZ,
|
||||
ZPOOL_PROP_DEDUP_FRAGMENTATION,
|
||||
ZPOOL_PROP_LOG_SIZE,
|
||||
ZPOOL_PROP_LOG_CAPACITY,
|
||||
ZPOOL_PROP_LOG_FREE,
|
||||
ZPOOL_PROP_LOG_ALLOCATED,
|
||||
ZPOOL_PROP_LOG_AVAILABLE,
|
||||
ZPOOL_PROP_LOG_USABLE,
|
||||
ZPOOL_PROP_LOG_USED,
|
||||
ZPOOL_PROP_LOG_EXPANDSZ,
|
||||
ZPOOL_PROP_LOG_FRAGMENTATION,
|
||||
ZPOOL_PROP_ELOG_SIZE,
|
||||
ZPOOL_PROP_ELOG_CAPACITY,
|
||||
ZPOOL_PROP_ELOG_FREE,
|
||||
ZPOOL_PROP_ELOG_ALLOCATED,
|
||||
ZPOOL_PROP_ELOG_AVAILABLE,
|
||||
ZPOOL_PROP_ELOG_USABLE,
|
||||
ZPOOL_PROP_ELOG_USED,
|
||||
ZPOOL_PROP_ELOG_EXPANDSZ,
|
||||
ZPOOL_PROP_ELOG_FRAGMENTATION,
|
||||
ZPOOL_PROP_SELOG_SIZE,
|
||||
ZPOOL_PROP_SELOG_CAPACITY,
|
||||
ZPOOL_PROP_SELOG_FREE,
|
||||
ZPOOL_PROP_SELOG_ALLOCATED,
|
||||
ZPOOL_PROP_SELOG_AVAILABLE,
|
||||
ZPOOL_PROP_SELOG_USABLE,
|
||||
ZPOOL_PROP_SELOG_USED,
|
||||
ZPOOL_PROP_SELOG_EXPANDSZ,
|
||||
ZPOOL_PROP_SELOG_FRAGMENTATION,
|
||||
ZPOOL_NUM_PROPS
|
||||
} zpool_prop_t;
|
||||
|
||||
/* Offsets for metaslab class properties. */
|
||||
typedef enum {
|
||||
ZPOOL_MC_PROP_SIZE,
|
||||
ZPOOL_MC_PROP_CAPACITY,
|
||||
ZPOOL_MC_PROP_FREE,
|
||||
ZPOOL_MC_PROP_ALLOCATED,
|
||||
ZPOOL_MC_PROP_AVAILABLE,
|
||||
ZPOOL_MC_PROP_USABLE,
|
||||
ZPOOL_MC_PROP_USED,
|
||||
ZPOOL_MC_PROP_EXPANDSZ,
|
||||
ZPOOL_MC_PROP_FRAGMENTATION,
|
||||
ZPOOL_NUM_MC_PROPS
|
||||
} zpool_mc_prop_t;
|
||||
|
||||
/* Offsets for metaslab class property groups. */
|
||||
typedef enum {
|
||||
ZPOOL_MC_PROPS_NORMAL = ZPOOL_PROP_NORMAL_SIZE,
|
||||
ZPOOL_MC_PROPS_SPECIAL = ZPOOL_PROP_SPECIAL_SIZE,
|
||||
ZPOOL_MC_PROPS_DEDUP = ZPOOL_PROP_DEDUP_SIZE,
|
||||
ZPOOL_MC_PROPS_LOG = ZPOOL_PROP_LOG_SIZE,
|
||||
ZPOOL_MC_PROPS_ELOG = ZPOOL_PROP_ELOG_SIZE,
|
||||
ZPOOL_MC_PROPS_SELOG = ZPOOL_PROP_SELOG_SIZE,
|
||||
} zpool_mc_props_t;
|
||||
|
||||
/* Small enough to not hog a whole line of printout in zpool(8). */
|
||||
#define ZPROP_MAX_COMMENT 32
|
||||
#define ZPROP_BOOLEAN_NA 2
|
||||
|
||||
@ -3372,7 +3372,64 @@
|
||||
<enumerator name='ZPOOL_PROP_LAST_SCRUBBED_TXG' value='39'/>
|
||||
<enumerator name='ZPOOL_PROP_DEDUPUSED' value='40'/>
|
||||
<enumerator name='ZPOOL_PROP_DEDUPSAVED' value='41'/>
|
||||
<enumerator name='ZPOOL_NUM_PROPS' value='42'/>
|
||||
<enumerator name='ZPOOL_PROP_AVAILABLE' value='42'/>
|
||||
<enumerator name='ZPOOL_PROP_USABLE' value='43'/>
|
||||
<enumerator name='ZPOOL_PROP_USED' value='44'/>
|
||||
<enumerator name='ZPOOL_PROP_NORMAL_SIZE' value='45'/>
|
||||
<enumerator name='ZPOOL_PROP_NORMAL_CAPACITY' value='46'/>
|
||||
<enumerator name='ZPOOL_PROP_NORMAL_FREE' value='47'/>
|
||||
<enumerator name='ZPOOL_PROP_NORMAL_ALLOCATED' value='48'/>
|
||||
<enumerator name='ZPOOL_PROP_NORMAL_AVAILABLE' value='49'/>
|
||||
<enumerator name='ZPOOL_PROP_NORMAL_USABLE' value='50'/>
|
||||
<enumerator name='ZPOOL_PROP_NORMAL_USED' value='51'/>
|
||||
<enumerator name='ZPOOL_PROP_NORMAL_EXPANDSZ' value='52'/>
|
||||
<enumerator name='ZPOOL_PROP_NORMAL_FRAGMENTATION' value='53'/>
|
||||
<enumerator name='ZPOOL_PROP_SPECIAL_SIZE' value='54'/>
|
||||
<enumerator name='ZPOOL_PROP_SPECIAL_CAPACITY' value='55'/>
|
||||
<enumerator name='ZPOOL_PROP_SPECIAL_FREE' value='56'/>
|
||||
<enumerator name='ZPOOL_PROP_SPECIAL_ALLOCATED' value='57'/>
|
||||
<enumerator name='ZPOOL_PROP_SPECIAL_AVAILABLE' value='58'/>
|
||||
<enumerator name='ZPOOL_PROP_SPECIAL_USABLE' value='59'/>
|
||||
<enumerator name='ZPOOL_PROP_SPECIAL_USED' value='60'/>
|
||||
<enumerator name='ZPOOL_PROP_SPECIAL_EXPANDSZ' value='61'/>
|
||||
<enumerator name='ZPOOL_PROP_SPECIAL_FRAGMENTATION' value='62'/>
|
||||
<enumerator name='ZPOOL_PROP_DEDUP_SIZE' value='63'/>
|
||||
<enumerator name='ZPOOL_PROP_DEDUP_CAPACITY' value='64'/>
|
||||
<enumerator name='ZPOOL_PROP_DEDUP_FREE' value='65'/>
|
||||
<enumerator name='ZPOOL_PROP_DEDUP_ALLOCATED' value='66'/>
|
||||
<enumerator name='ZPOOL_PROP_DEDUP_AVAILABLE' value='67'/>
|
||||
<enumerator name='ZPOOL_PROP_DEDUP_USABLE' value='68'/>
|
||||
<enumerator name='ZPOOL_PROP_DEDUP_USED' value='69'/>
|
||||
<enumerator name='ZPOOL_PROP_DEDUP_EXPANDSZ' value='70'/>
|
||||
<enumerator name='ZPOOL_PROP_DEDUP_FRAGMENTATION' value='71'/>
|
||||
<enumerator name='ZPOOL_PROP_LOG_SIZE' value='72'/>
|
||||
<enumerator name='ZPOOL_PROP_LOG_CAPACITY' value='73'/>
|
||||
<enumerator name='ZPOOL_PROP_LOG_FREE' value='74'/>
|
||||
<enumerator name='ZPOOL_PROP_LOG_ALLOCATED' value='75'/>
|
||||
<enumerator name='ZPOOL_PROP_LOG_AVAILABLE' value='76'/>
|
||||
<enumerator name='ZPOOL_PROP_LOG_USABLE' value='77'/>
|
||||
<enumerator name='ZPOOL_PROP_LOG_USED' value='78'/>
|
||||
<enumerator name='ZPOOL_PROP_LOG_EXPANDSZ' value='79'/>
|
||||
<enumerator name='ZPOOL_PROP_LOG_FRAGMENTATION' value='80'/>
|
||||
<enumerator name='ZPOOL_PROP_ELOG_SIZE' value='81'/>
|
||||
<enumerator name='ZPOOL_PROP_ELOG_CAPACITY' value='82'/>
|
||||
<enumerator name='ZPOOL_PROP_ELOG_FREE' value='83'/>
|
||||
<enumerator name='ZPOOL_PROP_ELOG_ALLOCATED' value='84'/>
|
||||
<enumerator name='ZPOOL_PROP_ELOG_AVAILABLE' value='85'/>
|
||||
<enumerator name='ZPOOL_PROP_ELOG_USABLE' value='86'/>
|
||||
<enumerator name='ZPOOL_PROP_ELOG_USED' value='87'/>
|
||||
<enumerator name='ZPOOL_PROP_ELOG_EXPANDSZ' value='88'/>
|
||||
<enumerator name='ZPOOL_PROP_ELOG_FRAGMENTATION' value='89'/>
|
||||
<enumerator name='ZPOOL_PROP_SELOG_SIZE' value='90'/>
|
||||
<enumerator name='ZPOOL_PROP_SELOG_CAPACITY' value='91'/>
|
||||
<enumerator name='ZPOOL_PROP_SELOG_FREE' value='92'/>
|
||||
<enumerator name='ZPOOL_PROP_SELOG_ALLOCATED' value='93'/>
|
||||
<enumerator name='ZPOOL_PROP_SELOG_AVAILABLE' value='94'/>
|
||||
<enumerator name='ZPOOL_PROP_SELOG_USABLE' value='95'/>
|
||||
<enumerator name='ZPOOL_PROP_SELOG_USED' value='96'/>
|
||||
<enumerator name='ZPOOL_PROP_SELOG_EXPANDSZ' value='97'/>
|
||||
<enumerator name='ZPOOL_PROP_SELOG_FRAGMENTATION' value='98'/>
|
||||
<enumerator name='ZPOOL_NUM_PROPS' value='99'/>
|
||||
</enum-decl>
|
||||
<typedef-decl name='zpool_prop_t' type-id='af1ba157' id='5d0c23fb'/>
|
||||
<typedef-decl name='regoff_t' type-id='95e97e5e' id='54a2a2a8'/>
|
||||
|
||||
@ -370,8 +370,47 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
|
||||
zfs_fallthrough;
|
||||
|
||||
case ZPOOL_PROP_SIZE:
|
||||
case ZPOOL_PROP_NORMAL_SIZE:
|
||||
case ZPOOL_PROP_SPECIAL_SIZE:
|
||||
case ZPOOL_PROP_DEDUP_SIZE:
|
||||
case ZPOOL_PROP_LOG_SIZE:
|
||||
case ZPOOL_PROP_ELOG_SIZE:
|
||||
case ZPOOL_PROP_SELOG_SIZE:
|
||||
case ZPOOL_PROP_ALLOCATED:
|
||||
case ZPOOL_PROP_NORMAL_ALLOCATED:
|
||||
case ZPOOL_PROP_SPECIAL_ALLOCATED:
|
||||
case ZPOOL_PROP_DEDUP_ALLOCATED:
|
||||
case ZPOOL_PROP_LOG_ALLOCATED:
|
||||
case ZPOOL_PROP_ELOG_ALLOCATED:
|
||||
case ZPOOL_PROP_SELOG_ALLOCATED:
|
||||
case ZPOOL_PROP_AVAILABLE:
|
||||
case ZPOOL_PROP_NORMAL_AVAILABLE:
|
||||
case ZPOOL_PROP_SPECIAL_AVAILABLE:
|
||||
case ZPOOL_PROP_DEDUP_AVAILABLE:
|
||||
case ZPOOL_PROP_LOG_AVAILABLE:
|
||||
case ZPOOL_PROP_ELOG_AVAILABLE:
|
||||
case ZPOOL_PROP_SELOG_AVAILABLE:
|
||||
case ZPOOL_PROP_FREE:
|
||||
case ZPOOL_PROP_NORMAL_FREE:
|
||||
case ZPOOL_PROP_SPECIAL_FREE:
|
||||
case ZPOOL_PROP_DEDUP_FREE:
|
||||
case ZPOOL_PROP_LOG_FREE:
|
||||
case ZPOOL_PROP_ELOG_FREE:
|
||||
case ZPOOL_PROP_SELOG_FREE:
|
||||
case ZPOOL_PROP_USABLE:
|
||||
case ZPOOL_PROP_NORMAL_USABLE:
|
||||
case ZPOOL_PROP_SPECIAL_USABLE:
|
||||
case ZPOOL_PROP_DEDUP_USABLE:
|
||||
case ZPOOL_PROP_LOG_USABLE:
|
||||
case ZPOOL_PROP_ELOG_USABLE:
|
||||
case ZPOOL_PROP_SELOG_USABLE:
|
||||
case ZPOOL_PROP_USED:
|
||||
case ZPOOL_PROP_NORMAL_USED:
|
||||
case ZPOOL_PROP_SPECIAL_USED:
|
||||
case ZPOOL_PROP_DEDUP_USED:
|
||||
case ZPOOL_PROP_LOG_USED:
|
||||
case ZPOOL_PROP_ELOG_USED:
|
||||
case ZPOOL_PROP_SELOG_USED:
|
||||
case ZPOOL_PROP_FREEING:
|
||||
case ZPOOL_PROP_LEAKED:
|
||||
case ZPOOL_PROP_ASHIFT:
|
||||
@ -391,6 +430,12 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
|
||||
break;
|
||||
|
||||
case ZPOOL_PROP_EXPANDSZ:
|
||||
case ZPOOL_PROP_NORMAL_EXPANDSZ:
|
||||
case ZPOOL_PROP_SPECIAL_EXPANDSZ:
|
||||
case ZPOOL_PROP_DEDUP_EXPANDSZ:
|
||||
case ZPOOL_PROP_LOG_EXPANDSZ:
|
||||
case ZPOOL_PROP_ELOG_EXPANDSZ:
|
||||
case ZPOOL_PROP_SELOG_EXPANDSZ:
|
||||
case ZPOOL_PROP_CHECKPOINT:
|
||||
if (intval == 0) {
|
||||
(void) strlcpy(buf, "-", len);
|
||||
@ -403,6 +448,12 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
|
||||
break;
|
||||
|
||||
case ZPOOL_PROP_CAPACITY:
|
||||
case ZPOOL_PROP_NORMAL_CAPACITY:
|
||||
case ZPOOL_PROP_SPECIAL_CAPACITY:
|
||||
case ZPOOL_PROP_DEDUP_CAPACITY:
|
||||
case ZPOOL_PROP_LOG_CAPACITY:
|
||||
case ZPOOL_PROP_ELOG_CAPACITY:
|
||||
case ZPOOL_PROP_SELOG_CAPACITY:
|
||||
if (literal) {
|
||||
(void) snprintf(buf, len, "%llu",
|
||||
(u_longlong_t)intval);
|
||||
@ -413,7 +464,13 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf,
|
||||
break;
|
||||
|
||||
case ZPOOL_PROP_FRAGMENTATION:
|
||||
if (intval == UINT64_MAX) {
|
||||
case ZPOOL_PROP_NORMAL_FRAGMENTATION:
|
||||
case ZPOOL_PROP_SPECIAL_FRAGMENTATION:
|
||||
case ZPOOL_PROP_DEDUP_FRAGMENTATION:
|
||||
case ZPOOL_PROP_LOG_FRAGMENTATION:
|
||||
case ZPOOL_PROP_ELOG_FRAGMENTATION:
|
||||
case ZPOOL_PROP_SELOG_FRAGMENTATION:
|
||||
if (intval == ZFS_FRAG_INVALID) {
|
||||
(void) strlcpy(buf, "-", len);
|
||||
} else if (literal) {
|
||||
(void) snprintf(buf, len, "%llu",
|
||||
|
||||
@ -27,9 +27,9 @@
|
||||
.\" Copyright 2017 Nexenta Systems, Inc.
|
||||
.\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
|
||||
.\" Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
|
||||
.\" Copyright (c) 2023, Klara Inc.
|
||||
.\" Copyright (c) 2023, 2026, Klara Inc.
|
||||
.\"
|
||||
.Dd December 4, 2024
|
||||
.Dd March 2, 2026
|
||||
.Dt ZPOOLPROPS 7
|
||||
.Os
|
||||
.
|
||||
@ -49,7 +49,7 @@ For more information about user properties, see the
|
||||
section.
|
||||
.Pp
|
||||
The following are read-only properties:
|
||||
.Bl -tag -width "unsupported@guid"
|
||||
.Bl -tag -width "last_scrubbed_txg"
|
||||
.It Sy allocated
|
||||
Amount of storage used within the pool.
|
||||
See
|
||||
@ -57,6 +57,21 @@ See
|
||||
and
|
||||
.Sy free
|
||||
for more information.
|
||||
.It Sy available
|
||||
The amount of free space available in the pool, adjusted for raidz parity
|
||||
overhead.
|
||||
The
|
||||
.Sy available
|
||||
property is calculated as:
|
||||
.Pp
|
||||
.Sy usable - used
|
||||
.Pp
|
||||
See
|
||||
.Sy usable ,
|
||||
.Sy used ,
|
||||
and
|
||||
.Sy free
|
||||
for more information.
|
||||
.It Sy bcloneratio
|
||||
The ratio of the total amount of storage that would be required to store all
|
||||
the cloned blocks without cloning to the actual storage used.
|
||||
@ -184,6 +199,21 @@ Information about unsupported features that are enabled on the pool.
|
||||
See
|
||||
.Xr zpool-features 7
|
||||
for details.
|
||||
.It Sy usable
|
||||
Estimate of total storage pool size, adjusted for raidz parity overhead.
|
||||
The adjustment assumes a fixed 128KiB record size to compute a data-to-parity
|
||||
ratio.
|
||||
.Sy usable
|
||||
is a heuristic for allocation and should not be interpreted as an exact measure
|
||||
of usable space.
|
||||
.It Sy used
|
||||
Estimate of storage used within the storage pool, adjusted for raidz parity
|
||||
overhead.
|
||||
The adjustment assumes a fixed 128KiB record size to compute a data-to-parity
|
||||
ratio.
|
||||
.Sy used
|
||||
is a heuristic for allocation and should not be interpreted as an exact measure
|
||||
of used space.
|
||||
.El
|
||||
.Pp
|
||||
The space usage properties report actual physical space available to the
|
||||
@ -201,6 +231,121 @@ For non-full pools of a reasonable size, these effects should be invisible.
|
||||
For small pools, or pools that are close to being completely full, these
|
||||
discrepancies may become more noticeable.
|
||||
.Pp
|
||||
The following properties are read-only metrics for allocation classes:
|
||||
.Bl -ohang
|
||||
.It Xo Sy class_dedup_allocated , class_dedup_available , class_dedup_capacity ,
|
||||
.Sy class_dedup_expandsize , class_dedup_fragmentation , class_dedup_free ,
|
||||
.Sy class_dedup_size , class_dedup_usable , class_dedup_used
|
||||
.Xc
|
||||
.Bd -ragged -offset Ds -compact
|
||||
Space usage properties of the pool's
|
||||
.Sy dedup
|
||||
metaslab allocator class.
|
||||
.Ed
|
||||
.It Xo Sy class_elog_allocated , class_elog_available , class_elog_capacity ,
|
||||
.Sy class_elog_expandsize , class_elog_fragmentation , class_elog_free ,
|
||||
.Sy class_elog_size , class_elog_usable , class_elog_used
|
||||
.Xc
|
||||
.Bd -ragged -offset Ds -compact
|
||||
Space usage properties of the pool's
|
||||
.Sy embedded_log
|
||||
metaslab allocator class.
|
||||
.Ed
|
||||
.It Xo Sy class_log_allocated , class_log_available , class_log_capacity ,
|
||||
.Sy class_log_expandsize , class_log_fragmentation , class_log_free ,
|
||||
.Sy class_log_size , class_log_usable , class_log_used
|
||||
.Xc
|
||||
.Bd -ragged -offset Ds -compact
|
||||
Space usage properties of the pool's
|
||||
.Sy log
|
||||
metaslab allocator class.
|
||||
.Ed
|
||||
.It Xo Sy class_normal_allocated , class_normal_available ,
|
||||
.Sy class_normal_capacity , class_normal_expandsize ,
|
||||
.Sy class_normal_fragmentation , class_normal_free , class_normal_size ,
|
||||
.Sy class_normal_usable , class_normal_used
|
||||
.Xc
|
||||
.Bd -ragged -offset Ds -compact
|
||||
Space usage properties of the pool's
|
||||
.Sy normal
|
||||
metaslab allocator class.
|
||||
.Ed
|
||||
.It Xo Sy class_special_allocated , class_special_available ,
|
||||
.Sy class_special_capacity , class_special_expandsize ,
|
||||
.Sy class_special_fragmentation , class_special_free , class_special_size ,
|
||||
.Sy class_special_usable , class_special_used
|
||||
.Xc
|
||||
.Bd -ragged -offset Ds -compact
|
||||
Space usage properties of the pool's
|
||||
.Sy special
|
||||
metaslab allocator class.
|
||||
.Ed
|
||||
.It Xo Sy class_special_elog_allocated , class_special_elog_available ,
|
||||
.Sy class_special_elog_capacity , class_special_elog_expandsize ,
|
||||
.Sy class_special_elog_fragmentation , class_special_elog_free ,
|
||||
.Sy class_special_elog_size , class_special_elog_usable ,
|
||||
.Sy class_special_elog_used
|
||||
.Xc
|
||||
.Bd -ragged -offset Ds -compact
|
||||
Space usage properties of the pool's
|
||||
.Sy special_embedded_log
|
||||
metaslab allocator class.
|
||||
.Ed
|
||||
.El
|
||||
.Pp
|
||||
Each allocation class is described by these values:
|
||||
.Bl -tag -width "fragmentation"
|
||||
.It Sy allocated
|
||||
Amount of storage used within the allocation class.
|
||||
.It Sy available
|
||||
Estimate of free space available in the allocation class, adjusted for raidz
|
||||
parity overhead.
|
||||
The adjustment assumes a fixed 128KiB record size to compute a data-to-parity
|
||||
ratio.
|
||||
.Sy available
|
||||
is a heuristic for allocation and should not be interpreted as an exact measure
|
||||
of usable space.
|
||||
Actual usable space depends on a variety of factors such as dataset record size
|
||||
and compression.
|
||||
.It Sy capacity
|
||||
Percentage of allocation class space used.
|
||||
.It Sy expandsize
|
||||
Amount of uninitialized space within the allocation class that can be used to
|
||||
increase the capacity of the allocator.
|
||||
See the pool-wide
|
||||
.Sy expandsize
|
||||
property.
|
||||
.It Sy fragmentation
|
||||
The amount of free space fragmentation in the allocation class.
|
||||
See the pool-wide
|
||||
.Sy fragmentation
|
||||
property.
|
||||
.It Sy free
|
||||
The amount of free space available in the allocation class.
|
||||
This value is not adjusted for factors such as dataset record size, compression,
|
||||
or raidz parity overhead.
|
||||
See the pool-wide
|
||||
.Sy free
|
||||
property.
|
||||
.It Sy size
|
||||
Total size of the allocation class.
|
||||
.It Sy usable
|
||||
Estimate of total allocation class size, adjusted for raidz parity overhead.
|
||||
The adjustment assumes a fixed 128KiB record size to compute a data-to-parity
|
||||
ratio.
|
||||
.Sy usable
|
||||
is a heuristic for allocation and should not be interpreted as an exact measure
|
||||
of usable space.
|
||||
.It Sy used
|
||||
Estimate of storage used within the allocation class, adjusted for raidz parity
|
||||
overhead.
|
||||
The adjustment assumes a fixed 128KiB record size to compute a data-to-parity
|
||||
ratio.
|
||||
.Sy used
|
||||
is a heuristic for allocation and should not be interpreted as an exact measure
|
||||
of used space.
|
||||
.El
|
||||
.Pp
|
||||
The following property can be set at creation time and import time:
|
||||
.Bl -tag -width Ds
|
||||
.It Sy altroot
|
||||
|
||||
@ -50,6 +50,41 @@ zpool_prop_get_table(void)
|
||||
return (zpool_prop_table);
|
||||
}
|
||||
|
||||
/* BEGIN CSTYLED */
|
||||
#define zprop_register_mc_props_impl(mcp, uprefix, lprefix, sfeatures) ({ \
|
||||
zprop_register_number(mcp + ZPOOL_MC_PROP_SIZE, \
|
||||
#lprefix "_size", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \
|
||||
#uprefix "_SIZE", B_FALSE, sfeatures); \
|
||||
zprop_register_number(mcp + ZPOOL_MC_PROP_CAPACITY, \
|
||||
#lprefix "_capacity", 0, PROP_READONLY, ZFS_TYPE_POOL, \
|
||||
"<percent>", #uprefix "_CAP", B_FALSE, sfeatures); \
|
||||
zprop_register_number(mcp + ZPOOL_MC_PROP_FREE, \
|
||||
#lprefix "_free", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \
|
||||
#uprefix "_FREE", B_FALSE, sfeatures); \
|
||||
zprop_register_number(mcp + ZPOOL_MC_PROP_ALLOCATED, \
|
||||
#lprefix "_allocated", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \
|
||||
#uprefix "_ALLOC", B_FALSE, sfeatures); \
|
||||
zprop_register_number(mcp + ZPOOL_MC_PROP_AVAILABLE, \
|
||||
#lprefix "_available", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \
|
||||
#uprefix "_AVAIL", B_FALSE, sfeatures); \
|
||||
zprop_register_number(mcp + ZPOOL_MC_PROP_USABLE, \
|
||||
#lprefix "_usable", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \
|
||||
#uprefix "_USABLE", B_FALSE, sfeatures); \
|
||||
zprop_register_number(mcp + ZPOOL_MC_PROP_USED, \
|
||||
#lprefix "_used", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \
|
||||
#uprefix "_USED", B_FALSE, sfeatures); \
|
||||
zprop_register_number(mcp + ZPOOL_MC_PROP_EXPANDSZ, \
|
||||
#lprefix "_expandsize", 0, PROP_READONLY, ZFS_TYPE_POOL, "<size>", \
|
||||
#uprefix "_EXPANDSZ", B_FALSE, sfeatures); \
|
||||
zprop_register_number(mcp + ZPOOL_MC_PROP_FRAGMENTATION, \
|
||||
#lprefix "_fragmentation", 0, PROP_READONLY, ZFS_TYPE_POOL, \
|
||||
"<percent>", #uprefix "_FRAG", B_FALSE, sfeatures); \
|
||||
})
|
||||
#define zprop_register_mc_props(uclass, lclass, sfeatures) \
|
||||
zprop_register_mc_props_impl(ZPOOL_MC_PROPS_##uclass, \
|
||||
CLASS_##uclass, class_##lclass, sfeatures)
|
||||
/* END CSTYLED */
|
||||
|
||||
void
|
||||
zpool_prop_init(void)
|
||||
{
|
||||
@ -138,6 +173,20 @@ zpool_prop_init(void)
|
||||
zprop_register_number(ZPOOL_PROP_LAST_SCRUBBED_TXG,
|
||||
"last_scrubbed_txg", 0, PROP_READONLY, ZFS_TYPE_POOL, "<txg>",
|
||||
"LAST_SCRUBBED_TXG", B_FALSE, sfeatures);
|
||||
zprop_register_number(ZPOOL_PROP_AVAILABLE, "available", 0,
|
||||
PROP_READONLY, ZFS_TYPE_POOL, "<size>", "AVAIL", B_FALSE,
|
||||
sfeatures);
|
||||
zprop_register_number(ZPOOL_PROP_USABLE, "usable", 0, PROP_READONLY,
|
||||
ZFS_TYPE_POOL, "<size>", "USABLE", B_FALSE, sfeatures);
|
||||
zprop_register_number(ZPOOL_PROP_USED, "used", 0, PROP_READONLY,
|
||||
ZFS_TYPE_POOL, "<size>", "USED", B_FALSE, sfeatures);
|
||||
|
||||
zprop_register_mc_props(NORMAL, normal, sfeatures);
|
||||
zprop_register_mc_props(SPECIAL, special, sfeatures);
|
||||
zprop_register_mc_props(DEDUP, dedup, sfeatures);
|
||||
zprop_register_mc_props(LOG, log, sfeatures);
|
||||
zprop_register_mc_props(ELOG, elog, sfeatures);
|
||||
zprop_register_mc_props(SELOG, special_elog, sfeatures);
|
||||
|
||||
/* default number properties */
|
||||
zprop_register_number(ZPOOL_PROP_VERSION, "version", SPA_VERSION,
|
||||
|
||||
@ -808,6 +808,12 @@ metaslab_class_fragmentation(metaslab_class_t *mc)
|
||||
|
||||
spa_config_enter(mc->mc_spa, SCL_VDEV, FTAG, RW_READER);
|
||||
|
||||
uint64_t space = metaslab_class_get_space(mc);
|
||||
if (space == 0) {
|
||||
spa_config_exit(mc->mc_spa, SCL_VDEV, FTAG);
|
||||
return (ZFS_FRAG_INVALID);
|
||||
}
|
||||
|
||||
for (int c = 0; c < rvd->vdev_children; c++) {
|
||||
vdev_t *tvd = rvd->vdev_child[c];
|
||||
metaslab_group_t *mg = tvd->vdev_mg;
|
||||
@ -837,7 +843,7 @@ metaslab_class_fragmentation(metaslab_class_t *mc)
|
||||
fragmentation += mg->mg_fragmentation *
|
||||
metaslab_group_get_space(mg);
|
||||
}
|
||||
fragmentation /= metaslab_class_get_space(mc);
|
||||
fragmentation /= space;
|
||||
|
||||
ASSERT3U(fragmentation, <=, 100);
|
||||
spa_config_exit(mc->mc_spa, SCL_VDEV, FTAG);
|
||||
|
||||
@ -417,6 +417,44 @@ spa_prop_get_nvlist(spa_t *spa, char **props, unsigned int n_props,
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add metaslab class properties to an nvlist.
|
||||
*/
|
||||
static void
|
||||
spa_prop_add_metaslab_class(nvlist_t *nv, metaslab_class_t *mc,
|
||||
zpool_mc_props_t mcp, uint64_t *sizep, uint64_t *allocp, uint64_t *usablep,
|
||||
uint64_t *usedp)
|
||||
{
|
||||
uint64_t size = metaslab_class_get_space(mc);
|
||||
uint64_t alloc = metaslab_class_get_alloc(mc);
|
||||
uint64_t dsize = metaslab_class_get_dspace(mc);
|
||||
uint64_t dalloc = metaslab_class_get_dalloc(mc);
|
||||
uint64_t cap = (size == 0) ? 0 : (alloc * 100 / size);
|
||||
const zprop_source_t src = ZPROP_SRC_NONE;
|
||||
|
||||
spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_SIZE, NULL, size, src);
|
||||
spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_ALLOCATED, NULL, alloc, src);
|
||||
spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_USABLE, NULL, dsize, src);
|
||||
spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_USED, NULL, dalloc, src);
|
||||
spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_FRAGMENTATION, NULL,
|
||||
metaslab_class_fragmentation(mc), src);
|
||||
spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_EXPANDSZ, NULL,
|
||||
metaslab_class_expandable_space(mc), src);
|
||||
spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_FREE, NULL, size - alloc,
|
||||
src);
|
||||
spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_AVAILABLE, NULL,
|
||||
dsize - dalloc, src);
|
||||
spa_prop_add_list(nv, mcp + ZPOOL_MC_PROP_CAPACITY, NULL, cap, src);
|
||||
if (sizep != NULL)
|
||||
*sizep += size;
|
||||
if (allocp != NULL)
|
||||
*allocp += alloc;
|
||||
if (usablep != NULL)
|
||||
*usablep += dsize;
|
||||
if (usedp != NULL)
|
||||
*usedp += dalloc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a user property (source=src, propname=propval) to an nvlist.
|
||||
*/
|
||||
@ -441,7 +479,7 @@ spa_prop_get_config(spa_t *spa, nvlist_t *nv)
|
||||
{
|
||||
vdev_t *rvd = spa->spa_root_vdev;
|
||||
dsl_pool_t *pool = spa->spa_dsl_pool;
|
||||
uint64_t size, alloc, cap, version;
|
||||
uint64_t size, alloc, usable, used, cap, version;
|
||||
const zprop_source_t src = ZPROP_SRC_NONE;
|
||||
spa_config_dirent_t *dp;
|
||||
metaslab_class_t *mc = spa_normal_class(spa);
|
||||
@ -449,37 +487,42 @@ spa_prop_get_config(spa_t *spa, nvlist_t *nv)
|
||||
ASSERT(MUTEX_HELD(&spa->spa_props_lock));
|
||||
|
||||
if (rvd != NULL) {
|
||||
alloc = metaslab_class_get_alloc(mc);
|
||||
alloc += metaslab_class_get_alloc(spa_special_class(spa));
|
||||
alloc += metaslab_class_get_alloc(spa_dedup_class(spa));
|
||||
alloc += metaslab_class_get_alloc(spa_embedded_log_class(spa));
|
||||
alloc += metaslab_class_get_alloc(
|
||||
spa_special_embedded_log_class(spa));
|
||||
|
||||
size = metaslab_class_get_space(mc);
|
||||
size += metaslab_class_get_space(spa_special_class(spa));
|
||||
size += metaslab_class_get_space(spa_dedup_class(spa));
|
||||
size += metaslab_class_get_space(spa_embedded_log_class(spa));
|
||||
size += metaslab_class_get_space(
|
||||
spa_special_embedded_log_class(spa));
|
||||
|
||||
spa_prop_add_list(nv, ZPOOL_PROP_NAME, spa_name(spa), 0, src);
|
||||
|
||||
size = alloc = usable = used = 0;
|
||||
spa_prop_add_metaslab_class(nv, mc, ZPOOL_MC_PROPS_NORMAL,
|
||||
&size, &alloc, &usable, &used);
|
||||
spa_prop_add_metaslab_class(nv, spa_special_class(spa),
|
||||
ZPOOL_MC_PROPS_SPECIAL, &size, &alloc, &usable, &used);
|
||||
spa_prop_add_metaslab_class(nv, spa_dedup_class(spa),
|
||||
ZPOOL_MC_PROPS_DEDUP, &size, &alloc, &usable, &used);
|
||||
spa_prop_add_metaslab_class(nv, spa_log_class(spa),
|
||||
ZPOOL_MC_PROPS_LOG, NULL, NULL, NULL, NULL);
|
||||
spa_prop_add_metaslab_class(nv, spa_embedded_log_class(spa),
|
||||
ZPOOL_MC_PROPS_ELOG, &size, &alloc, &usable, &used);
|
||||
spa_prop_add_metaslab_class(nv,
|
||||
spa_special_embedded_log_class(spa), ZPOOL_MC_PROPS_SELOG,
|
||||
&size, &alloc, &usable, &used);
|
||||
|
||||
spa_prop_add_list(nv, ZPOOL_PROP_SIZE, NULL, size, src);
|
||||
spa_prop_add_list(nv, ZPOOL_PROP_ALLOCATED, NULL, alloc, src);
|
||||
spa_prop_add_list(nv, ZPOOL_PROP_FREE, NULL,
|
||||
size - alloc, src);
|
||||
spa_prop_add_list(nv, ZPOOL_PROP_CHECKPOINT, NULL,
|
||||
spa->spa_checkpoint_info.sci_dspace, src);
|
||||
|
||||
spa_prop_add_list(nv, ZPOOL_PROP_FRAGMENTATION, NULL,
|
||||
metaslab_class_fragmentation(mc), src);
|
||||
spa_prop_add_list(nv, ZPOOL_PROP_EXPANDSZ, NULL,
|
||||
metaslab_class_expandable_space(mc), src);
|
||||
spa_prop_add_list(nv, ZPOOL_PROP_READONLY, NULL,
|
||||
(spa_mode(spa) == SPA_MODE_READ), src);
|
||||
|
||||
cap = (size == 0) ? 0 : (alloc * 100 / size);
|
||||
spa_prop_add_list(nv, ZPOOL_PROP_CAPACITY, NULL, cap, src);
|
||||
spa_prop_add_list(nv, ZPOOL_PROP_AVAILABLE, NULL, usable - used,
|
||||
src);
|
||||
spa_prop_add_list(nv, ZPOOL_PROP_USABLE, NULL, usable, src);
|
||||
spa_prop_add_list(nv, ZPOOL_PROP_USED, NULL, used, src);
|
||||
|
||||
spa_prop_add_list(nv, ZPOOL_PROP_CHECKPOINT, NULL,
|
||||
spa->spa_checkpoint_info.sci_dspace, src);
|
||||
spa_prop_add_list(nv, ZPOOL_PROP_READONLY, NULL,
|
||||
(spa_mode(spa) == SPA_MODE_READ), src);
|
||||
|
||||
spa_prop_add_list(nv, ZPOOL_PROP_DEDUPRATIO, NULL,
|
||||
ddt_get_pool_dedup_ratio(spa), src);
|
||||
|
||||
@ -456,8 +456,8 @@ tags = ['functional', 'cli_root', 'zpool_export']
|
||||
|
||||
[tests/functional/cli_root/zpool_get]
|
||||
tests = ['zpool_get_001_pos', 'zpool_get_002_pos', 'zpool_get_003_pos',
|
||||
'zpool_get_004_neg', 'zpool_get_005_pos', 'vdev_get_001_pos',
|
||||
'vdev_get_all']
|
||||
'zpool_get_004_neg', 'zpool_get_005_pos', 'zpool_get_006_pos',
|
||||
'vdev_get_001_pos', 'vdev_get_all']
|
||||
tags = ['functional', 'cli_root', 'zpool_get']
|
||||
|
||||
[tests/functional/cli_root/zpool_history]
|
||||
|
||||
@ -1132,6 +1132,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
||||
functional/cli_root/zpool_get/zpool_get_003_pos.ksh \
|
||||
functional/cli_root/zpool_get/zpool_get_004_neg.ksh \
|
||||
functional/cli_root/zpool_get/zpool_get_005_pos.ksh \
|
||||
functional/cli_root/zpool_get/zpool_get_006_pos.ksh \
|
||||
functional/cli_root/zpool_history/cleanup.ksh \
|
||||
functional/cli_root/zpool_history/setup.ksh \
|
||||
functional/cli_root/zpool_history/zpool_history_001_neg.ksh \
|
||||
|
||||
@ -67,6 +67,63 @@ typeset -a properties=(
|
||||
"last_scrubbed_txg"
|
||||
"dedupused"
|
||||
"dedupsaved"
|
||||
"available"
|
||||
"usable"
|
||||
"used"
|
||||
"class_normal_size"
|
||||
"class_normal_capacity"
|
||||
"class_normal_free"
|
||||
"class_normal_allocated"
|
||||
"class_normal_available"
|
||||
"class_normal_usable"
|
||||
"class_normal_used"
|
||||
"class_normal_expandsize"
|
||||
"class_normal_fragmentation"
|
||||
"class_special_size"
|
||||
"class_special_capacity"
|
||||
"class_special_free"
|
||||
"class_special_allocated"
|
||||
"class_special_available"
|
||||
"class_special_usable"
|
||||
"class_special_used"
|
||||
"class_special_expandsize"
|
||||
"class_special_fragmentation"
|
||||
"class_dedup_size"
|
||||
"class_dedup_capacity"
|
||||
"class_dedup_free"
|
||||
"class_dedup_allocated"
|
||||
"class_dedup_available"
|
||||
"class_dedup_usable"
|
||||
"class_dedup_used"
|
||||
"class_dedup_expandsize"
|
||||
"class_dedup_fragmentation"
|
||||
"class_log_size"
|
||||
"class_log_capacity"
|
||||
"class_log_free"
|
||||
"class_log_allocated"
|
||||
"class_log_available"
|
||||
"class_log_usable"
|
||||
"class_log_used"
|
||||
"class_log_expandsize"
|
||||
"class_log_fragmentation"
|
||||
"class_elog_size"
|
||||
"class_elog_capacity"
|
||||
"class_elog_free"
|
||||
"class_elog_allocated"
|
||||
"class_elog_available"
|
||||
"class_elog_usable"
|
||||
"class_elog_used"
|
||||
"class_elog_expandsize"
|
||||
"class_elog_fragmentation"
|
||||
"class_special_elog_size"
|
||||
"class_special_elog_capacity"
|
||||
"class_special_elog_free"
|
||||
"class_special_elog_allocated"
|
||||
"class_special_elog_available"
|
||||
"class_special_elog_usable"
|
||||
"class_special_elog_used"
|
||||
"class_special_elog_expandsize"
|
||||
"class_special_elog_fragmentation"
|
||||
"feature@async_destroy"
|
||||
"feature@empty_bpobj"
|
||||
"feature@lz4_compress"
|
||||
|
||||
@ -47,6 +47,8 @@ if ! is_global_zone ; then
|
||||
fi
|
||||
|
||||
typeset -i i=0
|
||||
typeset class="@(normal|special|dedup|log|elog|special_elog)"
|
||||
typeset optclass="@(special|dedup|log|elog|special_elog)"
|
||||
|
||||
while [[ $i -lt "${#properties[@]}" ]]; do
|
||||
log_note "Checking for parsable ${properties[$i]} property"
|
||||
@ -61,10 +63,14 @@ while [[ $i -lt "${#properties[@]}" ]]; do
|
||||
|
||||
# All properties must be positive integers in order to be
|
||||
# parsable (i.e. a return code of 0 or 1 from expr above).
|
||||
# The only exception is "expandsize", which may be "-".
|
||||
if [[ ! ($? -eq 0 || $? -eq 1 || \
|
||||
("${properties[$i]}" = "expandsize" && "$v" = "-")) ]]; then
|
||||
log_fail "${properties[$i]} is not parsable"
|
||||
# The only exceptions are "expandsize", "class_<class>_expandsize",
|
||||
# and "class_<optclass>_fragmentation", which may be "-".
|
||||
if [[ ! ($? -eq 0 || $? -eq 1) ]]; then
|
||||
case "${properties[$i]}" in
|
||||
?(class_${class}_)expandsize) ;&
|
||||
class_${optclass}_fragmentation) ;;
|
||||
*) log_fail "${properties[$i]} is not parsable"
|
||||
esac
|
||||
fi
|
||||
|
||||
i=$(( $i + 1 ))
|
||||
|
||||
416
tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_006_pos.ksh
Executable file
416
tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get_006_pos.ksh
Executable file
@ -0,0 +1,416 @@
|
||||
#!/bin/ksh -p
|
||||
# SPDX-License-Identifier: CDDL-1.0
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2026 Klara, Inc.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
#
|
||||
# Several zpool properties exist to expose metaslab allocation class space
|
||||
# accounting.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create a pool with raidz (to validate expansion and deflation metrics).
|
||||
# 2. For each allocation class:
|
||||
# - Add any required vdevs for this allocation class.
|
||||
# - Prepare a dataset configured to utilize this allocation class.
|
||||
# - Validate metrics reported by pool properties for allocation classes.
|
||||
# 3. For the whole pool, confirm that AVAIL, USABLE and USED report reasonable
|
||||
# values.
|
||||
#
|
||||
|
||||
bs=128K
|
||||
count=100
|
||||
|
||||
function writefile
|
||||
{
|
||||
dd if=/dev/urandom of=$1 bs=$bs count=$count 2>/dev/null
|
||||
}
|
||||
|
||||
nfiles=5
|
||||
|
||||
function writefiles # datadir [nfiles]
|
||||
{
|
||||
typeset datadir=$1
|
||||
typeset -i n=${2:-$nfiles}
|
||||
|
||||
for i in {1..$n}; do
|
||||
log_must writefile $TESTDIR/$datadir/file$i
|
||||
done
|
||||
}
|
||||
|
||||
pool=$TESTPOOL1
|
||||
|
||||
function get_class_prop
|
||||
{
|
||||
get_pool_prop "class_${1}_${2}" $pool
|
||||
}
|
||||
|
||||
# Wrapper for test to give more context to logs
|
||||
function check
|
||||
{
|
||||
shift 2 # class prop (test args)
|
||||
test "$@"
|
||||
}
|
||||
|
||||
function check_raidz_used # [mincap=1]
|
||||
{
|
||||
typeset -i mincap=${1:-1}
|
||||
|
||||
log_must check $class size $size -gt 0
|
||||
log_must check $class capacity $cap -ge $mincap -a $cap -le 100
|
||||
log_must check $class free $free -gt 0 -a $free -lt $size
|
||||
log_must check $class allocated $alloc -gt 0 -a $alloc -lt $size
|
||||
log_must check $class available $avail -gt 0 -a $avail -lt $free
|
||||
log_must check $class usable $usable -gt 0 -a $usable -lt $size
|
||||
log_must check $class used $used -gt 0 -a $used -lt $alloc
|
||||
log_must check $class expandsize $expandsz = "-"
|
||||
log_must check $class fragmentation $frag -lt 50
|
||||
}
|
||||
|
||||
function check_raidz_unused
|
||||
{
|
||||
log_must check $class size $size -gt 0
|
||||
log_must check $class capacity $cap -eq 0
|
||||
log_must check $class free $free -eq $size
|
||||
log_must check $class allocated $alloc -eq 0
|
||||
log_must check $class available $avail -gt 0 -a $avail -lt $free
|
||||
log_must check $class usable $usable -gt 0 -a $usable -lt $size
|
||||
log_must check $class used $used -eq 0
|
||||
log_must check $class expandsize $expandsz = "-"
|
||||
log_must check $class fragmentation $frag -eq 0
|
||||
}
|
||||
|
||||
function check_nonraidz_used # [mincap=1]
|
||||
{
|
||||
typeset -i mincap=${1:-1}
|
||||
|
||||
log_must check $class size $size -gt 0
|
||||
log_must check $class capacity $cap -ge $mincap -a $cap -le 100
|
||||
log_must check $class free $free -gt 0 -a $free -lt $size
|
||||
log_must check $class allocated $alloc -gt 0 -a $alloc -lt $size
|
||||
log_must check $class available $avail -eq $free
|
||||
log_must check $class usable $usable -eq $size
|
||||
log_must check $class used $used -eq $alloc
|
||||
log_must check $class expandsize $expandsz = "-"
|
||||
log_must check $class fragmentation $frag -lt 50
|
||||
}
|
||||
|
||||
function check_nonraidz_unused
|
||||
{
|
||||
log_must check $class size $size -gt 0
|
||||
log_must check $class capacity $cap -eq 0
|
||||
log_must check $class free $free -eq $size
|
||||
log_must check $class allocated $alloc -eq 0
|
||||
log_must check $class available $avail -eq $free
|
||||
log_must check $class usable $usable -eq $size
|
||||
log_must check $class used $used -eq $alloc
|
||||
log_must check $class expandsize $expandsz = "-"
|
||||
log_must check $class fragmentation $frag -eq 0
|
||||
}
|
||||
|
||||
# Log capacity tends to be >0% but <1% in these tests, so gets reported as 0.
|
||||
# Let that slide and rely on allocated/free checks for sanity, rather than
|
||||
# trying to tweak txg sync parameters to widen the race window.
|
||||
|
||||
function check_raidz_log_used
|
||||
{
|
||||
check_raidz_used 0
|
||||
}
|
||||
|
||||
function check_nonraidz_log_used
|
||||
{
|
||||
check_nonraidz_used 0
|
||||
}
|
||||
|
||||
function check_unavailable
|
||||
{
|
||||
log_must check $class size $size -eq 0
|
||||
log_must check $class capacity $cap -eq 0
|
||||
log_must check $class free $free -eq 0
|
||||
log_must check $class allocated $alloc -eq 0
|
||||
log_must check $class available $avail -eq 0
|
||||
log_must check $class usable $usable -eq 0
|
||||
log_must check $class used $used -eq 0
|
||||
log_must check $class expandsize $expandsz = "-"
|
||||
log_must check $class fragmentation $frag = "-"
|
||||
}
|
||||
|
||||
typeset -a classes=("normal" "special" "dedup" "log" "elog" "special_elog")
|
||||
|
||||
normal_vdevs=$(seq -f $TEST_BASE_DIR/normal-vdev-%g 3)
|
||||
normal_vdev_size=$((1 << 30)) # 1 GiB
|
||||
|
||||
special_vdevs=$(seq -f $TEST_BASE_DIR/special-vdev-%g 3)
|
||||
special_vdev_size=$((512 << 20)) # 512 MiB
|
||||
|
||||
# Use a mirror for dedup to test expandsize.
|
||||
dedup_vdevs=$(seq -f $TEST_BASE_DIR/dedup-vdev-%g 2)
|
||||
dedup_vdev_size=$((256 << 20)) # 256 MiB
|
||||
|
||||
# The log class can't be raided or expanded, so we only need one vdev.
|
||||
log_vdev="$TEST_BASE_DIR/log-vdev"
|
||||
log_vdev_size=$((128 << 20)) # 128 MiB
|
||||
|
||||
embedded_slog_min_ms=$(get_tunable EMBEDDED_SLOG_MIN_MS)
|
||||
|
||||
function cleanup
|
||||
{
|
||||
zpool destroy -f $pool
|
||||
rm -f $normal_vdevs $normal_expand_vdev
|
||||
rm -f $special_vdevs $special_expand_vdev
|
||||
rm -f $dedup_vdevs $dedup_expand_vdev
|
||||
rm -f $log_vdev
|
||||
set_tunable32 EMBEDDED_SLOG_MIN_MS $embedded_slog_min_ms
|
||||
}
|
||||
log_onexit cleanup
|
||||
|
||||
log_assert "zpool allocation class properties report metrics correctly"
|
||||
|
||||
# Lower the threshold for provisioning embedded log metaslabs on small vdevs.
|
||||
log_must set_tunable32 EMBEDDED_SLOG_MIN_MS 8
|
||||
|
||||
log_must truncate -s $normal_vdev_size $normal_vdevs
|
||||
log_must zpool create $pool \
|
||||
raidz $normal_vdevs
|
||||
log_must zfs set mountpoint=$TESTDIR $pool
|
||||
|
||||
log_note "Normal Class"
|
||||
log_must zfs create \
|
||||
$pool/normal
|
||||
writefiles normal
|
||||
sync_pool $pool
|
||||
for class in "${classes[@]}"; do
|
||||
typeset -il size=$(get_class_prop $class size)
|
||||
typeset -i cap=$(get_class_prop $class capacity)
|
||||
typeset -il free=$(get_class_prop $class free)
|
||||
typeset -il alloc=$(get_class_prop $class allocated)
|
||||
typeset -il avail=$(get_class_prop $class available)
|
||||
typeset -il usable=$(get_class_prop $class usable)
|
||||
typeset -il used=$(get_class_prop $class used)
|
||||
typeset expandsz=$(get_class_prop $class expandsize)
|
||||
typeset frag=$(get_class_prop $class fragmentation)
|
||||
case $class in
|
||||
normal)
|
||||
check_raidz_used
|
||||
;;
|
||||
elog)
|
||||
check_raidz_unused
|
||||
;;
|
||||
*)
|
||||
check_unavailable
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
log_note "Embedded Log Class"
|
||||
log_must zfs create \
|
||||
-o sync=always \
|
||||
$pool/elog
|
||||
writefiles elog
|
||||
for class in "${classes[@]}"; do
|
||||
typeset -il size=$(get_class_prop $class size)
|
||||
typeset -i cap=$(get_class_prop $class capacity)
|
||||
typeset -il free=$(get_class_prop $class free)
|
||||
typeset -il alloc=$(get_class_prop $class allocated)
|
||||
typeset -il avail=$(get_class_prop $class available)
|
||||
typeset -il usable=$(get_class_prop $class usable)
|
||||
typeset -il used=$(get_class_prop $class used)
|
||||
typeset expandsz=$(get_class_prop $class expandsize)
|
||||
typeset frag=$(get_class_prop $class fragmentation)
|
||||
case $class in
|
||||
normal)
|
||||
check_raidz_used
|
||||
;;
|
||||
elog)
|
||||
check_raidz_log_used
|
||||
;;
|
||||
*)
|
||||
check_unavailable
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
log_note "Special Class"
|
||||
log_must truncate -s $special_vdev_size $special_vdevs
|
||||
log_must zpool add $pool \
|
||||
special raidz $special_vdevs
|
||||
log_must zfs create \
|
||||
-o recordsize=32K -o special_small_blocks=32K \
|
||||
$pool/special
|
||||
writefiles special
|
||||
sync_pool $pool
|
||||
for class in "${classes[@]}"; do
|
||||
typeset -il size=$(get_class_prop $class size)
|
||||
typeset -i cap=$(get_class_prop $class capacity)
|
||||
typeset -il free=$(get_class_prop $class free)
|
||||
typeset -il alloc=$(get_class_prop $class allocated)
|
||||
typeset -il avail=$(get_class_prop $class available)
|
||||
typeset -il usable=$(get_class_prop $class usable)
|
||||
typeset -il used=$(get_class_prop $class used)
|
||||
typeset expandsz=$(get_class_prop $class expandsize)
|
||||
typeset frag=$(get_class_prop $class fragmentation)
|
||||
case $class in
|
||||
normal|special)
|
||||
check_raidz_used
|
||||
;;
|
||||
elog)
|
||||
check_raidz_log_used
|
||||
;;
|
||||
special_elog)
|
||||
check_raidz_unused
|
||||
;;
|
||||
*)
|
||||
check_unavailable
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
log_note "Special Embedded Log Class"
|
||||
log_must zfs create \
|
||||
-o recordsize=32K -o special_small_blocks=32K \
|
||||
-o sync=always \
|
||||
$pool/special_elog
|
||||
writefiles special_elog
|
||||
for class in "${classes[@]}"; do
|
||||
typeset -il size=$(get_class_prop $class size)
|
||||
typeset -i cap=$(get_class_prop $class capacity)
|
||||
typeset -il free=$(get_class_prop $class free)
|
||||
typeset -il alloc=$(get_class_prop $class allocated)
|
||||
typeset -il avail=$(get_class_prop $class available)
|
||||
typeset -il usable=$(get_class_prop $class usable)
|
||||
typeset -il used=$(get_class_prop $class used)
|
||||
typeset expandsz=$(get_class_prop $class expandsize)
|
||||
typeset frag=$(get_class_prop $class fragmentation)
|
||||
case $class in
|
||||
normal|special)
|
||||
check_raidz_used
|
||||
;;
|
||||
elog|special_elog)
|
||||
check_raidz_log_used
|
||||
;;
|
||||
*)
|
||||
check_unavailable
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
log_note "Log Class"
|
||||
log_must truncate -s $log_vdev_size $log_vdev
|
||||
log_must zpool add $pool \
|
||||
log $log_vdev
|
||||
log_must zfs create \
|
||||
-o sync=always \
|
||||
$pool/log
|
||||
writefiles log
|
||||
for class in "${classes[@]}"; do
|
||||
typeset -il size=$(get_class_prop $class size)
|
||||
typeset -i cap=$(get_class_prop $class capacity)
|
||||
typeset -il free=$(get_class_prop $class free)
|
||||
typeset -il alloc=$(get_class_prop $class allocated)
|
||||
typeset -il avail=$(get_class_prop $class available)
|
||||
typeset -il usable=$(get_class_prop $class usable)
|
||||
typeset -il used=$(get_class_prop $class used)
|
||||
typeset expandsz=$(get_class_prop $class expandsize)
|
||||
typeset frag=$(get_class_prop $class fragmentation)
|
||||
case $class in
|
||||
normal|special)
|
||||
check_raidz_used
|
||||
;;
|
||||
elog|special_elog)
|
||||
check_raidz_log_used
|
||||
;;
|
||||
log)
|
||||
check_nonraidz_log_used
|
||||
;;
|
||||
*)
|
||||
check_unavailable
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
log_note "Dedup Class"
|
||||
log_must truncate -s $dedup_vdev_size $dedup_vdevs
|
||||
log_must zpool add $pool \
|
||||
dedup mirror $dedup_vdevs
|
||||
log_must zfs create \
|
||||
-o dedup=on -o recordsize=4k \
|
||||
$pool/dedup
|
||||
writefiles dedup $((3 * nfiles))
|
||||
sync_pool $pool
|
||||
for class in "${classes[@]}"; do
|
||||
typeset -il size=$(get_class_prop $class size)
|
||||
typeset -i cap=$(get_class_prop $class capacity)
|
||||
typeset -il free=$(get_class_prop $class free)
|
||||
typeset -il alloc=$(get_class_prop $class allocated)
|
||||
typeset -il avail=$(get_class_prop $class available)
|
||||
typeset -il usable=$(get_class_prop $class usable)
|
||||
typeset -il used=$(get_class_prop $class used)
|
||||
typeset expandsz=$(get_class_prop $class expandsize)
|
||||
typeset frag=$(get_class_prop $class fragmentation)
|
||||
case $class in
|
||||
normal|special)
|
||||
check_raidz_used
|
||||
;;
|
||||
elog|special_elog)
|
||||
check_raidz_log_used
|
||||
;;
|
||||
log)
|
||||
check_nonraidz_log_used
|
||||
;;
|
||||
dedup)
|
||||
check_nonraidz_used
|
||||
;;
|
||||
*)
|
||||
log_fail "unhandled class: $class"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Expansion
|
||||
typeset -il delta=$((32 << 20)) # 32 MiB
|
||||
log_must truncate -s $((dedup_vdev_size + delta)) $dedup_vdevs
|
||||
typeset -a vdevs=($dedup_vdevs)
|
||||
log_must zpool online -e $pool ${vdevs[0]}
|
||||
typeset -il size=$(get_class_prop dedup size)
|
||||
typeset -il expandsz=$(get_class_prop dedup expandsize)
|
||||
log_must test $expandsz -eq $delta
|
||||
|
||||
# Pool-wide AVAIL/USABLE/USED
|
||||
typeset -il free=$(get_pool_prop free $pool)
|
||||
typeset -il avail=$(get_pool_prop available $pool)
|
||||
log_must test $avail -gt 0 -a $avail -lt $free
|
||||
typeset -il size=$(get_pool_prop size $pool)
|
||||
typeset -il usable=$(get_pool_prop usable $pool)
|
||||
log_must test $usable -gt 0 -a $usable -lt $size
|
||||
typeset -il alloc=$(get_pool_prop alloc $pool)
|
||||
typeset -il used=$(get_pool_prop used $pool)
|
||||
log_must test $used -gt 0 -a $used -lt $alloc
|
||||
|
||||
cleanup
|
||||
@ -29,6 +29,75 @@
|
||||
# Copyright (c) 2013, 2014 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
# Set the expected properties of zpool
|
||||
typeset -a properties=("allocated" "bcloneused" "bclonesaved" "capacity"
|
||||
"dedupused" "dedupsaved" "expandsize" "free" "freeing" "leaked" "size")
|
||||
# Set the expected parsable properties of zpool
|
||||
typeset -a properties=(
|
||||
"size"
|
||||
"capacity"
|
||||
"free"
|
||||
"allocated"
|
||||
"expandsize"
|
||||
"freeing"
|
||||
"fragmentation"
|
||||
"leaked"
|
||||
"bcloneused"
|
||||
"bclonesaved"
|
||||
"dedupused"
|
||||
"dedupsaved"
|
||||
"available"
|
||||
"usable"
|
||||
"used"
|
||||
"class_normal_size"
|
||||
"class_normal_capacity"
|
||||
"class_normal_free"
|
||||
"class_normal_allocated"
|
||||
"class_normal_available"
|
||||
"class_normal_usable"
|
||||
"class_normal_used"
|
||||
"class_normal_expandsize"
|
||||
"class_normal_fragmentation"
|
||||
"class_special_size"
|
||||
"class_special_capacity"
|
||||
"class_special_free"
|
||||
"class_special_allocated"
|
||||
"class_special_available"
|
||||
"class_special_usable"
|
||||
"class_special_used"
|
||||
"class_special_expandsize"
|
||||
"class_special_fragmentation"
|
||||
"class_dedup_size"
|
||||
"class_dedup_capacity"
|
||||
"class_dedup_free"
|
||||
"class_dedup_allocated"
|
||||
"class_dedup_available"
|
||||
"class_dedup_usable"
|
||||
"class_dedup_used"
|
||||
"class_dedup_expandsize"
|
||||
"class_dedup_fragmentation"
|
||||
"class_log_size"
|
||||
"class_log_capacity"
|
||||
"class_log_free"
|
||||
"class_log_allocated"
|
||||
"class_log_available"
|
||||
"class_log_usable"
|
||||
"class_log_used"
|
||||
"class_log_expandsize"
|
||||
"class_log_fragmentation"
|
||||
"class_elog_size"
|
||||
"class_elog_capacity"
|
||||
"class_elog_free"
|
||||
"class_elog_allocated"
|
||||
"class_elog_available"
|
||||
"class_elog_usable"
|
||||
"class_elog_used"
|
||||
"class_elog_expandsize"
|
||||
"class_elog_fragmentation"
|
||||
"class_special_elog_size"
|
||||
"class_special_elog_capacity"
|
||||
"class_special_elog_free"
|
||||
"class_special_elog_allocated"
|
||||
"class_special_elog_available"
|
||||
"class_special_elog_usable"
|
||||
"class_special_elog_used"
|
||||
"class_special_elog_expandsize"
|
||||
"class_special_elog_fragmentation"
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user