/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include "ses_impl.h"
{
return (pp);
return (NULL);
}
static int
{
return (-1);
return (0);
}
static ses_snap_page_t *
alloc_snap_page(void)
{
return (NULL);
return (NULL);
}
return (pp);
}
static void
{
return;
if (pp->ssp_mmap_base)
else
}
static void
{
}
}
/*
* Grow (if needed) the control page buffer, fill in the page code, page
* length, and generation count, and return a pointer to the page. The
* caller is responsible for filling in the rest of the page data. If 'unique'
* is specified, then a new page instance is created instead of sharing the
* current one.
*/
{
(void) ses_set_errno(ESES_NOTSUP);
return (NULL);
}
return (pp);
if (unique) {
/*
* The user has requested a unique instance of the page. Create
* a new ses_snap_page_t instance and chain it off the
* 'ssp_instances' list of the master page. These must be
* appended to the end of the chain, as the order of operations
* may be important (i.e. microcode download).
*/
return (NULL);
;
}
return (NULL);
return (pp);
}
static int
{
break;
/*
* No matching page. Since the page number is not under consumer or
* device control, this must be a bug.
*/
"allocate SCSI action"));
"receive diagnostic results failed"));
}
if (libscsi_action_get_status(ap) != 0) {
(void) ses_scsi_error(ap,
"receive diagnostic results failed");
return (-1);
}
if (grow_snap_page(pp, 0) != 0)
return (-1);
goto again;
}
}
return (0);
if (retpage == SES2_DIAGPAGE_ENCLOSURE_BUSY) {
if (++retries > LIBSES_MAX_BUSY_RETRIES)
"enclosure busy responses for page 0x%x", page));
goto again;
}
}
static int
{
"allocate SCSI action"));
"SEND DIAGNOSTIC command failed for page 0x%x",
}
if (libscsi_action_get_status(ap) != 0) {
return (-1);
}
return (0);
}
static int
{
off_t i;
return (-1);
return (-1);
}
for (i = 0; i < npages; i++) {
pagelen))
break;
/*
* Skip the page we already added during the bootstrap.
*/
if (page == SES2_DIAGPAGE_SUPPORTED_PAGES)
continue;
/*
* The end of the page list may be padded with zeros; ignore
* them all.
*/
if (page == 0 && i > 0)
break;
return (-1);
}
/*
* Allocate a control page as well, if we can use it.
*/
return (-1);
}
}
}
return (0);
}
static void
{
}
static void
{
return;
else
}
{
return (sp);
}
void
{
}
{
char *scratch;
return (NULL);
if (pages_skel_create(sp) != 0) {
return (NULL);
}
/*
* First check for the short enclosure status diagnostic page and
* determine if this is a simple subenclosure or not.
*/
}
/*
* We skip all of:
*
* - Control pages
* - Pages we've already filled in
* - Pages we don't understand (those with no descriptor)
*/
continue;
SES_PAGE_DIAG)) == NULL)
continue;
/*
* If this page is required, and this is not a simple
* subenclosure, then fail the entire snapshot.
*/
!simple)) {
return (NULL);
}
continue;
}
/*
* If the generation code has changed, we don't have a valid
* snapshot. Start over.
*/
if (++retries > LIBSES_MAX_GC_RETRIES) {
(void) ses_error(ESES_TOOMUCHCHANGE,
"too many generation count "
"mismatches: page 0x%x gc %u "
return (NULL);
}
goto again;
}
}
}
/*
* The LIBSES_TRUNCATE environment variable is a debugging tool which,
* if set, randomly truncates all pages (except
* SES2_DIAGPAGE_SUPPORTED_PAGES). In order to be truly evil, we
* mmap() each page with enough space after it so we can move the data
* up to the end of a page and unmap the following page so that any
* attempt to read past the end of the page results in a segfault.
*/
/*
* Count the maximum number of pages we will need and allocate
* the necessary space.
*/
pages = 0;
continue;
pagesize) + 1;
}
-1, 0)) == MAP_FAILED) {
(void) ses_error(ESES_NOMEM,
"failed to mmap() pages for truncation");
return (NULL);
}
continue;
pagesize);
}
}
if (ses_fill_snap(sp) != 0) {
return (NULL);
}
return (sp);
}
int
{
if (!pp->ssp_control)
continue;
goto error;
goto error;
}
}
ret = 0;
if (!pp->ssp_control)
continue;
}
}
return (ret);
}
{
return (sp->ss_generation);
}
static ses_walk_action_t
{
if (action == SES_WALK_ACTION_TERMINATE)
return (SES_WALK_ACTION_TERMINATE);
if (action == SES_WALK_ACTION_PRUNE ||
continue;
return (SES_WALK_ACTION_TERMINATE);
}
return (SES_WALK_ACTION_CONTINUE);
}
int
{
return (0);
}
/*ARGSUSED*/
static ses_walk_action_t
{
return (SES_WALK_ACTION_CONTINUE);
}
/*
* Given an ID returned by ses_node_id(), lookup and return the corresponding
* node in the snapshot. If the snapshot generation count has changed, then
* return failure.
*/
{
(void) ses_set_errno(ESES_CHANGED);
return (NULL);
}
(void) ses_error(ESES_BAD_NODE,
"no such node in snapshot");
return (NULL);
}
/*
* If this is our first lookup attempt, construct the array for fast
* lookups.
*/
return (NULL);
}
(void) ses_error(ESES_BAD_NODE,
"no such node in snapshot");
}