diff options
-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(); |