mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-11-17 01:51:00 +03:00
JSON: Fix class values for mirrored special vdevs
This fixes things so mirrored special vdevs report themselves as "class=special" rather than "class=normal". This happens due to the way the vdev nvlists are constructed: mirrored special devices - The 'mirror' vdev has allocation bias as "special" and it's leaf vdevs are "normal" single or RAID0 special devices - Leaf vdevs have allocation bias as "special". This commit adds in code to check if a leaf's parent is a "special" vdev to see if it should also report "special". Reviewed-by: Ameer Hamza <ahamza@ixsystems.com> Reviewed-by: Umer Saleem <usaleem@ixsystems.com> Signed-off-by: Tony Hutter <hutter2@llnl.gov> Closes #16217
This commit is contained in:
parent
dab810014e
commit
02a9f7fed7
@ -1154,11 +1154,16 @@ fill_vdev_info(nvlist_t *list, zpool_handle_t *zhp, char *name,
|
|||||||
vdev_stat_t *vs;
|
vdev_stat_t *vs;
|
||||||
uint_t c;
|
uint_t c;
|
||||||
nvlist_t *nvdev;
|
nvlist_t *nvdev;
|
||||||
|
nvlist_t *nvdev_parent = NULL;
|
||||||
|
char *_name;
|
||||||
|
|
||||||
if (strcmp(name, zpool_get_name(zhp)) != 0)
|
if (strcmp(name, zpool_get_name(zhp)) != 0)
|
||||||
nvdev = zpool_find_vdev(zhp, name, NULL, &l2c, NULL);
|
_name = name;
|
||||||
else
|
else
|
||||||
nvdev = zpool_find_vdev(zhp, "root-0", NULL, &l2c, NULL);
|
_name = (char *)"root-0";
|
||||||
|
|
||||||
|
nvdev = zpool_find_vdev(zhp, _name, NULL, &l2c, NULL);
|
||||||
|
|
||||||
fnvlist_add_string(list, "name", name);
|
fnvlist_add_string(list, "name", name);
|
||||||
if (addtype)
|
if (addtype)
|
||||||
fnvlist_add_string(list, "type", "VDEV");
|
fnvlist_add_string(list, "type", "VDEV");
|
||||||
@ -1203,8 +1208,32 @@ fill_vdev_info(nvlist_t *list, zpool_handle_t *zhp, char *name,
|
|||||||
ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
|
ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
|
||||||
if (bias != NULL)
|
if (bias != NULL)
|
||||||
fnvlist_add_string(list, "class", bias);
|
fnvlist_add_string(list, "class", bias);
|
||||||
else
|
else {
|
||||||
fnvlist_add_string(list, "class", "normal");
|
nvdev_parent = NULL;
|
||||||
|
nvdev_parent = zpool_find_parent_vdev(zhp,
|
||||||
|
_name, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* With a mirrored special device, the parent
|
||||||
|
* "mirror" vdev will have
|
||||||
|
* ZPOOL_CONFIG_ALLOCATION_BIAS set to "special"
|
||||||
|
* not the leaf vdevs. If we're a leaf vdev
|
||||||
|
* in that case we need to look at our parent
|
||||||
|
* to see if they're "special" to know if we
|
||||||
|
* are "special" too.
|
||||||
|
*/
|
||||||
|
if (nvdev_parent) {
|
||||||
|
(void) nvlist_lookup_string(
|
||||||
|
nvdev_parent,
|
||||||
|
ZPOOL_CONFIG_ALLOCATION_BIAS,
|
||||||
|
&bias);
|
||||||
|
}
|
||||||
|
if (bias != NULL)
|
||||||
|
fnvlist_add_string(list, "class", bias);
|
||||||
|
else
|
||||||
|
fnvlist_add_string(list, "class",
|
||||||
|
"normal");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (nvlist_lookup_uint64_array(nvdev, ZPOOL_CONFIG_VDEV_STATS,
|
if (nvlist_lookup_uint64_array(nvdev, ZPOOL_CONFIG_VDEV_STATS,
|
||||||
(uint64_t **)&vs, &c) == 0) {
|
(uint64_t **)&vs, &c) == 0) {
|
||||||
|
@ -327,6 +327,8 @@ _LIBZFS_H int zpool_vdev_clear(zpool_handle_t *, uint64_t);
|
|||||||
|
|
||||||
_LIBZFS_H nvlist_t *zpool_find_vdev(zpool_handle_t *, const char *, boolean_t *,
|
_LIBZFS_H nvlist_t *zpool_find_vdev(zpool_handle_t *, const char *, boolean_t *,
|
||||||
boolean_t *, boolean_t *);
|
boolean_t *, boolean_t *);
|
||||||
|
_LIBZFS_H nvlist_t *zpool_find_parent_vdev(zpool_handle_t *, const char *,
|
||||||
|
boolean_t *, boolean_t *, boolean_t *);
|
||||||
_LIBZFS_H nvlist_t *zpool_find_vdev_by_physpath(zpool_handle_t *, const char *,
|
_LIBZFS_H nvlist_t *zpool_find_vdev_by_physpath(zpool_handle_t *, const char *,
|
||||||
boolean_t *, boolean_t *, boolean_t *);
|
boolean_t *, boolean_t *, boolean_t *);
|
||||||
_LIBZFS_H int zpool_label_disk(libzfs_handle_t *, zpool_handle_t *,
|
_LIBZFS_H int zpool_label_disk(libzfs_handle_t *, zpool_handle_t *,
|
||||||
|
@ -486,6 +486,7 @@
|
|||||||
<elf-symbol name='zpool_feature_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
<elf-symbol name='zpool_feature_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||||
<elf-symbol name='zpool_find_config' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
<elf-symbol name='zpool_find_config' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||||
<elf-symbol name='zpool_find_vdev' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
<elf-symbol name='zpool_find_vdev' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||||
|
<elf-symbol name='zpool_find_parent_vdev' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||||
<elf-symbol name='zpool_find_vdev_by_physpath' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
<elf-symbol name='zpool_find_vdev_by_physpath' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||||
<elf-symbol name='zpool_free_handles' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
<elf-symbol name='zpool_free_handles' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||||
<elf-symbol name='zpool_get_all_vdev_props' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
<elf-symbol name='zpool_get_all_vdev_props' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||||
@ -6540,6 +6541,14 @@
|
|||||||
<parameter type-id='37e3bd22' name='log'/>
|
<parameter type-id='37e3bd22' name='log'/>
|
||||||
<return type-id='5ce45b60'/>
|
<return type-id='5ce45b60'/>
|
||||||
</function-decl>
|
</function-decl>
|
||||||
|
<function-decl name='zpool_find_parent_vdev' mangled-name='zpool_find_parent_vdev' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_find_parent_vdev'>
|
||||||
|
<parameter type-id='4c81de99' name='zhp'/>
|
||||||
|
<parameter type-id='80f4b756' name='path'/>
|
||||||
|
<parameter type-id='37e3bd22' name='avail_spare'/>
|
||||||
|
<parameter type-id='37e3bd22' name='l2cache'/>
|
||||||
|
<parameter type-id='37e3bd22' name='log'/>
|
||||||
|
<return type-id='5ce45b60'/>
|
||||||
|
</function-decl>
|
||||||
<function-decl name='zpool_vdev_path_to_guid' mangled-name='zpool_vdev_path_to_guid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_path_to_guid'>
|
<function-decl name='zpool_vdev_path_to_guid' mangled-name='zpool_vdev_path_to_guid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_vdev_path_to_guid'>
|
||||||
<parameter type-id='4c81de99' name='zhp'/>
|
<parameter type-id='4c81de99' name='zhp'/>
|
||||||
<parameter type-id='80f4b756' name='path'/>
|
<parameter type-id='80f4b756' name='path'/>
|
||||||
|
@ -2863,10 +2863,13 @@ zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func, pool_scrub_cmd_t cmd)
|
|||||||
* the nvpair name to determine how we should look for the device.
|
* the nvpair name to determine how we should look for the device.
|
||||||
* 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL
|
* 'avail_spare' is set to TRUE if the provided guid refers to an AVAIL
|
||||||
* spare; but FALSE if its an INUSE spare.
|
* spare; but FALSE if its an INUSE spare.
|
||||||
|
*
|
||||||
|
* If 'return_parent' is set, then return the *parent* of the vdev you're
|
||||||
|
* searching for rather than the vdev itself.
|
||||||
*/
|
*/
|
||||||
static nvlist_t *
|
static nvlist_t *
|
||||||
vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
|
vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
|
||||||
boolean_t *l2cache, boolean_t *log)
|
boolean_t *l2cache, boolean_t *log, boolean_t return_parent)
|
||||||
{
|
{
|
||||||
uint_t c, children;
|
uint_t c, children;
|
||||||
nvlist_t **child;
|
nvlist_t **child;
|
||||||
@ -2874,6 +2877,8 @@ vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
|
|||||||
uint64_t is_log;
|
uint64_t is_log;
|
||||||
const char *srchkey;
|
const char *srchkey;
|
||||||
nvpair_t *pair = nvlist_next_nvpair(search, NULL);
|
nvpair_t *pair = nvlist_next_nvpair(search, NULL);
|
||||||
|
const char *tmp = NULL;
|
||||||
|
boolean_t is_root;
|
||||||
|
|
||||||
/* Nothing to look for */
|
/* Nothing to look for */
|
||||||
if (search == NULL || pair == NULL)
|
if (search == NULL || pair == NULL)
|
||||||
@ -2882,6 +2887,12 @@ vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
|
|||||||
/* Obtain the key we will use to search */
|
/* Obtain the key we will use to search */
|
||||||
srchkey = nvpair_name(pair);
|
srchkey = nvpair_name(pair);
|
||||||
|
|
||||||
|
nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &tmp);
|
||||||
|
if (strcmp(tmp, "root") == 0)
|
||||||
|
is_root = B_TRUE;
|
||||||
|
else
|
||||||
|
is_root = B_FALSE;
|
||||||
|
|
||||||
switch (nvpair_type(pair)) {
|
switch (nvpair_type(pair)) {
|
||||||
case DATA_TYPE_UINT64:
|
case DATA_TYPE_UINT64:
|
||||||
if (strcmp(srchkey, ZPOOL_CONFIG_GUID) == 0) {
|
if (strcmp(srchkey, ZPOOL_CONFIG_GUID) == 0) {
|
||||||
@ -3012,7 +3023,7 @@ vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
|
|||||||
|
|
||||||
for (c = 0; c < children; c++) {
|
for (c = 0; c < children; c++) {
|
||||||
if ((ret = vdev_to_nvlist_iter(child[c], search,
|
if ((ret = vdev_to_nvlist_iter(child[c], search,
|
||||||
avail_spare, l2cache, NULL)) != NULL) {
|
avail_spare, l2cache, NULL, return_parent)) != NULL) {
|
||||||
/*
|
/*
|
||||||
* The 'is_log' value is only set for the toplevel
|
* The 'is_log' value is only set for the toplevel
|
||||||
* vdev, not the leaf vdevs. So we always lookup the
|
* vdev, not the leaf vdevs. So we always lookup the
|
||||||
@ -3025,7 +3036,7 @@ vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
|
|||||||
is_log) {
|
is_log) {
|
||||||
*log = B_TRUE;
|
*log = B_TRUE;
|
||||||
}
|
}
|
||||||
return (ret);
|
return (ret && return_parent && !is_root ? nv : ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3033,9 +3044,11 @@ vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
|
|||||||
&child, &children) == 0) {
|
&child, &children) == 0) {
|
||||||
for (c = 0; c < children; c++) {
|
for (c = 0; c < children; c++) {
|
||||||
if ((ret = vdev_to_nvlist_iter(child[c], search,
|
if ((ret = vdev_to_nvlist_iter(child[c], search,
|
||||||
avail_spare, l2cache, NULL)) != NULL) {
|
avail_spare, l2cache, NULL, return_parent))
|
||||||
|
!= NULL) {
|
||||||
*avail_spare = B_TRUE;
|
*avail_spare = B_TRUE;
|
||||||
return (ret);
|
return (ret && return_parent &&
|
||||||
|
!is_root ? nv : ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3044,9 +3057,11 @@ vdev_to_nvlist_iter(nvlist_t *nv, nvlist_t *search, boolean_t *avail_spare,
|
|||||||
&child, &children) == 0) {
|
&child, &children) == 0) {
|
||||||
for (c = 0; c < children; c++) {
|
for (c = 0; c < children; c++) {
|
||||||
if ((ret = vdev_to_nvlist_iter(child[c], search,
|
if ((ret = vdev_to_nvlist_iter(child[c], search,
|
||||||
avail_spare, l2cache, NULL)) != NULL) {
|
avail_spare, l2cache, NULL, return_parent))
|
||||||
|
!= NULL) {
|
||||||
*l2cache = B_TRUE;
|
*l2cache = B_TRUE;
|
||||||
return (ret);
|
return (ret && return_parent &&
|
||||||
|
!is_root ? nv : ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3081,7 +3096,8 @@ zpool_find_vdev_by_physpath(zpool_handle_t *zhp, const char *ppath,
|
|||||||
*l2cache = B_FALSE;
|
*l2cache = B_FALSE;
|
||||||
if (log != NULL)
|
if (log != NULL)
|
||||||
*log = B_FALSE;
|
*log = B_FALSE;
|
||||||
ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log);
|
ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log,
|
||||||
|
B_FALSE);
|
||||||
fnvlist_free(search);
|
fnvlist_free(search);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
@ -3109,11 +3125,12 @@ zpool_vdev_is_interior(const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lookup the nvlist for a given vdev.
|
* Lookup the nvlist for a given vdev or vdev's parent (depending on
|
||||||
|
* if 'return_parent' is set).
|
||||||
*/
|
*/
|
||||||
nvlist_t *
|
static nvlist_t *
|
||||||
zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
|
__zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
|
||||||
boolean_t *l2cache, boolean_t *log)
|
boolean_t *l2cache, boolean_t *log, boolean_t return_parent)
|
||||||
{
|
{
|
||||||
char *end;
|
char *end;
|
||||||
nvlist_t *nvroot, *search, *ret;
|
nvlist_t *nvroot, *search, *ret;
|
||||||
@ -3150,12 +3167,30 @@ zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
|
|||||||
*l2cache = B_FALSE;
|
*l2cache = B_FALSE;
|
||||||
if (log != NULL)
|
if (log != NULL)
|
||||||
*log = B_FALSE;
|
*log = B_FALSE;
|
||||||
ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log);
|
ret = vdev_to_nvlist_iter(nvroot, search, avail_spare, l2cache, log,
|
||||||
|
return_parent);
|
||||||
fnvlist_free(search);
|
fnvlist_free(search);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nvlist_t *
|
||||||
|
zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
|
||||||
|
boolean_t *l2cache, boolean_t *log)
|
||||||
|
{
|
||||||
|
return (__zpool_find_vdev(zhp, path, avail_spare, l2cache, log,
|
||||||
|
B_FALSE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given a vdev path, return its parent's nvlist */
|
||||||
|
nvlist_t *
|
||||||
|
zpool_find_parent_vdev(zpool_handle_t *zhp, const char *path,
|
||||||
|
boolean_t *avail_spare, boolean_t *l2cache, boolean_t *log)
|
||||||
|
{
|
||||||
|
return (__zpool_find_vdev(zhp, path, avail_spare, l2cache, log,
|
||||||
|
B_TRUE));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert a vdev path to a GUID. Returns GUID or 0 on error.
|
* Convert a vdev path to a GUID. Returns GUID or 0 on error.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user