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