[BACK]Return to rf_evenodd_dagfuncs.c CVS log [TXT][DIR] Up to [local] / sys / dev / raidframe

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