disk.c revision 184cd04c26b064536977dfbb913a1240eaf6f708
184cd04c26b064536977dfbb913a1240eaf6f708cth * CDDL HEADER START
184cd04c26b064536977dfbb913a1240eaf6f708cth * The contents of this file are subject to the terms of the
184cd04c26b064536977dfbb913a1240eaf6f708cth * Common Development and Distribution License (the "License").
184cd04c26b064536977dfbb913a1240eaf6f708cth * You may not use this file except in compliance with the License.
184cd04c26b064536977dfbb913a1240eaf6f708cth * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
184cd04c26b064536977dfbb913a1240eaf6f708cth * See the License for the specific language governing permissions
184cd04c26b064536977dfbb913a1240eaf6f708cth * and limitations under the License.
184cd04c26b064536977dfbb913a1240eaf6f708cth * When distributing Covered Code, include this CDDL HEADER in each
184cd04c26b064536977dfbb913a1240eaf6f708cth * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
184cd04c26b064536977dfbb913a1240eaf6f708cth * If applicable, add the following below this CDDL HEADER, with the
184cd04c26b064536977dfbb913a1240eaf6f708cth * fields enclosed by brackets "[]" replaced with your own identifying
184cd04c26b064536977dfbb913a1240eaf6f708cth * information: Portions Copyright [yyyy] [name of copyright owner]
184cd04c26b064536977dfbb913a1240eaf6f708cth * CDDL HEADER END
184cd04c26b064536977dfbb913a1240eaf6f708cth * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
184cd04c26b064536977dfbb913a1240eaf6f708cth * Use is subject to license terms.
184cd04c26b064536977dfbb913a1240eaf6f708cth#pragma ident "%Z%%M% %I% %E% SMI"
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic int disk_status(topo_mod_t *, tnode_t *, topo_version_t,
184cd04c26b064536977dfbb913a1240eaf6f708cth * Given a /devices path for a whole disk, appending this extension gives the
184cd04c26b064536977dfbb913a1240eaf6f708cth * path to a raw device that can be opened.
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic int disk_enum(topo_mod_t *, tnode_t *, const char *,
184cd04c26b064536977dfbb913a1240eaf6f708cth { TOPO_PGROUP_IO, TOPO_STABILITY_PRIVATE, TOPO_STABILITY_PRIVATE, 1 };
184cd04c26b064536977dfbb913a1240eaf6f708cth * Methods for disks. This is used by the disk-transport module to
184cd04c26b064536977dfbb913a1240eaf6f708cth * generate ereports based off SCSI disk status.
184cd04c26b064536977dfbb913a1240eaf6f708cth/* disk node information */
184cd04c26b064536977dfbb913a1240eaf6f708cthtypedef struct disk_di_node {
184cd04c26b064536977dfbb913a1240eaf6f708cthtypedef struct disk_di_nodes {
184cd04c26b064536977dfbb913a1240eaf6f708cth/* list of devices */
184cd04c26b064536977dfbb913a1240eaf6f708cth/* given a device find it in the global device list */
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_lock(&disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth for (dnode = topo_list_next(&(disk_di_nodes.disk_di_nodes_list));
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_unlock(&disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth/* get the disk storage group information */
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic void
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_storage_info(topo_mod_t *mod, disk_di_node_t *dnode,
184cd04c26b064536977dfbb913a1240eaf6f708cth char **model, char **manuf, char **serial, char **firm, char **cap)
184cd04c26b064536977dfbb913a1240eaf6f708cth * To save kernel memory, the driver may not
184cd04c26b064536977dfbb913a1240eaf6f708cth * define "device-dblksize" when its value is
184cd04c26b064536977dfbb913a1240eaf6f708cth * the default DEV_BSIZE value.
184cd04c26b064536977dfbb913a1240eaf6f708cth/* populate the protocol group properties */
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic void
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_set_proto_props(topo_mod_t *mod, tnode_t *dtn, int pinst)
184cd04c26b064536977dfbb913a1240eaf6f708cth /* set the asru */
184cd04c26b064536977dfbb913a1240eaf6f708cth "%s: topo_node_asru_set error %d\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth /* get the resource property */
184cd04c26b064536977dfbb913a1240eaf6f708cth /* set the child fru to the same as the resource */
184cd04c26b064536977dfbb913a1240eaf6f708cth * Set the properties of the disk node which include:
184cd04c26b064536977dfbb913a1240eaf6f708cth * group: protocol properties: resource, asru, label, fru
184cd04c26b064536977dfbb913a1240eaf6f708cth * group: authority properties: product-id, chasis-id, server-id
184cd04c26b064536977dfbb913a1240eaf6f708cth * group: io properties: devfs-path
184cd04c26b064536977dfbb913a1240eaf6f708cth * group: storage properties:
184cd04c26b064536977dfbb913a1240eaf6f708cth * - logical-disk, disk-model, disk-manufacturer, serial-number
184cd04c26b064536977dfbb913a1240eaf6f708cth * - firmware-revision, capacity-in-bytes
184cd04c26b064536977dfbb913a1240eaf6f708cthstatic void
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_set_props(tnode_t *dtn, tnode_t *parent, char *model, char *manuf,
184cd04c26b064536977dfbb913a1240eaf6f708cth char *serial, char *firm, char *cap, int *err, topo_mod_t *mod)
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_prop_get_string(parent, TOPO_BINDING_PGROUP, TOPO_BINDING_OCCUPANT,
184cd04c26b064536977dfbb913a1240eaf6f708cth /* set the protocol group properties */
184cd04c26b064536977dfbb913a1240eaf6f708cth /* create/set the authority group */
184cd04c26b064536977dfbb913a1240eaf6f708cth if (topo_pgroup_create(dtn, &disk_auth_pgroup, err) == 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth /* create/set the devfs-path in the io group */
184cd04c26b064536977dfbb913a1240eaf6f708cth /* create the storage group */
184cd04c26b064536977dfbb913a1240eaf6f708cth /* set the storage group properties */
184cd04c26b064536977dfbb913a1240eaf6f708cth /* populate the storage group properties */
184cd04c26b064536977dfbb913a1240eaf6f708cth TOPO_STORAGE_SERIAL_NUM, TOPO_PROP_IMMUTABLE, serial, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth TOPO_STORAGE_FIRMWARE_REV, TOPO_PROP_IMMUTABLE, firm, err);
184cd04c26b064536977dfbb913a1240eaf6f708cth/* create the disk topo node */
184cd04c26b064536977dfbb913a1240eaf6f708cth/*ARGSUSED*/
184cd04c26b064536977dfbb913a1240eaf6f708cth const char *name, topo_instance_t i, char *model, char *manuf,
184cd04c26b064536977dfbb913a1240eaf6f708cth fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, name, i,
184cd04c26b064536977dfbb913a1240eaf6f708cth else if (*s != NULL)
184cd04c26b064536977dfbb913a1240eaf6f708cth "Unable to make nvlist for %s bind: %s.\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth if ((dtn = topo_node_bind(mod, parent, name, i, fmri)) == NULL) {
184cd04c26b064536977dfbb913a1240eaf6f708cth "topo_node_bind (%s%d/%s%d) failed: %s\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth /* add the properties of the disk */
184cd04c26b064536977dfbb913a1240eaf6f708cth disk_set_props(dtn, parent, model, manuf, serial, firm, cap,
184cd04c26b064536977dfbb913a1240eaf6f708cth/*ARGSUSED*/
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_declare(tnode_t *parent, const char *name, topo_instance_t i,
184cd04c26b064536977dfbb913a1240eaf6f708cth /* create the node */
184cd04c26b064536977dfbb913a1240eaf6f708cth /* set the parent fru */
184cd04c26b064536977dfbb913a1240eaf6f708cth if (topo_method_register(mod, dtn, disk_methods) != 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth "topo_method_register failed: %s\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth/*ARGSUSED*/
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_enum(topo_mod_t *mod, tnode_t *rnode, const char *name,
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_instance_t min, topo_instance_t max, void *arg, void *notused)
184cd04c26b064536977dfbb913a1240eaf6f708cth "Currently only know how to enumerate %s components.\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth return (-1);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_prop_get_string(rnode, TOPO_BINDING_PGROUP, TOPO_BINDING_OCCUPANT,
184cd04c26b064536977dfbb913a1240eaf6f708cth if ((dnode = disk_di_node_match_device(device)) == NULL) {
184cd04c26b064536977dfbb913a1240eaf6f708cth "No occupant found for bay=%d.\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth return (-1);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (0);
184cd04c26b064536977dfbb913a1240eaf6f708cth * Query the current disk status. If successful, the disk status is returned as
184cd04c26b064536977dfbb913a1240eaf6f708cth * an nvlist consisting of at least the following members:
184cd04c26b064536977dfbb913a1240eaf6f708cth * protocol string Supported protocol (currently "scsi")
184cd04c26b064536977dfbb913a1240eaf6f708cth * status nvlist Arbitrary protocol-specific information
184cd04c26b064536977dfbb913a1240eaf6f708cth * about the current state of the disk.
184cd04c26b064536977dfbb913a1240eaf6f708cth * faults nvlist A list of supported faults. Each
184cd04c26b064536977dfbb913a1240eaf6f708cth * element of this list is a boolean value.
184cd04c26b064536977dfbb913a1240eaf6f708cth * An element's existence indicates that
184cd04c26b064536977dfbb913a1240eaf6f708cth * the drive supports detecting this fault,
184cd04c26b064536977dfbb913a1240eaf6f708cth * and the value indicates the current
184cd04c26b064536977dfbb913a1240eaf6f708cth * state of the fault.
184cd04c26b064536977dfbb913a1240eaf6f708cth * <fault-name> nvlist For each fault named in 'faults', a
184cd04c26b064536977dfbb913a1240eaf6f708cth * nvlist describing protocol-specific
184cd04c26b064536977dfbb913a1240eaf6f708cth * attributes of the fault.
184cd04c26b064536977dfbb913a1240eaf6f708cth * This method relies on the libdiskstatus library to query this information.
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_status(topo_mod_t *mod, tnode_t *nodep, topo_version_t vers,
184cd04c26b064536977dfbb913a1240eaf6f708cth * If the caller specifies the "path" parameter, then this indicates
184cd04c26b064536977dfbb913a1240eaf6f708cth * that we should use this instead of deriving it from the topo node
184cd04c26b064536977dfbb913a1240eaf6f708cth if (nvlist_lookup_string(in_nvl, "path", &fullpath) == 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth * Get the /devices path and attempt to open the disk status
184cd04c26b064536977dfbb913a1240eaf6f708cth * Note that sizeof(string) includes the terminating NULL byte
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) snprintf(fullpath, pathlen, "/devices%s%s", devpath,
184cd04c26b064536977dfbb913a1240eaf6f708cth return (0);
184cd04c26b064536977dfbb913a1240eaf6f708cth/* di_devlink callback for disk_drvinst2devpath */
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_drvinst2devpath_devlink_callback(di_devlink_t dl, void *arg)
184cd04c26b064536977dfbb913a1240eaf6f708cthdisk_di_node_add(int *instancep, char *devid, di_node_t node, topo_mod_t *mod)
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_lock(&(disk_di_nodes.disk_di_nodes_lock));
184cd04c26b064536977dfbb913a1240eaf6f708cth for (dnode = topo_list_next(&(disk_di_nodes.disk_di_nodes_list));
184cd04c26b064536977dfbb913a1240eaf6f708cth if ((dnode = topo_mod_alloc(mod, sizeof (disk_di_node_t))) == NULL) {
184cd04c26b064536977dfbb913a1240eaf6f708cth "disk_node_add - topo_mod_alloc failed\n");
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_unlock(&disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) snprintf(minorpath, mlen, "%s%s", dnode->ddn_dpath,
184cd04c26b064536977dfbb913a1240eaf6f708cth /* walk devlink looking for node that maps to /device path */
184cd04c26b064536977dfbb913a1240eaf6f708cth (void *)&devpath, disk_drvinst2devpath_devlink_callback);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_list_append(&disk_di_nodes.disk_di_nodes_list, (void *)dnode);
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_unlock(&disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth "disk_node_add - adding %s inst: %d\n",
184cd04c26b064536977dfbb913a1240eaf6f708cth/*ARGSUSED*/
184cd04c26b064536977dfbb913a1240eaf6f708cth static int instance_devid = 0;
184cd04c26b064536977dfbb913a1240eaf6f708cth /* only interested in nodes that have devids */
184cd04c26b064536977dfbb913a1240eaf6f708cth /* ... with a string representation of the devid */
184cd04c26b064536977dfbb913a1240eaf6f708cth /* create/find the devid scsi topology node */
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) disk_di_node_add(&instance_devid, devidstr, node, mod);
184cd04c26b064536977dfbb913a1240eaf6f708cth/*ARGSUSED*/
184cd04c26b064536977dfbb913a1240eaf6f708cth * Turn on module debugging output
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod, "initializing %s enumerator\n", DISK);
184cd04c26b064536977dfbb913a1240eaf6f708cth if (topo_mod_register(mod, &disk_info, TOPO_VERSION) != 0) {
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_init(&disk_di_nodes.disk_di_nodes_lock, NULL);
184cd04c26b064536977dfbb913a1240eaf6f708cth /* we don't get all the nodes with topo_mod_devinfo */
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_destroy(&disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (-1);
184cd04c26b064536977dfbb913a1240eaf6f708cth /* walk the tree to get the devids */
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_destroy(&disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (-1);
184cd04c26b064536977dfbb913a1240eaf6f708cth topo_mod_dprintf(mod, "%s enumerator initialized\n", DISK);
184cd04c26b064536977dfbb913a1240eaf6f708cth return (0);
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_lock(&disk_di_nodes.disk_di_nodes_lock);
184cd04c26b064536977dfbb913a1240eaf6f708cth while ((dnode = topo_list_next(&(disk_di_nodes.disk_di_nodes_list)))
184cd04c26b064536977dfbb913a1240eaf6f708cth (void) pthread_mutex_unlock(&disk_di_nodes.disk_di_nodes_lock);