vdev_stat_t *vs;
uint_t c;
nvlist_t *nvdev;
+ nvlist_t *nvdev_parent = NULL;
+ char *_name;
if (strcmp(name, zpool_get_name(zhp)) != 0)
- nvdev = zpool_find_vdev(zhp, name, NULL, &l2c, NULL);
+ _name = name;
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);
if (addtype)
fnvlist_add_string(list, "type", "VDEV");
ZPOOL_CONFIG_ALLOCATION_BIAS, &bias);
if (bias != NULL)
fnvlist_add_string(list, "class", bias);
- else
- fnvlist_add_string(list, "class", "normal");
+ else {
+ 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,
(uint64_t **)&vs, &c) == 0) {
<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_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_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'/>
<parameter type-id='37e3bd22' name='log'/>
<return type-id='5ce45b60'/>
</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'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='80f4b756' name='path'/>
* 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
* 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 *
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;
nvlist_t **child;
uint64_t is_log;
const char *srchkey;
nvpair_t *pair = nvlist_next_nvpair(search, NULL);
+ const char *tmp = NULL;
+ boolean_t is_root;
/* Nothing to look for */
if (search == NULL || pair == NULL)
/* Obtain the key we will use to search */
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)) {
case DATA_TYPE_UINT64:
if (strcmp(srchkey, ZPOOL_CONFIG_GUID) == 0) {
for (c = 0; c < children; c++) {
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
* vdev, not the leaf vdevs. So we always lookup the
is_log) {
*log = B_TRUE;
}
- return (ret);
+ return (ret && return_parent && !is_root ? nv : ret);
}
}
&child, &children) == 0) {
for (c = 0; c < children; c++) {
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;
- return (ret);
+ return (ret && return_parent &&
+ !is_root ? nv : ret);
}
}
}
&child, &children) == 0) {
for (c = 0; c < children; c++) {
if ((ret = vdev_to_nvlist_iter(child[c], search,
- avail_spare, l2cache, NULL)) != NULL) {
+ avail_spare, l2cache, NULL, return_parent))
+ != NULL) {
*l2cache = B_TRUE;
- return (ret);
+ return (ret && return_parent &&
+ !is_root ? nv : ret);
}
}
}
*l2cache = B_FALSE;
if (log != NULL)
*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);
return (ret);
}
/*
- * 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 *
-zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
- boolean_t *l2cache, boolean_t *log)
+static nvlist_t *
+__zpool_find_vdev(zpool_handle_t *zhp, const char *path, boolean_t *avail_spare,
+ boolean_t *l2cache, boolean_t *log, boolean_t return_parent)
{
char *end;
nvlist_t *nvroot, *search, *ret;
*l2cache = B_FALSE;
if (log != NULL)
*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);
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.
*