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