/*
* 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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* NAME: raid_replay.c
*
* DESCRIPTION: RAID driver source file containing routines related to replay
* operation.
*
* ROUTINES PROVIDED FOR EXTERNAL USE:
* raid_replay() - replay all the pre write entries in the unit.
*/
#include <sys/sysmacros.h>
/* functions forward declarations */
int raid_total_rply_entries = 0;
/*
* NAMES: raid_rply_dealloc, raid_rply_alloc
* DESCRIPTION: RAID metadevice replay buffer allocation/deallocation routines
* PARAMETERS: mr_unit_t *un - pointer to the unit structure
* mr_unit_t *un - pointer to the unit structure
* RETURNS:
*/
static void
{
int i;
}
}
}
}
}
}
}
}
static void
{
int i;
/* intialization */
KM_SLEEP);
/* allocate all the buffers required for the replay processing */
/* Initialize semaphores */
SEMA_DEFAULT, NULL);
SEMA_DEFAULT, NULL);
}
/* Initialize semaphores */
SEMA_DEFAULT, NULL);
SEMA_DEFAULT, NULL);
/* Initialize semaphores */
SEMA_DEFAULT, NULL);
SEMA_DEFAULT, NULL);
}
/*
* NAMES: rpl_insert, rpl_delete, rpl_find
* DESCRIPTION: RAID metadevice replay list processing APIs
* PARAMETERS: raid_rplylst_t *list - pointer to the replay list.
* raid_pwhdr_t *pwptr - pointer to a pre-write header.
* RETURNS:
*/
static void
{
break;
}
}
}
static void
{
}
static raid_rplylst_t *
{
return (tmp);
}
}
return ((raid_rplylst_t *)NULL);
}
/*
* NAMES: enq_rplylst
* DESCRIPTION: Enqueue a pre-write header into the replay list.
* PARAMETERS: raid_rplylst_t *list - pointer to the replay list.
* raid_pwhdr_t *pwptr - pointer to a pre-write header.
* RETURNS:
*/
static void
{
/* check if the pre-write existed in the list */
sizeof (raid_pwhdr_t));
} else {
KM_SLEEP);
sizeof (raid_pwhdr_t));
}
}
/*
* NAMES: pw_read_done and pw_write_done
* DESCRIPTION: don't know the usage yet ??? (TBD)
* PARAMETERS:
* RETURNS:
*/
static int
{
else
/* wakeup the thread waiting on this buf */
return (0);
}
static int
{
else
/* wakeup the thread waiting on this buf */
return (0);
}
/*
* NAMES: raid_pwhdr_read
* DESCRIPTION: issue a syncronous read to read a pre-write header
* PARAMETERS: mr_unit_t *un - pointer to the unit structure
* int pw_slot - pre-write entry slot number
* int column - column number for the pre-write entry
* raid_rplybuf_t *bufp - pointer to the replay buffer structure
* RETURNS:
*/
static void
{
/* set up pointers from raid_rplybuf_t *bufp */
/* calculate the data address or block number */
}
/*
* NAMES: raid_pw_read
* DESCRIPTION: issue a syncronous read to read a pre-write entry
* PARAMETERS: mr_unit_t *un - pointer to the unit structure
* int column - column number for the pre-write entry
* u_int slot - pre-write entry slot number
* raid_rplybuf_t *bufp - pointer to the replay buffer structure
* RETURNS:
*/
static int
{
int error;
/* if this column is no longer accessible, return */
return (RAID_RPLY_COMPREPLAY);
/* set up pointers from raid_rplybuf_t *bufp */
/* calculate the data address or block number */
return (error);
}
return (0);
}
/*
* NAMES: raid_pw_write
* DESCRIPTION: issue a syncronous write to write a pre-write entry
* PARAMETERS: mr_unit_t *un - pointer to the unit structure
* int column - column number for the pre-write entry
* raid_pwhdr_t *pwhp - needed for some infos about the pw header
* raid_rplybuf_t *bufp - pointer to the replay buffer structure
* RETURNS:
*/
static int
{
int error;
/* if this column is no longer accessible, return */
return (RAID_RPLY_COMPREPLAY);
/* set up pointers from raid_rplybuf_t *bufp */
/* calculate the data address or block number */
return (error);
}
return (0);
}
/*
* NAMES: genchecksum
* DESCRIPTION: generate check sum for a pre-write entry
* PARAMETERS: caddr_t addr - where the data bytes are
* int bcount - number of bytes in the pre-write entry
* RETURNS:
*/
static uint_t
{
while (wordcnt--) {
dbuf++;
}
return (dsum);
}
/*
* NAMES: raid_rply_verify
* DESCRIPTION: verify the pre-write entry for replay
* PARAMETERS: mr_unit_t *un - pointer to unit structure
* int col1 - column number 1
* int goodsum1 - flag to indicate good checksum
* int *do_1 - flag to indicate whether we should replay
* the first pre-write
* int col2 - column number 2
* int goodsum2 - flag to indicate good checksum
* int *do_2 - flag to indicate whether we should replay
* the first pre-write
* RETURNS:
*/
static void
{
int good_state1 = 0;
int good_state2 = 0;
good_state1 = 1;
}
good_state2 = 1;
}
/* if both columns check out, do it */
/* if one column is okay and the other is errored, do it */
/* if one column is okay and the other is errored, do it */
}
}
/*
* NAMES: raid_rplyeach
* DESCRIPTION: issue a syncronous read to read a pre-write header
* PARAMETERS: mr_unit_t *un - pointer to the unit structure
* raid_rplylst_t *eachp - pointer to the replay list entry
* raid_rplybuf_t *rwbuf1 - pointer to the replay buffer structure
* raid_rplybuf_t *rwbuf2 - pointer to the replay buffer structure
* RETURNS:
*/
static int
)
{
int good_pw1 = 0;
int good_pw2 = 0;
int do_1 = 0;
int do_2 = 0;
int error = 0;
/* First verify the normal case - two pre-write entries are all good */
/* read the pre-write entries */
if (error) {
if (error != RAID_RPLY_COMPREPLAY)
return (error);
} else {
/* generate checksum for each pre-write entry */
}
rwbuf2);
if (error) {
if (error != RAID_RPLY_COMPREPLAY)
return (error);
} else {
/* generate checksum for pre-write entry */
}
/* verify the checksums and states */
/* write (replay) the pre-write entries */
if (do_1) {
return (error);
}
}
if (do_2) {
return (error);
}
}
return (0);
}
/*
* if partner was errored at time of write
* or due to open or replay, replay this entry
*/
/* read the pre-write entry */
if (error)
return (error);
/* generate checksum for the pre-write entry */
return (error);
}
}
}
return (0);
}
return (0);
}
static int
{
int i;
int cnt;
long long id;
int dsum;
int error;
int down;
return (0);
/*
* check: 1 - enough equal ids
* 2 - all have same columncnt
* 3 - all have same blkno
* 4 - all have same blkcnt
*
* read each and check the checksum
* write each
*/
return (0);
if (error) {
if (error == RAID_RPLY_COMPREPLAY)
return (0);
else
return (1);
}
for (i = 1; i < cnt; i++) {
break;
return (0);
}
return (0);
}
colcnt = i;
if (error)
return (0);
if ((i != un->un_totalcolumncnt) &&
return (0);
/* there ara enough columns to write correctly */
for (i = 0; i < colcnt; i++) {
return (1);
}
return (0);
}
/*
* NAMES: raid_replay_error
* DESCRIPTION: RAID metadevice replay error handling routine (TBD)
* PARAMETERS:
* RETURNS:
*/
static int
{
}
return (error);
}
/*
* NAMES: raid_replay
* DESCRIPTION: RAID metadevice main replay processing routine
* PARAMETERS: mr_unit_t *un - pointer to an unit structure
* RETURNS:
*/
int
{
int error = 0;
int i, j;
/* build a replay list based on the order of pre-write id */
/* issue a synchronous read for each column */
for (j = 0; j < un->un_totalcolumncnt; j++) {
if (COLUMN_ISUP(un, j)) {
/* wait for I/O completion for each column */
/* potential state transition */
if (error == RAID_RPLY_COMPREPLAY)
continue;
else
goto replay_failed;
}
pwhdrp = (raid_pwhdr_t *)
} else {
pwhdrp);
}
/* first check pre-write magic number */
continue;
}
if (pwhdrp->rpw_column != j) {
continue;
}
continue;
}
continue;
}
if (pwhdrp->rpw_blkcnt == 0) {
continue;
}
continue;
}
if ((pwhdrp->rpw_columnnum < 0) ||
continue;
}
continue;
}
}
}
}
/* replay each entry in the replay list */
/* zero out the pre-write headers in the buffer */
else
goto replay_failed;
}
/* free the processed replay list entry */
}
/* zero out all pre-write entries in this unit */
for (j = 0; j < un->un_totalcolumncnt; j++) {
if (COLUMN_ISUP(un, j)) {
colptr->un_pwstart, j))
break;
}
}
/* deallocate all the buffer resource allocated in this routine */
return (RAID_RPLY_SUCCESS);
/* first release the list */
}
/* then release buffers */
/* also reset the pre-write id variable to one */
return (error);
}