Annotation of sys/dev/raidframe/rf_evenodd.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: rf_evenodd.c,v 1.5 2002/12/16 07:01:03 tdeval Exp $ */
! 2: /* $NetBSD: rf_evenodd.c,v 1.4 2000/01/07 03:40:59 oster Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1995 Carnegie-Mellon University.
! 6: * All rights reserved.
! 7: *
! 8: * Author: Chang-Ming Wu
! 9: *
! 10: * Permission to use, copy, modify and distribute this software and
! 11: * its documentation is hereby granted, provided that both the copyright
! 12: * notice and this permission notice appear in all copies of the
! 13: * software, derivative works or modified versions, and any portions
! 14: * thereof, and that both notices appear in supporting documentation.
! 15: *
! 16: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 17: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
! 18: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 19: *
! 20: * Carnegie Mellon requests users of this software to return to
! 21: *
! 22: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 23: * School of Computer Science
! 24: * Carnegie Mellon University
! 25: * Pittsburgh PA 15213-3890
! 26: *
! 27: * any improvements or extensions that they make and grant Carnegie the
! 28: * rights to redistribute these changes.
! 29: */
! 30:
! 31: /*****************************************************************************
! 32: *
! 33: * rf_evenodd.c -- implements EVENODD array architecture
! 34: *
! 35: *****************************************************************************/
! 36:
! 37: #include "rf_archs.h"
! 38:
! 39: #if RF_INCLUDE_EVENODD > 0
! 40:
! 41: #include "rf_types.h"
! 42: #include "rf_raid.h"
! 43: #include "rf_dag.h"
! 44: #include "rf_dagffrd.h"
! 45: #include "rf_dagffwr.h"
! 46: #include "rf_dagdegrd.h"
! 47: #include "rf_dagdegwr.h"
! 48: #include "rf_dagutils.h"
! 49: #include "rf_dagfuncs.h"
! 50: #include "rf_etimer.h"
! 51: #include "rf_general.h"
! 52: #include "rf_evenodd.h"
! 53: #include "rf_configure.h"
! 54: #include "rf_parityscan.h"
! 55: #include "rf_utils.h"
! 56: #include "rf_map.h"
! 57: #include "rf_pq.h"
! 58: #include "rf_mcpair.h"
! 59: #include "rf_evenodd.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; /*
! 66: * Filled in at config time & used by
! 67: * IdentifyStripe.
! 68: */
! 69: } RF_EvenOddConfigInfo_t;
! 70:
! 71: int
! 72: rf_ConfigureEvenOdd(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
! 73: RF_Config_t *cfgPtr)
! 74: {
! 75: RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
! 76: RF_EvenOddConfigInfo_t *info;
! 77: RF_RowCol_t i, j, startdisk;
! 78:
! 79: RF_MallocAndAdd(info, sizeof(RF_EvenOddConfigInfo_t),
! 80: (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,
! 86: raidPtr->numCol, raidPtr->cleanupList);
! 87: startdisk = 0;
! 88: for (i = 0; i < raidPtr->numCol; i++) {
! 89: for (j = 0; j < raidPtr->numCol; j++) {
! 90: info->stripeIdentifier[i][j] = (startdisk + j) %
! 91: raidPtr->numCol;
! 92: }
! 93: if ((startdisk -= 2) < 0)
! 94: startdisk += raidPtr->numCol;
! 95: }
! 96:
! 97: /* Fill in the remaining layout parameters. */
! 98: layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk;
! 99: layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit <<
! 100: raidPtr->logBytesPerSector;
! 101: layoutPtr->numDataCol = raidPtr->numCol - 2; /*
! 102: * ORIG:
! 103: * layoutPtr->numDataCol
! 104: * = raidPtr->numCol-1;
! 105: */
! 106: #if RF_EO_MATRIX_DIM > 17
! 107: if (raidPtr->numCol <= 17) {
! 108: printf("Number of stripe units in a parity stripe is smaller"
! 109: " than 17. Please\ndefine the macro RF_EO_MATRIX_DIM in"
! 110: " file rf_evenodd_dagfuncs.h to\nbe 17 to increase"
! 111: " performance.\n");
! 112: return (EINVAL);
! 113: }
! 114: #elif RF_EO_MATRIX_DIM == 17
! 115: if (raidPtr->numCol > 17) {
! 116: printf("Number of stripe units in a parity stripe is bigger"
! 117: " than 17. Please\ndefine the macro RF_EO_MATRIX_DIM in"
! 118: " file rf_evenodd_dagfuncs.h to\nbe 257 for encoding and"
! 119: " decoding functions to work.\n");
! 120: return (EINVAL);
! 121: }
! 122: #endif
! 123: layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol *
! 124: layoutPtr->sectorsPerStripeUnit;
! 125: layoutPtr->numParityCol = 2;
! 126: layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk;
! 127: raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk *
! 128: layoutPtr->sectorsPerStripeUnit;
! 129:
! 130: raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk *
! 131: layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
! 132:
! 133: return (0);
! 134: }
! 135:
! 136: int
! 137: rf_GetDefaultNumFloatingReconBuffersEvenOdd(RF_Raid_t *raidPtr)
! 138: {
! 139: return (20);
! 140: }
! 141:
! 142: RF_HeadSepLimit_t
! 143: rf_GetDefaultHeadSepLimitEvenOdd(RF_Raid_t *raidPtr)
! 144: {
! 145: return (10);
! 146: }
! 147:
! 148: void
! 149: rf_IdentifyStripeEvenOdd(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
! 150: RF_RowCol_t **diskids, RF_RowCol_t *outRow)
! 151: {
! 152: RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout,
! 153: addr);
! 154: RF_EvenOddConfigInfo_t *info =
! 155: (RF_EvenOddConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
! 156:
! 157: *outRow = 0;
! 158: *diskids = info->stripeIdentifier[stripeID % raidPtr->numCol];
! 159: }
! 160:
! 161:
! 162: /*
! 163: * The layout of stripe unit on the disks are: c0 c1 c2 c3 c4
! 164: *
! 165: * 0 1 2 E P
! 166: * 5 E P 3 4
! 167: * P 6 7 8 E
! 168: * 10 11 E P 9
! 169: * E P 12 13 14
! 170: * ....
! 171: *
! 172: * We use the MapSectorRAID5 to map data information because the routine can
! 173: * be shown to map exactly the layout of data stripe unit as shown above,
! 174: * although we have 2 redundant information now.
! 175: * But for E and P, we use rf_MapEEvenOdd and rf_MapParityEvenOdd which are
! 176: * different method from raid-5.
! 177: */
! 178:
! 179:
! 180: void
! 181: rf_MapParityEvenOdd(
! 182: RF_Raid_t *raidPtr,
! 183: RF_RaidAddr_t raidSector,
! 184: RF_RowCol_t *row,
! 185: RF_RowCol_t *col,
! 186: RF_SectorNum_t *diskSector,
! 187: int remap
! 188: )
! 189: {
! 190: RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
! 191: RF_StripeNum_t endSUIDofthisStrip =
! 192: (SUID / raidPtr->Layout.numDataCol + 1) *
! 193: raidPtr->Layout.numDataCol - 1;
! 194:
! 195: *row = 0;
! 196: *col = (endSUIDofthisStrip + 2) % raidPtr->numCol;
! 197: *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
! 198: raidPtr->Layout.sectorsPerStripeUnit +
! 199: (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
! 200: }
! 201:
! 202: void
! 203: rf_MapEEvenOdd(
! 204: RF_Raid_t *raidPtr,
! 205: RF_RaidAddr_t raidSector,
! 206: RF_RowCol_t *row,
! 207: RF_RowCol_t *col,
! 208: RF_SectorNum_t *diskSector,
! 209: int remap
! 210: )
! 211: {
! 212: RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
! 213: RF_StripeNum_t endSUIDofthisStrip =
! 214: (SUID / raidPtr->Layout.numDataCol + 1) *
! 215: raidPtr->Layout.numDataCol - 1;
! 216:
! 217: *row = 0;
! 218: *col = (endSUIDofthisStrip + 1) % raidPtr->numCol;
! 219: *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
! 220: raidPtr->Layout.sectorsPerStripeUnit +
! 221: (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
! 222: }
! 223:
! 224: void
! 225: rf_EODagSelect(
! 226: RF_Raid_t *raidPtr,
! 227: RF_IoType_t type,
! 228: RF_AccessStripeMap_t *asmap,
! 229: RF_VoidFuncPtr *createFunc
! 230: )
! 231: {
! 232: RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
! 233: unsigned ndfail = asmap->numDataFailed;
! 234: unsigned npfail = asmap->numParityFailed + asmap->numQFailed;
! 235: unsigned ntfail = npfail + ndfail;
! 236:
! 237: RF_ASSERT(RF_IO_IS_R_OR_W(type));
! 238: if (ntfail > 2) {
! 239: RF_ERRORMSG("more than two disks failed in a single group !"
! 240: " Aborting I/O operation.\n");
! 241: /* *infoFunc = */ *createFunc = NULL;
! 242: return;
! 243: }
! 244: /* Ok, we can do this I/O. */
! 245: if (type == RF_IO_TYPE_READ) {
! 246: switch (ndfail) {
! 247: case 0:
! 248: /* Fault free read. */
! 249: *createFunc = (RF_VoidFuncPtr)
! 250: rf_CreateFaultFreeReadDAG; /* Same as raid 5. */
! 251: break;
! 252: case 1:
! 253: /* Lost a single data unit. */
! 254: /*
! 255: * Two cases:
! 256: * (1) Parity is not lost. Do a normal raid 5
! 257: * reconstruct read.
! 258: * (2) Parity is lost. Do a reconstruct read using "e".
! 259: */
! 260: if (ntfail == 2) { /* Also lost redundancy. */
! 261: if (asmap->failedPDAs[1]->type ==
! 262: RF_PDA_TYPE_PARITY)
! 263: *createFunc = (RF_VoidFuncPtr)
! 264: rf_EO_110_CreateReadDAG;
! 265: else
! 266: *createFunc = (RF_VoidFuncPtr)
! 267: rf_EO_101_CreateReadDAG;
! 268: } else {
! 269: /*
! 270: * P and E are ok. But is there a failure in
! 271: * some unaccessed data unit ?
! 272: */
! 273: if (rf_NumFailedDataUnitsInStripe(raidPtr,
! 274: asmap) == 2)
! 275: *createFunc = (RF_VoidFuncPtr)
! 276: rf_EO_200_CreateReadDAG;
! 277: else
! 278: *createFunc = (RF_VoidFuncPtr)
! 279: rf_EO_100_CreateReadDAG;
! 280: }
! 281: break;
! 282: case 2:
! 283: /* *createFunc = rf_EO_200_CreateReadDAG; */
! 284: *createFunc = NULL;
! 285: break;
! 286: }
! 287: return;
! 288: }
! 289: /* A write. */
! 290: switch (ntfail) {
! 291: case 0: /* Fault free. */
! 292: if (rf_suppressLocksAndLargeWrites ||
! 293: (((asmap->numStripeUnitsAccessed <=
! 294: (layoutPtr->numDataCol / 2)) &&
! 295: (layoutPtr->numDataCol != 1)) ||
! 296: (asmap->parityInfo->next != NULL) ||
! 297: (asmap->qInfo->next != NULL) ||
! 298: rf_CheckStripeForFailures(raidPtr, asmap))) {
! 299:
! 300: *createFunc = (RF_VoidFuncPtr) rf_EOCreateSmallWriteDAG;
! 301: } else {
! 302: *createFunc = (RF_VoidFuncPtr) rf_EOCreateLargeWriteDAG;
! 303: }
! 304: break;
! 305:
! 306: case 1: /* Single disk fault. */
! 307: if (npfail == 1) {
! 308: RF_ASSERT((asmap->failedPDAs[0]->type ==
! 309: RF_PDA_TYPE_PARITY) ||
! 310: (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q));
! 311: if (asmap->failedPDAs[0]->type == RF_PDA_TYPE_Q) {
! 312: /*
! 313: * q died, treat like normal mode raid5
! 314: * write.
! 315: */
! 316: if (((asmap->numStripeUnitsAccessed <=
! 317: (layoutPtr->numDataCol / 2)) ||
! 318: (asmap->numStripeUnitsAccessed == 1)) ||
! 319: (asmap->parityInfo->next != NULL) ||
! 320: rf_NumFailedDataUnitsInStripe(raidPtr,
! 321: asmap))
! 322: *createFunc = (RF_VoidFuncPtr)
! 323: rf_EO_001_CreateSmallWriteDAG;
! 324: else
! 325: *createFunc = (RF_VoidFuncPtr)
! 326: rf_EO_001_CreateLargeWriteDAG;
! 327: } else {
! 328: /* Parity died, small write only updating Q. */
! 329: if (((asmap->numStripeUnitsAccessed <=
! 330: (layoutPtr->numDataCol / 2)) ||
! 331: (asmap->numStripeUnitsAccessed == 1)) ||
! 332: (asmap->qInfo->next != NULL) ||
! 333: rf_NumFailedDataUnitsInStripe(raidPtr,
! 334: asmap))
! 335: *createFunc = (RF_VoidFuncPtr)
! 336: rf_EO_010_CreateSmallWriteDAG;
! 337: else
! 338: *createFunc = (RF_VoidFuncPtr)
! 339: rf_EO_010_CreateLargeWriteDAG;
! 340: }
! 341: } else { /*
! 342: * Data missing. Do a P reconstruct write if
! 343: * only a single data unit is lost in the
! 344: * stripe, otherwise a reconstruct write which
! 345: * is employing both P and E units.
! 346: */
! 347: if (rf_NumFailedDataUnitsInStripe(raidPtr, asmap) == 2)
! 348: {
! 349: if (asmap->numStripeUnitsAccessed == 1)
! 350: *createFunc = (RF_VoidFuncPtr)
! 351: rf_EO_200_CreateWriteDAG;
! 352: else
! 353: /*
! 354: * No direct support for this case now,
! 355: * like that in Raid-5.
! 356: */
! 357: *createFunc = NULL;
! 358: } else {
! 359: if (asmap->numStripeUnitsAccessed != 1 &&
! 360: asmap->failedPDAs[0]->numSector !=
! 361: layoutPtr->sectorsPerStripeUnit)
! 362: /*
! 363: * No direct support for this case now,
! 364: * like that in Raid-5.
! 365: */
! 366: *createFunc = NULL;
! 367: else
! 368: *createFunc = (RF_VoidFuncPtr)
! 369: rf_EO_100_CreateWriteDAG;
! 370: }
! 371: }
! 372: break;
! 373:
! 374: case 2: /* Two disk faults. */
! 375: switch (npfail) {
! 376: case 2: /* Both p and q dead. */
! 377: *createFunc = (RF_VoidFuncPtr) rf_EO_011_CreateWriteDAG;
! 378: break;
! 379: case 1: /* Either p or q and dead data. */
! 380: RF_ASSERT(asmap->failedPDAs[0]->type ==
! 381: RF_PDA_TYPE_DATA);
! 382: RF_ASSERT((asmap->failedPDAs[1]->type ==
! 383: RF_PDA_TYPE_PARITY) ||
! 384: (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q));
! 385: if (asmap->failedPDAs[1]->type == RF_PDA_TYPE_Q) {
! 386: if (asmap->numStripeUnitsAccessed != 1 &&
! 387: asmap->failedPDAs[0]->numSector !=
! 388: layoutPtr->sectorsPerStripeUnit)
! 389: /*
! 390: * In both PQ and EvenOdd, no direct
! 391: * support for this case now, like that
! 392: * in Raid-5.
! 393: */
! 394: *createFunc = NULL;
! 395: else
! 396: *createFunc = (RF_VoidFuncPtr)
! 397: rf_EO_101_CreateWriteDAG;
! 398: } else {
! 399: if (asmap->numStripeUnitsAccessed != 1 &&
! 400: asmap->failedPDAs[0]->numSector !=
! 401: layoutPtr->sectorsPerStripeUnit)
! 402: /*
! 403: * No direct support for this case,
! 404: * like that in Raid-5.
! 405: */
! 406: *createFunc = NULL;
! 407: else
! 408: *createFunc = (RF_VoidFuncPtr)
! 409: rf_EO_110_CreateWriteDAG;
! 410: }
! 411: break;
! 412: case 0: /* Double data loss. */
! 413: /*
! 414: * if(asmap->failedPDAs[0]->numSector +
! 415: * asmap->failedPDAs[1]->numSector == 2 *
! 416: * layoutPtr->sectorsPerStripeUnit ) createFunc =
! 417: * rf_EOCreateLargeWriteDAG; else
! 418: */
! 419: *createFunc = NULL; /*
! 420: * Currently, in Evenodd, no
! 421: * support for simultaneous
! 422: * access of both failed SUs.
! 423: */
! 424: break;
! 425: }
! 426: break;
! 427:
! 428: default: /* More than 2 disk faults. */
! 429: *createFunc = NULL;
! 430: RF_PANIC();
! 431: }
! 432: return;
! 433: }
! 434:
! 435:
! 436: int
! 437: rf_VerifyParityEvenOdd(
! 438: RF_Raid_t *raidPtr,
! 439: RF_RaidAddr_t raidAddr,
! 440: RF_PhysDiskAddr_t *parityPDA,
! 441: int correct_it,
! 442: RF_RaidAccessFlags_t flags
! 443: )
! 444: {
! 445: RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
! 446: RF_RaidAddr_t startAddr =
! 447: rf_RaidAddressOfPrevStripeBoundary(layoutPtr, raidAddr);
! 448: RF_SectorCount_t numsector = parityPDA->numSector;
! 449: int numbytes = rf_RaidAddressToByte(raidPtr, numsector);
! 450: int bytesPerStripe = numbytes * layoutPtr->numDataCol;
! 451: RF_DagHeader_t *rd_dag_h, *wr_dag_h; /* Read, write dag. */
! 452: RF_DagNode_t *blockNode, *unblockNode, *wrBlock, *wrUnblock;
! 453: RF_AccessStripeMapHeader_t *asm_h;
! 454: RF_AccessStripeMap_t *asmap;
! 455: RF_AllocListElem_t *alloclist;
! 456: RF_PhysDiskAddr_t *pda;
! 457: char *pbuf, *buf, *end_p, *p;
! 458: char *redundantbuf2;
! 459: int redundantTwoErr = 0, redundantOneErr = 0;
! 460: int parity_cant_correct = RF_FALSE, red2_cant_correct = RF_FALSE,
! 461: parity_corrected = RF_FALSE, red2_corrected = RF_FALSE;
! 462: int i, retcode;
! 463: RF_ReconUnitNum_t which_ru;
! 464: RF_StripeNum_t psID = rf_RaidAddressToParityStripeID(layoutPtr,
! 465: raidAddr, &which_ru);
! 466: int stripeWidth = layoutPtr->numDataCol + layoutPtr->numParityCol;
! 467: RF_AccTraceEntry_t tracerec;
! 468: RF_MCPair_t *mcpair;
! 469:
! 470: retcode = RF_PARITY_OKAY;
! 471:
! 472: mcpair = rf_AllocMCPair();
! 473: rf_MakeAllocList(alloclist);
! 474: RF_MallocAndAdd(buf, numbytes * (layoutPtr->numDataCol +
! 475: layoutPtr->numParityCol), (char *), alloclist);
! 476: /* Use calloc to make sure buffer is zeroed. */
! 477: RF_CallocAndAdd(pbuf, 1, numbytes, (char *), alloclist);
! 478: end_p = buf + bytesPerStripe;
! 479: /* Use calloc to make sure buffer is zeroed. */
! 480: RF_CallocAndAdd(redundantbuf2, 1, numbytes, (char *), alloclist);
! 481:
! 482: rd_dag_h = rf_MakeSimpleDAG(raidPtr, stripeWidth, numbytes, buf,
! 483: rf_DiskReadFunc, rf_DiskReadUndoFunc, "Rod", alloclist, flags,
! 484: RF_IO_NORMAL_PRIORITY);
! 485: blockNode = rd_dag_h->succedents[0];
! 486: unblockNode = blockNode->succedents[0]->succedents[0];
! 487:
! 488: /* Map the stripe and fill in the PDAs in the dag. */
! 489: asm_h = rf_MapAccess(raidPtr, startAddr,
! 490: layoutPtr->dataSectorsPerStripe, buf, RF_DONT_REMAP);
! 491: asmap = asm_h->stripeMap;
! 492:
! 493: for (pda = asmap->physInfo, i = 0; i < layoutPtr->numDataCol;
! 494: i++, pda = pda->next) {
! 495: RF_ASSERT(pda);
! 496: rf_RangeRestrictPDA(raidPtr, parityPDA, pda, 0, 1);
! 497: RF_ASSERT(pda->numSector != 0);
! 498: if (rf_TryToRedirectPDA(raidPtr, pda, 0))
! 499: /*
! 500: * No way to verify parity if disk is dead.
! 501: * Return w/ good status.
! 502: */
! 503: goto out;
! 504: blockNode->succedents[i]->params[0].p = pda;
! 505: blockNode->succedents[i]->params[2].v = psID;
! 506: blockNode->succedents[i]->params[3].v =
! 507: RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
! 508: }
! 509:
! 510: RF_ASSERT(!asmap->parityInfo->next);
! 511: rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->parityInfo, 0, 1);
! 512: RF_ASSERT(asmap->parityInfo->numSector != 0);
! 513: if (rf_TryToRedirectPDA(raidPtr, asmap->parityInfo, 1))
! 514: goto out;
! 515: blockNode->succedents[layoutPtr->numDataCol]->params[0].p =
! 516: asmap->parityInfo;
! 517:
! 518: RF_ASSERT(!asmap->qInfo->next);
! 519: rf_RangeRestrictPDA(raidPtr, parityPDA, asmap->qInfo, 0, 1);
! 520: RF_ASSERT(asmap->qInfo->numSector != 0);
! 521: if (rf_TryToRedirectPDA(raidPtr, asmap->qInfo, 1))
! 522: goto out;
! 523: /*
! 524: * If disk is dead, b/c no reconstruction is implemented right now,
! 525: * the function "rf_TryToRedirectPDA" always return one, which causes
! 526: * go to out and return w/ good status.
! 527: */
! 528: blockNode->succedents[layoutPtr->numDataCol + 1]->params[0].p =
! 529: asmap->qInfo;
! 530:
! 531: /* Fire off the DAG. */
! 532: bzero((char *) &tracerec, sizeof(tracerec));
! 533: rd_dag_h->tracerec = &tracerec;
! 534:
! 535: if (rf_verifyParityDebug) {
! 536: printf("Parity verify read dag:\n");
! 537: rf_PrintDAGList(rd_dag_h);
! 538: }
! 539: RF_LOCK_MUTEX(mcpair->mutex);
! 540: mcpair->flag = 0;
! 541: rf_DispatchDAG(rd_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
! 542: (void *) mcpair);
! 543: while (!mcpair->flag)
! 544: RF_WAIT_COND(mcpair->cond, mcpair->mutex);
! 545: RF_UNLOCK_MUTEX(mcpair->mutex);
! 546: if (rd_dag_h->status != rf_enable) {
! 547: RF_ERRORMSG("Unable to verify parity: can't read"
! 548: " the stripe\n");
! 549: retcode = RF_PARITY_COULD_NOT_VERIFY;
! 550: goto out;
! 551: }
! 552: for (p = buf, i = 0; p < end_p; p += numbytes, i++) {
! 553: rf_e_encToBuf(raidPtr, i, p, RF_EO_MATRIX_DIM - 2,
! 554: redundantbuf2, numsector);
! 555: /*
! 556: * The corresponding columns in EvenOdd encoding Matrix for
! 557: * these p pointers that point to the databuffer in a full
! 558: * stripe are sequential from 0 to layoutPtr->numDataCol-1.
! 559: */
! 560: rf_bxor(p, pbuf, numbytes, NULL);
! 561: }
! 562: RF_ASSERT(i == layoutPtr->numDataCol);
! 563:
! 564: for (i = 0; i < numbytes; i++) {
! 565: if (pbuf[i] != buf[bytesPerStripe + i]) {
! 566: if (!correct_it) {
! 567: RF_ERRORMSG3("Parity verify error: byte %d of"
! 568: " parity is 0x%x should be 0x%x\n", i,
! 569: (u_char) buf[bytesPerStripe + i],
! 570: (u_char) pbuf[i]);
! 571: }
! 572: }
! 573: redundantOneErr = 1;
! 574: break;
! 575: }
! 576:
! 577: for (i = 0; i < numbytes; i++) {
! 578: if (redundantbuf2[i] != buf[bytesPerStripe + numbytes + i]) {
! 579: if (!correct_it) {
! 580: RF_ERRORMSG3("Parity verify error: byte %d of"
! 581: " second redundant information is 0x%x"
! 582: " should be 0x%x\n", i,
! 583: (u_char) buf[bytesPerStripe + numbytes + i],
! 584: (u_char) redundantbuf2[i]);
! 585: }
! 586: redundantTwoErr = 1;
! 587: break;
! 588: }
! 589: }
! 590: if (redundantOneErr || redundantTwoErr)
! 591: retcode = RF_PARITY_BAD;
! 592:
! 593: /* Correct the first redundant disk, ie parity if it is error. */
! 594: if (redundantOneErr && correct_it) {
! 595: wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes, pbuf,
! 596: rf_DiskWriteFunc, rf_DiskWriteUndoFunc, "Wnp", alloclist,
! 597: flags, RF_IO_NORMAL_PRIORITY);
! 598: wrBlock = wr_dag_h->succedents[0];
! 599: wrUnblock = wrBlock->succedents[0]->succedents[0];
! 600: wrBlock->succedents[0]->params[0].p = asmap->parityInfo;
! 601: wrBlock->succedents[0]->params[2].v = psID;
! 602: wrBlock->succedents[0]->params[3].v =
! 603: RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
! 604: bzero((char *) &tracerec, sizeof(tracerec));
! 605: wr_dag_h->tracerec = &tracerec;
! 606: if (rf_verifyParityDebug) {
! 607: printf("Parity verify write dag:\n");
! 608: rf_PrintDAGList(wr_dag_h);
! 609: }
! 610: RF_LOCK_MUTEX(mcpair->mutex);
! 611: mcpair->flag = 0;
! 612: rf_DispatchDAG(wr_dag_h,
! 613: (void (*) (void *)) rf_MCPairWakeupFunc, (void *) mcpair);
! 614: while (!mcpair->flag)
! 615: RF_WAIT_COND(mcpair->cond, mcpair->mutex);
! 616: RF_UNLOCK_MUTEX(mcpair->mutex);
! 617: if (wr_dag_h->status != rf_enable) {
! 618: RF_ERRORMSG("Unable to correct parity in VerifyParity:"
! 619: " can't write the stripe\n");
! 620: parity_cant_correct = RF_TRUE;
! 621: } else {
! 622: parity_corrected = RF_TRUE;
! 623: }
! 624: rf_FreeDAG(wr_dag_h);
! 625: }
! 626: if (redundantTwoErr && correct_it) {
! 627: wr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, numbytes,
! 628: redundantbuf2, rf_DiskWriteFunc, rf_DiskWriteUndoFunc,
! 629: "Wnred2", alloclist, flags, RF_IO_NORMAL_PRIORITY);
! 630: wrBlock = wr_dag_h->succedents[0];
! 631: wrUnblock = wrBlock->succedents[0]->succedents[0];
! 632: wrBlock->succedents[0]->params[0].p = asmap->qInfo;
! 633: wrBlock->succedents[0]->params[2].v = psID;
! 634: wrBlock->succedents[0]->params[3].v =
! 635: RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, which_ru);
! 636: bzero((char *) &tracerec, sizeof(tracerec));
! 637: wr_dag_h->tracerec = &tracerec;
! 638: if (rf_verifyParityDebug) {
! 639: printf("Dag of write new second redundant information"
! 640: " in parity verify :\n");
! 641: rf_PrintDAGList(wr_dag_h);
! 642: }
! 643: RF_LOCK_MUTEX(mcpair->mutex);
! 644: mcpair->flag = 0;
! 645: rf_DispatchDAG(wr_dag_h,
! 646: (void (*) (void *)) rf_MCPairWakeupFunc, (void *) mcpair);
! 647: while (!mcpair->flag)
! 648: RF_WAIT_COND(mcpair->cond, mcpair->mutex);
! 649: RF_UNLOCK_MUTEX(mcpair->mutex);
! 650: if (wr_dag_h->status != rf_enable) {
! 651: RF_ERRORMSG("Unable to correct second redundant"
! 652: " information in VerifyParity: can't write the"
! 653: " stripe\n");
! 654: red2_cant_correct = RF_TRUE;
! 655: } else {
! 656: red2_corrected = RF_TRUE;
! 657: }
! 658: rf_FreeDAG(wr_dag_h);
! 659: }
! 660: if ((redundantOneErr && parity_cant_correct) ||
! 661: (redundantTwoErr && red2_cant_correct))
! 662: retcode = RF_PARITY_COULD_NOT_CORRECT;
! 663: if ((retcode = RF_PARITY_BAD) && parity_corrected && red2_corrected)
! 664: retcode = RF_PARITY_CORRECTED;
! 665:
! 666:
! 667: out:
! 668: rf_FreeAccessStripeMap(asm_h);
! 669: rf_FreeAllocList(alloclist);
! 670: rf_FreeDAG(rd_dag_h);
! 671: rf_FreeMCPair(mcpair);
! 672: return (retcode);
! 673: }
! 674: #endif /* RF_INCLUDE_EVENODD > 0 */
CVSweb