275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * CDDL HEADER START
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * The contents of this file are subject to the terms of the
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * Common Development and Distribution License (the "License").
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * You may not use this file except in compliance with the License.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * See the License for the specific language governing permissions
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * and limitations under the License.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * When distributing Covered Code, include this CDDL HEADER in each
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * If applicable, add the following below this CDDL HEADER, with the
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * fields enclosed by brackets "[]" replaced with your own identifying
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * information: Portions Copyright [yyyy] [name of copyright owner]
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * CDDL HEADER END
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_snap_find_page(ses_snap_t *sp, ses2_diag_page_t page, boolean_t ctl)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (pp = sp->ss_pages; pp != NULL; pp = pp->ssp_next)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (pp->ssp_num == page && pp->ssp_control == ctl &&
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((newbuf = ses_realloc(pp->ssp_page, min)) == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock bzero(newbuf + pp->ssp_len, pp->ssp_alloc - pp->ssp_len);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((pp = ses_zalloc(sizeof (ses_snap_page_t))) == NULL)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((pp->ssp_page = ses_zalloc(SES2_MIN_DIAGPAGE_ALLOC)) == NULL) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) munmap(pp->ssp_mmap_base, pp->ssp_mmap_len);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * Grow (if needed) the control page buffer, fill in the page code, page
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * length, and generation count, and return a pointer to the page. The
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * caller is responsible for filling in the rest of the page data. If 'unique'
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * is specified, then a new page instance is created instead of sharing the
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * current one.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_snap_ctl_page(ses_snap_t *sp, ses2_diag_page_t page, size_t dlen,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * The user has requested a unique instance of the page. Create
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * a new ses_snap_page_t instance and chain it off the
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * 'ssp_instances' list of the master page. These must be
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * appended to the end of the chain, as the order of operations
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * may be important (i.e. microcode download).
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (pp->ssp_alloc < len && grow_snap_page(pp, len) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock len - offsetof(spc3_diag_page_impl_t, sdpi_data[0]));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SCSI_WRITE32((uint8_t *)pip + dp->spd_gcoff, sp->ss_generation);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockread_status_page(ses_snap_t *sp, ses2_diag_page_t page)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (pp = sp->ss_pages; pp != NULL; pp = pp->ssp_next)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * No matching page. Since the page number is not under consumer or
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * device control, this must be a bug.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock flags = LIBSCSI_AF_READ | LIBSCSI_AF_SILENT | LIBSCSI_AF_DIAGNOSE |
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SPC3_CMD_RECEIVE_DIAGNOSTIC_RESULTS, flags, pp->ssp_page,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (ses_libscsi_error(tp->st_scsi_hdl, "failed to "
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock "allocate SCSI action"));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock "receive diagnostic results failed"));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock "receive diagnostic results failed");
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) libscsi_action_get_buffer(ap, &buf, &alloc, &pp->ssp_len);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (pp->ssp_alloc - pp->ssp_len < 0x80 && pp->ssp_alloc < UINT16_MAX) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim if (pp->ssp_len < offsetof(spc3_diag_page_impl_t, sdpi_data)) {
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim return (ses_error(ESES_BAD_RESPONSE, "target returned "
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim "truncated page 0x%x (length %d)", page, pp->ssp_len));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (ses_error(ESES_BAD_RESPONSE, "target returned page 0x%x "
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock "instead of the requested page 0x%x", retpage, page));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrocksend_control_page(ses_snap_t *sp, ses_snap_page_t *pp)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock flags = LIBSCSI_AF_WRITE | LIBSCSI_AF_SILENT | LIBSCSI_AF_DIAGNOSE |
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock ap = libscsi_action_alloc(tp->st_scsi_hdl, SPC3_CMD_SEND_DIAGNOSTIC,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (ses_libscsi_error(tp->st_scsi_hdl, "failed to "
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock "allocate SCSI action"));
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock cp = (spc3_send_diagnostic_cdb_t *)libscsi_action_get_cdb(ap);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock SCSI_WRITE16(&cp->sdc_parameter_list_length, pp->ssp_len);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock "SEND DIAGNOSTIC command failed for page 0x%x",
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) ses_scsi_error(ap, "SEND DIAGNOSTIC command "
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (read_status_page(sp, SES2_DIAGPAGE_SUPPORTED_PAGES) != 0) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (i = 0; i < npages; i++) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (!SES_WITHIN_PAGE(pip->sssdpi_pages + i, 1, pip,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * Skip the page we already added during the bootstrap.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * The end of the page list may be padded with zeros; ignore
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * them all.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (page == 0 && i > 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * Allocate a control page as well, if we can use it.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (ses_get_pagedesc(tp, page, SES_PAGE_CTL) != NULL) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (-1);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if ((sp = ses_zalloc(sizeof (ses_snap_t))) == NULL)
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * First check for the short enclosure status diagnostic page and
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * determine if this is a simple subenclosure or not.
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim for (pp = sp->ss_pages; pp != NULL; pp = pp->ssp_next) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (pp = sp->ss_pages; pp != NULL; pp = pp->ssp_next) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * We skip all of:
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * - Control pages
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * - Pages we've already filled in
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * - Pages we don't understand (those with no descriptor)
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * If this page is required, and this is not a simple
ac88567a7a5bb7f01cf22cf366bc9d6203e24d7aHyon Kim * subenclosure, then fail the entire snapshot.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * If the generation code has changed, we don't have a valid
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * snapshot. Start over.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock "too many generation count "
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock "mismatches: page 0x%x gc %u "
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * The LIBSES_TRUNCATE environment variable is a debugging tool which,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * if set, randomly truncates all pages (except
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * SES2_DIAGPAGE_SUPPORTED_PAGES). In order to be truly evil, we
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * mmap() each page with enough space after it so we can move the data
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * up to the end of a page and unmap the following page so that any
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * attempt to read past the end of the page results in a segfault.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * Count the maximum number of pages we will need and allocate
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * the necessary space.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (pp = sp->ss_pages; pp != NULL; pp = pp->ssp_next) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock "failed to mmap() pages for truncation");
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (pp = sp->ss_pages; pp != NULL; pp = pp->ssp_next) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pages = P2ROUNDUP(pp->ssp_len, pagesize) / pagesize;
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) memcpy(pp->ssp_mmap_base + pp->ssp_mmap_len -
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock pp->ssp_page = pp->ssp_mmap_base + pp->ssp_mmap_len -
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) munmap(pp->ssp_mmap_base + pages * pagesize,
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (pp = sp->ss_pages; pp != NULL; pp = pp->ssp_next) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (pp->ssp_initialized && send_control_page(sp, pp) != 0)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (up = pp->ssp_unique; up != NULL; up = up->ssp_next) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock for (pp = sp->ss_pages; pp != NULL; pp = pp->ssp_next) {
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_walk_node(ses_node_t *np, ses_walk_f func, void *arg)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock if (ses_walk_node(ses_node_child(np), func, arg) ==
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrockses_walk(ses_snap_t *sp, ses_walk_f func, void *arg)
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock (void) ses_walk_node(ses_root_node(sp), func, arg);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock return (0);
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock/*ARGSUSED*/
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * Given an ID returned by ses_node_id(), lookup and return the corresponding
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * node in the snapshot. If the snapshot generation count has changed, then
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * return failure.
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock "no such node in snapshot");
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock * If this is our first lookup attempt, construct the array for fast
275c9da86e89f8abf71135cf63d9fc23671b2e60eschrock "no such node in snapshot");