Annotation of sys/dev/raidframe/rf_evenodd_dagfuncs.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: rf_evenodd_dagfuncs.c,v 1.7 2002/12/16 07:01:04 tdeval Exp $ */
2: /* $NetBSD: rf_evenodd_dagfuncs.c,v 1.6 2000/03/30 12:45:40 augustss Exp $ */
3:
4: /*
5: * Copyright (c) 1995 Carnegie-Mellon University.
6: * All rights reserved.
7: *
8: * Author: ChangMing 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: * Code for RAID-EVENODD architecture.
33: */
34:
35: #include "rf_types.h"
36: #include "rf_raid.h"
37: #include "rf_dag.h"
38: #include "rf_dagffrd.h"
39: #include "rf_dagffwr.h"
40: #include "rf_dagdegrd.h"
41: #include "rf_dagdegwr.h"
42: #include "rf_dagutils.h"
43: #include "rf_dagfuncs.h"
44: #include "rf_etimer.h"
45: #include "rf_general.h"
46: #include "rf_configure.h"
47: #include "rf_parityscan.h"
48: #include "rf_evenodd.h"
49: #include "rf_evenodd_dagfuncs.h"
50:
51: /* These redundant functions are for small write. */
52: RF_RedFuncs_t rf_EOSmallWritePFuncs = {
53: rf_RegularXorFunc, "Regular Old-New P",
54: rf_SimpleXorFunc, "Simple Old-New P"
55: };
56: RF_RedFuncs_t rf_EOSmallWriteEFuncs = {
57: rf_RegularONEFunc, "Regular Old-New E",
58: rf_SimpleONEFunc, "Regular Old-New E"
59: };
60: /* These redundant functions are for degraded read. */
61: RF_RedFuncs_t rf_eoPRecoveryFuncs = {
62: rf_RecoveryXorFunc, "Recovery Xr",
63: rf_RecoveryXorFunc, "Recovery Xr"
64: };
65: RF_RedFuncs_t rf_eoERecoveryFuncs = {
66: rf_RecoveryEFunc, "Recovery E Func",
67: rf_RecoveryEFunc, "Recovery E Func"
68: };
69:
70:
71: /*****************************************************************************
72: * The following encoding node functions is used in
73: * EO_000_CreateLargeWriteDAG.
74: *****************************************************************************/
75: int
76: rf_RegularPEFunc(RF_DagNode_t *node)
77: {
78: rf_RegularESubroutine(node, node->results[1]);
79: rf_RegularXorFunc(node); /* Do the wakeup here ! */
80: #if 1
81: return (0); /* XXX This was missing... GO */
82: #endif
83: }
84:
85:
86: /*****************************************************************************
87: * For EO_001_CreateSmallWriteDAG, there are (i) RegularONEFunc() and
88: * (ii) SimpleONEFunc() to be used. The previous case is when write accesses
89: * at least sectors of full stripe unit.
90: * The later function is used when the write accesses two stripe units but
91: * with total sectors less than sectors per SU. In this case, the access of
92: * parity and 'E' are shown as disconnected areas in their stripe unit and
93: * parity write and 'E' write are both divided into two distinct writes
94: * (totally four). This simple old-new write and regular old-new write happen
95: * as in RAID-5.
96: *****************************************************************************/
97:
98: /*
99: * Algorithm:
100: * 1. Store the difference of old data and new data in the Rod buffer.
101: * 2. Then encode this buffer into the buffer that already have old 'E'
102: * information inside it, the result can be shown to be the new 'E'
103: * information.
104: * 3. Xor the Wnd buffer into the difference buffer to recover the original
105: * old data.
106: * Here we have another alternative: to allocate a temporary buffer for
107: * storing the difference of old data and new data, then encode temp buf
108: * into old 'E' buf to form new 'E', but this approach takes the same speed
109: * as the previous, and needs more memory.
110: */
111: int
112: rf_RegularONEFunc(RF_DagNode_t *node)
113: {
114: RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[node->numParams - 1].p;
115: RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) & raidPtr->Layout;
116: int EpdaIndex = (node->numParams - 1) / 2 - 1; /*
117: * The parameter of node
118: * where you can find
119: * e-pda.
120: */
121: int i, k, retcode = 0;
122: int suoffset, length;
123: RF_RowCol_t scol;
124: char *srcbuf, *destbuf;
125: RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;
126: RF_Etimer_t timer;
127: RF_PhysDiskAddr_t *pda, *EPDA = (RF_PhysDiskAddr_t *)
128: node->params[EpdaIndex].p;
129: /* Generally zero. */
130: int ESUOffset = rf_StripeUnitOffset(layoutPtr, EPDA->startSector);
131:
132: RF_ASSERT(EPDA->type == RF_PDA_TYPE_Q);
133: RF_ASSERT(ESUOffset == 0);
134:
135: RF_ETIMER_START(timer);
136:
137: /*
138: * Xor the Wnd buffer into Rod buffer. The difference of old data and
139: * new data is stored in Rod buffer.
140: */
141: for (k = 0; k < EpdaIndex; k += 2) {
142: length = rf_RaidAddressToByte(raidPtr,
143: ((RF_PhysDiskAddr_t *) node->params[k].p)->numSector);
144: retcode = rf_bxor(node->params[k + EpdaIndex + 3].p,
145: node->params[k + 1].p, length, node->dagHdr->bp);
146: }
147: /*
148: * Start to encode the buffer, storing the difference of old data and
149: * new data into 'E' buffer.
150: */
151: for (i = 0; i < EpdaIndex; i += 2)
152: if (node->params[i + 1].p != node->results[0]) {
153: /* results[0] is buf ptr of E. */
154: pda = (RF_PhysDiskAddr_t *) node->params[i].p;
155: srcbuf = (char *) node->params[i + 1].p;
156: scol = rf_EUCol(layoutPtr, pda->raidAddress);
157: suoffset = rf_StripeUnitOffset(layoutPtr,
158: pda->startSector);
159: destbuf = ((char *) node->results[0]) +
160: rf_RaidAddressToByte(raidPtr, suoffset);
161: rf_e_encToBuf(raidPtr, scol, srcbuf,
162: RF_EO_MATRIX_DIM - 2, destbuf, pda->numSector);
163: }
164: /*
165: * Recover the original old data to be used by parity encoding
166: * function in XorNode.
167: */
168: for (k = 0; k < EpdaIndex; k += 2) {
169: length = rf_RaidAddressToByte(raidPtr,
170: ((RF_PhysDiskAddr_t *) node->params[k].p)->numSector);
171: retcode = rf_bxor(node->params[k + EpdaIndex + 3].p,
172: node->params[k + 1].p, length, node->dagHdr->bp);
173: }
174: RF_ETIMER_STOP(timer);
175: RF_ETIMER_EVAL(timer);
176: tracerec->q_us += RF_ETIMER_VAL_US(timer);
177: rf_GenericWakeupFunc(node, 0);
178: #if 1
179: return (0); /* XXX This was missing... GO */
180: #endif
181: }
182:
183: int
184: rf_SimpleONEFunc(RF_DagNode_t *node)
185: {
186: RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[node->numParams - 1].p;
187: RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) & raidPtr->Layout;
188: RF_PhysDiskAddr_t *pda = (RF_PhysDiskAddr_t *) node->params[0].p;
189: int retcode = 0;
190: char *srcbuf, *destbuf;
191: RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;
192: int length;
193: RF_RowCol_t scol;
194: RF_Etimer_t timer;
195:
196: RF_ASSERT(((RF_PhysDiskAddr_t *) node->params[2].p)->type ==
197: RF_PDA_TYPE_Q);
198: if (node->dagHdr->status == rf_enable) {
199: RF_ETIMER_START(timer);
200: /* This is a pda of writeDataNodes. */
201: length = rf_RaidAddressToByte(raidPtr,
202: ((RF_PhysDiskAddr_t *) node->params[4].p)->numSector);
203: /* bxor to buffer of readDataNodes. */
204: retcode = rf_bxor(node->params[5].p, node->params[1].p,
205: length, node->dagHdr->bp);
206: /*
207: * Find out the corresponding column in encoding matrix for
208: * write column to be encoded into redundant disk 'E'.
209: */
210: scol = rf_EUCol(layoutPtr, pda->raidAddress);
211: srcbuf = node->params[1].p;
212: destbuf = node->params[3].p;
213: /* Start encoding process. */
214: rf_e_encToBuf(raidPtr, scol, srcbuf, RF_EO_MATRIX_DIM - 2,
215: destbuf, pda->numSector);
216: rf_bxor(node->params[5].p, node->params[1].p, length,
217: node->dagHdr->bp);
218: RF_ETIMER_STOP(timer);
219: RF_ETIMER_EVAL(timer);
220: tracerec->q_us += RF_ETIMER_VAL_US(timer);
221:
222: }
223: return (rf_GenericWakeupFunc(node, retcode)); /*
224: * Call wake func
225: * explicitly since no
226: * I/O in this node.
227: */
228: }
229:
230:
231: /*
232: * Called by rf_RegularPEFunc(node) and rf_RegularEFunc(node)
233: * in f.f. large write.
234: */
235: void
236: rf_RegularESubroutine(RF_DagNode_t *node, char *ebuf)
237: {
238: RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[node->numParams - 1].p;
239: RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) & raidPtr->Layout;
240: RF_PhysDiskAddr_t *pda;
241: int i, suoffset;
242: RF_RowCol_t scol;
243: char *srcbuf, *destbuf;
244: RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;
245: RF_Etimer_t timer;
246:
247: RF_ETIMER_START(timer);
248: for (i = 0; i < node->numParams - 2; i += 2) {
249: RF_ASSERT(node->params[i + 1].p != ebuf);
250: pda = (RF_PhysDiskAddr_t *) node->params[i].p;
251: suoffset = rf_StripeUnitOffset(layoutPtr, pda->startSector);
252: scol = rf_EUCol(layoutPtr, pda->raidAddress);
253: srcbuf = (char *) node->params[i + 1].p;
254: destbuf = ebuf + rf_RaidAddressToByte(raidPtr, suoffset);
255: rf_e_encToBuf(raidPtr, scol, srcbuf, RF_EO_MATRIX_DIM - 2,
256: destbuf, pda->numSector);
257: }
258: RF_ETIMER_STOP(timer);
259: RF_ETIMER_EVAL(timer);
260: tracerec->xor_us += RF_ETIMER_VAL_US(timer);
261: }
262:
263:
264: /*****************************************************************************
265: * Used in EO_001_CreateLargeWriteDAG.
266: *****************************************************************************/
267: int
268: rf_RegularEFunc(RF_DagNode_t *node)
269: {
270: rf_RegularESubroutine(node, node->results[0]);
271: rf_GenericWakeupFunc(node, 0);
272: #if 1
273: return (0); /* XXX This was missing... GO */
274: #endif
275: }
276:
277:
278: /*****************************************************************************
279: * This degraded function allow only two cases:
280: * 1. When write accesses the full failed stripe unit, then the access can
281: * be more than one stripe unit.
282: * 2. When write accesses only part of the failed SU, we assume accesses of
283: * more than one stripe unit are not allowed so that the write can be
284: * dealt with like a large write.
285: * The following function is based on these assumptions. So except in the
286: * second case, it looks the same as a large write encoding function. But
287: * this is not exactly the normal way of doing a degraded write, since
288: * RAIDframe has to break cases of accesses other than the above two into
289: * smaller accesses. We may have to change DegrESubroutin in the future.
290: *****************************************************************************/
291: void
292: rf_DegrESubroutine(RF_DagNode_t *node, char *ebuf)
293: {
294: RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[node->numParams - 1].p;
295: RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) & raidPtr->Layout;
296: RF_PhysDiskAddr_t *failedPDA = (RF_PhysDiskAddr_t *) node->params[node->numParams - 2].p;
297: RF_PhysDiskAddr_t *pda;
298: int i, suoffset, failedSUOffset = rf_StripeUnitOffset(layoutPtr, failedPDA->startSector);
299: RF_RowCol_t scol;
300: char *srcbuf, *destbuf;
301: RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;
302: RF_Etimer_t timer;
303:
304: RF_ETIMER_START(timer);
305: for (i = 0; i < node->numParams - 2; i += 2) {
306: RF_ASSERT(node->params[i + 1].p != ebuf);
307: pda = (RF_PhysDiskAddr_t *) node->params[i].p;
308: suoffset = rf_StripeUnitOffset(layoutPtr, pda->startSector);
309: scol = rf_EUCol(layoutPtr, pda->raidAddress);
310: srcbuf = (char *) node->params[i + 1].p;
311: destbuf = ebuf + rf_RaidAddressToByte(raidPtr, suoffset - failedSUOffset);
312: rf_e_encToBuf(raidPtr, scol, srcbuf, RF_EO_MATRIX_DIM - 2, destbuf, pda->numSector);
313: }
314:
315: RF_ETIMER_STOP(timer);
316: RF_ETIMER_EVAL(timer);
317: tracerec->q_us += RF_ETIMER_VAL_US(timer);
318: }
319:
320:
321: /*****************************************************************************
322: * This function is used in case where one data disk failed and both redundant
323: * disks are alive. It is used in the EO_100_CreateWriteDAG. Note: if there is
324: * another disk failed in the stripe but not accessed at this time, then we
325: * should, instead, use the rf_EOWriteDoubleRecoveryFunc().
326: *****************************************************************************/
327: int
328: rf_Degraded_100_EOFunc(RF_DagNode_t *node)
329: {
330: rf_DegrESubroutine(node, node->results[1]);
331: rf_RecoveryXorFunc(node); /* Does the wakeup here ! */
332: #if 1
333: return (0); /* XXX This was missing... Should these be
334: * void functions ??? GO */
335: #endif
336: }
337:
338:
339: /*****************************************************************************
340: * This function is to encode one sector in one of the data disks to the E
341: * disk. However, in evenodd this function can also be used as decoding
342: * function to recover data from dead disk in the case of parity failure and
343: * a single data failure.
344: *****************************************************************************/
345: void
346: rf_e_EncOneSect(RF_RowCol_t srcLogicCol, char *srcSecbuf,
347: RF_RowCol_t destLogicCol, char *destSecbuf, int bytesPerSector)
348: {
349: int S_index; /*
350: * Index of the EU in the src col which need
351: * be Xored into all EUs in a dest sector.
352: */
353: int numRowInEncMatrix = (RF_EO_MATRIX_DIM) - 1;
354: RF_RowCol_t j, indexInDest; /*
355: * Row index of an encoding unit in
356: * the destination column of encoding
357: * matrix.
358: */
359: RF_RowCol_t indexInSrc; /*
360: * Row index of an encoding unit in the source
361: * column used for recovery.
362: */
363: int bytesPerEU = bytesPerSector / numRowInEncMatrix;
364:
365: #if RF_EO_MATRIX_DIM > 17
366: int shortsPerEU = bytesPerEU / sizeof(short);
367: short *destShortBuf, *srcShortBuf1, *srcShortBuf2;
368: short temp1;
369: #elif RF_EO_MATRIX_DIM == 17
370: int longsPerEU = bytesPerEU / sizeof(long);
371: long *destLongBuf, *srcLongBuf1, *srcLongBuf2;
372: long temp1;
373: #endif
374:
375: #if RF_EO_MATRIX_DIM > 17
376: RF_ASSERT(sizeof(short) == 2 || sizeof(short) == 1);
377: RF_ASSERT(bytesPerEU % sizeof(short) == 0);
378: #elif RF_EO_MATRIX_DIM == 17
379: RF_ASSERT(sizeof(long) == 8 || sizeof(long) == 4);
380: RF_ASSERT(bytesPerEU % sizeof(long) == 0);
381: #endif
382:
383: S_index = rf_EO_Mod((RF_EO_MATRIX_DIM - 1 + destLogicCol - srcLogicCol), RF_EO_MATRIX_DIM);
384: #if RF_EO_MATRIX_DIM > 17
385: srcShortBuf1 = (short *) (srcSecbuf + S_index * bytesPerEU);
386: #elif RF_EO_MATRIX_DIM == 17
387: srcLongBuf1 = (long *) (srcSecbuf + S_index * bytesPerEU);
388: #endif
389:
390: for (indexInDest = 0; indexInDest < numRowInEncMatrix; indexInDest++) {
391: indexInSrc = rf_EO_Mod((indexInDest + destLogicCol - srcLogicCol), RF_EO_MATRIX_DIM);
392:
393: #if RF_EO_MATRIX_DIM > 17
394: destShortBuf = (short *) (destSecbuf + indexInDest * bytesPerEU);
395: srcShortBuf2 = (short *) (srcSecbuf + indexInSrc * bytesPerEU);
396: for (j = 0; j < shortsPerEU; j++) {
397: temp1 = destShortBuf[j] ^ srcShortBuf1[j];
398: /* Note: S_index won't be at the end row for any src
399: * col ! */
400: if (indexInSrc != RF_EO_MATRIX_DIM - 1)
401: destShortBuf[j] = (srcShortBuf2[j]) ^ temp1;
402: /* if indexInSrc is at the end row, ie.
403: * RF_EO_MATRIX_DIM -1, then all elements are zero ! */
404: else
405: destShortBuf[j] = temp1;
406: }
407:
408: #elif RF_EO_MATRIX_DIM == 17
409: destLongBuf = (long *) (destSecbuf + indexInDest * bytesPerEU);
410: srcLongBuf2 = (long *) (srcSecbuf + indexInSrc * bytesPerEU);
411: for (j = 0; j < longsPerEU; j++) {
412: temp1 = destLongBuf[j] ^ srcLongBuf1[j];
413: if (indexInSrc != RF_EO_MATRIX_DIM - 1)
414: destLongBuf[j] = (srcLongBuf2[j]) ^ temp1;
415: else
416: destLongBuf[j] = temp1;
417: }
418: #endif
419: }
420: }
421:
422: void
423: rf_e_encToBuf(RF_Raid_t *raidPtr, RF_RowCol_t srcLogicCol, char *srcbuf,
424: RF_RowCol_t destLogicCol, char *destbuf, int numSector)
425: {
426: int i, bytesPerSector = rf_RaidAddressToByte(raidPtr, 1);
427:
428: for (i = 0; i < numSector; i++) {
429: rf_e_EncOneSect(srcLogicCol, srcbuf, destLogicCol, destbuf, bytesPerSector);
430: srcbuf += bytesPerSector;
431: destbuf += bytesPerSector;
432: }
433: }
434:
435:
436: /*****************************************************************************
437: * when parity die and one data die, We use second redundant information, 'E',
438: * to recover the data in dead disk. This function is used in the recovery node of
439: * for EO_110_CreateReadDAG
440: *****************************************************************************/
441: int
442: rf_RecoveryEFunc(RF_DagNode_t *node)
443: {
444: RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[node->numParams - 1].p;
445: RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) & raidPtr->Layout;
446: RF_PhysDiskAddr_t *failedPDA = (RF_PhysDiskAddr_t *) node->params[node->numParams - 2].p;
447: RF_RowCol_t scol; /* source logical column */
448: RF_RowCol_t fcol = rf_EUCol(layoutPtr, failedPDA->raidAddress); /* logical column of
449: * failed SU */
450: int i;
451: RF_PhysDiskAddr_t *pda;
452: int suoffset, failedSUOffset = rf_StripeUnitOffset(layoutPtr, failedPDA->startSector);
453: char *srcbuf, *destbuf;
454: RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;
455: RF_Etimer_t timer;
456:
457: bzero((char *) node->results[0], rf_RaidAddressToByte(raidPtr, failedPDA->numSector));
458: if (node->dagHdr->status == rf_enable) {
459: RF_ETIMER_START(timer);
460: for (i = 0; i < node->numParams - 2; i += 2)
461: if (node->params[i + 1].p != node->results[0]) {
462: pda = (RF_PhysDiskAddr_t *) node->params[i].p;
463: if (i == node->numParams - 4)
464: scol = RF_EO_MATRIX_DIM - 2; /* the colume of
465: * redundant E */
466: else
467: scol = rf_EUCol(layoutPtr, pda->raidAddress);
468: srcbuf = (char *) node->params[i + 1].p;
469: suoffset = rf_StripeUnitOffset(layoutPtr, pda->startSector);
470: destbuf = ((char *) node->results[0]) + rf_RaidAddressToByte(raidPtr, suoffset - failedSUOffset);
471: rf_e_encToBuf(raidPtr, scol, srcbuf, fcol, destbuf, pda->numSector);
472: }
473: RF_ETIMER_STOP(timer);
474: RF_ETIMER_EVAL(timer);
475: tracerec->xor_us += RF_ETIMER_VAL_US(timer);
476: }
477: return (rf_GenericWakeupFunc(node, 0)); /* node execute successfully */
478: }
479:
480:
481: /*****************************************************************************
482: * This function is used in the case where one data and the parity have filed.
483: * (in EO_110_CreateWriteDAG)
484: *****************************************************************************/
485: int
486: rf_EO_DegradedWriteEFunc(RF_DagNode_t *node)
487: {
488: rf_DegrESubroutine(node, node->results[0]);
489: rf_GenericWakeupFunc(node, 0);
490: #if 1
491: return (0); /* XXX Yet another one !!! GO */
492: #endif
493: }
494:
495:
496:
497: /*****************************************************************************
498: * THE FUNCTION IS FOR DOUBLE DEGRADED READ AND WRITE CASES.
499: *****************************************************************************/
500:
501: void
502: rf_doubleEOdecode(RF_Raid_t *raidPtr, char **rrdbuf, char **dest,
503: RF_RowCol_t *fcol, char *pbuf, char *ebuf)
504: {
505: RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) &(raidPtr->Layout);
506: int i, j, k, f1, f2, row;
507: int rrdrow, erow, count = 0;
508: int bytesPerSector = rf_RaidAddressToByte(raidPtr, 1);
509: int numRowInEncMatrix = (RF_EO_MATRIX_DIM) - 1;
510: #if 0
511: int pcol = (RF_EO_MATRIX_DIM) - 1;
512: #endif
513: int ecol = (RF_EO_MATRIX_DIM) - 2;
514: int bytesPerEU = bytesPerSector / numRowInEncMatrix;
515: int numDataCol = layoutPtr->numDataCol;
516: #if RF_EO_MATRIX_DIM > 17
517: int shortsPerEU = bytesPerEU / sizeof(short);
518: short *rrdbuf_current, *pbuf_current, *ebuf_current;
519: short *dest_smaller, *dest_smaller_current;
520: short *dest_larger, *dest_larger_current;
521: short *temp;
522: short *P;
523:
524: RF_ASSERT(bytesPerEU % sizeof(short) == 0);
525: RF_Malloc(P, bytesPerEU, (short *));
526: RF_Malloc(temp, bytesPerEU, (short *));
527: #elif RF_EO_MATRIX_DIM == 17
528: int longsPerEU = bytesPerEU / sizeof(long);
529: long *rrdbuf_current, *pbuf_current, *ebuf_current;
530: long *dest_smaller, *dest_smaller_current;
531: long *dest_larger, *dest_larger_current;
532: long *temp;
533: long *P;
534:
535: RF_ASSERT(bytesPerEU % sizeof(long) == 0);
536: RF_Malloc(P, bytesPerEU, (long *));
537: RF_Malloc(temp, bytesPerEU, (long *));
538: #endif
539: RF_ASSERT(*((long *) dest[0]) == 0);
540: RF_ASSERT(*((long *) dest[1]) == 0);
541: bzero((char *) P, bytesPerEU);
542: bzero((char *) temp, bytesPerEU);
543: RF_ASSERT(*P == 0);
544: /*
545: * Calculate the 'P' parameter, which, not parity, is the Xor of all
546: * elements in the last two column, ie. 'E' and 'parity' columns, see
547: * the Ref. paper by Blaum, et al 1993.
548: */
549: for (i = 0; i < numRowInEncMatrix; i++)
550: for (k = 0; k < longsPerEU; k++) {
551: #if RF_EO_MATRIX_DIM > 17
552: ebuf_current = ((short *) ebuf) + i * shortsPerEU + k;
553: pbuf_current = ((short *) pbuf) + i * shortsPerEU + k;
554: #elif RF_EO_MATRIX_DIM == 17
555: ebuf_current = ((long *) ebuf) + i * longsPerEU + k;
556: pbuf_current = ((long *) pbuf) + i * longsPerEU + k;
557: #endif
558: P[k] ^= *ebuf_current;
559: P[k] ^= *pbuf_current;
560: }
561: RF_ASSERT(fcol[0] != fcol[1]);
562: if (fcol[0] < fcol[1]) {
563: #if RF_EO_MATRIX_DIM > 17
564: dest_smaller = (short *) (dest[0]);
565: dest_larger = (short *) (dest[1]);
566: #elif RF_EO_MATRIX_DIM == 17
567: dest_smaller = (long *) (dest[0]);
568: dest_larger = (long *) (dest[1]);
569: #endif
570: f1 = fcol[0];
571: f2 = fcol[1];
572: } else {
573: #if RF_EO_MATRIX_DIM > 17
574: dest_smaller = (short *) (dest[1]);
575: dest_larger = (short *) (dest[0]);
576: #elif RF_EO_MATRIX_DIM == 17
577: dest_smaller = (long *) (dest[1]);
578: dest_larger = (long *) (dest[0]);
579: #endif
580: f1 = fcol[1];
581: f2 = fcol[0];
582: }
583: row = (RF_EO_MATRIX_DIM) - 1;
584: while ((row = rf_EO_Mod((row + f1 - f2), RF_EO_MATRIX_DIM)) !=
585: ((RF_EO_MATRIX_DIM) - 1)) {
586: #if RF_EO_MATRIX_DIM > 17
587: dest_larger_current = dest_larger + row * shortsPerEU;
588: dest_smaller_current = dest_smaller + row * shortsPerEU;
589: #elif RF_EO_MATRIX_DIM == 17
590: dest_larger_current = dest_larger + row * longsPerEU;
591: dest_smaller_current = dest_smaller + row * longsPerEU;
592: #endif
593: /*
594: * Do the diagonal recovery. Initially, temp[k] = (failed 1),
595: * which is the failed data in the column that has smaller
596: * col index.
597: */
598: /* Step 1: ^(SUM of nonfailed in-diagonal A(rrdrow,0..m-3)) */
599: for (j = 0; j < numDataCol; j++) {
600: if (j == f1 || j == f2)
601: continue;
602: rrdrow = rf_EO_Mod((row + f2 - j), RF_EO_MATRIX_DIM);
603: if (rrdrow != (RF_EO_MATRIX_DIM) - 1) {
604: #if RF_EO_MATRIX_DIM > 17
605: rrdbuf_current = (short *) (rrdbuf[j]) +
606: rrdrow * shortsPerEU;
607: for (k = 0; k < shortsPerEU; k++)
608: temp[k] ^= *(rrdbuf_current + k);
609: #elif RF_EO_MATRIX_DIM == 17
610: rrdbuf_current = (long *) (rrdbuf[j]) +
611: rrdrow * longsPerEU;
612: for (k = 0; k < longsPerEU; k++)
613: temp[k] ^= *(rrdbuf_current + k);
614: #endif
615: }
616: }
617: /*
618: * Step 2: ^E(erow,m-2), If erow is at the bottom row, don't
619: * Xor into it. E(erow,m-2) = (principle diagonal) ^ (failed
620: * 1) ^ (failed 2) ^ (SUM of nonfailed in-diagonal
621: * A(rrdrow,0..m-3))
622: * After this step, temp[k] = (principle diagonal) ^ (failed 2).
623: */
624:
625: erow = rf_EO_Mod((row + f2 - ecol), (RF_EO_MATRIX_DIM));
626: if (erow != (RF_EO_MATRIX_DIM) - 1) {
627: #if RF_EO_MATRIX_DIM > 17
628: ebuf_current = (short *) ebuf + shortsPerEU * erow;
629: for (k = 0; k < shortsPerEU; k++)
630: temp[k] ^= *(ebuf_current + k);
631: #elif RF_EO_MATRIX_DIM == 17
632: ebuf_current = (long *) ebuf + longsPerEU * erow;
633: for (k = 0; k < longsPerEU; k++)
634: temp[k] ^= *(ebuf_current + k);
635: #endif
636: }
637: /*
638: * Step 3: ^P to obtain the failed data (failed 2). P can be
639: * proved to be actually (principal diagonal). After this
640: * step, temp[k] = (failed 2), the failed data to be recovered.
641: */
642: #if RF_EO_MATRIX_DIM > 17
643: for (k = 0; k < shortsPerEU; k++)
644: temp[k] ^= P[k];
645: /* Put the data into the destination buffer. */
646: for (k = 0; k < shortsPerEU; k++)
647: dest_larger_current[k] = temp[k];
648: #elif RF_EO_MATRIX_DIM == 17
649: for (k = 0; k < longsPerEU; k++)
650: temp[k] ^= P[k];
651: /* Put the data into the destination buffer. */
652: for (k = 0; k < longsPerEU; k++)
653: dest_larger_current[k] = temp[k];
654: #endif
655:
656: /* THE FOLLOWING DO THE HORIZONTAL XOR. */
657: /*
658: * Step 1: ^(SUM of A(row,0..m-3)), ie. all nonfailed data
659: * columns.
660: */
661: for (j = 0; j < numDataCol; j++) {
662: if (j == f1 || j == f2)
663: continue;
664: #if RF_EO_MATRIX_DIM > 17
665: rrdbuf_current = (short *) (rrdbuf[j]) +
666: row * shortsPerEU;
667: for (k = 0; k < shortsPerEU; k++)
668: temp[k] ^= *(rrdbuf_current + k);
669: #elif RF_EO_MATRIX_DIM == 17
670: rrdbuf_current = (long *) (rrdbuf[j]) +
671: row * longsPerEU;
672: for (k = 0; k < longsPerEU; k++)
673: temp[k] ^= *(rrdbuf_current + k);
674: #endif
675: }
676: /* Step 2: ^A(row,m-1) */
677: /* Step 3: Put the data into the destination buffer. */
678: #if RF_EO_MATRIX_DIM > 17
679: pbuf_current = (short *) pbuf + shortsPerEU * row;
680: for (k = 0; k < shortsPerEU; k++)
681: temp[k] ^= *(pbuf_current + k);
682: for (k = 0; k < shortsPerEU; k++)
683: dest_smaller_current[k] = temp[k];
684: #elif RF_EO_MATRIX_DIM == 17
685: pbuf_current = (long *) pbuf + longsPerEU * row;
686: for (k = 0; k < longsPerEU; k++)
687: temp[k] ^= *(pbuf_current + k);
688: for (k = 0; k < longsPerEU; k++)
689: dest_smaller_current[k] = temp[k];
690: #endif
691: count++;
692: }
693: /*
694: * Check if all Encoding Unit in the data buffer have been decoded ?
695: * According to EvenOdd theory, if "RF_EO_MATRIX_DIM" is a prime
696: * number, this algorithm will covered all buffer.
697: */
698: RF_ASSERT(count == numRowInEncMatrix);
699: RF_Free((char *) P, bytesPerEU);
700: RF_Free((char *) temp, bytesPerEU);
701: }
702:
703:
704: /*****************************************************************************
705: * This function is called by double degraded read EO_200_CreateReadDAG.
706: *****************************************************************************/
707: int
708: rf_EvenOddDoubleRecoveryFunc(RF_DagNode_t *node)
709: {
710: int ndataParam = 0;
711: int np = node->numParams;
712: RF_AccessStripeMap_t *asmap = (RF_AccessStripeMap_t *)
713: node->params[np - 1].p;
714: RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[np - 2].p;
715: RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) & (raidPtr->Layout);
716: int i, prm, sector, nresults = node->numResults;
717: RF_SectorCount_t secPerSU = layoutPtr->sectorsPerStripeUnit;
718: unsigned sosAddr;
719: int two = 0, mallc_one = 0, mallc_two = 0; /*
720: * Flags to indicate if
721: * memory is allocated.
722: */
723: int bytesPerSector = rf_RaidAddressToByte(raidPtr, 1);
724: RF_PhysDiskAddr_t *ppda, *ppda2, *epda, *epda2, *pda, *pda0, *pda1,
725: npda;
726: RF_RowCol_t fcol[2], fsuoff[2], fsuend[2],
727: numDataCol = layoutPtr->numDataCol;
728: char **buf, *ebuf, *pbuf, *dest[2];
729: long *suoff = NULL, *suend = NULL, *prmToCol = NULL, psuoff, esuoff;
730: RF_SectorNum_t startSector, endSector;
731: RF_Etimer_t timer;
732: RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;
733:
734: RF_ETIMER_START(timer);
735:
736: /*
737: * Find out the number of parameters that are pdas for data
738: * information.
739: */
740: for (i = 0; i <= np; i++)
741: if (((RF_PhysDiskAddr_t *) node->params[i].p)->type !=
742: RF_PDA_TYPE_DATA) {
743: ndataParam = i;
744: break;
745: }
746: RF_Malloc(buf, numDataCol * sizeof(char *), (char **));
747: if (ndataParam != 0) {
748: RF_Malloc(suoff, ndataParam * sizeof(long), (long *));
749: RF_Malloc(suend, ndataParam * sizeof(long), (long *));
750: RF_Malloc(prmToCol, ndataParam * sizeof(long), (long *));
751: }
752: if (asmap->failedPDAs[1] &&
753: (asmap->failedPDAs[1]->numSector +
754: asmap->failedPDAs[0]->numSector) < secPerSU) {
755: RF_ASSERT(0); /* Currently, no support for this situation. */
756: ppda = node->params[np - 6].p;
757: ppda2 = node->params[np - 5].p;
758: RF_ASSERT(ppda2->type == RF_PDA_TYPE_PARITY);
759: epda = node->params[np - 4].p;
760: epda2 = node->params[np - 3].p;
761: RF_ASSERT(epda2->type == RF_PDA_TYPE_Q);
762: two = 1;
763: } else {
764: ppda = node->params[np - 4].p;
765: epda = node->params[np - 3].p;
766: psuoff = rf_StripeUnitOffset(layoutPtr, ppda->startSector);
767: esuoff = rf_StripeUnitOffset(layoutPtr, epda->startSector);
768: RF_ASSERT(psuoff == esuoff);
769: }
770: /*
771: * The followings have three goals:
772: * 1. Determine the startSector to begin decoding and endSector
773: * to end decoding.
774: * 2. Determine the column numbers of the two failed disks.
775: * 3. Determine the offset and end offset of the access within
776: * each failed stripe unit.
777: */
778: if (nresults == 1) {
779: /* Find the startSector to begin decoding. */
780: pda = node->results[0];
781: bzero(pda->bufPtr, bytesPerSector * pda->numSector);
782: fsuoff[0] = rf_StripeUnitOffset(layoutPtr, pda->startSector);
783: fsuend[0] = fsuoff[0] + pda->numSector;
784: startSector = fsuoff[0];
785: endSector = fsuend[0];
786:
787: /* Find out the column of failed disk being accessed. */
788: fcol[0] = rf_EUCol(layoutPtr, pda->raidAddress);
789:
790: /* Find out the other failed column not accessed. */
791: sosAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr,
792: asmap->raidAddress);
793: for (i = 0; i < numDataCol; i++) {
794: npda.raidAddress = sosAddr + (i * secPerSU);
795: (raidPtr->Layout.map->MapSector) (raidPtr,
796: npda.raidAddress, &(npda.row), &(npda.col),
797: &(npda.startSector), 0);
798: /* Skip over dead disks. */
799: if (RF_DEAD_DISK(raidPtr
800: ->Disks[npda.row][npda.col].status))
801: if (i != fcol[0])
802: break;
803: }
804: RF_ASSERT(i < numDataCol);
805: fcol[1] = i;
806: } else {
807: RF_ASSERT(nresults == 2);
808: pda0 = node->results[0];
809: bzero(pda0->bufPtr, bytesPerSector * pda0->numSector);
810: pda1 = node->results[1];
811: bzero(pda1->bufPtr, bytesPerSector * pda1->numSector);
812: /*
813: * Determine the failed column numbers of the two failed
814: * disks.
815: */
816: fcol[0] = rf_EUCol(layoutPtr, pda0->raidAddress);
817: fcol[1] = rf_EUCol(layoutPtr, pda1->raidAddress);
818: /*
819: * Determine the offset and end offset of the access within
820: * each failed stripe unit.
821: */
822: fsuoff[0] = rf_StripeUnitOffset(layoutPtr, pda0->startSector);
823: fsuend[0] = fsuoff[0] + pda0->numSector;
824: fsuoff[1] = rf_StripeUnitOffset(layoutPtr, pda1->startSector);
825: fsuend[1] = fsuoff[1] + pda1->numSector;
826: /* Determine the startSector to begin decoding. */
827: startSector = RF_MIN(pda0->startSector, pda1->startSector);
828: /* Determine the endSector to end decoding. */
829: endSector = RF_MAX(fsuend[0], fsuend[1]);
830: }
831: /*
832: * Assign the beginning sector and the end sector for each parameter.
833: * Find out the corresponding column # for each parameter.
834: */
835: for (prm = 0; prm < ndataParam; prm++) {
836: pda = node->params[prm].p;
837: suoff[prm] = rf_StripeUnitOffset(layoutPtr, pda->startSector);
838: suend[prm] = suoff[prm] + pda->numSector;
839: prmToCol[prm] = rf_EUCol(layoutPtr, pda->raidAddress);
840: }
841: /*
842: * 'sector' is the sector for the current decoding algorithm. For each
843: * sector in the failed SU
844: * 1. Find out the corresponding parameters that cover the current
845: * sector and that are needed for the decoding of this sector in
846: * failed SU.
847: * 2. Find out if sector is in the shadow of any accessed failed SU.
848: * If not, malloc a temporary space of a sector in size.
849: */
850: for (sector = startSector; sector < endSector; sector++) {
851: if (nresults == 2)
852: if (!(fsuoff[0] <= sector && sector < fsuend[0]) &&
853: !(fsuoff[1] <= sector && sector < fsuend[1]))
854: continue;
855: for (prm = 0; prm < ndataParam; prm++)
856: if (suoff[prm] <= sector && sector < suend[prm])
857: buf[(prmToCol[prm])] = ((RF_PhysDiskAddr_t *)
858: node->params[prm].p)->bufPtr +
859: rf_RaidAddressToByte(raidPtr,
860: sector - suoff[prm]);
861: /*
862: * Find out if sector is in the shadow of any accessed failed
863: * SU. If yes, assign dest[0], dest[1] to point at suitable
864: * position of the buffer corresponding to failed SUs. If no,
865: * malloc a temporary space of a sector in size for
866: * destination of decoding.
867: */
868: RF_ASSERT(nresults == 1 || nresults == 2);
869: if (nresults == 1) {
870: dest[0] = ((RF_PhysDiskAddr_t *)
871: node->results[0])->bufPtr +
872: rf_RaidAddressToByte(raidPtr, sector - fsuoff[0]);
873: /* Always malloc temp buffer to dest[1]. */
874: RF_Malloc(dest[1], bytesPerSector, (char *));
875: bzero(dest[1], bytesPerSector);
876: mallc_two = 1;
877: } else {
878: if (fsuoff[0] <= sector && sector < fsuend[0])
879: dest[0] = ((RF_PhysDiskAddr_t *)
880: node->results[0])->bufPtr +
881: rf_RaidAddressToByte(raidPtr,
882: sector - fsuoff[0]);
883: else {
884: RF_Malloc(dest[0], bytesPerSector, (char *));
885: bzero(dest[0], bytesPerSector);
886: mallc_one = 1;
887: }
888: if (fsuoff[1] <= sector && sector < fsuend[1])
889: dest[1] = ((RF_PhysDiskAddr_t *)
890: node->results[1])->bufPtr +
891: rf_RaidAddressToByte(raidPtr,
892: sector - fsuoff[1]);
893: else {
894: RF_Malloc(dest[1], bytesPerSector, (char *));
895: bzero(dest[1], bytesPerSector);
896: mallc_two = 1;
897: }
898: RF_ASSERT(mallc_one == 0 || mallc_two == 0);
899: }
900: pbuf = ppda->bufPtr + rf_RaidAddressToByte(raidPtr,
901: sector - psuoff);
902: ebuf = epda->bufPtr + rf_RaidAddressToByte(raidPtr,
903: sector - esuoff);
904: /*
905: * After finish finding all needed sectors, call doubleEOdecode
906: * function for decoding one sector to destination.
907: */
908: rf_doubleEOdecode(raidPtr, buf, dest, fcol, pbuf, ebuf);
909: /*
910: * Free all allocated memory, and mark flag to indicate no
911: * memory is being allocated.
912: */
913: if (mallc_one == 1)
914: RF_Free(dest[0], bytesPerSector);
915: if (mallc_two == 1)
916: RF_Free(dest[1], bytesPerSector);
917: mallc_one = mallc_two = 0;
918: }
919: RF_Free(buf, numDataCol * sizeof(char *));
920: if (ndataParam != 0) {
921: RF_Free(suoff, ndataParam * sizeof(long));
922: RF_Free(suend, ndataParam * sizeof(long));
923: RF_Free(prmToCol, ndataParam * sizeof(long));
924: }
925: RF_ETIMER_STOP(timer);
926: RF_ETIMER_EVAL(timer);
927: if (tracerec) {
928: tracerec->q_us += RF_ETIMER_VAL_US(timer);
929: }
930: rf_GenericWakeupFunc(node, 0);
931: #if 1
932: return (0); /* XXX Is this even close !!?!?!!? GO */
933: #endif
934: }
935:
936:
937: /*
938: * Currently, only access of one of the two failed SU is allowed in this
939: * function. Also, asmap->numStripeUnitsAccessed is limited to be one,
940: * the RAIDframe will break large access into many accesses of single
941: * stripe unit.
942: */
943:
944: int
945: rf_EOWriteDoubleRecoveryFunc(RF_DagNode_t *node)
946: {
947: int np = node->numParams;
948: RF_AccessStripeMap_t *asmap =
949: (RF_AccessStripeMap_t *) node->params[np - 1].p;
950: RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[np - 2].p;
951: RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) &(raidPtr->Layout);
952: RF_SectorNum_t sector;
953: RF_RowCol_t col, scol;
954: int prm, i, j;
955: RF_SectorCount_t secPerSU = layoutPtr->sectorsPerStripeUnit;
956: unsigned sosAddr;
957: unsigned bytesPerSector = rf_RaidAddressToByte(raidPtr, 1);
958: RF_int64 numbytes;
959: RF_SectorNum_t startSector, endSector;
960: RF_PhysDiskAddr_t *ppda, *epda, *pda, *fpda, npda;
961: RF_RowCol_t fcol[2], numDataCol = layoutPtr->numDataCol;
962: char **buf; /*
963: * buf[0], buf[1], buf[2], ... etc, point to
964: * buffer storing data read from col0, col1,
965: * col2.
966: */
967: char *ebuf, *pbuf, *dest[2], *olddata[2];
968: RF_Etimer_t timer;
969: RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;
970:
971: RF_ASSERT(asmap->numDataFailed == 1); /*
972: * Currently only support this
973: * case, the other failed SU
974: * is not being accessed.
975: */
976: RF_ETIMER_START(timer);
977: RF_Malloc(buf, numDataCol * sizeof(char *), (char **));
978:
979: ppda = node->results[0]; /*
980: * Instead of being buffers,
981: * node->results[0] and [1]
982: * are Ppda and Epda.
983: */
984: epda = node->results[1];
985: fpda = asmap->failedPDAs[0];
986:
987: /* First, recovery the failed old SU using EvenOdd double decoding. */
988: /* Determine the startSector and endSector for decoding. */
989: startSector = rf_StripeUnitOffset(layoutPtr, fpda->startSector);
990: endSector = startSector + fpda->numSector;
991: /*
992: * Assign buf[col] pointers to point to each non-failed column and
993: * initialize the pbuf and ebuf to point at the beginning of each
994: * source buffers and destination buffers. */
995: for (prm = 0; prm < numDataCol - 2; prm++) {
996: pda = (RF_PhysDiskAddr_t *) node->params[prm].p;
997: col = rf_EUCol(layoutPtr, pda->raidAddress);
998: buf[col] = pda->bufPtr;
999: }
1000: /*
1001: * pbuf and ebuf: They will change values as double recovery decoding
1002: * goes on.
1003: */
1004: pbuf = ppda->bufPtr;
1005: ebuf = epda->bufPtr;
1006: /*
1007: * Find out the logical column numbers in the encoding matrix of the
1008: * two failed columns.
1009: */
1010: fcol[0] = rf_EUCol(layoutPtr, fpda->raidAddress);
1011:
1012: /* Find out the other failed column not accessed this time. */
1013: sosAddr = rf_RaidAddressOfPrevStripeBoundary(layoutPtr,
1014: asmap->raidAddress);
1015: for (i = 0; i < numDataCol; i++) {
1016: npda.raidAddress = sosAddr + (i * secPerSU);
1017: (raidPtr->Layout.map->MapSector) (raidPtr, npda.raidAddress,
1018: &(npda.row), &(npda.col), &(npda.startSector), 0);
1019: /* Skip over dead disks. */
1020: if (RF_DEAD_DISK(raidPtr->Disks[npda.row][npda.col].status))
1021: if (i != fcol[0])
1022: break;
1023: }
1024: RF_ASSERT(i < numDataCol);
1025: fcol[1] = i;
1026: /* Assign temporary space to put recovered failed SU. */
1027: numbytes = fpda->numSector * bytesPerSector;
1028: RF_Malloc(olddata[0], numbytes, (char *));
1029: RF_Malloc(olddata[1], numbytes, (char *));
1030: dest[0] = olddata[0];
1031: dest[1] = olddata[1];
1032: bzero(olddata[0], numbytes);
1033: bzero(olddata[1], numbytes);
1034: /*
1035: * Begin the recovery decoding, initially buf[j], ebuf, pbuf, dest[j]
1036: * have already pointed at the beginning of each source buffers and
1037: * destination buffers.
1038: */
1039: for (sector = startSector, i = 0; sector < endSector; sector++, i++) {
1040: rf_doubleEOdecode(raidPtr, buf, dest, fcol, pbuf, ebuf);
1041: for (j = 0; j < numDataCol; j++)
1042: if ((j != fcol[0]) && (j != fcol[1]))
1043: buf[j] += bytesPerSector;
1044: dest[0] += bytesPerSector;
1045: dest[1] += bytesPerSector;
1046: ebuf += bytesPerSector;
1047: pbuf += bytesPerSector;
1048: }
1049: /*
1050: * After recovery, the buffer pointed by olddata[0] is the old failed
1051: * data. With new writing data and this old data, use small write to
1052: * calculate the new redundant informations.
1053: */
1054: /*
1055: * node->params[ 0, ... PDAPerDisk * (numDataCol - 2)-1 ] are Pdas of
1056: * Rrd; params[ PDAPerDisk*(numDataCol - 2), ... PDAPerDisk*numDataCol
1057: * -1 ] are Pdas of Rp, ( Rp2 ), Re, ( Re2 ) ; params[
1058: * PDAPerDisk*numDataCol, ... PDAPerDisk*numDataCol
1059: * +asmap->numStripeUnitsAccessed -asmap->numDataFailed-1] are Pdas of
1060: * wudNodes; For current implementation, we assume the simplest case:
1061: * asmap->numStripeUnitsAccessed == 1 and asmap->numDataFailed == 1
1062: * ie. PDAPerDisk = 1 then node->params[numDataCol] must be the new
1063: * data to be written to the failed disk. We first bxor the new data
1064: * into the old recovered data, then do the same things as small
1065: * write.
1066: */
1067:
1068: rf_bxor(((RF_PhysDiskAddr_t *) node->params[numDataCol].p)->bufPtr,
1069: olddata[0], numbytes, node->dagHdr->bp);
1070: /* Do new 'E' calculation. */
1071: /*
1072: * Find out the corresponding column in encoding matrix for write
1073: * column to be encoded into redundant disk 'E'.
1074: */
1075: scol = rf_EUCol(layoutPtr, fpda->raidAddress);
1076: /*
1077: * olddata[0] now is source buffer pointer; epda->bufPtr is the dest
1078: * buffer pointer.
1079: */
1080: rf_e_encToBuf(raidPtr, scol, olddata[0], RF_EO_MATRIX_DIM - 2,
1081: epda->bufPtr, fpda->numSector);
1082:
1083: /* Do new 'P' calculation. */
1084: rf_bxor(olddata[0], ppda->bufPtr, numbytes, node->dagHdr->bp);
1085: /* Free the allocated buffer. */
1086: RF_Free(olddata[0], numbytes);
1087: RF_Free(olddata[1], numbytes);
1088: RF_Free(buf, numDataCol * sizeof(char *));
1089:
1090: RF_ETIMER_STOP(timer);
1091: RF_ETIMER_EVAL(timer);
1092: if (tracerec) {
1093: tracerec->q_us += RF_ETIMER_VAL_US(timer);
1094: }
1095: rf_GenericWakeupFunc(node, 0);
1096: return (0);
1097: }
CVSweb