mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-23 02:44:41 +03:00
Vdev Properties Feature
Add properties, similar to pool properties, to each vdev. This makes use of the existing per-vdev ZAP that was added as part of device evacuation/removal. A large number of read-only properties are exposed, many of the members of struct vdev_t, that provide useful statistics. Adds support for read-only "removing" vdev property. Adds the "allocating" property that defaults to "on" and can be set to "off" to prevent future allocations from that top-level vdev. Supports user-defined vdev properties. Includes support for properties.vdev in SYSFS. Co-authored-by: Allan Jude <allan@klarasystems.com> Co-authored-by: Mark Maybee <mark.maybee@delphix.com> Reviewed-by: Matthew Ahrens <mahrens@delphix.com> Reviewed-by: Mark Maybee <mark.maybee@delphix.com> Signed-off-by: Allan Jude <allan@klarasystems.com> Closes #11711
This commit is contained in:
@@ -723,18 +723,6 @@ zfs_name_to_prop(const char *propname)
|
||||
return (zprop_name_to_prop(propname, ZFS_TYPE_DATASET));
|
||||
}
|
||||
|
||||
/*
|
||||
* For user property names, we allow all lowercase alphanumeric characters, plus
|
||||
* a few useful punctuation characters.
|
||||
*/
|
||||
static int
|
||||
valid_char(char c)
|
||||
{
|
||||
return ((c >= 'a' && c <= 'z') ||
|
||||
(c >= '0' && c <= '9') ||
|
||||
c == '-' || c == '_' || c == '.' || c == ':');
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if this is a valid user-defined property (one with a ':').
|
||||
*/
|
||||
@@ -747,7 +735,7 @@ zfs_prop_user(const char *name)
|
||||
|
||||
for (i = 0; i < strlen(name); i++) {
|
||||
c = name[i];
|
||||
if (!valid_char(c))
|
||||
if (!zprop_valid_char(c))
|
||||
return (B_FALSE);
|
||||
if (c == ':')
|
||||
foundsep = B_TRUE;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2012, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
|
||||
* Copyright (c) 2021, Klara Inc.
|
||||
*/
|
||||
|
||||
#include <sys/zio.h>
|
||||
@@ -40,6 +41,7 @@
|
||||
#endif
|
||||
|
||||
static zprop_desc_t zpool_prop_table[ZPOOL_NUM_PROPS];
|
||||
static zprop_desc_t vdev_prop_table[VDEV_NUM_PROPS];
|
||||
|
||||
zprop_desc_t *
|
||||
zpool_prop_get_table(void)
|
||||
@@ -260,12 +262,249 @@ zpool_prop_align_right(zpool_prop_t prop)
|
||||
}
|
||||
#endif
|
||||
|
||||
zprop_desc_t *
|
||||
vdev_prop_get_table(void)
|
||||
{
|
||||
return (vdev_prop_table);
|
||||
}
|
||||
|
||||
void
|
||||
vdev_prop_init(void)
|
||||
{
|
||||
static zprop_index_t boolean_table[] = {
|
||||
{ "off", 0},
|
||||
{ "on", 1},
|
||||
{ NULL }
|
||||
};
|
||||
static zprop_index_t boolean_na_table[] = {
|
||||
{ "off", 0},
|
||||
{ "on", 1},
|
||||
{ "-", 2}, /* ZPROP_BOOLEAN_NA */
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
/* string properties */
|
||||
zprop_register_string(VDEV_PROP_COMMENT, "comment", NULL,
|
||||
PROP_DEFAULT, ZFS_TYPE_VDEV, "<comment-string>", "COMMENT");
|
||||
zprop_register_string(VDEV_PROP_PATH, "path", NULL,
|
||||
PROP_DEFAULT, ZFS_TYPE_VDEV, "<device-path>", "PATH");
|
||||
zprop_register_string(VDEV_PROP_DEVID, "devid", NULL,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<devid>", "DEVID");
|
||||
zprop_register_string(VDEV_PROP_PHYS_PATH, "physpath", NULL,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<physpath>", "PHYSPATH");
|
||||
zprop_register_string(VDEV_PROP_ENC_PATH, "encpath", NULL,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<encpath>", "ENCPATH");
|
||||
zprop_register_string(VDEV_PROP_FRU, "fru", NULL,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<fru>", "FRU");
|
||||
zprop_register_string(VDEV_PROP_PARENT, "parent", NULL,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<parent>", "PARENT");
|
||||
zprop_register_string(VDEV_PROP_CHILDREN, "children", NULL,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<child[,...]>", "CHILDREN");
|
||||
|
||||
/* readonly number properties */
|
||||
zprop_register_number(VDEV_PROP_SIZE, "size", 0, PROP_READONLY,
|
||||
ZFS_TYPE_VDEV, "<size>", "SIZE");
|
||||
zprop_register_number(VDEV_PROP_FREE, "free", 0, PROP_READONLY,
|
||||
ZFS_TYPE_VDEV, "<size>", "FREE");
|
||||
zprop_register_number(VDEV_PROP_ALLOCATED, "allocated", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<size>", "ALLOC");
|
||||
zprop_register_number(VDEV_PROP_EXPANDSZ, "expandsize", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<size>", "EXPANDSZ");
|
||||
zprop_register_number(VDEV_PROP_FRAGMENTATION, "fragmentation", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<percent>", "FRAG");
|
||||
zprop_register_number(VDEV_PROP_CAPACITY, "capacity", 0, PROP_READONLY,
|
||||
ZFS_TYPE_VDEV, "<size>", "CAP");
|
||||
zprop_register_number(VDEV_PROP_GUID, "guid", 0, PROP_READONLY,
|
||||
ZFS_TYPE_VDEV, "<guid>", "GUID");
|
||||
zprop_register_number(VDEV_PROP_STATE, "state", 0, PROP_READONLY,
|
||||
ZFS_TYPE_VDEV, "<state>", "STATE");
|
||||
zprop_register_number(VDEV_PROP_BOOTSIZE, "bootsize", 0, PROP_READONLY,
|
||||
ZFS_TYPE_VDEV, "<size>", "BOOTSIZE");
|
||||
zprop_register_number(VDEV_PROP_ASIZE, "asize", 0, PROP_READONLY,
|
||||
ZFS_TYPE_VDEV, "<asize>", "ASIZE");
|
||||
zprop_register_number(VDEV_PROP_PSIZE, "psize", 0, PROP_READONLY,
|
||||
ZFS_TYPE_VDEV, "<psize>", "PSIZE");
|
||||
zprop_register_number(VDEV_PROP_ASHIFT, "ashift", 0, PROP_READONLY,
|
||||
ZFS_TYPE_VDEV, "<ashift>", "ASHIFT");
|
||||
zprop_register_number(VDEV_PROP_PARITY, "parity", 0, PROP_READONLY,
|
||||
ZFS_TYPE_VDEV, "<parity>", "PARITY");
|
||||
zprop_register_number(VDEV_PROP_NUMCHILDREN, "numchildren", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<number-of-children>", "NUMCHILD");
|
||||
zprop_register_number(VDEV_PROP_READ_ERRORS, "read_errors", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<errors>", "RDERR");
|
||||
zprop_register_number(VDEV_PROP_WRITE_ERRORS, "write_errors", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<errors>", "WRERR");
|
||||
zprop_register_number(VDEV_PROP_CHECKSUM_ERRORS, "checksum_errors", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<errors>", "CKERR");
|
||||
zprop_register_number(VDEV_PROP_INITIALIZE_ERRORS,
|
||||
"initialize_errors", 0, PROP_READONLY, ZFS_TYPE_VDEV, "<errors>",
|
||||
"INITERR");
|
||||
zprop_register_number(VDEV_PROP_OPS_NULL, "null_ops", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<operations>", "NULLOP");
|
||||
zprop_register_number(VDEV_PROP_OPS_READ, "read_ops", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<operations>", "READOP");
|
||||
zprop_register_number(VDEV_PROP_OPS_WRITE, "write_ops", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<operations>", "WRITEOP");
|
||||
zprop_register_number(VDEV_PROP_OPS_FREE, "free_ops", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<operations>", "FREEOP");
|
||||
zprop_register_number(VDEV_PROP_OPS_CLAIM, "claim_ops", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<operations>", "CLAIMOP");
|
||||
zprop_register_number(VDEV_PROP_OPS_TRIM, "trim_ops", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<operations>", "TRIMOP");
|
||||
zprop_register_number(VDEV_PROP_BYTES_NULL, "null_bytes", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<bytes>", "NULLBYTE");
|
||||
zprop_register_number(VDEV_PROP_BYTES_READ, "read_bytes", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<bytes>", "READBYTE");
|
||||
zprop_register_number(VDEV_PROP_BYTES_WRITE, "write_bytes", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<bytes>", "WRITEBYTE");
|
||||
zprop_register_number(VDEV_PROP_BYTES_FREE, "free_bytes", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<bytes>", "FREEBYTE");
|
||||
zprop_register_number(VDEV_PROP_BYTES_CLAIM, "claim_bytes", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<bytes>", "CLAIMBYTE");
|
||||
zprop_register_number(VDEV_PROP_BYTES_TRIM, "trim_bytes", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "<bytes>", "TRIMBYTE");
|
||||
|
||||
/* default numeric properties */
|
||||
|
||||
/* default index (boolean) properties */
|
||||
zprop_register_index(VDEV_PROP_REMOVING, "removing", 0,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "on | off", "REMOVING",
|
||||
boolean_table);
|
||||
zprop_register_index(VDEV_PROP_ALLOCATING, "allocating", 1,
|
||||
PROP_DEFAULT, ZFS_TYPE_VDEV, "on | off", "ALLOCATING",
|
||||
boolean_na_table);
|
||||
|
||||
/* default index properties */
|
||||
|
||||
/* hidden properties */
|
||||
zprop_register_hidden(VDEV_PROP_NAME, "name", PROP_TYPE_STRING,
|
||||
PROP_READONLY, ZFS_TYPE_VDEV, "NAME");
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a property name and its type, returns the corresponding property ID.
|
||||
*/
|
||||
vdev_prop_t
|
||||
vdev_name_to_prop(const char *propname)
|
||||
{
|
||||
return (zprop_name_to_prop(propname, ZFS_TYPE_VDEV));
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if this is a valid user-defined property (one with a ':').
|
||||
*/
|
||||
boolean_t
|
||||
vdev_prop_user(const char *name)
|
||||
{
|
||||
int i;
|
||||
char c;
|
||||
boolean_t foundsep = B_FALSE;
|
||||
|
||||
for (i = 0; i < strlen(name); i++) {
|
||||
c = name[i];
|
||||
if (!zprop_valid_char(c))
|
||||
return (B_FALSE);
|
||||
if (c == ':')
|
||||
foundsep = B_TRUE;
|
||||
}
|
||||
|
||||
return (foundsep);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a pool property ID, returns the corresponding name.
|
||||
* Assuming the pool property ID is valid.
|
||||
*/
|
||||
const char *
|
||||
vdev_prop_to_name(vdev_prop_t prop)
|
||||
{
|
||||
return (vdev_prop_table[prop].pd_name);
|
||||
}
|
||||
|
||||
zprop_type_t
|
||||
vdev_prop_get_type(vdev_prop_t prop)
|
||||
{
|
||||
return (vdev_prop_table[prop].pd_proptype);
|
||||
}
|
||||
|
||||
boolean_t
|
||||
vdev_prop_readonly(vdev_prop_t prop)
|
||||
{
|
||||
return (vdev_prop_table[prop].pd_attr == PROP_READONLY);
|
||||
}
|
||||
|
||||
const char *
|
||||
vdev_prop_default_string(vdev_prop_t prop)
|
||||
{
|
||||
return (vdev_prop_table[prop].pd_strdefault);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
vdev_prop_default_numeric(vdev_prop_t prop)
|
||||
{
|
||||
return (vdev_prop_table[prop].pd_numdefault);
|
||||
}
|
||||
|
||||
int
|
||||
vdev_prop_string_to_index(vdev_prop_t prop, const char *string,
|
||||
uint64_t *index)
|
||||
{
|
||||
return (zprop_string_to_index(prop, string, index, ZFS_TYPE_VDEV));
|
||||
}
|
||||
|
||||
int
|
||||
vdev_prop_index_to_string(vdev_prop_t prop, uint64_t index,
|
||||
const char **string)
|
||||
{
|
||||
return (zprop_index_to_string(prop, index, string, ZFS_TYPE_VDEV));
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if this is a valid vdev property.
|
||||
*/
|
||||
boolean_t
|
||||
zpool_prop_vdev(const char *name)
|
||||
{
|
||||
return (vdev_name_to_prop(name) != VDEV_PROP_INVAL);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
vdev_prop_random_value(vdev_prop_t prop, uint64_t seed)
|
||||
{
|
||||
return (zprop_random_value(prop, seed, ZFS_TYPE_VDEV));
|
||||
}
|
||||
|
||||
#ifndef _KERNEL
|
||||
const char *
|
||||
vdev_prop_values(vdev_prop_t prop)
|
||||
{
|
||||
return (vdev_prop_table[prop].pd_values);
|
||||
}
|
||||
|
||||
const char *
|
||||
vdev_prop_column_name(vdev_prop_t prop)
|
||||
{
|
||||
return (vdev_prop_table[prop].pd_colname);
|
||||
}
|
||||
|
||||
boolean_t
|
||||
vdev_prop_align_right(vdev_prop_t prop)
|
||||
{
|
||||
return (vdev_prop_table[prop].pd_rightalign);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_KERNEL)
|
||||
/* zpool property functions */
|
||||
EXPORT_SYMBOL(zpool_prop_init);
|
||||
EXPORT_SYMBOL(zpool_prop_get_type);
|
||||
EXPORT_SYMBOL(zpool_prop_get_table);
|
||||
|
||||
/* vdev property functions */
|
||||
EXPORT_SYMBOL(vdev_prop_init);
|
||||
EXPORT_SYMBOL(vdev_prop_get_type);
|
||||
EXPORT_SYMBOL(vdev_prop_get_table);
|
||||
|
||||
/* Pool property functions shared between libzfs and kernel. */
|
||||
EXPORT_SYMBOL(zpool_name_to_prop);
|
||||
EXPORT_SYMBOL(zpool_prop_to_name);
|
||||
@@ -276,4 +515,15 @@ EXPORT_SYMBOL(zpool_prop_feature);
|
||||
EXPORT_SYMBOL(zpool_prop_unsupported);
|
||||
EXPORT_SYMBOL(zpool_prop_index_to_string);
|
||||
EXPORT_SYMBOL(zpool_prop_string_to_index);
|
||||
EXPORT_SYMBOL(zpool_prop_vdev);
|
||||
|
||||
/* vdev property functions shared between libzfs and kernel. */
|
||||
EXPORT_SYMBOL(vdev_name_to_prop);
|
||||
EXPORT_SYMBOL(vdev_prop_user);
|
||||
EXPORT_SYMBOL(vdev_prop_to_name);
|
||||
EXPORT_SYMBOL(vdev_prop_default_string);
|
||||
EXPORT_SYMBOL(vdev_prop_default_numeric);
|
||||
EXPORT_SYMBOL(vdev_prop_readonly);
|
||||
EXPORT_SYMBOL(vdev_prop_index_to_string);
|
||||
EXPORT_SYMBOL(vdev_prop_string_to_index);
|
||||
#endif
|
||||
|
||||
@@ -53,6 +53,8 @@ zprop_get_proptable(zfs_type_t type)
|
||||
{
|
||||
if (type == ZFS_TYPE_POOL)
|
||||
return (zpool_prop_get_table());
|
||||
else if (type == ZFS_TYPE_VDEV)
|
||||
return (vdev_prop_get_table());
|
||||
else
|
||||
return (zfs_prop_get_table());
|
||||
}
|
||||
@@ -62,6 +64,8 @@ zprop_get_numprops(zfs_type_t type)
|
||||
{
|
||||
if (type == ZFS_TYPE_POOL)
|
||||
return (ZPOOL_NUM_PROPS);
|
||||
else if (type == ZFS_TYPE_VDEV)
|
||||
return (VDEV_NUM_PROPS);
|
||||
else
|
||||
return (ZFS_NUM_PROPS);
|
||||
}
|
||||
@@ -81,7 +85,8 @@ zfs_mod_supported_prop(const char *name, zfs_type_t type)
|
||||
return (B_TRUE);
|
||||
#else
|
||||
return (zfs_mod_supported(type == ZFS_TYPE_POOL ?
|
||||
ZFS_SYSFS_POOL_PROPERTIES : ZFS_SYSFS_DATASET_PROPERTIES, name));
|
||||
ZFS_SYSFS_POOL_PROPERTIES : (type == ZFS_TYPE_VDEV ?
|
||||
ZFS_SYSFS_VDEV_PROPERTIES : ZFS_SYSFS_DATASET_PROPERTIES), name));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -235,6 +240,8 @@ propname_match(const char *p, size_t len, zprop_desc_t *prop_entry)
|
||||
int c;
|
||||
#endif
|
||||
|
||||
ASSERT(propname != NULL);
|
||||
|
||||
if (len == strlen(propname) &&
|
||||
strncmp(p, propname, len) == 0)
|
||||
return (B_TRUE);
|
||||
@@ -391,6 +398,18 @@ zprop_valid_for_type(int prop, zfs_type_t type, boolean_t headcheck)
|
||||
return ((prop_tbl[prop].pd_types & type) != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* For user property names, we allow all lowercase alphanumeric characters, plus
|
||||
* a few useful punctuation characters.
|
||||
*/
|
||||
int
|
||||
zprop_valid_char(char c)
|
||||
{
|
||||
return ((c >= 'a' && c <= 'z') ||
|
||||
(c >= '0' && c <= '9') ||
|
||||
c == '-' || c == '_' || c == '.' || c == ':');
|
||||
}
|
||||
|
||||
#ifndef _KERNEL
|
||||
|
||||
/*
|
||||
@@ -477,4 +496,5 @@ EXPORT_SYMBOL(zprop_index_to_string);
|
||||
EXPORT_SYMBOL(zprop_random_value);
|
||||
EXPORT_SYMBOL(zprop_values);
|
||||
EXPORT_SYMBOL(zprop_valid_for_type);
|
||||
EXPORT_SYMBOL(zprop_valid_char);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user