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@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