Print this page
NEX-2846 Enable Automatic/Intelligent Hot Sparing capability
Reviewed by: Jeffry Molanus <jeffry.molanus@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>

*** 19,28 **** --- 19,29 ---- * CDDL HEADER END */ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2016 Nexenta Systems, Inc. All rights reserved. */ #include <sys/types.h> #include <sys/fm/protocol.h> #include <fm/topo_hc.h>
*** 756,765 **** --- 757,839 ---- "topo handle: %p\n", (void *)thp); fmd_module_unlock(mp); } + /* + * Visit a libtopo node trying to find a disk with the specified devid. + * If we find it, copy it's FRU and resource fields. + */ + static int + fmd_hdl_topo_walk_cb(topo_hdl_t *thp, tnode_t *tn, void *arg) + { + + fmd_hdl_topo_node_info_t *node = (fmd_hdl_topo_node_info_t *)arg; + char *cur_devid; + nvlist_t *fru; + nvlist_t *resource; + int err = 0; + _NOTE(ARGUNUSED(thp)); + + if (strcmp(topo_node_name(tn), "disk") != 0) + return (TOPO_WALK_NEXT); + + if (topo_prop_get_string(tn, "io", "devid", &cur_devid, &err) != 0) + return (TOPO_WALK_NEXT); + + if (strcmp(cur_devid, node->device) == 0) { + if (topo_node_fru(tn, &fru, NULL, &err) == 0 && err == 0 && + topo_node_resource(tn, &resource, &err) == 0 && err == 0) { + node->fru = fnvlist_dup(fru); + node->resource = fnvlist_dup(resource); + return (TOPO_WALK_TERMINATE); + } + } + + return (TOPO_WALK_NEXT); + } + + /* + * Extract FRU and resource values from a libtopo node with the matching devid + */ + fmd_hdl_topo_node_info_t * + fmd_hdl_topo_node_get_by_devid(fmd_hdl_t *hdl, char *device) + { + + int err = 0; + topo_hdl_t *thp; + topo_walk_t *twp; + + fmd_hdl_topo_node_info_t *node = (fmd_hdl_topo_node_info_t *) + fmd_hdl_zalloc(hdl, sizeof (fmd_hdl_topo_node_info_t), FMD_SLEEP); + + thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION); + + node->device = device; + + if ((twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC, fmd_hdl_topo_walk_cb, + node, &err)) == NULL) { + fmd_hdl_error(hdl, "failed to get topology: %s", + topo_strerror(err)); + fmd_hdl_topo_rele(hdl, thp); + return (NULL); + } + + (void) topo_walk_step(twp, TOPO_WALK_CHILD); + topo_walk_fini(twp); + fmd_hdl_topo_rele(hdl, thp); + + if (node->fru == NULL || node->resource == NULL) { + fmd_hdl_debug(hdl, "Could not find device with matching FRU"); + fmd_hdl_free(hdl, node, sizeof (fmd_hdl_topo_node_info_t)); + return (NULL); + } else { + fmd_hdl_debug(hdl, "Found FRU for device %s", device); + return (node); + } + } + static void * fmd_hdl_alloc_locked(fmd_module_t *mp, size_t size, int flags) { void *data;