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