mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
Rescan enclosure sysfs path on import
When you create a pool, zfs writes vd->vdev_enc_sysfs_path with the
enclosure sysfs path to the fault LEDs, like:
vdev_enc_sysfs_path = /sys/class/enclosure/0:0:1:0/SLOT8
However, this enclosure path doesn't get updated on successive imports
even if enclosure path to the disk changes. This patch fixes the issue.
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tony Hutter <hutter2@llnl.gov>
Closes #11950
Closes #12095
This commit is contained in:
@@ -247,3 +247,8 @@ zfs_dev_flush(int fd __unused)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
update_vdevs_config_dev_sysfs_path(nvlist_t *config)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
#include <thread_pool.h>
|
||||
#include <libzutil.h>
|
||||
#include <libnvpair.h>
|
||||
#include <libzfs.h>
|
||||
|
||||
#include "zutil_import.h"
|
||||
|
||||
@@ -776,6 +777,58 @@ no_dev:
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Rescan the enclosure sysfs path for turning on enclosure LEDs and store it
|
||||
* in the nvlist * (if applicable). Like:
|
||||
* vdev_enc_sysfs_path: '/sys/class/enclosure/11:0:1:0/SLOT 4'
|
||||
*/
|
||||
static void
|
||||
update_vdev_config_dev_sysfs_path(nvlist_t *nv, char *path)
|
||||
{
|
||||
char *upath, *spath;
|
||||
|
||||
/* Add enclosure sysfs path (if disk is in an enclosure). */
|
||||
upath = zfs_get_underlying_path(path);
|
||||
spath = zfs_get_enclosure_sysfs_path(upath);
|
||||
|
||||
if (spath) {
|
||||
nvlist_add_string(nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH, spath);
|
||||
} else {
|
||||
nvlist_remove_all(nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
|
||||
}
|
||||
|
||||
free(upath);
|
||||
free(spath);
|
||||
}
|
||||
|
||||
/*
|
||||
* This will get called for each leaf vdev.
|
||||
*/
|
||||
static int
|
||||
sysfs_path_pool_vdev_iter_f(void *hdl_data, nvlist_t *nv, void *data)
|
||||
{
|
||||
char *path = NULL;
|
||||
if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) != 0)
|
||||
return (1);
|
||||
|
||||
/* Rescan our enclosure sysfs path for this vdev */
|
||||
update_vdev_config_dev_sysfs_path(nv, path);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given an nvlist for our pool (with vdev tree), iterate over all the
|
||||
* leaf vdevs and update their ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH.
|
||||
*/
|
||||
void
|
||||
update_vdevs_config_dev_sysfs_path(nvlist_t *config)
|
||||
{
|
||||
nvlist_t *nvroot = NULL;
|
||||
verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
|
||||
&nvroot) == 0);
|
||||
for_each_vdev_in_nvlist(nvroot, sysfs_path_pool_vdev_iter_f, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update a leaf vdev's persistent device strings
|
||||
*
|
||||
@@ -802,7 +855,6 @@ update_vdev_config_dev_strs(nvlist_t *nv)
|
||||
vdev_dev_strs_t vds;
|
||||
char *env, *type, *path;
|
||||
uint64_t wholedisk = 0;
|
||||
char *upath, *spath;
|
||||
|
||||
/*
|
||||
* For the benefit of legacy ZFS implementations, allow
|
||||
@@ -849,18 +901,7 @@ update_vdev_config_dev_strs(nvlist_t *nv)
|
||||
(void) nvlist_add_string(nv, ZPOOL_CONFIG_PHYS_PATH,
|
||||
vds.vds_devphys);
|
||||
}
|
||||
|
||||
/* Add enclosure sysfs path (if disk is in an enclosure). */
|
||||
upath = zfs_get_underlying_path(path);
|
||||
spath = zfs_get_enclosure_sysfs_path(upath);
|
||||
if (spath)
|
||||
nvlist_add_string(nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH,
|
||||
spath);
|
||||
else
|
||||
nvlist_remove_all(nv, ZPOOL_CONFIG_VDEV_ENC_SYSFS_PATH);
|
||||
|
||||
free(upath);
|
||||
free(spath);
|
||||
update_vdev_config_dev_sysfs_path(nv, path);
|
||||
} else {
|
||||
/* Clear out any stale entries. */
|
||||
(void) nvlist_remove_all(nv, ZPOOL_CONFIG_DEVID);
|
||||
|
||||
@@ -1678,6 +1678,8 @@ zpool_find_import_cached(libpc_handle_t *hdl, importargs_t *iarg)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
update_vdevs_config_dev_sysfs_path(src);
|
||||
|
||||
if ((dst = zutil_refresh_config(hdl, src)) == NULL) {
|
||||
nvlist_free(raw);
|
||||
nvlist_free(pools);
|
||||
@@ -1835,3 +1837,69 @@ zpool_find_config(void *hdl, const char *target, nvlist_t **configp,
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal function for iterating over the vdevs.
|
||||
*
|
||||
* For each vdev, func() will be called and will be passed 'zhp' (which is
|
||||
* typically the zpool_handle_t cast as a void pointer), the vdev's nvlist, and
|
||||
* a user-defined data pointer).
|
||||
*
|
||||
* The return values from all the func() calls will be OR'd together and
|
||||
* returned.
|
||||
*/
|
||||
int
|
||||
for_each_vdev_cb(void *zhp, nvlist_t *nv, pool_vdev_iter_f func,
|
||||
void *data)
|
||||
{
|
||||
nvlist_t **child;
|
||||
uint_t c, children;
|
||||
int ret = 0;
|
||||
int i;
|
||||
char *type;
|
||||
|
||||
const char *list[] = {
|
||||
ZPOOL_CONFIG_SPARES,
|
||||
ZPOOL_CONFIG_L2CACHE,
|
||||
ZPOOL_CONFIG_CHILDREN
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(list); i++) {
|
||||
if (nvlist_lookup_nvlist_array(nv, list[i], &child,
|
||||
&children) == 0) {
|
||||
for (c = 0; c < children; c++) {
|
||||
uint64_t ishole = 0;
|
||||
|
||||
(void) nvlist_lookup_uint64(child[c],
|
||||
ZPOOL_CONFIG_IS_HOLE, &ishole);
|
||||
|
||||
if (ishole)
|
||||
continue;
|
||||
|
||||
ret |= for_each_vdev_cb(zhp, child[c],
|
||||
func, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0)
|
||||
return (ret);
|
||||
|
||||
/* Don't run our function on root vdevs */
|
||||
if (strcmp(type, VDEV_TYPE_ROOT) != 0) {
|
||||
ret |= func(zhp, nv, data);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given an ZPOOL_CONFIG_VDEV_TREE nvpair, iterate over all the vdevs, calling
|
||||
* func() for each one. func() is passed the vdev's nvlist and an optional
|
||||
* user-defined 'data' pointer.
|
||||
*/
|
||||
int
|
||||
for_each_vdev_in_nvlist(nvlist_t *nvroot, pool_vdev_iter_f func, void *data)
|
||||
{
|
||||
return (for_each_vdev_cb(NULL, nvroot, func, data));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user