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

Annotation of sys/dev/raidframe/rf_paritylogging.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: rf_paritylogging.c,v 1.6 2002/12/16 07:01:04 tdeval Exp $     */
        !             2: /*     $NetBSD: rf_paritylogging.c,v 1.10 2000/02/12 16:06:27 oster Exp $      */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1995 Carnegie-Mellon University.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Author: William V. Courtright II
        !             9:  *
        !            10:  * Permission to use, copy, modify and distribute this software and
        !            11:  * its documentation is hereby granted, provided that both the copyright
        !            12:  * notice and this permission notice appear in all copies of the
        !            13:  * software, derivative works or modified versions, and any portions
        !            14:  * thereof, and that both notices appear in supporting documentation.
        !            15:  *
        !            16:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            17:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
        !            18:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            19:  *
        !            20:  * Carnegie Mellon requests users of this software to return to
        !            21:  *
        !            22:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
        !            23:  *  School of Computer Science
        !            24:  *  Carnegie Mellon University
        !            25:  *  Pittsburgh PA 15213-3890
        !            26:  *
        !            27:  * any improvements or extensions that they make and grant Carnegie the
        !            28:  * rights to redistribute these changes.
        !            29:  */
        !            30:
        !            31:
        !            32: /*
        !            33:  * Parity logging configuration, dag selection, and mapping is implemented here.
        !            34:  */
        !            35:
        !            36: #include "rf_archs.h"
        !            37:
        !            38: #if    RF_INCLUDE_PARITYLOGGING > 0
        !            39:
        !            40: #include "rf_types.h"
        !            41: #include "rf_raid.h"
        !            42: #include "rf_dag.h"
        !            43: #include "rf_dagutils.h"
        !            44: #include "rf_dagfuncs.h"
        !            45: #include "rf_dagffrd.h"
        !            46: #include "rf_dagffwr.h"
        !            47: #include "rf_dagdegrd.h"
        !            48: #include "rf_dagdegwr.h"
        !            49: #include "rf_paritylog.h"
        !            50: #include "rf_paritylogDiskMgr.h"
        !            51: #include "rf_paritylogging.h"
        !            52: #include "rf_parityloggingdags.h"
        !            53: #include "rf_general.h"
        !            54: #include "rf_map.h"
        !            55: #include "rf_utils.h"
        !            56: #include "rf_shutdown.h"
        !            57:
        !            58: typedef struct RF_ParityLoggingConfigInfo_s {
        !            59:        RF_RowCol_t **stripeIdentifier; /*
        !            60:                                         * Filled in at config time & used by
        !            61:                                         * IdentifyStripe.
        !            62:                                         */
        !            63: } RF_ParityLoggingConfigInfo_t;
        !            64:
        !            65: void rf_FreeRegionInfo(RF_Raid_t *, RF_RegionId_t);
        !            66: void rf_FreeParityLogQueue(RF_Raid_t *, RF_ParityLogQueue_t *);
        !            67: void rf_FreeRegionBufferQueue(RF_RegionBufferQueue_t *);
        !            68: void rf_ShutdownParityLogging(RF_ThreadArg_t);
        !            69: void rf_ShutdownParityLoggingRegionInfo(RF_ThreadArg_t);
        !            70: void rf_ShutdownParityLoggingPool(RF_ThreadArg_t);
        !            71: void rf_ShutdownParityLoggingRegionBufferPool(RF_ThreadArg_t);
        !            72: void rf_ShutdownParityLoggingParityBufferPool(RF_ThreadArg_t);
        !            73: void rf_ShutdownParityLoggingDiskQueue(RF_ThreadArg_t);
        !            74:
        !            75:
        !            76: int
        !            77: rf_ConfigureParityLogging(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
        !            78:     RF_Config_t *cfgPtr)
        !            79: {
        !            80:        int i, j, startdisk, rc;
        !            81:        RF_SectorCount_t totalLogCapacity, fragmentation, lastRegionCapacity;
        !            82:        RF_SectorCount_t parityBufferCapacity, maxRegionParityRange;
        !            83:        RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
        !            84:        RF_ParityLoggingConfigInfo_t *info;
        !            85:        RF_ParityLog_t *l = NULL, *next;
        !            86:        caddr_t lHeapPtr;
        !            87:
        !            88:        if (rf_numParityRegions <= 0)
        !            89:                return(EINVAL);
        !            90:
        !            91:        /*
        !            92:         * We create multiple entries on the shutdown list here, since
        !            93:         * this configuration routine is fairly complicated in and of
        !            94:         * itself, and this makes backing out of a failed configuration
        !            95:         * much simpler.
        !            96:         */
        !            97:
        !            98:        raidPtr->numSectorsPerLog = RF_DEFAULT_NUM_SECTORS_PER_LOG;
        !            99:
        !           100:        /* Create a parity logging configuration structure. */
        !           101:        RF_MallocAndAdd(info, sizeof(RF_ParityLoggingConfigInfo_t),
        !           102:                        (RF_ParityLoggingConfigInfo_t *),
        !           103:                        raidPtr->cleanupList);
        !           104:        if (info == NULL)
        !           105:                return (ENOMEM);
        !           106:        layoutPtr->layoutSpecificInfo = (void *) info;
        !           107:
        !           108:        RF_ASSERT(raidPtr->numRow == 1);
        !           109:
        !           110:        /*
        !           111:         * The stripe identifier must identify the disks in each stripe, IN
        !           112:         * THE ORDER THAT THEY APPEAR IN THE STRIPE.
        !           113:         */
        !           114:        info->stripeIdentifier = rf_make_2d_array((raidPtr->numCol),
        !           115:                                                  (raidPtr->numCol),
        !           116:                                                  raidPtr->cleanupList);
        !           117:        if (info->stripeIdentifier == NULL)
        !           118:                return (ENOMEM);
        !           119:
        !           120:        startdisk = 0;
        !           121:        for (i = 0; i < (raidPtr->numCol); i++) {
        !           122:                for (j = 0; j < (raidPtr->numCol); j++) {
        !           123:                        info->stripeIdentifier[i][j] = (startdisk + j) %
        !           124:                            (raidPtr->numCol - 1);
        !           125:                }
        !           126:                if ((--startdisk) < 0)
        !           127:                        startdisk = raidPtr->numCol - 1 - 1;
        !           128:        }
        !           129:
        !           130:        /* Fill in the remaining layout parameters. */
        !           131:        layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk;
        !           132:        layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit <<
        !           133:            raidPtr->logBytesPerSector;
        !           134:        layoutPtr->numParityCol = 1;
        !           135:        layoutPtr->numParityLogCol = 1;
        !           136:        layoutPtr->numDataCol = raidPtr->numCol - layoutPtr->numParityCol -
        !           137:            layoutPtr->numParityLogCol;
        !           138:        layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol *
        !           139:            layoutPtr->sectorsPerStripeUnit;
        !           140:        layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk;
        !           141:        raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk *
        !           142:            layoutPtr->sectorsPerStripeUnit;
        !           143:
        !           144:        raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk *
        !           145:            layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
        !           146:
        !           147:        /*
        !           148:         * Configure parity log parameters.
        !           149:         *
        !           150:         * Parameter                    Comment/constraints
        !           151:         * ------------------------------------------------
        !           152:         * numParityRegions*            All regions (except possibly last)
        !           153:         *                              of equal size.
        !           154:         * totalInCoreLogCapacity*      Amount of memory in bytes available
        !           155:         *                              for in-core logs (default 1 MB).
        !           156:         * numSectorsPerLog#            Capacity of an in-core log in sectors
        !           157:         *                              (1 * disk track).
        !           158:         * numParityLogs                Total number of in-core logs,
        !           159:         *                              should be at least numParityRegions.
        !           160:         * regionLogCapacity            Size of a region log (except possibly
        !           161:         *                              last one) in sectors.
        !           162:         * totalLogCapacity             Total amount of log space in sectors.
        !           163:         *
        !           164:         * Where '*' denotes a user settable parameter.
        !           165:         * Note that logs are fixed to be the size of a disk track,
        !           166:         * value #defined in rf_paritylog.h.
        !           167:         *
        !           168:         */
        !           169:
        !           170:        totalLogCapacity = layoutPtr->stripeUnitsPerDisk *
        !           171:            layoutPtr->sectorsPerStripeUnit * layoutPtr->numParityLogCol;
        !           172:        raidPtr->regionLogCapacity = totalLogCapacity / rf_numParityRegions;
        !           173:        if (rf_parityLogDebug)
        !           174:                printf("bytes per sector %d\n", raidPtr->bytesPerSector);
        !           175:
        !           176:        /*
        !           177:         * Reduce fragmentation within a disk region by adjusting the number
        !           178:         * of regions in an attempt to allow an integral number of logs to fit
        !           179:         * into a disk region.
        !           180:         */
        !           181:        fragmentation = raidPtr->regionLogCapacity % raidPtr->numSectorsPerLog;
        !           182:        if (fragmentation > 0)
        !           183:                for (i = 1; i < (raidPtr->numSectorsPerLog / 2); i++) {
        !           184:                        if (((totalLogCapacity / (rf_numParityRegions + i)) %
        !           185:                             raidPtr->numSectorsPerLog) < fragmentation) {
        !           186:                                rf_numParityRegions++;
        !           187:                                raidPtr->regionLogCapacity = totalLogCapacity /
        !           188:                                    rf_numParityRegions;
        !           189:                                fragmentation = raidPtr->regionLogCapacity %
        !           190:                                    raidPtr->numSectorsPerLog;
        !           191:                        }
        !           192:                        if (((totalLogCapacity / (rf_numParityRegions - i)) %
        !           193:                             raidPtr->numSectorsPerLog) < fragmentation) {
        !           194:                                rf_numParityRegions--;
        !           195:                                raidPtr->regionLogCapacity = totalLogCapacity /
        !           196:                                    rf_numParityRegions;
        !           197:                                fragmentation = raidPtr->regionLogCapacity %
        !           198:                                    raidPtr->numSectorsPerLog;
        !           199:                        }
        !           200:                }
        !           201:        /* Ensure integral number of regions per log. */
        !           202:        raidPtr->regionLogCapacity = (raidPtr->regionLogCapacity /
        !           203:            raidPtr->numSectorsPerLog) * raidPtr->numSectorsPerLog;
        !           204:
        !           205:        raidPtr->numParityLogs = rf_totalInCoreLogCapacity /
        !           206:            (raidPtr->bytesPerSector * raidPtr->numSectorsPerLog);
        !           207:        /*
        !           208:         * To avoid deadlock, must ensure that enough logs exist for each
        !           209:         * region to have one simultaneously.
        !           210:         */
        !           211:        if (raidPtr->numParityLogs < rf_numParityRegions)
        !           212:                raidPtr->numParityLogs = rf_numParityRegions;
        !           213:
        !           214:        /* Create region information structs. */
        !           215:        printf("Allocating %d bytes for in-core parity region info\n",
        !           216:               (int) (rf_numParityRegions * sizeof(RF_RegionInfo_t)));
        !           217:        RF_Malloc(raidPtr->regionInfo,
        !           218:                  (rf_numParityRegions * sizeof(RF_RegionInfo_t)),
        !           219:                  (RF_RegionInfo_t *));
        !           220:        if (raidPtr->regionInfo == NULL)
        !           221:                return (ENOMEM);
        !           222:
        !           223:        /* Last region may not be full capacity. */
        !           224:        lastRegionCapacity = raidPtr->regionLogCapacity;
        !           225:        while ((rf_numParityRegions - 1) * raidPtr->regionLogCapacity +
        !           226:               lastRegionCapacity > totalLogCapacity)
        !           227:                lastRegionCapacity = lastRegionCapacity -
        !           228:                    raidPtr->numSectorsPerLog;
        !           229:
        !           230:        raidPtr->regionParityRange = raidPtr->sectorsPerDisk /
        !           231:            rf_numParityRegions;
        !           232:        maxRegionParityRange = raidPtr->regionParityRange;
        !           233:
        !           234:        /* I can't remember why this line is in the code -wvcii 6/30/95. */
        !           235:        /* if (raidPtr->sectorsPerDisk % rf_numParityRegions > 0)
        !           236:         *      regionParityRange++; */
        !           237:
        !           238:        /* Build pool of unused parity logs. */
        !           239:        printf("Allocating %d bytes for %d parity logs\n",
        !           240:               raidPtr->numParityLogs * raidPtr->numSectorsPerLog *
        !           241:               raidPtr->bytesPerSector,
        !           242:               raidPtr->numParityLogs);
        !           243:        RF_Malloc(raidPtr->parityLogBufferHeap, raidPtr->numParityLogs *
        !           244:                  raidPtr->numSectorsPerLog * raidPtr->bytesPerSector,
        !           245:                  (caddr_t));
        !           246:        if (raidPtr->parityLogBufferHeap == NULL)
        !           247:                return (ENOMEM);
        !           248:        lHeapPtr = raidPtr->parityLogBufferHeap;
        !           249:        rc = rf_mutex_init(&raidPtr->parityLogPool.mutex);
        !           250:        if (rc) {
        !           251:                RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n",
        !           252:                             __FILE__, __LINE__, rc);
        !           253:                RF_Free(raidPtr->parityLogBufferHeap, raidPtr->numParityLogs *
        !           254:                        raidPtr->numSectorsPerLog * raidPtr->bytesPerSector);
        !           255:                return (ENOMEM);
        !           256:        }
        !           257:        for (i = 0; i < raidPtr->numParityLogs; i++) {
        !           258:                if (i == 0) {
        !           259:                        RF_Calloc(raidPtr->parityLogPool.parityLogs, 1,
        !           260:                                  sizeof(RF_ParityLog_t), (RF_ParityLog_t *));
        !           261:                        if (raidPtr->parityLogPool.parityLogs == NULL) {
        !           262:                                RF_Free(raidPtr->parityLogBufferHeap,
        !           263:                                        raidPtr->numParityLogs *
        !           264:                                        raidPtr->numSectorsPerLog *
        !           265:                                        raidPtr->bytesPerSector);
        !           266:                                return (ENOMEM);
        !           267:                        }
        !           268:                        l = raidPtr->parityLogPool.parityLogs;
        !           269:                } else {
        !           270:                        RF_Calloc(l->next, 1, sizeof(RF_ParityLog_t),
        !           271:                                  (RF_ParityLog_t *));
        !           272:                        if (l->next == NULL) {
        !           273:                                RF_Free(raidPtr->parityLogBufferHeap,
        !           274:                                        raidPtr->numParityLogs *
        !           275:                                        raidPtr->numSectorsPerLog *
        !           276:                                        raidPtr->bytesPerSector);
        !           277:                                for (l = raidPtr->parityLogPool.parityLogs;
        !           278:                                     l;
        !           279:                                     l = next) {
        !           280:                                        next = l->next;
        !           281:                                        if (l->records)
        !           282:                                                RF_Free(l->records,
        !           283:                                                    (raidPtr->numSectorsPerLog *
        !           284:                                                 sizeof(RF_ParityLogRecord_t)));
        !           285:                                        RF_Free(l, sizeof(RF_ParityLog_t));
        !           286:                                }
        !           287:                                return (ENOMEM);
        !           288:                        }
        !           289:                        l = l->next;
        !           290:                }
        !           291:                l->bufPtr = lHeapPtr;
        !           292:                lHeapPtr += raidPtr->numSectorsPerLog *
        !           293:                    raidPtr->bytesPerSector;
        !           294:                RF_Malloc(l->records, (raidPtr->numSectorsPerLog *
        !           295:                                       sizeof(RF_ParityLogRecord_t)),
        !           296:                          (RF_ParityLogRecord_t *));
        !           297:                if (l->records == NULL) {
        !           298:                        RF_Free(raidPtr->parityLogBufferHeap,
        !           299:                                raidPtr->numParityLogs *
        !           300:                                raidPtr->numSectorsPerLog *
        !           301:                                raidPtr->bytesPerSector);
        !           302:                        for (l = raidPtr->parityLogPool.parityLogs;
        !           303:                             l;
        !           304:                             l = next) {
        !           305:                                next = l->next;
        !           306:                                if (l->records)
        !           307:                                        RF_Free(l->records,
        !           308:                                                (raidPtr->numSectorsPerLog *
        !           309:                                                 sizeof(RF_ParityLogRecord_t)));
        !           310:                                RF_Free(l, sizeof(RF_ParityLog_t));
        !           311:                        }
        !           312:                        return (ENOMEM);
        !           313:                }
        !           314:        }
        !           315:        rc = rf_ShutdownCreate(listp, rf_ShutdownParityLoggingPool, raidPtr);
        !           316:        if (rc) {
        !           317:                RF_ERRORMSG3("Unable to create shutdown entry file %s line %d"
        !           318:                             " rc=%d\n", __FILE__, __LINE__, rc);
        !           319:                rf_ShutdownParityLoggingPool(raidPtr);
        !           320:                return (rc);
        !           321:        }
        !           322:        /* Build pool of region buffers. */
        !           323:        rc = rf_mutex_init(&raidPtr->regionBufferPool.mutex);
        !           324:        if (rc) {
        !           325:                RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n",
        !           326:                             __FILE__, __LINE__, rc);
        !           327:                return (ENOMEM);
        !           328:        }
        !           329:        rc = rf_cond_init(&raidPtr->regionBufferPool.cond);
        !           330:        if (rc) {
        !           331:                RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d\n",
        !           332:                             __FILE__, __LINE__, rc);
        !           333:                rf_mutex_destroy(&raidPtr->regionBufferPool.mutex);
        !           334:                return (ENOMEM);
        !           335:        }
        !           336:        raidPtr->regionBufferPool.bufferSize = raidPtr->regionLogCapacity *
        !           337:            raidPtr->bytesPerSector;
        !           338:        printf("regionBufferPool.bufferSize %d\n",
        !           339:               raidPtr->regionBufferPool.bufferSize);
        !           340:
        !           341:        /* For now, only one region at a time may be reintegrated. */
        !           342:        raidPtr->regionBufferPool.totalBuffers = 1;
        !           343:
        !           344:        raidPtr->regionBufferPool.availableBuffers =
        !           345:            raidPtr->regionBufferPool.totalBuffers;
        !           346:        raidPtr->regionBufferPool.availBuffersIndex = 0;
        !           347:        raidPtr->regionBufferPool.emptyBuffersIndex = 0;
        !           348:        printf("Allocating %d bytes for regionBufferPool\n",
        !           349:               (int) (raidPtr->regionBufferPool.totalBuffers *
        !           350:                      sizeof(caddr_t)));
        !           351:        RF_Malloc(raidPtr->regionBufferPool.buffers,
        !           352:                  raidPtr->regionBufferPool.totalBuffers * sizeof(caddr_t),
        !           353:                  (caddr_t *));
        !           354:        if (raidPtr->regionBufferPool.buffers == NULL) {
        !           355:                rf_mutex_destroy(&raidPtr->regionBufferPool.mutex);
        !           356:                rf_cond_destroy(&raidPtr->regionBufferPool.cond);
        !           357:                return (ENOMEM);
        !           358:        }
        !           359:        for (i = 0; i < raidPtr->regionBufferPool.totalBuffers; i++) {
        !           360:                printf("Allocating %d bytes for regionBufferPool#%d\n",
        !           361:                       (int) (raidPtr->regionBufferPool.bufferSize *
        !           362:                              sizeof(char)), i);
        !           363:                RF_Malloc(raidPtr->regionBufferPool.buffers[i],
        !           364:                          raidPtr->regionBufferPool.bufferSize * sizeof(char),
        !           365:                          (caddr_t));
        !           366:                if (raidPtr->regionBufferPool.buffers[i] == NULL) {
        !           367:                        rf_mutex_destroy(&raidPtr->regionBufferPool.mutex);
        !           368:                        rf_cond_destroy(&raidPtr->regionBufferPool.cond);
        !           369:                        for (j = 0; j < i; j++) {
        !           370:                                RF_Free(raidPtr->regionBufferPool.buffers[i],
        !           371:                                        raidPtr->regionBufferPool.bufferSize *
        !           372:                                        sizeof(char));
        !           373:                        }
        !           374:                        RF_Free(raidPtr->regionBufferPool.buffers,
        !           375:                                raidPtr->regionBufferPool.totalBuffers *
        !           376:                                sizeof(caddr_t));
        !           377:                        return (ENOMEM);
        !           378:                }
        !           379:                printf("raidPtr->regionBufferPool.buffers[%d] = %lx\n", i,
        !           380:                    (long) raidPtr->regionBufferPool.buffers[i]);
        !           381:        }
        !           382:        rc = rf_ShutdownCreate(listp,
        !           383:                               rf_ShutdownParityLoggingRegionBufferPool,
        !           384:                               raidPtr);
        !           385:        if (rc) {
        !           386:                RF_ERRORMSG3("Unable to create shutdown entry file %s line %d"
        !           387:                             " rc=%d\n", __FILE__, __LINE__, rc);
        !           388:                rf_ShutdownParityLoggingRegionBufferPool(raidPtr);
        !           389:                return (rc);
        !           390:        }
        !           391:        /* Build pool of parity buffers. */
        !           392:        parityBufferCapacity = maxRegionParityRange;
        !           393:        rc = rf_mutex_init(&raidPtr->parityBufferPool.mutex);
        !           394:        if (rc) {
        !           395:                RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n",
        !           396:                             __FILE__, __LINE__, rc);
        !           397:                return (rc);
        !           398:        }
        !           399:        rc = rf_cond_init(&raidPtr->parityBufferPool.cond);
        !           400:        if (rc) {
        !           401:                RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d\n",
        !           402:                             __FILE__, __LINE__, rc);
        !           403:                rf_mutex_destroy(&raidPtr->parityBufferPool.mutex);
        !           404:                return (ENOMEM);
        !           405:        }
        !           406:        raidPtr->parityBufferPool.bufferSize = parityBufferCapacity *
        !           407:            raidPtr->bytesPerSector;
        !           408:        printf("parityBufferPool.bufferSize %d\n",
        !           409:               raidPtr->parityBufferPool.bufferSize);
        !           410:
        !           411:        /* For now, only one region at a time may be reintegrated. */
        !           412:        raidPtr->parityBufferPool.totalBuffers = 1;
        !           413:
        !           414:        raidPtr->parityBufferPool.availableBuffers =
        !           415:            raidPtr->parityBufferPool.totalBuffers;
        !           416:        raidPtr->parityBufferPool.availBuffersIndex = 0;
        !           417:        raidPtr->parityBufferPool.emptyBuffersIndex = 0;
        !           418:        printf("Allocating %d bytes for parityBufferPool of %d units\n",
        !           419:               (int) (raidPtr->parityBufferPool.totalBuffers *
        !           420:                      sizeof(caddr_t)),
        !           421:               raidPtr->parityBufferPool.totalBuffers);
        !           422:        RF_Malloc(raidPtr->parityBufferPool.buffers,
        !           423:                  raidPtr->parityBufferPool.totalBuffers * sizeof(caddr_t),
        !           424:                  (caddr_t *));
        !           425:        if (raidPtr->parityBufferPool.buffers == NULL) {
        !           426:                rf_mutex_destroy(&raidPtr->parityBufferPool.mutex);
        !           427:                rf_cond_destroy(&raidPtr->parityBufferPool.cond);
        !           428:                return (ENOMEM);
        !           429:        }
        !           430:        for (i = 0; i < raidPtr->parityBufferPool.totalBuffers; i++) {
        !           431:                printf("Allocating %d bytes for parityBufferPool#%d\n",
        !           432:                       (int) (raidPtr->parityBufferPool.bufferSize *
        !           433:                              sizeof(char)), i);
        !           434:                RF_Malloc(raidPtr->parityBufferPool.buffers[i],
        !           435:                          raidPtr->parityBufferPool.bufferSize * sizeof(char),
        !           436:                          (caddr_t));
        !           437:                if (raidPtr->parityBufferPool.buffers == NULL) {
        !           438:                        rf_mutex_destroy(&raidPtr->parityBufferPool.mutex);
        !           439:                        rf_cond_destroy(&raidPtr->parityBufferPool.cond);
        !           440:                        for (j = 0; j < i; j++) {
        !           441:                                RF_Free(raidPtr->parityBufferPool.buffers[i],
        !           442:                                        raidPtr->regionBufferPool.bufferSize *
        !           443:                                        sizeof(char));
        !           444:                        }
        !           445:                        RF_Free(raidPtr->parityBufferPool.buffers,
        !           446:                                raidPtr->regionBufferPool.totalBuffers *
        !           447:                                sizeof(caddr_t));
        !           448:                        return (ENOMEM);
        !           449:                }
        !           450:                printf("parityBufferPool.buffers[%d] = %lx\n", i,
        !           451:                    (long) raidPtr->parityBufferPool.buffers[i]);
        !           452:        }
        !           453:        rc = rf_ShutdownCreate(listp,
        !           454:                               rf_ShutdownParityLoggingParityBufferPool,
        !           455:                               raidPtr);
        !           456:        if (rc) {
        !           457:                RF_ERRORMSG3("Unable to create shutdown entry file %s line %d"
        !           458:                             " rc=%d\n", __FILE__, __LINE__, rc);
        !           459:                rf_ShutdownParityLoggingParityBufferPool(raidPtr);
        !           460:                return (rc);
        !           461:        }
        !           462:        /* Initialize parityLogDiskQueue. */
        !           463:        rc = rf_create_managed_mutex(listp,
        !           464:                                     &raidPtr->parityLogDiskQueue.mutex);
        !           465:        if (rc) {
        !           466:                RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n",
        !           467:                             __FILE__, __LINE__, rc);
        !           468:                return (rc);
        !           469:        }
        !           470:        rc = rf_create_managed_cond(listp, &raidPtr->parityLogDiskQueue.cond);
        !           471:        if (rc) {
        !           472:                RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d\n",
        !           473:                             __FILE__, __LINE__, rc);
        !           474:                return (rc);
        !           475:        }
        !           476:        raidPtr->parityLogDiskQueue.flushQueue = NULL;
        !           477:        raidPtr->parityLogDiskQueue.reintQueue = NULL;
        !           478:        raidPtr->parityLogDiskQueue.bufHead = NULL;
        !           479:        raidPtr->parityLogDiskQueue.bufTail = NULL;
        !           480:        raidPtr->parityLogDiskQueue.reintHead = NULL;
        !           481:        raidPtr->parityLogDiskQueue.reintTail = NULL;
        !           482:        raidPtr->parityLogDiskQueue.logBlockHead = NULL;
        !           483:        raidPtr->parityLogDiskQueue.logBlockTail = NULL;
        !           484:        raidPtr->parityLogDiskQueue.reintBlockHead = NULL;
        !           485:        raidPtr->parityLogDiskQueue.reintBlockTail = NULL;
        !           486:        raidPtr->parityLogDiskQueue.freeDataList = NULL;
        !           487:        raidPtr->parityLogDiskQueue.freeCommonList = NULL;
        !           488:
        !           489:        rc = rf_ShutdownCreate(listp,
        !           490:                               rf_ShutdownParityLoggingDiskQueue,
        !           491:                               raidPtr);
        !           492:        if (rc) {
        !           493:                RF_ERRORMSG3("Unable to create shutdown entry file %s line %d"
        !           494:                             " rc=%d\n", __FILE__, __LINE__, rc);
        !           495:                return (rc);
        !           496:        }
        !           497:        for (i = 0; i < rf_numParityRegions; i++) {
        !           498:                rc = rf_mutex_init(&raidPtr->regionInfo[i].mutex);
        !           499:                if (rc) {
        !           500:                        RF_ERRORMSG3("Unable to init mutex file %s line %d"
        !           501:                                     " rc=%d\n", __FILE__, __LINE__, rc);
        !           502:                        for (j = 0; j < i; j++)
        !           503:                                rf_FreeRegionInfo(raidPtr, j);
        !           504:                        RF_Free(raidPtr->regionInfo,
        !           505:                                (rf_numParityRegions *
        !           506:                                 sizeof(RF_RegionInfo_t)));
        !           507:                        return (ENOMEM);
        !           508:                }
        !           509:                rc = rf_mutex_init(&raidPtr->regionInfo[i].reintMutex);
        !           510:                if (rc) {
        !           511:                        RF_ERRORMSG3("Unable to init mutex file %s line %d"
        !           512:                                     " rc=%d\n", __FILE__, __LINE__, rc);
        !           513:                        rf_mutex_destroy(&raidPtr->regionInfo[i].mutex);
        !           514:                        for (j = 0; j < i; j++)
        !           515:                                rf_FreeRegionInfo(raidPtr, j);
        !           516:                        RF_Free(raidPtr->regionInfo,
        !           517:                                (rf_numParityRegions *
        !           518:                                 sizeof(RF_RegionInfo_t)));
        !           519:                        return (ENOMEM);
        !           520:                }
        !           521:                raidPtr->regionInfo[i].reintInProgress = RF_FALSE;
        !           522:                raidPtr->regionInfo[i].regionStartAddr =
        !           523:                    raidPtr->regionLogCapacity * i;
        !           524:                raidPtr->regionInfo[i].parityStartAddr =
        !           525:                    raidPtr->regionParityRange * i;
        !           526:                if (i < rf_numParityRegions - 1) {
        !           527:                        raidPtr->regionInfo[i].capacity =
        !           528:                            raidPtr->regionLogCapacity;
        !           529:                        raidPtr->regionInfo[i].numSectorsParity =
        !           530:                            raidPtr->regionParityRange;
        !           531:                } else {
        !           532:                        raidPtr->regionInfo[i].capacity = lastRegionCapacity;
        !           533:                        raidPtr->regionInfo[i].numSectorsParity =
        !           534:                            raidPtr->sectorsPerDisk -
        !           535:                            raidPtr->regionParityRange * i;
        !           536:                        if (raidPtr->regionInfo[i].numSectorsParity >
        !           537:                            maxRegionParityRange)
        !           538:                                maxRegionParityRange =
        !           539:                                    raidPtr->regionInfo[i].numSectorsParity;
        !           540:                }
        !           541:                raidPtr->regionInfo[i].diskCount = 0;
        !           542:                RF_ASSERT(raidPtr->regionInfo[i].capacity +
        !           543:                          raidPtr->regionInfo[i].regionStartAddr <=
        !           544:                          totalLogCapacity);
        !           545:                RF_ASSERT(raidPtr->regionInfo[i].parityStartAddr +
        !           546:                          raidPtr->regionInfo[i].numSectorsParity <=
        !           547:                          raidPtr->sectorsPerDisk);
        !           548:                printf("Allocating %d bytes for region %d\n",
        !           549:                       (int) (raidPtr->regionInfo[i].capacity *
        !           550:                           sizeof(RF_DiskMap_t)), i);
        !           551:                RF_Malloc(raidPtr->regionInfo[i].diskMap,
        !           552:                          (raidPtr->regionInfo[i].capacity *
        !           553:                           sizeof(RF_DiskMap_t)),
        !           554:                          (RF_DiskMap_t *));
        !           555:                if (raidPtr->regionInfo[i].diskMap == NULL) {
        !           556:                        rf_mutex_destroy(&raidPtr->regionInfo[i].mutex);
        !           557:                        rf_mutex_destroy(&raidPtr->regionInfo[i].reintMutex);
        !           558:                        for (j = 0; j < i; j++)
        !           559:                                rf_FreeRegionInfo(raidPtr, j);
        !           560:                        RF_Free(raidPtr->regionInfo,
        !           561:                                (rf_numParityRegions *
        !           562:                                 sizeof(RF_RegionInfo_t)));
        !           563:                        return (ENOMEM);
        !           564:                }
        !           565:                raidPtr->regionInfo[i].loggingEnabled = RF_FALSE;
        !           566:                raidPtr->regionInfo[i].coreLog = NULL;
        !           567:        }
        !           568:        rc = rf_ShutdownCreate(listp,
        !           569:                               rf_ShutdownParityLoggingRegionInfo,
        !           570:                               raidPtr);
        !           571:        if (rc) {
        !           572:                RF_ERRORMSG3("Unable to create shutdown entry file %s line %d"
        !           573:                             " rc=%d\n", __FILE__, __LINE__, rc);
        !           574:                rf_ShutdownParityLoggingRegionInfo(raidPtr);
        !           575:                return (rc);
        !           576:        }
        !           577:        RF_ASSERT(raidPtr->parityLogDiskQueue.threadState == 0);
        !           578:        raidPtr->parityLogDiskQueue.threadState = RF_PLOG_CREATED;
        !           579:        rc = RF_CREATE_THREAD(raidPtr->pLogDiskThreadHandle,
        !           580:                              rf_ParityLoggingDiskManager, raidPtr, "rf_log");
        !           581:        if (rc) {
        !           582:                raidPtr->parityLogDiskQueue.threadState = 0;
        !           583:                RF_ERRORMSG3("Unable to create parity logging disk thread"
        !           584:                             " file %s line %d rc=%d\n",
        !           585:                             __FILE__, __LINE__, rc);
        !           586:                return (ENOMEM);
        !           587:        }
        !           588:        /* Wait for thread to start. */
        !           589:        RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
        !           590:        while (!(raidPtr->parityLogDiskQueue.threadState & RF_PLOG_RUNNING)) {
        !           591:                RF_WAIT_COND(raidPtr->parityLogDiskQueue.cond,
        !           592:                             raidPtr->parityLogDiskQueue.mutex);
        !           593:        }
        !           594:        RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
        !           595:
        !           596:        rc = rf_ShutdownCreate(listp, rf_ShutdownParityLogging, raidPtr);
        !           597:        if (rc) {
        !           598:                RF_ERRORMSG1("Got rc=%d adding parity logging shutdown"
        !           599:                             " event.\n", rc);
        !           600:                rf_ShutdownParityLogging(raidPtr);
        !           601:                return (rc);
        !           602:        }
        !           603:        if (rf_parityLogDebug) {
        !           604:                printf("\t\t\tsize of disk log in sectors: %d\n",
        !           605:                       (int) totalLogCapacity);
        !           606:                printf("\t\t\ttotal number of parity regions is %d\n",
        !           607:                       (int) rf_numParityRegions);
        !           608:                printf("\t\t\tnominal sectors of log per parity region is %d\n",
        !           609:                       (int) raidPtr->regionLogCapacity);
        !           610:                printf("\t\t\tnominal region fragmentation is %d sectors\n",
        !           611:                       (int) fragmentation);
        !           612:                printf("\t\t\ttotal number of parity logs is %d\n",
        !           613:                       raidPtr->numParityLogs);
        !           614:                printf("\t\t\tparity log size is %d sectors\n",
        !           615:                       raidPtr->numSectorsPerLog);
        !           616:                printf("\t\t\ttotal in-core log space is %d bytes\n",
        !           617:                       (int) rf_totalInCoreLogCapacity);
        !           618:        }
        !           619:        rf_EnableParityLogging(raidPtr);
        !           620:
        !           621:        return (0);
        !           622: }
        !           623:
        !           624:
        !           625: void
        !           626: rf_FreeRegionInfo(RF_Raid_t *raidPtr, RF_RegionId_t regionID)
        !           627: {
        !           628:        RF_LOCK_MUTEX(raidPtr->regionInfo[regionID].mutex);
        !           629:        RF_Free(raidPtr->regionInfo[regionID].diskMap,
        !           630:                (raidPtr->regionInfo[regionID].capacity *
        !           631:                 sizeof(RF_DiskMap_t)));
        !           632:        if (!rf_forceParityLogReint && raidPtr->regionInfo[regionID].coreLog) {
        !           633:                rf_ReleaseParityLogs(raidPtr,
        !           634:                                     raidPtr->regionInfo[regionID].coreLog);
        !           635:                raidPtr->regionInfo[regionID].coreLog = NULL;
        !           636:        } else {
        !           637:                RF_ASSERT(raidPtr->regionInfo[regionID].coreLog == NULL);
        !           638:                RF_ASSERT(raidPtr->regionInfo[regionID].diskCount == 0);
        !           639:        }
        !           640:        RF_UNLOCK_MUTEX(raidPtr->regionInfo[regionID].mutex);
        !           641:        rf_mutex_destroy(&raidPtr->regionInfo[regionID].mutex);
        !           642:        rf_mutex_destroy(&raidPtr->regionInfo[regionID].reintMutex);
        !           643: }
        !           644:
        !           645:
        !           646: void
        !           647: rf_FreeParityLogQueue(RF_Raid_t *raidPtr, RF_ParityLogQueue_t *queue)
        !           648: {
        !           649:        RF_ParityLog_t *l1, *l2;
        !           650:
        !           651:        RF_LOCK_MUTEX(queue->mutex);
        !           652:        l1 = queue->parityLogs;
        !           653:        while (l1) {
        !           654:                l2 = l1;
        !           655:                l1 = l2->next;
        !           656:                RF_Free(l2->records, (raidPtr->numSectorsPerLog *
        !           657:                                      sizeof(RF_ParityLogRecord_t)));
        !           658:                RF_Free(l2, sizeof(RF_ParityLog_t));
        !           659:        }
        !           660:        RF_UNLOCK_MUTEX(queue->mutex);
        !           661:        rf_mutex_destroy(&queue->mutex);
        !           662: }
        !           663:
        !           664:
        !           665: void
        !           666: rf_FreeRegionBufferQueue(RF_RegionBufferQueue_t *queue)
        !           667: {
        !           668:        int i;
        !           669:
        !           670:        RF_LOCK_MUTEX(queue->mutex);
        !           671:        if (queue->availableBuffers != queue->totalBuffers) {
        !           672:                printf("Attempt to free region queue that is still in use !\n");
        !           673:                RF_ASSERT(0);
        !           674:        }
        !           675:        for (i = 0; i < queue->totalBuffers; i++)
        !           676:                RF_Free(queue->buffers[i], queue->bufferSize);
        !           677:        RF_Free(queue->buffers, queue->totalBuffers * sizeof(caddr_t));
        !           678:        RF_UNLOCK_MUTEX(queue->mutex);
        !           679:        rf_mutex_destroy(&queue->mutex);
        !           680: }
        !           681:
        !           682:
        !           683: void
        !           684: rf_ShutdownParityLoggingRegionInfo(RF_ThreadArg_t arg)
        !           685: {
        !           686:        RF_Raid_t *raidPtr;
        !           687:        RF_RegionId_t i;
        !           688:
        !           689:        raidPtr = (RF_Raid_t *) arg;
        !           690:        if (rf_parityLogDebug) {
        !           691:                printf("raid%d: ShutdownParityLoggingRegionInfo\n",
        !           692:                       raidPtr->raidid);
        !           693:        }
        !           694:        /* Free region information structs. */
        !           695:        for (i = 0; i < rf_numParityRegions; i++)
        !           696:                rf_FreeRegionInfo(raidPtr, i);
        !           697:        RF_Free(raidPtr->regionInfo, (rf_numParityRegions *
        !           698:                                      sizeof(raidPtr->regionInfo)));
        !           699:        raidPtr->regionInfo = NULL;
        !           700: }
        !           701:
        !           702:
        !           703: void
        !           704: rf_ShutdownParityLoggingPool(RF_ThreadArg_t arg)
        !           705: {
        !           706:        RF_Raid_t *raidPtr;
        !           707:
        !           708:        raidPtr = (RF_Raid_t *) arg;
        !           709:        if (rf_parityLogDebug) {
        !           710:                printf("raid%d: ShutdownParityLoggingPool\n", raidPtr->raidid);
        !           711:        }
        !           712:        /* Free contents of parityLogPool. */
        !           713:        rf_FreeParityLogQueue(raidPtr, &raidPtr->parityLogPool);
        !           714:        RF_Free(raidPtr->parityLogBufferHeap, raidPtr->numParityLogs *
        !           715:                raidPtr->numSectorsPerLog * raidPtr->bytesPerSector);
        !           716: }
        !           717:
        !           718:
        !           719: void
        !           720: rf_ShutdownParityLoggingRegionBufferPool(RF_ThreadArg_t arg)
        !           721: {
        !           722:        RF_Raid_t *raidPtr;
        !           723:
        !           724:        raidPtr = (RF_Raid_t *) arg;
        !           725:        if (rf_parityLogDebug) {
        !           726:                printf("raid%d: ShutdownParityLoggingRegionBufferPool\n",
        !           727:                       raidPtr->raidid);
        !           728:        }
        !           729:        rf_FreeRegionBufferQueue(&raidPtr->regionBufferPool);
        !           730: }
        !           731:
        !           732:
        !           733: void
        !           734: rf_ShutdownParityLoggingParityBufferPool(RF_ThreadArg_t arg)
        !           735: {
        !           736:        RF_Raid_t *raidPtr;
        !           737:
        !           738:        raidPtr = (RF_Raid_t *) arg;
        !           739:        if (rf_parityLogDebug) {
        !           740:                printf("raid%d: ShutdownParityLoggingParityBufferPool\n",
        !           741:                       raidPtr->raidid);
        !           742:        }
        !           743:        rf_FreeRegionBufferQueue(&raidPtr->parityBufferPool);
        !           744: }
        !           745:
        !           746:
        !           747: void
        !           748: rf_ShutdownParityLoggingDiskQueue(RF_ThreadArg_t arg)
        !           749: {
        !           750:        RF_ParityLogData_t *d;
        !           751:        RF_CommonLogData_t *c;
        !           752:        RF_Raid_t *raidPtr;
        !           753:
        !           754:        raidPtr = (RF_Raid_t *) arg;
        !           755:        if (rf_parityLogDebug) {
        !           756:                printf("raid%d: ShutdownParityLoggingDiskQueue\n",
        !           757:                       raidPtr->raidid);
        !           758:        }
        !           759:        /* Free disk manager stuff. */
        !           760:        RF_ASSERT(raidPtr->parityLogDiskQueue.bufHead == NULL);
        !           761:        RF_ASSERT(raidPtr->parityLogDiskQueue.bufTail == NULL);
        !           762:        RF_ASSERT(raidPtr->parityLogDiskQueue.reintHead == NULL);
        !           763:        RF_ASSERT(raidPtr->parityLogDiskQueue.reintTail == NULL);
        !           764:        while (raidPtr->parityLogDiskQueue.freeDataList) {
        !           765:                d = raidPtr->parityLogDiskQueue.freeDataList;
        !           766:                raidPtr->parityLogDiskQueue.freeDataList =
        !           767:                    raidPtr->parityLogDiskQueue.freeDataList->next;
        !           768:                RF_Free(d, sizeof(RF_ParityLogData_t));
        !           769:        }
        !           770:        while (raidPtr->parityLogDiskQueue.freeCommonList) {
        !           771:                c = raidPtr->parityLogDiskQueue.freeCommonList;
        !           772:                rf_mutex_destroy(&c->mutex);
        !           773:                raidPtr->parityLogDiskQueue.freeCommonList =
        !           774:                    raidPtr->parityLogDiskQueue.freeCommonList->next;
        !           775:                RF_Free(c, sizeof(RF_CommonLogData_t));
        !           776:        }
        !           777: }
        !           778:
        !           779:
        !           780: void
        !           781: rf_ShutdownParityLogging(RF_ThreadArg_t arg)
        !           782: {
        !           783:        RF_Raid_t *raidPtr;
        !           784:
        !           785:        raidPtr = (RF_Raid_t *) arg;
        !           786:        if (rf_parityLogDebug) {
        !           787:                printf("raid%d: ShutdownParityLogging\n", raidPtr->raidid);
        !           788:        }
        !           789:        /* Shutdown disk thread. */
        !           790:        /*
        !           791:         * This has the desirable side-effect of forcing all regions to be
        !           792:         * reintegrated. This is necessary since all parity log maps are
        !           793:         * currently held in volatile memory.
        !           794:         */
        !           795:
        !           796:        RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
        !           797:        raidPtr->parityLogDiskQueue.threadState |= RF_PLOG_TERMINATE;
        !           798:        RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
        !           799:        RF_SIGNAL_COND(raidPtr->parityLogDiskQueue.cond);
        !           800:        /*
        !           801:         * pLogDiskThread will now terminate when queues are cleared.
        !           802:         * Now wait for it to be done.
        !           803:         */
        !           804:        RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
        !           805:        while (!(raidPtr->parityLogDiskQueue.threadState & RF_PLOG_SHUTDOWN)) {
        !           806:                RF_WAIT_COND(raidPtr->parityLogDiskQueue.cond,
        !           807:                             raidPtr->parityLogDiskQueue.mutex);
        !           808:        }
        !           809:        RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
        !           810:        if (rf_parityLogDebug) {
        !           811:                printf("raid%d: ShutdownParityLogging done"
        !           812:                       " (thread completed)\n", raidPtr->raidid);
        !           813:        }
        !           814: }
        !           815:
        !           816:
        !           817: int
        !           818: rf_GetDefaultNumFloatingReconBuffersParityLogging(RF_Raid_t *raidPtr)
        !           819: {
        !           820:        return (20);
        !           821: }
        !           822:
        !           823:
        !           824: RF_HeadSepLimit_t
        !           825: rf_GetDefaultHeadSepLimitParityLogging(RF_Raid_t *raidPtr)
        !           826: {
        !           827:        return (10);
        !           828: }
        !           829:
        !           830:
        !           831: /* Return the region ID for a given RAID address. */
        !           832: RF_RegionId_t
        !           833: rf_MapRegionIDParityLogging(RF_Raid_t *raidPtr, RF_SectorNum_t address)
        !           834: {
        !           835:        RF_RegionId_t regionID;
        !           836:
        !           837:        /* regionID = address / (raidPtr->regionParityRange *
        !           838:         *     raidPtr->Layout.numDataCol); */
        !           839:        regionID = address / raidPtr->regionParityRange;
        !           840:        if (regionID == rf_numParityRegions) {
        !           841:                /* Last region may be larger than other regions. */
        !           842:                regionID--;
        !           843:        }
        !           844:        RF_ASSERT(address >= raidPtr->regionInfo[regionID].parityStartAddr);
        !           845:        RF_ASSERT(address < raidPtr->regionInfo[regionID].parityStartAddr +
        !           846:                  raidPtr->regionInfo[regionID].numSectorsParity);
        !           847:        RF_ASSERT(regionID < rf_numParityRegions);
        !           848:        return (regionID);
        !           849: }
        !           850:
        !           851:
        !           852: /* Given a logical RAID sector, determine physical disk address of data. */
        !           853: void
        !           854: rf_MapSectorParityLogging(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
        !           855:     RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
        !           856: {
        !           857:        RF_StripeNum_t SUID = raidSector /
        !           858:                raidPtr->Layout.sectorsPerStripeUnit;
        !           859:        *row = 0;
        !           860:        /* *col = (SUID % (raidPtr->numCol -
        !           861:         *     raidPtr->Layout.numParityLogCol)); */
        !           862:        *col = SUID % raidPtr->Layout.numDataCol;
        !           863:        *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
        !           864:            raidPtr->Layout.sectorsPerStripeUnit +
        !           865:            (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
        !           866: }
        !           867:
        !           868:
        !           869: /* Given a logical RAID sector, determine physical disk address of parity. */
        !           870: void
        !           871: rf_MapParityParityLogging(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
        !           872:     RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
        !           873: {
        !           874:        RF_StripeNum_t SUID = raidSector /
        !           875:            raidPtr->Layout.sectorsPerStripeUnit;
        !           876:
        !           877:        *row = 0;
        !           878:        /* *col =
        !           879:         *     raidPtr->Layout.numDataCol-(SUID / raidPtr->Layout.numDataCol) %
        !           880:         *      (raidPtr->numCol - raidPtr->Layout.numParityLogCol); */
        !           881:        *col = raidPtr->Layout.numDataCol;
        !           882:        *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
        !           883:            raidPtr->Layout.sectorsPerStripeUnit +
        !           884:            (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
        !           885: }
        !           886:
        !           887:
        !           888: /*
        !           889:  * Given a regionID and sector offset, determine the physical disk address
        !           890:  * of the parity log.
        !           891:  */
        !           892: void
        !           893: rf_MapLogParityLogging(RF_Raid_t *raidPtr, RF_RegionId_t regionID,
        !           894:     RF_SectorNum_t regionOffset, RF_RowCol_t *row, RF_RowCol_t *col,
        !           895:     RF_SectorNum_t *startSector)
        !           896: {
        !           897:        *row = 0;
        !           898:        *col = raidPtr->numCol - 1;
        !           899:        *startSector =
        !           900:            raidPtr->regionInfo[regionID].regionStartAddr + regionOffset;
        !           901: }
        !           902:
        !           903:
        !           904: /*
        !           905:  * Given a regionID, determine the physical disk address of the logged
        !           906:  * parity for that region.
        !           907:  */
        !           908: void
        !           909: rf_MapRegionParity(RF_Raid_t *raidPtr, RF_RegionId_t regionID,
        !           910:     RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *startSector,
        !           911:     RF_SectorCount_t *numSector)
        !           912: {
        !           913:        *row = 0;
        !           914:        *col = raidPtr->numCol - 2;
        !           915:        *startSector = raidPtr->regionInfo[regionID].parityStartAddr;
        !           916:        *numSector = raidPtr->regionInfo[regionID].numSectorsParity;
        !           917: }
        !           918:
        !           919:
        !           920: /*
        !           921:  * Given a logical RAID address, determine the participating disks in
        !           922:  * the stripe.
        !           923:  */
        !           924: void
        !           925: rf_IdentifyStripeParityLogging(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
        !           926:     RF_RowCol_t **diskids, RF_RowCol_t *outRow)
        !           927: {
        !           928:        RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout,
        !           929:                                                           addr);
        !           930:        RF_ParityLoggingConfigInfo_t *info = (RF_ParityLoggingConfigInfo_t *)
        !           931:            raidPtr->Layout.layoutSpecificInfo;
        !           932:        *outRow = 0;
        !           933:        *diskids = info->stripeIdentifier[stripeID % raidPtr->numCol];
        !           934: }
        !           935:
        !           936:
        !           937: void
        !           938: rf_MapSIDToPSIDParityLogging(RF_RaidLayout_t *layoutPtr,
        !           939:     RF_StripeNum_t stripeID, RF_StripeNum_t *psID, RF_ReconUnitNum_t *which_ru)
        !           940: {
        !           941:        *which_ru = 0;
        !           942:        *psID = stripeID;
        !           943: }
        !           944:
        !           945:
        !           946: /*
        !           947:  * Select an algorithm for performing an access. Returns two pointers,
        !           948:  * one to a function that will return information about the DAG, and
        !           949:  * another to a function that will create the dag.
        !           950:  */
        !           951: void
        !           952: rf_ParityLoggingDagSelect(RF_Raid_t *raidPtr, RF_IoType_t type,
        !           953:     RF_AccessStripeMap_t *asmp, RF_VoidFuncPtr *createFunc)
        !           954: {
        !           955:        RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
        !           956:        RF_PhysDiskAddr_t *failedPDA = NULL;
        !           957:        RF_RowCol_t frow, fcol;
        !           958:        RF_RowStatus_t rstat;
        !           959:        int prior_recon;
        !           960:
        !           961:        RF_ASSERT(RF_IO_IS_R_OR_W(type));
        !           962:
        !           963:        if (asmp->numDataFailed + asmp->numParityFailed > 1) {
        !           964:                RF_ERRORMSG("Multiple disks failed in a single group !"
        !           965:                            "  Aborting I/O operation.\n");
        !           966:                 /* *infoFunc = */ *createFunc = NULL;
        !           967:                return;
        !           968:        } else
        !           969:                if (asmp->numDataFailed + asmp->numParityFailed == 1) {
        !           970:
        !           971:                        /*
        !           972:                         * If under recon & already reconstructed, redirect
        !           973:                         * the access to the spare drive and eliminate the
        !           974:                         * failure indication.
        !           975:                         */
        !           976:                        failedPDA = asmp->failedPDAs[0];
        !           977:                        frow = failedPDA->row;
        !           978:                        fcol = failedPDA->col;
        !           979:                        rstat = raidPtr->status[failedPDA->row];
        !           980:                        prior_recon = (rstat == rf_rs_reconfigured) ||
        !           981:                            ((rstat == rf_rs_reconstructing) ?
        !           982:                             rf_CheckRUReconstructed(raidPtr->reconControl[frow]
        !           983:                              ->reconMap, failedPDA->startSector) : 0);
        !           984:                        if (prior_recon) {
        !           985:                                RF_RowCol_t or = failedPDA->row;
        !           986:                                RF_RowCol_t oc = failedPDA->col;
        !           987:                                RF_SectorNum_t oo = failedPDA->startSector;
        !           988:                                if (layoutPtr->map->flags &
        !           989:                                    RF_DISTRIBUTE_SPARE) {
        !           990:                                        /* Redirect to dist spare space. */
        !           991:
        !           992:                                        if (failedPDA == asmp->parityInfo) {
        !           993:
        !           994:                                                /* Parity has failed. */
        !           995:                                                (layoutPtr->map->MapParity)
        !           996:                                                    (raidPtr,
        !           997:                                                     failedPDA->raidAddress,
        !           998:                                                     &failedPDA->row,
        !           999:                                                     &failedPDA->col,
        !          1000:                                                     &failedPDA->startSector,
        !          1001:                                                     RF_REMAP);
        !          1002:
        !          1003:                                                if (asmp->parityInfo->next) {
        !          1004:                                                        /*
        !          1005:                                                         * Redir 2nd component,
        !          1006:                                                         * if any.
        !          1007:                                                         */
        !          1008:                                                        RF_PhysDiskAddr_t *p =
        !          1009:                                                         asmp->parityInfo->next;
        !          1010:                                                        RF_SectorNum_t SUoffs =
        !          1011:                                                            p->startSector %
        !          1012:                                                layoutPtr->sectorsPerStripeUnit;
        !          1013:                                                        p->row = failedPDA->row;
        !          1014:                                                        p->col = failedPDA->col;
        !          1015:                                                        /*
        !          1016:                                                         * Cheating:
        !          1017:                                                         * startSector is not
        !          1018:                                                         * really a RAID
        !          1019:                                                         * address.
        !          1020:                                                         */
        !          1021:                                                        p->startSector =
        !          1022:                            rf_RaidAddressOfPrevStripeUnitBoundary(layoutPtr,
        !          1023:                                failedPDA->startSector) + SUoffs;
        !          1024:                                                }
        !          1025:                                        } else
        !          1026:                                                if (asmp->parityInfo->next &&
        !          1027:                                                    failedPDA ==
        !          1028:                                                    asmp->parityInfo->next) {
        !          1029:                                                        /*
        !          1030:                                                         * Should not ever
        !          1031:                                                         * happen.
        !          1032:                                                         */
        !          1033:                                                        RF_ASSERT(0);
        !          1034:                                                } else {
        !          1035:                                                        /* Data has failed. */
        !          1036:                                                        (layoutPtr->map
        !          1037:                                                         ->MapSector)
        !          1038:                                                            (raidPtr,
        !          1039:                                                         failedPDA->raidAddress,
        !          1040:                                                            &failedPDA->row,
        !          1041:                                                            &failedPDA->col,
        !          1042:                                                        &failedPDA->startSector,
        !          1043:                                                            RF_REMAP);
        !          1044:                                                }
        !          1045:
        !          1046:                                } else {
        !          1047:                                        /* Redirect to dedicated spare space. */
        !          1048:
        !          1049:                                        failedPDA->row =
        !          1050:                                            raidPtr->Disks[frow][fcol].spareRow;
        !          1051:                                        failedPDA->col =
        !          1052:                                            raidPtr->Disks[frow][fcol].spareCol;
        !          1053:
        !          1054:                                        /*
        !          1055:                                         * The parity may have two distinct
        !          1056:                                         * components, both of which may need
        !          1057:                                         * to be redirected.
        !          1058:                                         */
        !          1059:                                        if (asmp->parityInfo->next) {
        !          1060:                                                if (failedPDA ==
        !          1061:                                                    asmp->parityInfo) {
        !          1062:                                                        failedPDA->next->row =
        !          1063:                                                            failedPDA->row;
        !          1064:                                                        failedPDA->next->col =
        !          1065:                                                            failedPDA->col;
        !          1066:                                                } else {
        !          1067:                                                        if (failedPDA ==
        !          1068:                                                            asmp->parityInfo
        !          1069:                                                             ->next) {
        !          1070:                                                                /*
        !          1071:                                                                 * Paranoid:
        !          1072:                                                                 * Should never
        !          1073:                                                                 * occur.
        !          1074:                                                                 */
        !          1075:                                                                asmp->parityInfo
        !          1076:                                                                ->row =
        !          1077:                                                                 failedPDA->row;
        !          1078:                                                                asmp->parityInfo
        !          1079:                                                                ->col =
        !          1080:                                                                 failedPDA->col;
        !          1081:                                                        }
        !          1082:                                                }
        !          1083:                                        }
        !          1084:                                }
        !          1085:
        !          1086:                                RF_ASSERT(failedPDA->col != -1);
        !          1087:
        !          1088:                                if (rf_dagDebug || rf_mapDebug) {
        !          1089:                                        printf("raid%d: Redirected type '%c'"
        !          1090:                                               " r %d c %d o %ld -> r %d c %d"
        !          1091:                                               " o %ld\n", raidPtr->raidid,
        !          1092:                                               type, or, oc, (long) oo,
        !          1093:                                               failedPDA->row, failedPDA->col,
        !          1094:                                               (long) failedPDA->startSector);
        !          1095:                                }
        !          1096:                                asmp->numDataFailed = asmp->numParityFailed = 0;
        !          1097:                        }
        !          1098:                }
        !          1099:        if (type == RF_IO_TYPE_READ) {
        !          1100:
        !          1101:                if (asmp->numDataFailed == 0)
        !          1102:                        *createFunc =
        !          1103:                            (RF_VoidFuncPtr) rf_CreateFaultFreeReadDAG;
        !          1104:                else
        !          1105:                        *createFunc =
        !          1106:                            (RF_VoidFuncPtr) rf_CreateRaidFiveDegradedReadDAG;
        !          1107:
        !          1108:        } else {
        !          1109:
        !          1110:
        !          1111:                /*
        !          1112:                 * If mirroring, always use large writes. If the access
        !          1113:                 * requires two distinct parity updates, always do a small
        !          1114:                 * write. If the stripe contains a failure but the access
        !          1115:                 * does not, do a small write. The first conditional
        !          1116:                 * (numStripeUnitsAccessed <= numDataCol/2) uses a
        !          1117:                 * less-than-or-equal rather than just a less-than because
        !          1118:                 * when G is 3 or 4, numDataCol/2 is 1, and I want
        !          1119:                 * single-stripe-unit updates to use just one disk.
        !          1120:                 */
        !          1121:                if ((asmp->numDataFailed + asmp->numParityFailed) == 0) {
        !          1122:                        if (((asmp->numStripeUnitsAccessed <=
        !          1123:                              (layoutPtr->numDataCol / 2)) &&
        !          1124:                             (layoutPtr->numDataCol != 1)) ||
        !          1125:                            (asmp->parityInfo->next != NULL) ||
        !          1126:                            rf_CheckStripeForFailures(raidPtr, asmp)) {
        !          1127:                                *createFunc = (RF_VoidFuncPtr)
        !          1128:                                    rf_CreateParityLoggingSmallWriteDAG;
        !          1129:                        } else
        !          1130:                                *createFunc = (RF_VoidFuncPtr)
        !          1131:                                    rf_CreateParityLoggingLargeWriteDAG;
        !          1132:                } else
        !          1133:                        if (asmp->numParityFailed == 1)
        !          1134:                                *createFunc = (RF_VoidFuncPtr)
        !          1135:                                    rf_CreateNonRedundantWriteDAG;
        !          1136:                        else
        !          1137:                                if (asmp->numStripeUnitsAccessed != 1 &&
        !          1138:                                    failedPDA->numSector !=
        !          1139:                                    layoutPtr->sectorsPerStripeUnit)
        !          1140:                                        *createFunc = NULL;
        !          1141:                                else
        !          1142:                                        *createFunc = (RF_VoidFuncPtr)
        !          1143:                                            rf_CreateDegradedWriteDAG;
        !          1144:        }
        !          1145: }
        !          1146: #endif /* RF_INCLUDE_PARITYLOGGING > 0 */

CVSweb