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