diff options
author | David Quigley <[email protected]> | 2017-09-18 18:06:40 -0600 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2017-09-18 17:06:40 -0700 |
commit | a9a2bf71520ffb5668c9204db5c7df0445dc912a (patch) | |
tree | e0f60e10e5ae4d751b6792e05de771037a91bc9b | |
parent | ea49beba66106dcb272b43323fad147df1df13fd (diff) |
Remove FRU and LIBTOPO Support
FRU and LIBTOPO support are illumos only features that will not be ported to
Linux and make the code more complicated than necessary. This commit
makes way for further cleanups of the zed/FMA code.
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: David Quigley <[email protected]>
Closes #6641
-rw-r--r-- | cmd/zed/agents/zfs_diagnosis.c | 63 | ||||
-rw-r--r-- | cmd/zed/agents/zfs_retire.c | 152 | ||||
-rw-r--r-- | include/libzfs.h | 11 | ||||
-rw-r--r-- | include/libzfs_impl.h | 18 | ||||
-rw-r--r-- | lib/libzfs/Makefile.am | 1 | ||||
-rw-r--r-- | lib/libzfs/libzfs_fru.c | 475 | ||||
-rw-r--r-- | lib/libzfs/libzfs_util.c | 1 |
7 files changed, 10 insertions, 711 deletions
diff --git a/cmd/zed/agents/zfs_diagnosis.c b/cmd/zed/agents/zfs_diagnosis.c index 704873499..49e3e1660 100644 --- a/cmd/zed/agents/zfs_diagnosis.c +++ b/cmd/zed/agents/zfs_diagnosis.c @@ -377,11 +377,6 @@ zfs_case_solve(fmd_hdl_t *hdl, zfs_case_t *zcp, const char *faultname, nvlist_t *detector, *fault; boolean_t serialize; nvlist_t *fru = NULL; -#ifdef HAVE_LIBTOPO - nvlist_t *fmri; - topo_hdl_t *thp; - int err; -#endif fmd_hdl_debug(hdl, "solving fault '%s'", faultname); /* @@ -400,64 +395,6 @@ zfs_case_solve(fmd_hdl_t *hdl, zfs_case_t *zcp, const char *faultname, zcp->zc_data.zc_vdev_guid); } -#ifdef HAVE_LIBTOPO - /* - * We also want to make sure that the detector (pool or vdev) properly - * reflects the diagnosed state, when the fault corresponds to internal - * ZFS state (i.e. not checksum or I/O error-induced). Otherwise, a - * device which was unavailable early in boot (because the driver/file - * wasn't available) and is now healthy will be mis-diagnosed. - */ - if (!fmd_nvl_fmri_present(hdl, detector) || - (checkunusable && !fmd_nvl_fmri_unusable(hdl, detector))) { - fmd_case_close(hdl, zcp->zc_case); - nvlist_free(detector); - return; - } - - - fru = NULL; - if (zcp->zc_fru != NULL && - (thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) != NULL) { - /* - * If the vdev had an associated FRU, then get the FRU nvlist - * from the topo handle and use that in the suspect list. We - * explicitly lookup the FRU because the fmri reported from the - * kernel may not have up to date details about the disk itself - * (serial, part, etc). - */ - if (topo_fmri_str2nvl(thp, zcp->zc_fru, &fmri, &err) == 0) { - libzfs_handle_t *zhdl = fmd_hdl_getspecific(hdl); - - /* - * If the disk is part of the system chassis, but the - * FRU indicates a different chassis ID than our - * current system, then ignore the error. This - * indicates that the device was part of another - * cluster head, and for obvious reasons cannot be - * imported on this system. - */ - if (libzfs_fru_notself(zhdl, zcp->zc_fru)) { - fmd_case_close(hdl, zcp->zc_case); - nvlist_free(fmri); - fmd_hdl_topo_rele(hdl, thp); - nvlist_free(detector); - return; - } - - /* - * If the device is no longer present on the system, or - * topo_fmri_fru() fails for other reasons, then fall - * back to the fmri specified in the vdev. - */ - if (topo_fmri_fru(thp, fmri, &fru, &err) != 0) - fru = fmd_nvl_dup(hdl, fmri, FMD_SLEEP); - nvlist_free(fmri); - } - - fmd_hdl_topo_rele(hdl, thp); - } -#endif fault = fmd_nvl_create_fault(hdl, faultname, 100, detector, fru, detector); fmd_case_add_suspect(hdl, zcp->zc_case, fault); diff --git a/cmd/zed/agents/zfs_retire.c b/cmd/zed/agents/zfs_retire.c index c1349fb30..f69c583f0 100644 --- a/cmd/zed/agents/zfs_retire.c +++ b/cmd/zed/agents/zfs_retire.c @@ -71,7 +71,6 @@ zfs_retire_clear_data(fmd_hdl_t *hdl, zfs_retire_data_t *zdp) */ typedef struct find_cbdata { uint64_t cb_guid; - const char *cb_fru; zpool_handle_t *cb_zhp; nvlist_t *cb_vdev; } find_cbdata_t; @@ -95,26 +94,18 @@ find_pool(zpool_handle_t *zhp, void *data) * Find a vdev within a tree with a matching GUID. */ static nvlist_t * -find_vdev(libzfs_handle_t *zhdl, nvlist_t *nv, const char *search_fru, - uint64_t search_guid) +find_vdev(libzfs_handle_t *zhdl, nvlist_t *nv, uint64_t search_guid) { uint64_t guid; nvlist_t **child; uint_t c, children; nvlist_t *ret; - char *fru; - - if (search_fru != NULL) { - if (nvlist_lookup_string(nv, ZPOOL_CONFIG_FRU, &fru) == 0 && - libzfs_fru_compare(zhdl, fru, search_fru)) - return (nv); - } else { - if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 && - guid == search_guid) { - fmd_hdl_debug(fmd_module_hdl("zfs-retire"), - "matched vdev %llu", guid); - return (nv); - } + + if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 && + guid == search_guid) { + fmd_hdl_debug(fmd_module_hdl("zfs-retire"), + "matched vdev %llu", guid); + return (nv); } if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, @@ -122,8 +113,7 @@ find_vdev(libzfs_handle_t *zhdl, nvlist_t *nv, const char *search_fru, return (NULL); for (c = 0; c < children; c++) { - if ((ret = find_vdev(zhdl, child[c], search_fru, - search_guid)) != NULL) + if ((ret = find_vdev(zhdl, child[c], search_guid)) != NULL) return (ret); } @@ -132,8 +122,7 @@ find_vdev(libzfs_handle_t *zhdl, nvlist_t *nv, const char *search_fru, return (NULL); for (c = 0; c < children; c++) { - if ((ret = find_vdev(zhdl, child[c], search_fru, - search_guid)) != NULL) + if ((ret = find_vdev(zhdl, child[c], search_guid)) != NULL) return (ret); } @@ -167,8 +156,7 @@ find_by_guid(libzfs_handle_t *zhdl, uint64_t pool_guid, uint64_t vdev_guid, } if (vdev_guid != 0) { - if ((*vdevp = find_vdev(zhdl, nvroot, NULL, - vdev_guid)) == NULL) { + if ((*vdevp = find_vdev(zhdl, nvroot, vdev_guid)) == NULL) { zpool_close(zhp); return (NULL); } @@ -177,49 +165,6 @@ find_by_guid(libzfs_handle_t *zhdl, uint64_t pool_guid, uint64_t vdev_guid, return (zhp); } -#ifdef HAVE_LIBTOPO -static int -search_pool(zpool_handle_t *zhp, void *data) -{ - find_cbdata_t *cbp = data; - nvlist_t *config; - nvlist_t *nvroot; - - config = zpool_get_config(zhp, NULL); - if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, - &nvroot) != 0) { - zpool_close(zhp); - return (0); - } - - if ((cbp->cb_vdev = find_vdev(zpool_get_handle(zhp), nvroot, - cbp->cb_fru, 0)) != NULL) { - cbp->cb_zhp = zhp; - return (1); - } - - zpool_close(zhp); - return (0); -} - -/* - * Given a FRU FMRI, find the matching pool and vdev. - */ -static zpool_handle_t * -find_by_fru(libzfs_handle_t *zhdl, const char *fru, nvlist_t **vdevp) -{ - find_cbdata_t cb; - - cb.cb_fru = fru; - cb.cb_zhp = NULL; - if (zpool_iter(zhdl, search_pool, &cb) != 1) - return (NULL); - - *vdevp = cb.cb_vdev; - return (cb.cb_zhp); -} -#endif /* HAVE_LIBTOPO */ - /* * Given a vdev, attempt to replace it with every known spare until one * succeeds. @@ -289,10 +234,6 @@ zfs_vdev_repair(fmd_hdl_t *hdl, nvlist_t *nvl) zfs_retire_data_t *zdp = fmd_hdl_getspecific(hdl); zfs_retire_repaired_t *zrp; uint64_t pool_guid, vdev_guid; -#ifdef HAVE_LIBTOPO - nvlist_t *asru; -#endif - if (nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_POOL_GUID, &pool_guid) != 0 || nvlist_lookup_uint64(nvl, FM_EREPORT_PAYLOAD_ZFS_VDEV_GUID, &vdev_guid) != 0) @@ -315,47 +256,6 @@ zfs_vdev_repair(fmd_hdl_t *hdl, nvlist_t *nvl) return; } -#ifdef HAVE_LIBTOPO - asru = fmd_nvl_alloc(hdl, FMD_SLEEP); - - (void) nvlist_add_uint8(asru, FM_VERSION, ZFS_SCHEME_VERSION0); - (void) nvlist_add_string(asru, FM_FMRI_SCHEME, FM_FMRI_SCHEME_ZFS); - (void) nvlist_add_uint64(asru, FM_FMRI_ZFS_POOL, pool_guid); - (void) nvlist_add_uint64(asru, FM_FMRI_ZFS_VDEV, vdev_guid); - - /* - * We explicitly check for the unusable state here to make sure we - * aren't responding to a transient state change. As part of opening a - * vdev, it's possible to see the 'statechange' event, only to be - * followed by a vdev failure later. If we don't check the current - * state of the vdev (or pool) before marking it repaired, then we risk - * generating spurious repair events followed immediately by the same - * diagnosis. - * - * This assumes that the ZFS scheme code associated unusable (i.e. - * isolated) with its own definition of faulty state. In the case of a - * DEGRADED leaf vdev (due to checksum errors), this is not the case. - * This works, however, because the transient state change is not - * posted in this case. This could be made more explicit by not - * relying on the scheme's unusable callback and instead directly - * checking the vdev state, where we could correctly account for - * DEGRADED state. - */ - if (!fmd_nvl_fmri_unusable(hdl, asru) && fmd_nvl_fmri_has_fault(hdl, - asru, FMD_HAS_FAULT_ASRU, NULL)) { - topo_hdl_t *thp; - char *fmri = NULL; - int err; - - thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION); - if (topo_fmri_nvl2str(thp, asru, &fmri, &err) == 0) - (void) fmd_repair_asru(hdl, fmri); - fmd_hdl_topo_rele(hdl, thp); - - topo_hdl_strfree(thp, fmri); - } - nvlist_free(asru); -#endif zrp = fmd_hdl_alloc(hdl, sizeof (zfs_retire_repaired_t), FMD_SLEEP); zrp->zrr_next = zdp->zrd_repaired; zrp->zrr_pool = pool_guid; @@ -477,39 +377,7 @@ zfs_retire_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, } if (is_disk) { -#ifdef HAVE_LIBTOPO - /* - * This is a disk fault. Lookup the FRU, convert it to - * an FMRI string, and attempt to find a matching vdev. - */ - if (nvlist_lookup_nvlist(fault, FM_FAULT_FRU, - &fru) != 0 || - nvlist_lookup_string(fru, FM_FMRI_SCHEME, - &scheme) != 0) - continue; - - if (strcmp(scheme, FM_FMRI_SCHEME_HC) != 0) - continue; - - thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION); - if (topo_fmri_nvl2str(thp, fru, &fmri, &err) != 0) { - fmd_hdl_topo_rele(hdl, thp); - continue; - } - - zhp = find_by_fru(zhdl, fmri, &vdev); - topo_hdl_strfree(thp, fmri); - fmd_hdl_topo_rele(hdl, thp); - - if (zhp == NULL) - continue; - - (void) nvlist_lookup_uint64(vdev, - ZPOOL_CONFIG_GUID, &vdev_guid); - aux = VDEV_AUX_EXTERNAL; -#else continue; -#endif } else { /* * This is a ZFS fault. Lookup the resource, and diff --git a/include/libzfs.h b/include/libzfs.h index df8d738b7..ac5a30c35 100644 --- a/include/libzfs.h +++ b/include/libzfs.h @@ -873,17 +873,6 @@ extern int zpool_enable_datasets(zpool_handle_t *, const char *, int); extern int zpool_disable_datasets(zpool_handle_t *, boolean_t); /* - * Mappings between vdev and FRU. - */ -extern void libzfs_fru_refresh(libzfs_handle_t *); -extern const char *libzfs_fru_lookup(libzfs_handle_t *, const char *); -extern const char *libzfs_fru_devpath(libzfs_handle_t *, const char *); -extern boolean_t libzfs_fru_compare(libzfs_handle_t *, const char *, - const char *); -extern boolean_t libzfs_fru_notself(libzfs_handle_t *, const char *); -extern int zpool_fru_set(zpool_handle_t *, uint64_t, const char *); - -/* * Support for Linux libudev derived persistent device strings */ extern boolean_t is_mpath_whole_disk(const char *); diff --git a/include/libzfs_impl.h b/include/libzfs_impl.h index 2efd85e31..8107ed48b 100644 --- a/include/libzfs_impl.h +++ b/include/libzfs_impl.h @@ -38,21 +38,10 @@ #include <libshare.h> #include <libzfs_core.h> -#if defined(HAVE_LIBTOPO) -#include <fm/libtopo.h> -#endif /* HAVE_LIBTOPO */ - #ifdef __cplusplus extern "C" { #endif -typedef struct libzfs_fru { - char *zf_device; - char *zf_fru; - struct libzfs_fru *zf_chain; - struct libzfs_fru *zf_next; -} libzfs_fru_t; - struct libzfs_handle { int libzfs_error; int libzfs_fd; @@ -72,11 +61,6 @@ struct libzfs_handle { boolean_t libzfs_mnttab_enable; avl_tree_t libzfs_mnttab_cache; int libzfs_pool_iter; -#if defined(HAVE_LIBTOPO) - topo_hdl_t *libzfs_topo_hdl; - libzfs_fru_t **libzfs_fru_hash; - libzfs_fru_t *libzfs_fru_list; -#endif /* HAVE_LIBTOPO */ char libzfs_chassis_id[256]; }; @@ -208,8 +192,6 @@ extern int zfs_parse_options(char *, zfs_share_proto_t); extern int zfs_unshare_proto(zfs_handle_t *, const char *, zfs_share_proto_t *); -extern void libzfs_fru_clear(libzfs_handle_t *, boolean_t); - #ifdef __cplusplus } #endif diff --git a/lib/libzfs/Makefile.am b/lib/libzfs/Makefile.am index cae4b7c16..7389f002d 100644 --- a/lib/libzfs/Makefile.am +++ b/lib/libzfs/Makefile.am @@ -21,7 +21,6 @@ USER_C = \ libzfs_crypto.c \ libzfs_dataset.c \ libzfs_diff.c \ - libzfs_fru.c \ libzfs_import.c \ libzfs_iter.c \ libzfs_mount.c \ diff --git a/lib/libzfs/libzfs_fru.c b/lib/libzfs/libzfs_fru.c deleted file mode 100644 index 2ee8bdfb2..000000000 --- a/lib/libzfs/libzfs_fru.c +++ /dev/null @@ -1,475 +0,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 http://www.opensolaris.org/os/licensing. - * 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 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <dlfcn.h> -#include <errno.h> -#include <libintl.h> -#include <link.h> -#include <pthread.h> -#include <strings.h> -#include <unistd.h> - -#include <libzfs.h> - -#if defined(HAVE_LIBTOPO) - -#include <fm/libtopo.h> -#include <sys/fm/protocol.h> -#include <sys/systeminfo.h> - -#include "libzfs_impl.h" - -/* - * This file is responsible for determining the relationship between I/O - * devices paths and physical locations. In the world of MPxIO and external - * enclosures, the device path is not synonymous with the physical location. - * If you remove a drive and insert it into a different slot, it will end up - * with the same path under MPxIO. If you recable storage enclosures, the - * device paths may change. All of this makes it difficult to implement the - * 'autoreplace' property, which is supposed to automatically manage disk - * replacement based on physical slot. - * - * In order to work around these limitations, we have a per-vdev FRU property - * that is the libtopo path (minus disk-specific authority information) to the - * physical location of the device on the system. This is an optional - * property, and is only needed when using the 'autoreplace' property or when - * generating FMA faults against vdevs. - */ - -/* - * Because the FMA packages depend on ZFS, we have to dlopen() libtopo in case - * it is not present. We only need this once per library instance, so it is - * not part of the libzfs handle. - */ -static void *_topo_dlhandle; -static topo_hdl_t *(*_topo_open)(int, const char *, int *); -static void (*_topo_close)(topo_hdl_t *); -static char *(*_topo_snap_hold)(topo_hdl_t *, const char *, int *); -static void (*_topo_snap_release)(topo_hdl_t *); -static topo_walk_t *(*_topo_walk_init)(topo_hdl_t *, const char *, - topo_walk_cb_t, void *, int *); -static int (*_topo_walk_step)(topo_walk_t *, int); -static void (*_topo_walk_fini)(topo_walk_t *); -static void (*_topo_hdl_strfree)(topo_hdl_t *, char *); -static char *(*_topo_node_name)(tnode_t *); -static int (*_topo_prop_get_string)(tnode_t *, const char *, const char *, - char **, int *); -static int (*_topo_node_fru)(tnode_t *, nvlist_t **, nvlist_t *, int *); -static int (*_topo_fmri_nvl2str)(topo_hdl_t *, nvlist_t *, char **, int *); -static int (*_topo_fmri_strcmp_noauth)(topo_hdl_t *, const char *, - const char *); - -#define ZFS_FRU_HASH_SIZE 257 - -static size_t -fru_strhash(const char *key) -{ - ulong_t g, h = 0; - const char *p; - - for (p = key; *p != '\0'; p++) { - h = (h << 4) + *p; - - if ((g = (h & 0xf0000000)) != 0) { - h ^= (g >> 24); - h ^= g; - } - } - - return (h % ZFS_FRU_HASH_SIZE); -} - -static int -libzfs_fru_gather(topo_hdl_t *thp, tnode_t *tn, void *arg) -{ - libzfs_handle_t *hdl = arg; - nvlist_t *fru; - char *devpath, *frustr; - int err; - libzfs_fru_t *frup; - size_t idx; - - /* - * If this is the chassis node, and we don't yet have the system - * chassis ID, then fill in this value now. - */ - if (hdl->libzfs_chassis_id[0] == '\0' && - strcmp(_topo_node_name(tn), "chassis") == 0) { - if (_topo_prop_get_string(tn, FM_FMRI_AUTHORITY, - FM_FMRI_AUTH_CHASSIS, &devpath, &err) == 0) - (void) strlcpy(hdl->libzfs_chassis_id, devpath, - sizeof (hdl->libzfs_chassis_id)); - } - - /* - * Skip non-disk nodes. - */ - if (strcmp(_topo_node_name(tn), "disk") != 0) - return (TOPO_WALK_NEXT); - - /* - * Get the devfs path and FRU. - */ - if (_topo_prop_get_string(tn, "io", "devfs-path", &devpath, &err) != 0) - return (TOPO_WALK_NEXT); - - if (libzfs_fru_lookup(hdl, devpath) != NULL) { - _topo_hdl_strfree(thp, devpath); - return (TOPO_WALK_NEXT); - } - - if (_topo_node_fru(tn, &fru, NULL, &err) != 0) { - _topo_hdl_strfree(thp, devpath); - return (TOPO_WALK_NEXT); - } - - /* - * Convert the FRU into a string. - */ - if (_topo_fmri_nvl2str(thp, fru, &frustr, &err) != 0) { - nvlist_free(fru); - _topo_hdl_strfree(thp, devpath); - return (TOPO_WALK_NEXT); - } - - nvlist_free(fru); - - /* - * Finally, we have a FRU string and device path. Add it to the hash. - */ - if ((frup = calloc(sizeof (libzfs_fru_t), 1)) == NULL) { - _topo_hdl_strfree(thp, devpath); - _topo_hdl_strfree(thp, frustr); - return (TOPO_WALK_NEXT); - } - - if ((frup->zf_device = strdup(devpath)) == NULL || - (frup->zf_fru = strdup(frustr)) == NULL) { - free(frup->zf_device); - free(frup); - _topo_hdl_strfree(thp, devpath); - _topo_hdl_strfree(thp, frustr); - return (TOPO_WALK_NEXT); - } - - _topo_hdl_strfree(thp, devpath); - _topo_hdl_strfree(thp, frustr); - - idx = fru_strhash(frup->zf_device); - frup->zf_chain = hdl->libzfs_fru_hash[idx]; - hdl->libzfs_fru_hash[idx] = frup; - frup->zf_next = hdl->libzfs_fru_list; - hdl->libzfs_fru_list = frup; - - return (TOPO_WALK_NEXT); -} - -/* - * Called during initialization to setup the dynamic libtopo connection. - */ -#pragma init(libzfs_init_fru) -static void -libzfs_init_fru(void) -{ - char path[MAXPATHLEN]; - char isa[257]; - -#if defined(_LP64) - if (sysinfo(SI_ARCHITECTURE_64, isa, sizeof (isa)) < 0) - isa[0] = '\0'; -#else - isa[0] = '\0'; -#endif - (void) snprintf(path, sizeof (path), - "/usr/lib/fm/%s/libtopo.so", isa); - - if ((_topo_dlhandle = dlopen(path, RTLD_LAZY)) == NULL) - return; - - _topo_open = (topo_hdl_t *(*)()) - dlsym(_topo_dlhandle, "topo_open"); - _topo_close = (void (*)()) - dlsym(_topo_dlhandle, "topo_close"); - _topo_snap_hold = (char *(*)()) - dlsym(_topo_dlhandle, "topo_snap_hold"); - _topo_snap_release = (void (*)()) - dlsym(_topo_dlhandle, "topo_snap_release"); - _topo_walk_init = (topo_walk_t *(*)()) - dlsym(_topo_dlhandle, "topo_walk_init"); - _topo_walk_step = (int (*)()) - dlsym(_topo_dlhandle, "topo_walk_step"); - _topo_walk_fini = (void (*)()) - dlsym(_topo_dlhandle, "topo_walk_fini"); - _topo_hdl_strfree = (void (*)()) - dlsym(_topo_dlhandle, "topo_hdl_strfree"); - _topo_node_name = (char *(*)()) - dlsym(_topo_dlhandle, "topo_node_name"); - _topo_prop_get_string = (int (*)()) - dlsym(_topo_dlhandle, "topo_prop_get_string"); - _topo_node_fru = (int (*)()) - dlsym(_topo_dlhandle, "topo_node_fru"); - _topo_fmri_nvl2str = (int (*)()) - dlsym(_topo_dlhandle, "topo_fmri_nvl2str"); - _topo_fmri_strcmp_noauth = (int (*)()) - dlsym(_topo_dlhandle, "topo_fmri_strcmp_noauth"); - - if (_topo_open == NULL || _topo_close == NULL || - _topo_snap_hold == NULL || _topo_snap_release == NULL || - _topo_walk_init == NULL || _topo_walk_step == NULL || - _topo_walk_fini == NULL || _topo_hdl_strfree == NULL || - _topo_node_name == NULL || _topo_prop_get_string == NULL || - _topo_node_fru == NULL || _topo_fmri_nvl2str == NULL || - _topo_fmri_strcmp_noauth == NULL) { - (void) dlclose(_topo_dlhandle); - _topo_dlhandle = NULL; - } -} - -/* - * Refresh the mappings from device path -> FMRI. We do this by walking the - * hc topology looking for disk nodes, and recording the io/devfs-path and FRU. - * Note that we strip out the disk-specific authority information (serial, - * part, revision, etc) so that we are left with only the identifying - * characteristics of the slot (hc path and chassis-id). - */ -void -libzfs_fru_refresh(libzfs_handle_t *hdl) -{ - int err; - char *uuid; - topo_hdl_t *thp; - topo_walk_t *twp; - - if (_topo_dlhandle == NULL) - return; - - /* - * Clear the FRU hash and initialize our basic structures. - */ - libzfs_fru_clear(hdl, B_FALSE); - - if ((hdl->libzfs_topo_hdl = _topo_open(TOPO_VERSION, - NULL, &err)) == NULL) - return; - - thp = hdl->libzfs_topo_hdl; - - if ((uuid = _topo_snap_hold(thp, NULL, &err)) == NULL) - return; - - _topo_hdl_strfree(thp, uuid); - - if (hdl->libzfs_fru_hash == NULL && - (hdl->libzfs_fru_hash = - calloc(ZFS_FRU_HASH_SIZE, sizeof (void *))) == NULL) - return; - - /* - * We now have a topo snapshot, so iterate over the hc topology looking - * for disks to add to the hash. - */ - twp = _topo_walk_init(thp, FM_FMRI_SCHEME_HC, - libzfs_fru_gather, hdl, &err); - if (twp != NULL) { - (void) _topo_walk_step(twp, TOPO_WALK_CHILD); - _topo_walk_fini(twp); - } -} - -/* - * Given a devfs path, return the FRU for the device, if known. This will - * automatically call libzfs_fru_refresh() if it hasn't already been called by - * the consumer. The string returned is valid until the next call to - * libzfs_fru_refresh(). - */ -const char * -libzfs_fru_lookup(libzfs_handle_t *hdl, const char *devpath) -{ - size_t idx = fru_strhash(devpath); - libzfs_fru_t *frup; - - if (hdl->libzfs_fru_hash == NULL) - libzfs_fru_refresh(hdl); - - if (hdl->libzfs_fru_hash == NULL) - return (NULL); - - for (frup = hdl->libzfs_fru_hash[idx]; frup != NULL; - frup = frup->zf_chain) { - if (strcmp(devpath, frup->zf_device) == 0) - return (frup->zf_fru); - } - - return (NULL); -} - -/* - * Given a fru path, return the device path. This will automatically call - * libzfs_fru_refresh() if it hasn't already been called by the consumer. The - * string returned is valid until the next call to libzfs_fru_refresh(). - */ -const char * -libzfs_fru_devpath(libzfs_handle_t *hdl, const char *fru) -{ - libzfs_fru_t *frup; - size_t idx; - - if (hdl->libzfs_fru_hash == NULL) - libzfs_fru_refresh(hdl); - - if (hdl->libzfs_fru_hash == NULL) - return (NULL); - - for (idx = 0; idx < ZFS_FRU_HASH_SIZE; idx++) { - for (frup = hdl->libzfs_fru_hash[idx]; frup != NULL; - frup = frup->zf_next) { - if (_topo_fmri_strcmp_noauth(hdl->libzfs_topo_hdl, - fru, frup->zf_fru)) - return (frup->zf_device); - } - } - - return (NULL); -} - -/* - * Change the stored FRU for the given vdev. - */ -int -zpool_fru_set(zpool_handle_t *zhp, uint64_t vdev_guid, const char *fru) -{ - zfs_cmd_t zc = {"\0"}; - - (void) strncpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); - (void) strncpy(zc.zc_value, fru, sizeof (zc.zc_value)); - zc.zc_guid = vdev_guid; - - if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_VDEV_SETFRU, &zc) != 0) - return (zpool_standard_error_fmt(zhp->zpool_hdl, errno, - dgettext(TEXT_DOMAIN, "cannot set FRU"))); - - return (0); -} - -/* - * Compare to two FRUs, ignoring any authority information. - */ -boolean_t -libzfs_fru_compare(libzfs_handle_t *hdl, const char *a, const char *b) -{ - if (hdl->libzfs_fru_hash == NULL) - libzfs_fru_refresh(hdl); - - if (hdl->libzfs_fru_hash == NULL) - return (strcmp(a, b) == 0); - - return (_topo_fmri_strcmp_noauth(hdl->libzfs_topo_hdl, a, b)); -} - -/* - * This special function checks to see whether the FRU indicates it's supposed - * to be in the system chassis, but the chassis-id doesn't match. This can - * happen in a clustered case, where both head nodes have the same logical - * disk, but opening the device on the other head node is meaningless. - */ -boolean_t -libzfs_fru_notself(libzfs_handle_t *hdl, const char *fru) -{ - const char *chassisid; - size_t len; - - if (hdl->libzfs_fru_hash == NULL) - libzfs_fru_refresh(hdl); - - if (hdl->libzfs_chassis_id[0] == '\0') - return (B_FALSE); - - if (strstr(fru, "/chassis=0/") == NULL) - return (B_FALSE); - - if ((chassisid = strstr(fru, ":chassis-id=")) == NULL) - return (B_FALSE); - - chassisid += 12; - len = strlen(hdl->libzfs_chassis_id); - if (strncmp(chassisid, hdl->libzfs_chassis_id, len) == 0 && - (chassisid[len] == '/' || chassisid[len] == ':')) - return (B_FALSE); - - return (B_TRUE); -} - -/* - * Clear memory associated with the FRU hash. - */ -void -libzfs_fru_clear(libzfs_handle_t *hdl, boolean_t final) -{ - libzfs_fru_t *frup; - - while ((frup = hdl->libzfs_fru_list) != NULL) { - hdl->libzfs_fru_list = frup->zf_next; - free(frup->zf_device); - free(frup->zf_fru); - free(frup); - } - - hdl->libzfs_fru_list = NULL; - - if (hdl->libzfs_topo_hdl != NULL) { - _topo_snap_release(hdl->libzfs_topo_hdl); - _topo_close(hdl->libzfs_topo_hdl); - hdl->libzfs_topo_hdl = NULL; - } - - if (final) { - free(hdl->libzfs_fru_hash); - } else if (hdl->libzfs_fru_hash != NULL) { - bzero(hdl->libzfs_fru_hash, - ZFS_FRU_HASH_SIZE * sizeof (void *)); - } -} - -#else /* HAVE_LIBTOPO */ - -/* - * Compare to two FRUs, ignoring any authority information. - */ -boolean_t -libzfs_fru_compare(libzfs_handle_t *hdl, const char *a, const char *b) -{ - return (B_FALSE); -} - -/* - * Clear memory associated with the FRU hash. - */ -void -libzfs_fru_clear(libzfs_handle_t *hdl, boolean_t final) -{ -} - -#endif /* HAVE_LIBTOPO */ diff --git a/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index d4414b0c9..e13fee16d 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -1070,7 +1070,6 @@ libzfs_fini(libzfs_handle_t *hdl) (void) fclose(hdl->libzfs_sharetab); zfs_uninit_libshare(hdl); zpool_free_handles(hdl); - libzfs_fru_clear(hdl, B_TRUE); namespace_clear(hdl); libzfs_mnttab_fini(hdl); libzfs_core_fini(); |