1 /* $NetBSD: rf_evenodd.c,v 1.9 2002/09/23 02:40:08 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.9 2002/09/23 02:40:08 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(listp, raidPtr, cfgPtr) 72 RF_ShutdownList_t **listp; 73 RF_Raid_t *raidPtr; 74 RF_Config_t *cfgPtr; 75 { 76 RF_RaidLayout_t *layoutPtr = &raidPtr->Layout; 77 RF_EvenOddConfigInfo_t *info; 78 RF_RowCol_t i, j, startdisk; 79 80 RF_MallocAndAdd(info, sizeof(RF_EvenOddConfigInfo_t), (RF_EvenOddConfigInfo_t *), raidPtr->cleanupList); 81 layoutPtr->layoutSpecificInfo = (void *) info; 82 83 RF_ASSERT(raidPtr->numRow == 1); 84 85 info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol, raidPtr->numCol, raidPtr->cleanupList); 86 startdisk = 0; 87 for (i = 0; i < raidPtr->numCol; i++) { 88 for (j = 0; j < raidPtr->numCol; j++) { 89 info->stripeIdentifier[i][j] = (startdisk + j) % raidPtr->numCol; 90 } 91 if ((startdisk -= 2) < 0) 92 startdisk += raidPtr->numCol; 93 } 94 95 /* fill in the remaining layout parameters */ 96 layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk; 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 memset((char *) &tracerec, 0, sizeof(tracerec)); 433 rd_dag_h->tracerec = &tracerec; 434 435 #if RF_DEBUG_VALIDATE_DAG 436 if (rf_verifyParityDebug) { 437 printf("Parity verify read dag:\n"); 438 rf_PrintDAGList(rd_dag_h); 439 } 440 #endif 441 RF_LOCK_MUTEX(mcpair->mutex); 442 mcpair->flag = 0; 443 rf_DispatchDAG(rd_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc, 444 (void *) mcpair); 445 while (!mcpair->flag) 446 RF_WAIT_COND(mcpair->cond, mcpair->mutex); 447 RF_UNLOCK_MUTEX(mcpair->mutex); 448 if (rd_dag_h->status != rf_enable) { 449 RF_ERRORMSG("Unable to verify parity: can't read the stripe\n"); 450 retcode = RF_PARITY_COULD_NOT_VERIFY; 451 goto out; 452 } 453 for (p = buf, i = 0; p < end_p; p += numbytes, i++) { 454 rf_e_encToBuf(raidPtr, i, p, RF_EO_MATRIX_DIM - 2, redundantbuf2, numsector); 455 /* the corresponding columes in EvenOdd encoding Matrix for 456 * these p pointers which point to the databuffer in a full 457 * stripe are sequentially from 0 to layoutPtr->numDataCol-1 */ 458 rf_bxor(p, pbuf, numbytes, NULL); 459 } 460 RF_ASSERT(i == layoutPtr->numDataCol); 461 462 for (i = 0; i < numbytes; i++) { 463 if (pbuf[i] != buf[bytesPerStripe + i]) { 464 if (!correct_it) { 465 RF_ERRORMSG3("Parity verify error: byte %d of parity is 0x%x should be 0x%x\n", 466 i, (u_char) buf[bytesPerStripe + i], (u_char) pbuf[i]); 467 } 468 } 469 redundantOneErr = 1; 470 break; 471 } 472 473 for (i = 0; i < numbytes; i++) { 474 if (redundantbuf2[i] != buf[bytesPerStripe + numbytes + i]) { 475 if (!correct_it) { 476 RF_ERRORMSG3("Parity verify error: byte %d of second redundant information is 0x%x should be 0x%x\n", 477 i, (u_char) buf[bytesPerStripe + numbytes + i], (u_char) redundantbuf2[i]); 478 } 479 redundantTwoErr = 1; 480 break; 481 } 482 } 483 if (redundantOneErr || redundantTwoErr) 484 retcode = RF_PARITY_BAD; 485 486 /* correct the first redundant disk, ie parity if it is error */ 487 if (redundantOneErr && correct_it) { 488 wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, pbuf, rf_DiskWriteFunc, rf_DiskWriteUndoFunc, 489 "Wnp", alloclist, flags, RF_IO_NORMAL_PRIORITY); 490 wrBlock = wr_dag_h->succedents[0]; 491 wrUnblock = wrBlock->succedents[0]->succedents[0]; 492 wrBlock->succedents[0]->params[0].p = asmap->parityInfo; 493 wrBlock->succedents[0]->params[2].v = psID; 494 wrBlock->succedents[0]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru); 495 memset((char *) &tracerec, 0, sizeof(tracerec)); 496 wr_dag_h->tracerec = &tracerec; 497 #if RF_DEBUG_VALIDATE_DAG 498 if (rf_verifyParityDebug) { 499 printf("Parity verify write dag:\n"); 500 rf_PrintDAGList(wr_dag_h); 501 } 502 #endif 503 RF_LOCK_MUTEX(mcpair->mutex); 504 mcpair->flag = 0; 505 rf_DispatchDAG(wr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc, 506 (void *) mcpair); 507 while (!mcpair->flag) 508 RF_WAIT_COND(mcpair->cond, mcpair->mutex); 509 RF_UNLOCK_MUTEX(mcpair->mutex); 510 if (wr_dag_h->status != rf_enable) { 511 RF_ERRORMSG("Unable to correct parity in VerifyParity: can't write the stripe\n"); 512 parity_cant_correct = RF_TRUE; 513 } else { 514 parity_corrected = RF_TRUE; 515 } 516 rf_FreeDAG(wr_dag_h); 517 } 518 if (redundantTwoErr && correct_it) { 519 wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, redundantbuf2, rf_DiskWriteFunc, rf_DiskWriteUndoFunc, 520 "Wnred2", alloclist, flags, RF_IO_NORMAL_PRIORITY); 521 wrBlock = wr_dag_h->succedents[0]; 522 wrUnblock = wrBlock->succedents[0]->succedents[0]; 523 wrBlock->succedents[0]->params[0].p = asmap->qInfo; 524 wrBlock->succedents[0]->params[2].v = psID; 525 wrBlock->succedents[0]->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru); 526 memset((char *) &tracerec, 0, sizeof(tracerec)); 527 wr_dag_h->tracerec = &tracerec; 528 #if RF_DEBUG_VALIDATE_DAG 529 if (rf_verifyParityDebug) { 530 printf("Dag of write new second redundant information in parity verify :\n"); 531 rf_PrintDAGList(wr_dag_h); 532 } 533 #endif 534 RF_LOCK_MUTEX(mcpair->mutex); 535 mcpair->flag = 0; 536 rf_DispatchDAG(wr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc, 537 (void *) mcpair); 538 while (!mcpair->flag) 539 RF_WAIT_COND(mcpair->cond, mcpair->mutex); 540 RF_UNLOCK_MUTEX(mcpair->mutex); 541 if (wr_dag_h->status != rf_enable) { 542 RF_ERRORMSG("Unable to correct second redundant information in VerifyParity: can't write the stripe\n"); 543 red2_cant_correct = RF_TRUE; 544 } else { 545 red2_corrected = RF_TRUE; 546 } 547 rf_FreeDAG(wr_dag_h); 548 } 549 if ((redundantOneErr && parity_cant_correct) || 550 (redundantTwoErr && red2_cant_correct)) 551 retcode = RF_PARITY_COULD_NOT_CORRECT; 552 if ((retcode = RF_PARITY_BAD) && parity_corrected && red2_corrected) 553 retcode = RF_PARITY_CORRECTED; 554 555 556 out: 557 rf_FreeAccessStripeMap(asm_h); 558 rf_FreeAllocList(alloclist); 559 rf_FreeDAG(rd_dag_h); 560 rf_FreeMCPair(mcpair); 561 return (retcode); 562 } 563 #endif /* RF_INCLUDE_EVENODD > 0 */ 564