/*
* 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
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/ddi_impldefs.h>
#include <sys/ddi_implfuncs.h>
#include <sys/sysmacros.h>
#include <sys/devcache.h>
/*
* The nvpair name in the I/O retire specific sub-nvlist
*/
/*
* decoded retire list element
*/
typedef enum rio_store_flags {
RIO_STORE_F_INVAL = 0,
typedef struct rio_store {
char *rst_devpath;
} rio_store_t;
/*
* Retire I/O persistent store registration info
*/
"/etc/devices/retire_store", /* path to store */
rio_store_decode, /* decode nvlist into retire_list */
rio_store_encode, /* encode retire_list into nvlist */
retire_list_free, /* free retire_list */
NULL /* write complete callback */
};
static int store_debug = 0;
static int bypass_msg = 0;
static int retire_msg = 0;
/*
* We don't use the simple read disable offered by the
* caching framework (see devcache.c) as it will not
* have the desired effect of bypassing the persistent
* store. A simple read disable will
*
* 1. cause any additions to the cache to destroy the
* existing on-disk cache
*
* 2. prevent deletions from the existing on-disk
* cache which is needed for recovery from bad
* retire decisions.
*
* Use the following tunable instead
*
*/
int ddi_retire_store_bypass = 0;
/*
* Initialize retire store data structures
*/
void
retire_store_init(void)
{
if (boothowto & RB_ASKNAME) {
} else if (store_path[0] != '\0') {
if (store_path[0] != '/') {
printf("Invalid store path: %s. Using default"
"\n", store_path);
} else {
}
}
}
}
/*
* Read and populate the in-core retire store
*/
void
retire_store_read(void)
{
(void) nvf_read_file(rio_store_handle);
}
static void
{
}
static void
{
}
}
static int
{
int rval;
version = 0;
return (EINVAL);
}
magic = 0;
return (EINVAL);
}
flags = 0;
return (EINVAL);
}
if (ddi_retire_store_bypass) {
if (!bypass_msg) {
bypass_msg = 1;
"Bypassing retire store /etc/devices/retire_store");
}
}
if (!retire_msg) {
retire_msg = 1;
}
return (0);
}
static int
{
int rval;
if (rval != 0) {
return (DDI_FAILURE);
}
int flags;
if (rval != 0) {
goto error;
}
if (rval != 0) {
goto error;
}
if (rval != 0) {
goto error;
}
/* don't save the bypass flag */
flags);
if (rval != 0) {
goto error;
}
if (rval != 0) {
goto error;
}
}
return (DDI_SUCCESS);
return (DDI_FAILURE);
}
int
{
char *new_path;
/* already there */
/* explicit retire, clear bypass flag (if any) */
": %s", devpath));
return (0);
}
}
return (0);
}
int
{
int is_dirty = 0;
continue;
devpath));
is_dirty = 1;
}
if (is_dirty)
return (is_dirty);
}
int
{
int retired;
retired = 0;
/*
* If the "bypass" flag is set, then the device
* is *not* retired for the current boot of the
* system. It indicates that the retire store
* was read but the devices in the retire store
* were not retired i.e. effectively the store
* was bypassed. For why we bother to even read
* the store when we bypass it, see the comments
* for the tunable ddi_retire_store_bypass.
*/
rsp->rst_devpath));
continue;
}
/*
* device is retired, if it or a parent exists
* in the in-core list
*/
continue;
/* exact match or a child */
retired = 1;
devpath));
break;
}
}
return (retired);
}