diff options
author | Stephen Hanson <Stephen.Hanson@Sun.COM> | 2010-04-09 02:28:49 -0700 |
---|---|---|
committer | Stephen Hanson <Stephen.Hanson@Sun.COM> | 2010-04-09 02:28:49 -0700 |
commit | 44ed9dbbfa620821ecf59a131462082f628dd0f3 (patch) | |
tree | a380202e19cdd6eb9aaf5b7c2658ae71fa2a54f2 /usr/src/lib | |
parent | 706ba8e25e7464e4f8a0231c2fa247d917482739 (diff) | |
download | illumos-joyent-44ed9dbbfa620821ecf59a131462082f628dd0f3.tar.gz |
6934497 ses enumerator should add disk nodes in bays even if no devid is available
6901867 topology of storage enclosures should match physical reality
6934813 should be able to associate a disk ereport with a topo node by target port wwn
6938578 should identify ses-enclosure nodes in hc-scheme ereports by chassis-sn not node instance number
Diffstat (limited to 'usr/src/lib')
-rw-r--r-- | usr/src/lib/fm/topo/libtopo/common/topo_hc.h | 7 | ||||
-rw-r--r-- | usr/src/lib/fm/topo/modules/common/disk/disk.h | 6 | ||||
-rw-r--r-- | usr/src/lib/fm/topo/modules/common/disk/disk_common.c | 176 | ||||
-rw-r--r-- | usr/src/lib/fm/topo/modules/common/ses/ses.c | 49 |
4 files changed, 167 insertions, 71 deletions
diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_hc.h b/usr/src/lib/fm/topo/libtopo/common/topo_hc.h index 8195b66e5a..db663b1074 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_hc.h +++ b/usr/src/lib/fm/topo/libtopo/common/topo_hc.h @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _TOPO_HC_H @@ -106,6 +105,10 @@ extern "C" { #define TOPO_PCI_CLASS "class-code" #define TOPO_PCI_AADDR "assigned-addresses" +#define TOPO_PGROUP_STORAGE "storage" +#define TOPO_STORAGE_TARGET_PORT_L0ID "target-port-l0id" +#define TOPO_STORAGE_TARGET_PORT_L0IDS "target-port-l0ids" + #define TOPO_PGROUP_BINDING "binding" #define TOPO_BINDING_OCCUPANT "occupant-path" diff --git a/usr/src/lib/fm/topo/modules/common/disk/disk.h b/usr/src/lib/fm/topo/modules/common/disk/disk.h index e87e1a9493..b758db06e3 100644 --- a/usr/src/lib/fm/topo/modules/common/disk/disk.h +++ b/usr/src/lib/fm/topo/modules/common/disk/disk.h @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _DISK_H @@ -55,10 +54,11 @@ struct topo_list; /* Methods shared with the ses module (disk_common.c) */ extern int disk_list_gather(topo_mod_t *, struct topo_list *); extern void disk_list_free(topo_mod_t *, struct topo_list *); +extern int disk_declare_non_enumerated(topo_mod_t *, tnode_t *, tnode_t **); extern int disk_declare_path(topo_mod_t *, tnode_t *, struct topo_list *, const char *); extern int disk_declare_addr(topo_mod_t *, tnode_t *, - struct topo_list *, const char *); + struct topo_list *, const char *, tnode_t **); extern char *disk_auth_clean(topo_mod_t *, const char *); #ifdef __cplusplus diff --git a/usr/src/lib/fm/topo/modules/common/disk/disk_common.c b/usr/src/lib/fm/topo/modules/common/disk/disk_common.c index 6ae3c4a341..6780e591f8 100644 --- a/usr/src/lib/fm/topo/modules/common/disk/disk_common.c +++ b/usr/src/lib/fm/topo/modules/common/disk/disk_common.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -139,6 +138,10 @@ static const topo_pgroup_info_t storage_pgroup = { * group: storage properties: * - logical-disk, disk-model, disk-manufacturer, serial-number * - firmware-revision, capacity-in-bytes + * + * NOTE: the io and storage groups won't be present if the dnode passed in is + * NULL. This happens when a disk is found through ses, but is not enumerated + * in the devinfo tree. */ static int disk_set_props(topo_mod_t *mod, tnode_t *parent, @@ -149,20 +152,6 @@ disk_set_props(topo_mod_t *mod, tnode_t *parent, nvlist_t *fmri = NULL; int err; - /* form and set the asru */ - if ((asru = topo_mod_devfmri(mod, FM_DEV_SCHEME_VERSION, - dnode->ddn_dpath, dnode->ddn_devid)) == NULL) { - err = ETOPO_FMRI_UNKNOWN; - topo_mod_dprintf(mod, "disk_set_props: " - "asru error %s\n", topo_strerror(err)); - goto error; - } - if (topo_node_asru_set(dtn, asru, 0, &err) != 0) { - topo_mod_dprintf(mod, "disk_set_props: " - "asru_set error %s\n", topo_strerror(err)); - goto error; - } - /* pull the label property down from our parent 'bay' node */ if (topo_node_label(parent, &label, &err) != 0) { topo_mod_dprintf(mod, "disk_set_props: " @@ -195,6 +184,33 @@ disk_set_props(topo_mod_t *mod, tnode_t *parent, goto error; } + /* create the storage group */ + if (topo_pgroup_create(dtn, &storage_pgroup, &err) != 0) { + topo_mod_dprintf(mod, "disk_set_props: " + "create storage error %s\n", topo_strerror(err)); + goto error; + } + + /* no dnode was found for this disk - skip the io and storage groups */ + if (dnode == NULL) { + err = 0; + goto out; + } + + /* form and set the asru */ + if ((asru = topo_mod_devfmri(mod, FM_DEV_SCHEME_VERSION, + dnode->ddn_dpath, dnode->ddn_devid)) == NULL) { + err = ETOPO_FMRI_UNKNOWN; + topo_mod_dprintf(mod, "disk_set_props: " + "asru error %s\n", topo_strerror(err)); + goto error; + } + if (topo_node_asru_set(dtn, asru, 0, &err) != 0) { + topo_mod_dprintf(mod, "disk_set_props: " + "asru_set error %s\n", topo_strerror(err)); + goto error; + } + /* create/set the devfs-path and devid in the io group */ if (topo_pgroup_create(dtn, &io_pgroup, &err) != 0) { topo_mod_dprintf(mod, "disk_set_props: " @@ -209,8 +225,8 @@ disk_set_props(topo_mod_t *mod, tnode_t *parent, goto error; } - if (topo_prop_set_string(dtn, TOPO_PGROUP_IO, TOPO_IO_DEVID, - TOPO_PROP_IMMUTABLE, dnode->ddn_devid, &err) != 0) { + if (dnode->ddn_devid && topo_prop_set_string(dtn, TOPO_PGROUP_IO, + TOPO_IO_DEVID, TOPO_PROP_IMMUTABLE, dnode->ddn_devid, &err) != 0) { topo_mod_dprintf(mod, "disk_set_props: " "set devid error %s\n", topo_strerror(err)); goto error; @@ -225,13 +241,6 @@ disk_set_props(topo_mod_t *mod, tnode_t *parent, goto error; } - /* create the storage group */ - if (topo_pgroup_create(dtn, &storage_pgroup, &err) != 0) { - topo_mod_dprintf(mod, "disk_set_props: " - "create storage error %s\n", topo_strerror(err)); - goto error; - } - /* set the storage group public /dev name */ if (topo_prop_set_string(dtn, TOPO_PGROUP_STORAGE, TOPO_STORAGE_LOGICAL_DISK_NAME, TOPO_PROP_IMMUTABLE, @@ -343,9 +352,9 @@ disk_auth_clean(topo_mod_t *mod, const char *str) } /* create the disk topo node */ -static tnode_t * +static int disk_tnode_create(topo_mod_t *mod, tnode_t *parent, - disk_di_node_t *dnode, const char *name, topo_instance_t i) + disk_di_node_t *dnode, const char *name, topo_instance_t i, tnode_t **rval) { int len; nvlist_t *fmri; @@ -354,10 +363,15 @@ disk_tnode_create(topo_mod_t *mod, tnode_t *parent, nvlist_t *auth; char *mfg, *model, *firm, *serial; - mfg = disk_auth_clean(mod, dnode->ddn_mfg); - model = disk_auth_clean(mod, dnode->ddn_model); - firm = disk_auth_clean(mod, dnode->ddn_firm); - serial = disk_auth_clean(mod, dnode->ddn_serial); + *rval = NULL; + if (dnode != NULL) { + mfg = disk_auth_clean(mod, dnode->ddn_mfg); + model = disk_auth_clean(mod, dnode->ddn_model); + firm = disk_auth_clean(mod, dnode->ddn_firm); + serial = disk_auth_clean(mod, dnode->ddn_serial); + } else { + mfg = model = firm = serial = NULL; + } /* form 'part=' of fmri as "<mfg>-<model>" */ if (mfg != NULL && model != NULL) { @@ -383,16 +397,23 @@ disk_tnode_create(topo_mod_t *mod, tnode_t *parent, "hcfmri (%s%d/%s%d) error %s\n", topo_node_name(parent), topo_node_instance(parent), name, i, topo_strerror(topo_mod_errno(mod))); - return (NULL); + return (-1); } if ((dtn = topo_node_bind(mod, parent, name, i, fmri)) == NULL) { + if (topo_mod_errno(mod) == EMOD_NODE_BOUND) { + /* + * if disk 0 is already there then we're done + */ + nvlist_free(fmri); + return (0); + } topo_mod_dprintf(mod, "disk_tnode_create: " "bind (%s%d/%s%d) error %s\n", topo_node_name(parent), topo_node_instance(parent), name, i, topo_strerror(topo_mod_errno(mod))); nvlist_free(fmri); - return (NULL); + return (-1); } nvlist_free(fmri); @@ -403,19 +424,23 @@ disk_tnode_create(topo_mod_t *mod, tnode_t *parent, topo_node_name(parent), topo_node_instance(parent), name, i, topo_strerror(topo_mod_errno(mod))); topo_node_unbind(dtn); - return (NULL); + return (-1); } - return (dtn); + *rval = dtn; + return (0); } static int -disk_declare(topo_mod_t *mod, tnode_t *parent, disk_di_node_t *dnode) +disk_declare(topo_mod_t *mod, tnode_t *parent, disk_di_node_t *dnode, + tnode_t **childp) { - tnode_t *dtn; + tnode_t *dtn = NULL; + int rval; - /* create the disk topo node: one disk per 'bay' */ - dtn = disk_tnode_create(mod, parent, dnode, DISK, 0); + rval = disk_tnode_create(mod, parent, dnode, DISK, 0, &dtn); if (dtn == NULL) { + if (rval == 0) + return (0); topo_mod_dprintf(mod, "disk_declare: " "disk_tnode_create error %s\n", topo_strerror(topo_mod_errno(mod))); @@ -430,6 +455,8 @@ disk_declare(topo_mod_t *mod, tnode_t *parent, disk_di_node_t *dnode) topo_node_unbind(dtn); return (-1); } + if (childp != NULL) + *childp = dtn; return (0); } @@ -451,7 +478,7 @@ disk_declare_path(topo_mod_t *mod, tnode_t *parent, topo_list_t *listp, for (i = 0; i < dnode->ddn_ppath_count; i++) { if (di_devfs_path_match(dnode->ddn_ppath[0], path)) - return (disk_declare(mod, parent, dnode)); + return (disk_declare(mod, parent, dnode, NULL)); } } @@ -462,7 +489,7 @@ disk_declare_path(topo_mod_t *mod, tnode_t *parent, topo_list_t *listp, int disk_declare_addr(topo_mod_t *mod, tnode_t *parent, topo_list_t *listp, - const char *addr) + const char *addr, tnode_t **childp) { disk_di_node_t *dnode; int i; @@ -476,13 +503,25 @@ disk_declare_addr(topo_mod_t *mod, tnode_t *parent, topo_list_t *listp, for (i = 0; i < dnode->ddn_target_port_count; i++) { if (strncmp(dnode->ddn_target_port[i], addr, strcspn(dnode->ddn_target_port[i], ":")) == 0) - return (disk_declare(mod, parent, dnode)); + return (disk_declare(mod, parent, dnode, + childp)); } } topo_mod_dprintf(mod, "disk_declare_addr: " "failed to find disk matching addr %s", addr); - return (0); + + return (1); +} + +/* + * Used to declare a disk that has been discovered through other means (usually + * ses), that is not enumerated in the devinfo tree. + */ +int +disk_declare_non_enumerated(topo_mod_t *mod, tnode_t *parent, tnode_t **childp) +{ + return (disk_declare(mod, parent, NULL, childp)); } /* di_devlink callback for disk_di_node_add */ @@ -518,7 +557,8 @@ disk_di_node_free(topo_mod_t *mod, disk_di_node_t *dnode) int i; /* free the stuff we point to */ - topo_mod_strfree(mod, dnode->ddn_devid); + if (dnode->ddn_devid) + topo_mod_strfree(mod, dnode->ddn_devid); for (i = 0; i < dnode->ddn_ppath_count; i++) topo_mod_strfree(mod, dnode->ddn_ppath[i]); topo_mod_free(mod, dnode->ddn_ppath, @@ -560,23 +600,32 @@ disk_di_node_add(di_node_t node, char *devid, disk_cbdata_t *cbp) int pathcount, portcount; int ret, i; - /* check for list duplicate using devid search */ - for (dnode = topo_list_next(cbp->dcb_list); - dnode != NULL; dnode = topo_list_next(dnode)) { - if (devid_str_compare(dnode->ddn_devid, devid) == 0) { - topo_mod_dprintf(mod, "disk_di_node_add: " - "already there %s\n", devid); - return (0); + if (devid) { + /* + * Check for list duplicate using devid search. + * Note if there is no devid, then we can end up with duplicates + * in the list, but this doesn't do any harm. + */ + for (dnode = topo_list_next(cbp->dcb_list); + dnode != NULL; dnode = topo_list_next(dnode)) { + if (dnode->ddn_devid && + devid_str_compare(dnode->ddn_devid, devid) == 0) { + topo_mod_dprintf(mod, "disk_di_node_add: " + "already there %s\n", devid); + return (0); + } } } if ((dnode = topo_mod_zalloc(mod, sizeof (disk_di_node_t))) == NULL) return (-1); - /* Establish the devid. */ - dnode->ddn_devid = topo_mod_strdup(mod, devid); - if (dnode->ddn_devid == NULL) - goto error; + if (devid) { + /* Establish the devid. */ + dnode->ddn_devid = topo_mod_strdup(mod, devid); + if (dnode->ddn_devid == NULL) + goto error; + } /* Establish the devinfo dpath */ if ((path = di_devfs_path(node)) == NULL) { @@ -748,7 +797,7 @@ disk_di_node_add(di_node_t node, char *devid, disk_cbdata_t *cbp) } topo_mod_dprintf(mod, "disk_di_node_add: " - "adding %s\n", dnode->ddn_devid); + "adding %s\n", devid ? dnode->ddn_devid : "NULL devid"); topo_mod_dprintf(mod, " " " %s\n", dnode->ddn_dpath); for (i = 0; i < dnode->ddn_ppath_count; i++) { @@ -768,12 +817,19 @@ static int disk_walk_di_nodes(di_node_t node, void *arg) { char *devidstr = NULL; + char *s; - /* only interested in nodes that have devids */ - if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, - DEVID_PROP_NAME, &devidstr) < 0) { + /* + * if it's not a scsi_vhci client and doesn't have a target port + * then we're not interested + */ + if (di_path_client_next_path(node, NULL) == NULL && + di_prop_lookup_strings(DDI_DEV_T_ANY, node, + SCSI_ADDR_PROP_TARGET_PORT, &s) <= 0) { return (DI_WALK_CONTINUE); } + (void) di_prop_lookup_strings(DDI_DEV_T_ANY, node, + DEVID_PROP_NAME, &devidstr); /* create/find the devid scsi topology node */ (void) disk_di_node_add(node, devidstr, arg); @@ -804,7 +860,7 @@ disk_list_gather(topo_mod_t *mod, topo_list_t *listp) dcb.dcb_list = listp; dcb.dcb_devhdl = devhdl; - /* walk the devinfo snapshot looking for nodes with devids */ + /* walk the devinfo snapshot looking for disk nodes */ (void) di_walk_node(devtree, DI_WALK_CLDFIRST, &dcb, disk_walk_di_nodes); diff --git a/usr/src/lib/fm/topo/modules/common/ses/ses.c b/usr/src/lib/fm/topo/modules/common/ses/ses.c index e3db1928ad..59e7efd6d1 100644 --- a/usr/src/lib/fm/topo/modules/common/ses/ses.c +++ b/usr/src/lib/fm/topo/modules/common/ses/ses.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <alloca.h> @@ -34,6 +33,7 @@ #include <unistd.h> #include <sys/dkio.h> #include <sys/fm/protocol.h> +#include <sys/libdevid.h> #include <sys/scsi/scsi_types.h> #include "disk.h" @@ -509,7 +509,8 @@ ses_create_disk(ses_enum_data_t *sdp, tnode_t *pnode, nvlist_t *props) nvlist_t **sas; uint_t s, nsas; char **paths; - int err; + int err, ret; + tnode_t *child = NULL; /* * Skip devices that are not in a present (and possibly damaged) state. @@ -552,14 +553,50 @@ ses_create_disk(ses_enum_data_t *sdp, tnode_t *pnode, nvlist_t *props) err = 0; for (s = 0; s < nsas; s++) { - if (disk_declare_addr(mod, pnode, - &sdp->sed_disks, paths[s]) != 0 && - topo_mod_errno(mod) != EMOD_NODE_BOUND) { + ret = disk_declare_addr(mod, pnode, &sdp->sed_disks, paths[s], + &child); + if (ret == 0) { + break; + } else if (ret < 0) { err = -1; break; } } + if (s == nsas) + disk_declare_non_enumerated(mod, pnode, &child); + + /* copy sas_addresses (target-ports) from parent (with 'w'added) */ + if (child != NULL) { + int i; + char **tports; + uint64_t wwn; + + tports = topo_mod_zalloc(mod, sizeof (char *) * nsas); + if (tports != NULL) { + for (i = 0; i < nsas; i++) { + if (scsi_wwnstr_to_wwn(paths[i], &wwn) != + DDI_SUCCESS) + break; + tports[i] = scsi_wwn_to_wwnstr(wwn, 1, NULL); + if (tports[i] == NULL) + break; + } + /* if they all worked then create the property */ + if (i == nsas) + (void) topo_prop_set_string_array(child, + TOPO_PGROUP_STORAGE, + TOPO_STORAGE_TARGET_PORT_L0IDS, + TOPO_PROP_IMMUTABLE, (const char **)tports, + nsas, &err); + + for (i = 0; i < nsas; i++) + if (tports[i] != NULL) + scsi_free_wwnstr(tports[i]); + topo_mod_free(mod, tports, sizeof (char *) * nsas); + } + } + for (s = 0; s < nsas; s++) topo_mod_free(mod, paths[s], strlen(paths[s]) + 1); topo_mod_free(mod, paths, nsas * sizeof (char *)); |