Annotation of sys/dev/raidframe/rf_evenodd.c, Revision 1.1.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