summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
authorStephen Hanson <Stephen.Hanson@Sun.COM>2010-04-09 02:28:49 -0700
committerStephen Hanson <Stephen.Hanson@Sun.COM>2010-04-09 02:28:49 -0700
commit44ed9dbbfa620821ecf59a131462082f628dd0f3 (patch)
treea380202e19cdd6eb9aaf5b7c2658ae71fa2a54f2 /usr/src/lib
parent706ba8e25e7464e4f8a0231c2fa247d917482739 (diff)
downloadillumos-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.h7
-rw-r--r--usr/src/lib/fm/topo/modules/common/disk/disk.h6
-rw-r--r--usr/src/lib/fm/topo/modules/common/disk/disk_common.c176
-rw-r--r--usr/src/lib/fm/topo/modules/common/ses/ses.c49
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 *));