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