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