Home | History | Annotate | Line # | Download | only in raidframe
rf_evenodd.c revision 1.8
      1  1.8    oster /*	$NetBSD: rf_evenodd.c,v 1.8 2002/09/07 23:11:46 oster Exp $	*/
      2  1.1    oster /*
      3  1.1    oster  * Copyright (c) 1995 Carnegie-Mellon University.
      4  1.1    oster  * All rights reserved.
      5  1.1    oster  *
      6  1.1    oster  * Author: Chang-Ming Wu
      7  1.1    oster  *
      8  1.1    oster  * Permission to use, copy, modify and distribute this software and
      9  1.1    oster  * its documentation is hereby granted, provided that both the copyright
     10  1.1    oster  * notice and this permission notice appear in all copies of the
     11  1.1    oster  * software, derivative works or modified versions, and any portions
     12  1.1    oster  * thereof, and that both notices appear in supporting documentation.
     13  1.1    oster  *
     14  1.1    oster  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     15  1.1    oster  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
     16  1.1    oster  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     17  1.1    oster  *
     18  1.1    oster  * Carnegie Mellon requests users of this software to return to
     19  1.1    oster  *
     20  1.1    oster  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     21  1.1    oster  *  School of Computer Science
     22  1.1    oster  *  Carnegie Mellon University
     23  1.1    oster  *  Pittsburgh PA 15213-3890
     24  1.1    oster  *
     25  1.1    oster  * any improvements or extensions that they make and grant Carnegie the
     26  1.1    oster  * rights to redistribute these changes.
     27  1.1    oster  */
     28  1.1    oster 
     29  1.1    oster /*****************************************************************************************
     30  1.1    oster  *
     31  1.1    oster  * rf_evenodd.c -- implements EVENODD array architecture
     32  1.1    oster  *
     33  1.1    oster  ****************************************************************************************/
     34  1.7    lukem 
     35  1.7    lukem #include <sys/cdefs.h>
     36  1.8    oster __KERNEL_RCSID(0, "$NetBSD: rf_evenodd.c,v 1.8 2002/09/07 23:11:46 oster Exp $");
     37  1.1    oster 
     38  1.1    oster #include "rf_archs.h"
     39  1.1    oster 
     40  1.1    oster #if RF_INCLUDE_EVENODD > 0
     41  1.1    oster 
     42  1.6    oster #include <dev/raidframe/raidframevar.h>
     43  1.6    oster 
     44  1.1    oster #include "rf_raid.h"
     45  1.1    oster #include "rf_dag.h"
     46  1.1    oster #include "rf_dagffrd.h"
     47  1.1    oster #include "rf_dagffwr.h"
     48  1.1    oster #include "rf_dagdegrd.h"
     49  1.1    oster #include "rf_dagdegwr.h"
     50  1.1    oster #include "rf_dagutils.h"
     51  1.1    oster #include "rf_dagfuncs.h"
     52  1.1    oster #include "rf_etimer.h"
     53  1.1    oster #include "rf_general.h"
     54  1.1    oster #include "rf_evenodd.h"
     55  1.1    oster #include "rf_parityscan.h"
     56  1.1    oster #include "rf_utils.h"
     57  1.1    oster #include "rf_map.h"
     58  1.1    oster #include "rf_pq.h"
     59  1.1    oster #include "rf_mcpair.h"
     60  1.1    oster #include "rf_evenodd.h"
     61  1.1    oster #include "rf_evenodd_dagfuncs.h"
     62  1.1    oster #include "rf_evenodd_dags.h"
     63  1.1    oster #include "rf_engine.h"
     64  1.1    oster 
     65  1.1    oster typedef struct RF_EvenOddConfigInfo_s {
     66  1.2    oster 	RF_RowCol_t **stripeIdentifier;	/* filled in at config time & used by
     67  1.2    oster 					 * IdentifyStripe */
     68  1.2    oster }       RF_EvenOddConfigInfo_t;
     69  1.2    oster 
     70  1.2    oster int
     71  1.2    oster rf_ConfigureEvenOdd(listp, raidPtr, cfgPtr)
     72  1.2    oster 	RF_ShutdownList_t **listp;
     73  1.2    oster 	RF_Raid_t *raidPtr;
     74  1.2    oster 	RF_Config_t *cfgPtr;
     75  1.2    oster {
     76  1.2    oster 	RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
     77  1.2    oster 	RF_EvenOddConfigInfo_t *info;
     78  1.2    oster 	RF_RowCol_t i, j, startdisk;
     79  1.2    oster 
     80  1.2    oster 	RF_MallocAndAdd(info, sizeof(RF_EvenOddConfigInfo_t), (RF_EvenOddConfigInfo_t *), raidPtr->cleanupList);
     81  1.2    oster 	layoutPtr->layoutSpecificInfo = (void *) info;
     82  1.2    oster 
     83  1.2    oster 	RF_ASSERT(raidPtr->numRow == 1);
     84  1.2    oster 
     85  1.2    oster 	info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol, raidPtr->numCol, raidPtr->cleanupList);
     86  1.2    oster 	startdisk = 0;
     87  1.2    oster 	for (i = 0; i < raidPtr->numCol; i++) {
     88  1.2    oster 		for (j = 0; j < raidPtr->numCol; j++) {
     89  1.2    oster 			info->stripeIdentifier[i][j] = (startdisk + j) % raidPtr->numCol;
     90  1.2    oster 		}
     91  1.2    oster 		if ((startdisk -= 2) < 0)
     92  1.2    oster 			startdisk += raidPtr->numCol;
     93  1.2    oster 	}
     94  1.1    oster 
     95  1.2    oster 	/* fill in the remaining layout parameters */
     96  1.2    oster 	layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk;
     97  1.2    oster 	layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit << raidPtr->logBytesPerSector;
     98  1.2    oster 	layoutPtr->numDataCol = raidPtr->numCol - 2;	/* ORIG:
     99  1.2    oster 							 * layoutPtr->numDataCol
    100  1.2    oster 							 * = raidPtr->numCol-1;  */
    101  1.1    oster #if RF_EO_MATRIX_DIM > 17
    102  1.2    oster 	if (raidPtr->numCol <= 17) {
    103  1.2    oster 		printf("Number of stripe units in a parity stripe is smaller than 17. Please\n");
    104  1.2    oster 		printf("define the macro RF_EO_MATRIX_DIM in file rf_evenodd_dagfuncs.h to \n");
    105  1.2    oster 		printf("be 17 to increase performance. \n");
    106  1.2    oster 		return (EINVAL);
    107  1.2    oster 	}
    108  1.1    oster #elif RF_EO_MATRIX_DIM == 17
    109  1.2    oster 	if (raidPtr->numCol > 17) {
    110  1.2    oster 		printf("Number of stripe units in a parity stripe is bigger than 17. Please\n");
    111  1.2    oster 		printf("define the macro RF_EO_MATRIX_DIM in file rf_evenodd_dagfuncs.h to \n");
    112  1.2    oster 		printf("be 257 for encoding and decoding functions to work. \n");
    113  1.2    oster 		return (EINVAL);
    114  1.2    oster 	}
    115  1.1    oster #endif
    116  1.2    oster 	layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
    117  1.2    oster 	layoutPtr->numParityCol = 2;
    118  1.2    oster 	layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk;
    119  1.2    oster 	raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
    120  1.1    oster 
    121  1.2    oster 	raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk * layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
    122  1.1    oster 
    123  1.2    oster 	return (0);
    124  1.1    oster }
    125  1.1    oster 
    126  1.2    oster int
    127  1.2    oster rf_GetDefaultNumFloatingReconBuffersEvenOdd(RF_Raid_t * raidPtr)
    128  1.1    oster {
    129  1.2    oster 	return (20);
    130  1.1    oster }
    131  1.1    oster 
    132  1.2    oster RF_HeadSepLimit_t
    133  1.2    oster rf_GetDefaultHeadSepLimitEvenOdd(RF_Raid_t * raidPtr)
    134  1.1    oster {
    135  1.2    oster 	return (10);
    136  1.1    oster }
    137  1.1    oster 
    138  1.2    oster void
    139  1.2    oster rf_IdentifyStripeEvenOdd(
    140  1.2    oster     RF_Raid_t * raidPtr,
    141  1.2    oster     RF_RaidAddr_t addr,
    142  1.2    oster     RF_RowCol_t ** diskids,
    143  1.2    oster     RF_RowCol_t * outRow)
    144  1.1    oster {
    145  1.2    oster 	RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout, addr);
    146  1.2    oster 	RF_EvenOddConfigInfo_t *info = (RF_EvenOddConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
    147  1.1    oster 
    148  1.2    oster 	*outRow = 0;
    149  1.2    oster 	*diskids = info->stripeIdentifier[stripeID % raidPtr->numCol];
    150  1.1    oster }
    151  1.2    oster /* The layout of stripe unit on the disks are:      c0 c1 c2 c3 c4
    152  1.1    oster 
    153  1.1    oster  						     0  1  2  E  P
    154  1.1    oster 						     5  E  P  3  4
    155  1.1    oster 						     P  6  7  8  E
    156  1.1    oster 	 					    10 11  E  P  9
    157  1.1    oster 						     E  P 12 13 14
    158  1.1    oster 						     ....
    159  1.1    oster 
    160  1.2    oster   We use the MapSectorRAID5 to map data information because the routine can be shown to map exactly
    161  1.1    oster   the layout of data stripe unit as shown above although we have 2 redundant information now.
    162  1.1    oster   But for E and P, we use rf_MapEEvenOdd and rf_MapParityEvenOdd which are different method from raid-5.
    163  1.1    oster */
    164  1.1    oster 
    165  1.1    oster 
    166  1.2    oster void
    167  1.2    oster rf_MapParityEvenOdd(
    168  1.2    oster     RF_Raid_t * raidPtr,
    169  1.2    oster     RF_RaidAddr_t raidSector,
    170  1.2    oster     RF_RowCol_t * row,
    171  1.2    oster     RF_RowCol_t * col,
    172  1.2    oster     RF_SectorNum_t * diskSector,
    173  1.2    oster     int remap)
    174  1.1    oster {
    175  1.2    oster 	RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
    176  1.2    oster 	RF_StripeNum_t endSUIDofthisStrip = (SUID / raidPtr->Layout.numDataCol + 1) * raidPtr->Layout.numDataCol - 1;
    177  1.1    oster 
    178  1.2    oster 	*row = 0;
    179  1.2    oster 	*col = (endSUIDofthisStrip + 2) % raidPtr->numCol;
    180  1.2    oster 	*diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit +
    181  1.2    oster 	    (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
    182  1.1    oster }
    183  1.1    oster 
    184  1.2    oster void
    185  1.2    oster rf_MapEEvenOdd(
    186  1.2    oster     RF_Raid_t * raidPtr,
    187  1.2    oster     RF_RaidAddr_t raidSector,
    188  1.2    oster     RF_RowCol_t * row,
    189  1.2    oster     RF_RowCol_t * col,
    190  1.2    oster     RF_SectorNum_t * diskSector,
    191  1.2    oster     int remap)
    192  1.1    oster {
    193  1.2    oster 	RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
    194  1.2    oster 	RF_StripeNum_t endSUIDofthisStrip = (SUID / raidPtr->Layout.numDataCol + 1) * raidPtr->Layout.numDataCol - 1;
    195  1.1    oster 
    196  1.2    oster 	*row = 0;
    197  1.2    oster 	*col = (endSUIDofthisStrip + 1) % raidPtr->numCol;
    198  1.2    oster 	*diskSector = (SUID / (raidPtr->Layout.numDataCol)) * raidPtr->Layout.sectorsPerStripeUnit +
    199  1.2    oster 	    (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
    200  1.1    oster }
    201  1.1    oster 
    202  1.2    oster void
    203  1.2    oster rf_EODagSelect(
    204  1.2    oster     RF_Raid_t * raidPtr,
    205  1.2    oster     RF_IoType_t type,
    206  1.2    oster     RF_AccessStripeMap_t * asmap,
    207  1.2    oster     RF_VoidFuncPtr * createFunc)
    208  1.1    oster {
    209  1.2    oster 	RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
    210  1.2    oster 	unsigned ndfail = asmap->numDataFailed;
    211  1.2    oster 	unsigned npfail = asmap->numParityFailed + asmap->numQFailed;
    212  1.2    oster 	unsigned ntfail = npfail + ndfail;
    213  1.2    oster 
    214  1.2    oster 	RF_ASSERT(RF_IO_IS_R_OR_W(type));
    215  1.2    oster 	if (ntfail > 2) {
    216  1.2    oster 		RF_ERRORMSG("more than two disks failed in a single group!  Aborting I/O operation.\n");
    217  1.2    oster 		 /* *infoFunc = */ *createFunc = NULL;
    218  1.2    oster 		return;
    219  1.2    oster 	}
    220  1.2    oster 	/* ok, we can do this I/O */
    221  1.2    oster 	if (type == RF_IO_TYPE_READ) {
    222  1.2    oster 		switch (ndfail) {
    223  1.2    oster 		case 0:
    224  1.2    oster 			/* fault free read */
    225  1.2    oster 			*createFunc = (RF_VoidFuncPtr) rf_CreateFaultFreeReadDAG;	/* same as raid 5 */
    226  1.2    oster 			break;
    227  1.2    oster 		case 1:
    228  1.2    oster 			/* lost a single data unit */
    229  1.2    oster 			/* two cases: (1) parity is not lost. do a normal raid
    230  1.2    oster 			 * 5 reconstruct read. (2) parity is lost. do a
    231  1.2    oster 			 * reconstruct read using "e". */
    232  1.2    oster 			if (ntfail == 2) {	/* also lost redundancy */
    233  1.2    oster 				if (asmap->failedPDAs[1]->type == RF_PDA_TYPE_PARITY)
    234  1.2    oster 					*createFunc = (RF_VoidFuncPtr) rf_EO_110_CreateReadDAG;
    235  1.2    oster 				else
    236  1.2    oster 					*createFunc = (RF_VoidFuncPtr) rf_EO_101_CreateReadDAG;
    237  1.2    oster 			} else {
    238  1.2    oster 				/* P and E are ok. But is there a failure in
    239  1.2    oster 				 * some unaccessed data unit? */
    240  1.2    oster 				if (rf_NumFailedDataUnitsInStripe(raidPtr, asmap) == 2)
    241  1.2    oster 					*createFunc = (RF_VoidFuncPtr) rf_EO_200_CreateReadDAG;
    242  1.2    oster 				else
    243  1.2    oster 					*createFunc = (RF_VoidFuncPtr) rf_EO_100_CreateReadDAG;
    244  1.2    oster 			}
    245  1.2    oster 			break;
    246  1.2    oster 		case 2:
    247  1.2    oster 			/* *createFunc = rf_EO_200_CreateReadDAG; */
    248  1.2    oster 			*createFunc = NULL;
    249  1.2    oster 			break;
    250  1.2    oster 		}
    251  1.2    oster 		return;
    252  1.2    oster 	}
    253  1.2    oster 	/* a write */
    254  1.2    oster 	switch (ntfail) {
    255  1.2    oster 	case 0:		/* fault free */
    256  1.2    oster 		if (rf_suppressLocksAndLargeWrites ||
    257  1.2    oster 		    (((asmap->numStripeUnitsAccessed <= (layoutPtr->numDataCol / 2)) && (layoutPtr->numDataCol != 1)) ||
    258  1.2    oster 			(asmap->parityInfo->next != NULL) || (asmap->qInfo->next != NULL) || rf_CheckStripeForFailures(raidPtr, asmap))) {
    259  1.2    oster 
    260  1.2    oster 			*createFunc = (RF_VoidFuncPtr) rf_EOCreateSmallWriteDAG;
    261  1.2    oster 		} else {
    262  1.2    oster 			*createFunc = (RF_VoidFuncPtr) rf_EOCreateLargeWriteDAG;
    263  1.2    oster 		}
    264  1.2    oster 		break;
    265  1.2    oster 
    266  1.2    oster 	case 1:		/* single disk fault */
    267  1.2    oster 		if (npfail == 1) {
    268  1.2    oster 			RF_ASSERT((asmap->failedPDAs[0]->type == RF_PDA_TYPE_PARITY) || (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q));
    269  1.2    oster 			if (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q) {	/* q died, treat like
    270  1.2    oster 										 * normal mode raid5
    271  1.2    oster 										 * write. */
    272  1.2    oster 				if (((asmap->numStripeUnitsAccessed <= (layoutPtr->numDataCol / 2)) || (asmap->numStripeUnitsAccessed == 1))
    273  1.2    oster 				    || (asmap->parityInfo->next != NULL) || rf_NumFailedDataUnitsInStripe(raidPtr, asmap))
    274  1.2    oster 					*createFunc = (RF_VoidFuncPtr) rf_EO_001_CreateSmallWriteDAG;
    275  1.2    oster 				else
    276  1.2    oster 					*createFunc = (RF_VoidFuncPtr) rf_EO_001_CreateLargeWriteDAG;
    277  1.2    oster 			} else {/* parity died, small write only updating Q */
    278  1.2    oster 				if (((asmap->numStripeUnitsAccessed <= (layoutPtr->numDataCol / 2)) || (asmap->numStripeUnitsAccessed == 1))
    279  1.2    oster 				    || (asmap->qInfo->next != NULL) || rf_NumFailedDataUnitsInStripe(raidPtr, asmap))
    280  1.2    oster 					*createFunc = (RF_VoidFuncPtr) rf_EO_010_CreateSmallWriteDAG;
    281  1.2    oster 				else
    282  1.2    oster 					*createFunc = (RF_VoidFuncPtr) rf_EO_010_CreateLargeWriteDAG;
    283  1.2    oster 			}
    284  1.2    oster 		} else {	/* data missing. Do a P reconstruct write if
    285  1.2    oster 				 * only a single data unit is lost in the
    286  1.2    oster 				 * stripe, otherwise a reconstruct write which
    287  1.2    oster 				 * employnig both P and E units. */
    288  1.2    oster 			if (rf_NumFailedDataUnitsInStripe(raidPtr, asmap) == 2) {
    289  1.2    oster 				if (asmap->numStripeUnitsAccessed == 1)
    290  1.2    oster 					*createFunc = (RF_VoidFuncPtr) rf_EO_200_CreateWriteDAG;
    291  1.2    oster 				else
    292  1.2    oster 					*createFunc = NULL;	/* No direct support for
    293  1.2    oster 								 * this case now, like
    294  1.2    oster 								 * that in Raid-5  */
    295  1.2    oster 			} else {
    296  1.2    oster 				if (asmap->numStripeUnitsAccessed != 1 && asmap->failedPDAs[0]->numSector != layoutPtr->sectorsPerStripeUnit)
    297  1.2    oster 					*createFunc = NULL;	/* No direct support for
    298  1.2    oster 								 * this case now, like
    299  1.2    oster 								 * that in Raid-5  */
    300  1.2    oster 				else
    301  1.2    oster 					*createFunc = (RF_VoidFuncPtr) rf_EO_100_CreateWriteDAG;
    302  1.2    oster 			}
    303  1.2    oster 		}
    304  1.2    oster 		break;
    305  1.2    oster 
    306  1.2    oster 	case 2:		/* two disk faults */
    307  1.2    oster 		switch (npfail) {
    308  1.2    oster 		case 2:	/* both p and q dead */
    309  1.2    oster 			*createFunc = (RF_VoidFuncPtr) rf_EO_011_CreateWriteDAG;
    310  1.2    oster 			break;
    311  1.2    oster 		case 1:	/* either p or q and dead data */
    312  1.2    oster 			RF_ASSERT(asmap->failedPDAs[0]->type == RF_PDA_TYPE_DATA);
    313  1.2    oster 			RF_ASSERT((asmap->failedPDAs[1]->type == RF_PDA_TYPE_PARITY) || (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q));
    314  1.2    oster 			if (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q) {
    315  1.2    oster 				if (asmap->numStripeUnitsAccessed != 1 && asmap->failedPDAs[0]->numSector != layoutPtr->sectorsPerStripeUnit)
    316  1.2    oster 					*createFunc = NULL;	/* In both PQ and
    317  1.2    oster 								 * EvenOdd, no direct
    318  1.2    oster 								 * support for this case
    319  1.2    oster 								 * now, like that in
    320  1.2    oster 								 * Raid-5  */
    321  1.2    oster 				else
    322  1.2    oster 					*createFunc = (RF_VoidFuncPtr) rf_EO_101_CreateWriteDAG;
    323  1.2    oster 			} else {
    324  1.2    oster 				if (asmap->numStripeUnitsAccessed != 1 && asmap->failedPDAs[0]->numSector != layoutPtr->sectorsPerStripeUnit)
    325  1.2    oster 					*createFunc = NULL;	/* No direct support for
    326  1.2    oster 								 * this case, like that
    327  1.2    oster 								 * in Raid-5  */
    328  1.2    oster 				else
    329  1.2    oster 					*createFunc = (RF_VoidFuncPtr) rf_EO_110_CreateWriteDAG;
    330  1.2    oster 			}
    331  1.2    oster 			break;
    332  1.2    oster 		case 0:	/* double data loss */
    333  1.2    oster 			/* if(asmap->failedPDAs[0]->numSector +
    334  1.2    oster 			 * asmap->failedPDAs[1]->numSector == 2 *
    335  1.2    oster 			 * layoutPtr->sectorsPerStripeUnit ) createFunc =
    336  1.2    oster 			 * rf_EOCreateLargeWriteDAG; else    							 */
    337  1.2    oster 			*createFunc = NULL;	/* currently, in Evenodd, No
    338  1.2    oster 						 * support for simultaneous
    339  1.2    oster 						 * access of both failed SUs */
    340  1.2    oster 			break;
    341  1.2    oster 		}
    342  1.2    oster 		break;
    343  1.2    oster 
    344  1.2    oster 	default:		/* more than 2 disk faults */
    345  1.2    oster 		*createFunc = NULL;
    346  1.2    oster 		RF_PANIC();
    347  1.2    oster 	}
    348  1.2    oster 	return;
    349  1.1    oster }
    350  1.1    oster 
    351  1.1    oster 
    352  1.2    oster int
    353  1.2    oster rf_VerifyParityEvenOdd(raidPtr, raidAddr, parityPDA, correct_it, flags)
    354  1.2    oster 	RF_Raid_t *raidPtr;
    355  1.2    oster 	RF_RaidAddr_t raidAddr;
    356  1.2    oster 	RF_PhysDiskAddr_t *parityPDA;
    357  1.2    oster 	int     correct_it;
    358  1.2    oster 	RF_RaidAccessFlags_t flags;
    359  1.1    oster {
    360  1.2    oster 	RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
    361  1.2    oster 	RF_RaidAddr_t startAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr, raidAddr);
    362  1.2    oster 	RF_SectorCount_t numsector = parityPDA->numSector;
    363  1.2    oster 	int     numbytes = rf_RaidAddressToByte(raidPtr, numsector);
    364  1.2    oster 	int     bytesPerStripe = numbytes * layoutPtr->numDataCol;
    365  1.2    oster 	RF_DagHeader_t *rd_dag_h, *wr_dag_h;	/* read, write dag */
    366  1.2    oster 	RF_DagNode_t *blockNode, *unblockNode, *wrBlock, *wrUnblock;
    367  1.2    oster 	RF_AccessStripeMapHeader_t *asm_h;
    368  1.2    oster 	RF_AccessStripeMap_t *asmap;
    369  1.2    oster 	RF_AllocListElem_t *alloclist;
    370  1.2    oster 	RF_PhysDiskAddr_t *pda;
    371  1.2    oster 	char   *pbuf, *buf, *end_p, *p;
    372  1.2    oster 	char   *redundantbuf2;
    373  1.2    oster 	int     redundantTwoErr = 0, redundantOneErr = 0;
    374  1.2    oster 	int     parity_cant_correct = RF_FALSE, red2_cant_correct = RF_FALSE,
    375  1.2    oster 	        parity_corrected = RF_FALSE, red2_corrected = RF_FALSE;
    376  1.2    oster 	int     i, retcode;
    377  1.2    oster 	RF_ReconUnitNum_t which_ru;
    378  1.2    oster 	RF_StripeNum_t psID = rf_RaidAddressToParityStripeID(layoutPtr, raidAddr, &which_ru);
    379  1.2    oster 	int     stripeWidth = layoutPtr->numDataCol + layoutPtr->numParityCol;
    380  1.2    oster 	RF_AccTraceEntry_t tracerec;
    381  1.2    oster 	RF_MCPair_t *mcpair;
    382  1.2    oster 
    383  1.2    oster 	retcode = RF_PARITY_OKAY;
    384  1.2    oster 
    385  1.2    oster 	mcpair = rf_AllocMCPair();
    386  1.2    oster 	rf_MakeAllocList(alloclist);
    387  1.2    oster 	RF_MallocAndAdd(buf, numbytes * (layoutPtr->numDataCol + layoutPtr->numParityCol), (char *), alloclist);
    388  1.2    oster 	RF_CallocAndAdd(pbuf, 1, numbytes, (char *), alloclist);	/* use calloc to make
    389  1.2    oster 									 * sure buffer is zeroed */
    390  1.2    oster 	end_p = buf + bytesPerStripe;
    391  1.2    oster 	RF_CallocAndAdd(redundantbuf2, 1, numbytes, (char *), alloclist);	/* use calloc to make
    392  1.2    oster 										 * sure buffer is zeroed */
    393  1.2    oster 
    394  1.2    oster 	rd_dag_h = rf_MakeSimpleDAG(raidPtr, stripeWidth, numbytes, buf, rf_DiskReadFunc, rf_DiskReadUndoFunc,
    395  1.2    oster 	    "Rod", alloclist, flags, RF_IO_NORMAL_PRIORITY);
    396  1.2    oster 	blockNode = rd_dag_h->succedents[0];
    397  1.2    oster 	unblockNode = blockNode->succedents[0]->succedents[0];
    398  1.2    oster 
    399  1.2    oster 	/* map the stripe and fill in the PDAs in the dag */
    400  1.2    oster 	asm_h = rf_MapAccess(raidPtr, startAddr, layoutPtr->dataSectorsPerStripe, buf, RF_DONT_REMAP);
    401  1.2    oster 	asmap = asm_h->stripeMap;
    402  1.2    oster 
    403  1.2    oster 	for (pda = asmap->physInfo, i = 0; i < layoutPtr->numDataCol; i++, pda = pda->next) {
    404  1.2    oster 		RF_ASSERT(pda);
    405  1.2    oster 		rf_RangeRestrictPDA(raidPtr, parityPDA, pda, 0, 1);
    406  1.2    oster 		RF_ASSERT(pda->numSector != 0);
    407  1.2    oster 		if (rf_TryToRedirectPDA(raidPtr, pda, 0))
    408  1.2    oster 			goto out;	/* no way to verify parity if disk is
    409  1.2    oster 					 * dead.  return w/ good status */
    410  1.2    oster 		blockNode->succedents[i]->params[0].p = pda;
    411  1.2    oster 		blockNode->succedents[i]->params[2].v = psID;
    412  1.2    oster 		blockNode->succedents[i]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
    413  1.2    oster 	}
    414  1.2    oster 
    415  1.2    oster 	RF_ASSERT(!asmap->parityInfo->next);
    416  1.2    oster 	rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->parityInfo, 0, 1);
    417  1.2    oster 	RF_ASSERT(asmap->parityInfo->numSector != 0);
    418  1.2    oster 	if (rf_TryToRedirectPDA(raidPtr, asmap->parityInfo, 1))
    419  1.2    oster 		goto out;
    420  1.2    oster 	blockNode->succedents[layoutPtr->numDataCol]->params[0].p = asmap->parityInfo;
    421  1.2    oster 
    422  1.2    oster 	RF_ASSERT(!asmap->qInfo->next);
    423  1.2    oster 	rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->qInfo, 0, 1);
    424  1.2    oster 	RF_ASSERT(asmap->qInfo->numSector != 0);
    425  1.2    oster 	if (rf_TryToRedirectPDA(raidPtr, asmap->qInfo, 1))
    426  1.2    oster 		goto out;
    427  1.2    oster 	/* if disk is dead, b/c no reconstruction is implemented right now,
    428  1.2    oster 	 * the function "rf_TryToRedirectPDA" always return one, which cause
    429  1.2    oster 	 * go to out and return w/ good status   */
    430  1.2    oster 	blockNode->succedents[layoutPtr->numDataCol + 1]->params[0].p = asmap->qInfo;
    431  1.2    oster 
    432  1.2    oster 	/* fire off the DAG */
    433  1.5  thorpej 	memset((char *) &tracerec, 0, sizeof(tracerec));
    434  1.2    oster 	rd_dag_h->tracerec = &tracerec;
    435  1.2    oster 
    436  1.8    oster #if RF_DEBUG_VALIDATE_DAG
    437  1.2    oster 	if (rf_verifyParityDebug) {
    438  1.2    oster 		printf("Parity verify read dag:\n");
    439  1.2    oster 		rf_PrintDAGList(rd_dag_h);
    440  1.2    oster 	}
    441  1.8    oster #endif
    442  1.2    oster 	RF_LOCK_MUTEX(mcpair->mutex);
    443  1.2    oster 	mcpair->flag = 0;
    444  1.2    oster 	rf_DispatchDAG(rd_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
    445  1.2    oster 	    (void *) mcpair);
    446  1.2    oster 	while (!mcpair->flag)
    447  1.2    oster 		RF_WAIT_COND(mcpair->cond, mcpair->mutex);
    448  1.2    oster 	RF_UNLOCK_MUTEX(mcpair->mutex);
    449  1.2    oster 	if (rd_dag_h->status != rf_enable) {
    450  1.2    oster 		RF_ERRORMSG("Unable to verify parity:  can't read the stripe\n");
    451  1.2    oster 		retcode = RF_PARITY_COULD_NOT_VERIFY;
    452  1.2    oster 		goto out;
    453  1.2    oster 	}
    454  1.2    oster 	for (p = buf, i = 0; p < end_p; p += numbytes, i++) {
    455  1.2    oster 		rf_e_encToBuf(raidPtr, i, p, RF_EO_MATRIX_DIM - 2, redundantbuf2, numsector);
    456  1.2    oster 		/* the corresponding columes in EvenOdd encoding Matrix for
    457  1.2    oster 		 * these p pointers which point to the databuffer in a full
    458  1.2    oster 		 * stripe are sequentially from 0 to layoutPtr->numDataCol-1 */
    459  1.2    oster 		rf_bxor(p, pbuf, numbytes, NULL);
    460  1.2    oster 	}
    461  1.2    oster 	RF_ASSERT(i == layoutPtr->numDataCol);
    462  1.2    oster 
    463  1.2    oster 	for (i = 0; i < numbytes; i++) {
    464  1.2    oster 		if (pbuf[i] != buf[bytesPerStripe + i]) {
    465  1.2    oster 			if (!correct_it) {
    466  1.2    oster 				RF_ERRORMSG3("Parity verify error: byte %d of parity is 0x%x should be 0x%x\n",
    467  1.2    oster 				    i, (u_char) buf[bytesPerStripe + i], (u_char) pbuf[i]);
    468  1.2    oster 			}
    469  1.2    oster 		}
    470  1.2    oster 		redundantOneErr = 1;
    471  1.2    oster 		break;
    472  1.2    oster 	}
    473  1.2    oster 
    474  1.2    oster 	for (i = 0; i < numbytes; i++) {
    475  1.2    oster 		if (redundantbuf2[i] != buf[bytesPerStripe + numbytes + i]) {
    476  1.2    oster 			if (!correct_it) {
    477  1.2    oster 				RF_ERRORMSG3("Parity verify error: byte %d of second redundant information is 0x%x should be 0x%x\n",
    478  1.2    oster 				    i, (u_char) buf[bytesPerStripe + numbytes + i], (u_char) redundantbuf2[i]);
    479  1.2    oster 			}
    480  1.2    oster 			redundantTwoErr = 1;
    481  1.2    oster 			break;
    482  1.2    oster 		}
    483  1.2    oster 	}
    484  1.2    oster 	if (redundantOneErr || redundantTwoErr)
    485  1.2    oster 		retcode = RF_PARITY_BAD;
    486  1.2    oster 
    487  1.2    oster 	/* correct the first redundant disk, ie parity if it is error    */
    488  1.2    oster 	if (redundantOneErr && correct_it) {
    489  1.2    oster 		wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, pbuf, rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
    490  1.2    oster 		    "Wnp", alloclist, flags, RF_IO_NORMAL_PRIORITY);
    491  1.2    oster 		wrBlock = wr_dag_h->succedents[0];
    492  1.2    oster 		wrUnblock = wrBlock->succedents[0]->succedents[0];
    493  1.2    oster 		wrBlock->succedents[0]->params[0].p = asmap->parityInfo;
    494  1.2    oster 		wrBlock->succedents[0]->params[2].v = psID;
    495  1.2    oster 		wrBlock->succedents[0]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
    496  1.5  thorpej 		memset((char *) &tracerec, 0, sizeof(tracerec));
    497  1.2    oster 		wr_dag_h->tracerec = &tracerec;
    498  1.8    oster #if RF_DEBUG_VALIDATE_DAG
    499  1.2    oster 		if (rf_verifyParityDebug) {
    500  1.2    oster 			printf("Parity verify write dag:\n");
    501  1.2    oster 			rf_PrintDAGList(wr_dag_h);
    502  1.2    oster 		}
    503  1.8    oster #endif
    504  1.2    oster 		RF_LOCK_MUTEX(mcpair->mutex);
    505  1.2    oster 		mcpair->flag = 0;
    506  1.2    oster 		rf_DispatchDAG(wr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
    507  1.2    oster 		    (void *) mcpair);
    508  1.2    oster 		while (!mcpair->flag)
    509  1.2    oster 			RF_WAIT_COND(mcpair->cond, mcpair->mutex);
    510  1.2    oster 		RF_UNLOCK_MUTEX(mcpair->mutex);
    511  1.2    oster 		if (wr_dag_h->status != rf_enable) {
    512  1.2    oster 			RF_ERRORMSG("Unable to correct parity in VerifyParity:  can't write the stripe\n");
    513  1.2    oster 			parity_cant_correct = RF_TRUE;
    514  1.2    oster 		} else {
    515  1.2    oster 			parity_corrected = RF_TRUE;
    516  1.2    oster 		}
    517  1.2    oster 		rf_FreeDAG(wr_dag_h);
    518  1.2    oster 	}
    519  1.2    oster 	if (redundantTwoErr && correct_it) {
    520  1.2    oster 		wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, redundantbuf2, rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
    521  1.2    oster 		    "Wnred2", alloclist, flags, RF_IO_NORMAL_PRIORITY);
    522  1.2    oster 		wrBlock = wr_dag_h->succedents[0];
    523  1.2    oster 		wrUnblock = wrBlock->succedents[0]->succedents[0];
    524  1.2    oster 		wrBlock->succedents[0]->params[0].p = asmap->qInfo;
    525  1.2    oster 		wrBlock->succedents[0]->params[2].v = psID;
    526  1.2    oster 		wrBlock->succedents[0]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
    527  1.5  thorpej 		memset((char *) &tracerec, 0, sizeof(tracerec));
    528  1.2    oster 		wr_dag_h->tracerec = &tracerec;
    529  1.8    oster #if RF_DEBUG_VALIDATE_DAG
    530  1.2    oster 		if (rf_verifyParityDebug) {
    531  1.2    oster 			printf("Dag of write new second redundant information in parity verify :\n");
    532  1.2    oster 			rf_PrintDAGList(wr_dag_h);
    533  1.2    oster 		}
    534  1.8    oster #endif
    535  1.2    oster 		RF_LOCK_MUTEX(mcpair->mutex);
    536  1.2    oster 		mcpair->flag = 0;
    537  1.2    oster 		rf_DispatchDAG(wr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
    538  1.2    oster 		    (void *) mcpair);
    539  1.2    oster 		while (!mcpair->flag)
    540  1.2    oster 			RF_WAIT_COND(mcpair->cond, mcpair->mutex);
    541  1.2    oster 		RF_UNLOCK_MUTEX(mcpair->mutex);
    542  1.2    oster 		if (wr_dag_h->status != rf_enable) {
    543  1.2    oster 			RF_ERRORMSG("Unable to correct second redundant information in VerifyParity:  can't write the stripe\n");
    544  1.2    oster 			red2_cant_correct = RF_TRUE;
    545  1.2    oster 		} else {
    546  1.2    oster 			red2_corrected = RF_TRUE;
    547  1.2    oster 		}
    548  1.2    oster 		rf_FreeDAG(wr_dag_h);
    549  1.2    oster 	}
    550  1.2    oster 	if ((redundantOneErr && parity_cant_correct) ||
    551  1.2    oster 	    (redundantTwoErr && red2_cant_correct))
    552  1.2    oster 		retcode = RF_PARITY_COULD_NOT_CORRECT;
    553  1.2    oster 	if ((retcode = RF_PARITY_BAD) && parity_corrected && red2_corrected)
    554  1.2    oster 		retcode = RF_PARITY_CORRECTED;
    555  1.1    oster 
    556  1.1    oster 
    557  1.1    oster out:
    558  1.2    oster 	rf_FreeAccessStripeMap(asm_h);
    559  1.2    oster 	rf_FreeAllocList(alloclist);
    560  1.2    oster 	rf_FreeDAG(rd_dag_h);
    561  1.2    oster 	rf_FreeMCPair(mcpair);
    562  1.2    oster 	return (retcode);
    563  1.1    oster }
    564  1.2    oster #endif				/* RF_INCLUDE_EVENODD > 0 */
    565