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