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

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

1.1     ! nbrk        1: /*     $OpenBSD: rf_paritylogDiskMgr.c,v 1.6 2002/12/16 07:01:04 tdeval Exp $  */
        !             2: /*     $NetBSD: rf_paritylogDiskMgr.c,v 1.10 2000/01/15 01:57:57 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:  * Code for flushing and reintegrating operations related to parity logging.
        !            32:  */
        !            33:
        !            34: #include "rf_archs.h"
        !            35:
        !            36: #if    RF_INCLUDE_PARITYLOGGING > 0
        !            37:
        !            38: #include "rf_types.h"
        !            39: #include "rf_threadstuff.h"
        !            40: #include "rf_mcpair.h"
        !            41: #include "rf_raid.h"
        !            42: #include "rf_dag.h"
        !            43: #include "rf_dagfuncs.h"
        !            44: #include "rf_desc.h"
        !            45: #include "rf_layout.h"
        !            46: #include "rf_diskqueue.h"
        !            47: #include "rf_paritylog.h"
        !            48: #include "rf_general.h"
        !            49: #include "rf_etimer.h"
        !            50: #include "rf_paritylogging.h"
        !            51: #include "rf_engine.h"
        !            52: #include "rf_dagutils.h"
        !            53: #include "rf_map.h"
        !            54: #include "rf_parityscan.h"
        !            55:
        !            56: #include "rf_paritylogDiskMgr.h"
        !            57:
        !            58: caddr_t rf_AcquireReintBuffer(RF_RegionBufferQueue_t *);
        !            59: void rf_ReleaseReintBuffer(RF_RegionBufferQueue_t *, caddr_t);
        !            60: void rf_ReadRegionLog(RF_RegionId_t, RF_MCPair_t *, caddr_t, RF_Raid_t *,
        !            61:        RF_DagHeader_t **, RF_AllocListElem_t **, RF_PhysDiskAddr_t **);
        !            62: void rf_WriteCoreLog(RF_ParityLog_t *, RF_MCPair_t *, RF_Raid_t *,
        !            63:        RF_DagHeader_t **, RF_AllocListElem_t **, RF_PhysDiskAddr_t **);
        !            64: void rf_ReadRegionParity(RF_RegionId_t, RF_MCPair_t *, caddr_t, RF_Raid_t *,
        !            65:        RF_DagHeader_t **, RF_AllocListElem_t **, RF_PhysDiskAddr_t **);
        !            66: void rf_WriteRegionParity(RF_RegionId_t, RF_MCPair_t *, caddr_t, RF_Raid_t *,
        !            67:        RF_DagHeader_t **, RF_AllocListElem_t **, RF_PhysDiskAddr_t **);
        !            68: void rf_FlushLogsToDisk(RF_Raid_t *, RF_ParityLog_t *);
        !            69: void rf_ReintegrateRegion(RF_Raid_t *, RF_RegionId_t, RF_ParityLog_t *);
        !            70: void rf_ReintegrateLogs(RF_Raid_t *, RF_ParityLog_t *);
        !            71:
        !            72:
        !            73: caddr_t
        !            74: rf_AcquireReintBuffer(RF_RegionBufferQueue_t *pool)
        !            75: {
        !            76:        caddr_t bufPtr = NULL;
        !            77:
        !            78:        /*
        !            79:         * Return a region buffer from the free list (pool). If the free list
        !            80:         * is empty, WAIT. BLOCKING
        !            81:         */
        !            82:
        !            83:        RF_LOCK_MUTEX(pool->mutex);
        !            84:        if (pool->availableBuffers > 0) {
        !            85:                bufPtr = pool->buffers[pool->availBuffersIndex];
        !            86:                pool->availableBuffers--;
        !            87:                pool->availBuffersIndex++;
        !            88:                if (pool->availBuffersIndex == pool->totalBuffers)
        !            89:                        pool->availBuffersIndex = 0;
        !            90:                RF_UNLOCK_MUTEX(pool->mutex);
        !            91:        } else {
        !            92:                RF_PANIC();     /*
        !            93:                                 * Should never happen in correct config,
        !            94:                                 * single reint.
        !            95:                                 */
        !            96:                RF_WAIT_COND(pool->cond, pool->mutex);
        !            97:        }
        !            98:        return (bufPtr);
        !            99: }
        !           100:
        !           101:
        !           102: void
        !           103: rf_ReleaseReintBuffer(RF_RegionBufferQueue_t *pool, caddr_t bufPtr)
        !           104: {
        !           105:        /*
        !           106:         * Insert a region buffer (bufPtr) into the free list (pool).
        !           107:         * NON-BLOCKING
        !           108:         */
        !           109:
        !           110:        RF_LOCK_MUTEX(pool->mutex);
        !           111:        pool->availableBuffers++;
        !           112:        pool->buffers[pool->emptyBuffersIndex] = bufPtr;
        !           113:        pool->emptyBuffersIndex++;
        !           114:        if (pool->emptyBuffersIndex == pool->totalBuffers)
        !           115:                pool->emptyBuffersIndex = 0;
        !           116:        RF_ASSERT(pool->availableBuffers <= pool->totalBuffers);
        !           117:        RF_UNLOCK_MUTEX(pool->mutex);
        !           118:        RF_SIGNAL_COND(pool->cond);
        !           119: }
        !           120:
        !           121:
        !           122: void
        !           123: rf_ReadRegionLog(RF_RegionId_t regionID, RF_MCPair_t *rrd_mcpair,
        !           124:     caddr_t regionBuffer, RF_Raid_t *raidPtr, RF_DagHeader_t **rrd_dag_h,
        !           125:     RF_AllocListElem_t **rrd_alloclist, RF_PhysDiskAddr_t **rrd_pda)
        !           126: {
        !           127:        /*
        !           128:         * Initiate the read a region log from disk. Once initiated, return
        !           129:         * to the calling routine.
        !           130:         *
        !           131:         * NON-BLOCKING
        !           132:         */
        !           133:
        !           134:        RF_AccTraceEntry_t *tracerec;
        !           135:        RF_DagNode_t *rrd_rdNode;
        !           136:
        !           137:        /* Create DAG to read region log from disk. */
        !           138:        rf_MakeAllocList(*rrd_alloclist);
        !           139:        *rrd_dag_h = rf_MakeSimpleDAG(raidPtr, 1, 0, regionBuffer,
        !           140:            rf_DiskReadFunc, rf_DiskReadUndoFunc, "Rrl", *rrd_alloclist,
        !           141:            RF_DAG_FLAGS_NONE, RF_IO_NORMAL_PRIORITY);
        !           142:
        !           143:        /* Create and initialize PDA for the core log. */
        !           144:        /* RF_Malloc(*rrd_pda, sizeof(RF_PhysDiskAddr_t),
        !           145:         * (RF_PhysDiskAddr_t *)); */
        !           146:        *rrd_pda = rf_AllocPDAList(1);
        !           147:        rf_MapLogParityLogging(raidPtr, regionID, 0, &((*rrd_pda)->row),
        !           148:            &((*rrd_pda)->col), &((*rrd_pda)->startSector));
        !           149:        (*rrd_pda)->numSector = raidPtr->regionInfo[regionID].capacity;
        !           150:
        !           151:        if ((*rrd_pda)->next) {
        !           152:                (*rrd_pda)->next = NULL;
        !           153:                printf("set rrd_pda->next to NULL\n");
        !           154:        }
        !           155:        /* Initialize DAG parameters. */
        !           156:        RF_Malloc(tracerec, sizeof(RF_AccTraceEntry_t), (RF_AccTraceEntry_t *));
        !           157:        bzero((char *) tracerec, sizeof(RF_AccTraceEntry_t));
        !           158:        (*rrd_dag_h)->tracerec = tracerec;
        !           159:        rrd_rdNode = (*rrd_dag_h)->succedents[0]->succedents[0];
        !           160:        rrd_rdNode->params[0].p = *rrd_pda;
        !           161:        /* rrd_rdNode->params[1] = regionBuffer; */
        !           162:        rrd_rdNode->params[2].v = 0;
        !           163:        rrd_rdNode->params[3].v = RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY,
        !           164:                                                   0, 0, 0);
        !           165:
        !           166:        /* Launch region log read dag. */
        !           167:        rf_DispatchDAG(*rrd_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
        !           168:            (void *) rrd_mcpair);
        !           169: }
        !           170:
        !           171:
        !           172: void
        !           173: rf_WriteCoreLog(RF_ParityLog_t *log, RF_MCPair_t *fwr_mcpair,
        !           174:     RF_Raid_t *raidPtr, RF_DagHeader_t **fwr_dag_h,
        !           175:     RF_AllocListElem_t **fwr_alloclist, RF_PhysDiskAddr_t **fwr_pda)
        !           176: {
        !           177:        RF_RegionId_t regionID = log->regionID;
        !           178:        RF_AccTraceEntry_t *tracerec;
        !           179:        RF_SectorNum_t regionOffset;
        !           180:        RF_DagNode_t *fwr_wrNode;
        !           181:
        !           182:        /*
        !           183:         * Initiate the write of a core log to a region log disk. Once
        !           184:         * initiated, return to the calling routine.
        !           185:         *
        !           186:         * NON-BLOCKING
        !           187:         */
        !           188:
        !           189:        /* Create DAG to write a core log to a region log disk. */
        !           190:        rf_MakeAllocList(*fwr_alloclist);
        !           191:        *fwr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, 0, log->bufPtr,
        !           192:            rf_DiskWriteFunc, rf_DiskWriteUndoFunc, "Wcl", *fwr_alloclist,
        !           193:            RF_DAG_FLAGS_NONE, RF_IO_NORMAL_PRIORITY);
        !           194:
        !           195:        /* Create and initialize PDA for the region log. */
        !           196:        /* RF_Malloc(*fwr_pda, sizeof(RF_PhysDiskAddr_t),
        !           197:         * (RF_PhysDiskAddr_t *)); */
        !           198:        *fwr_pda = rf_AllocPDAList(1);
        !           199:        regionOffset = log->diskOffset;
        !           200:        rf_MapLogParityLogging(raidPtr, regionID, regionOffset,
        !           201:            &((*fwr_pda)->row), &((*fwr_pda)->col), &((*fwr_pda)->startSector));
        !           202:        (*fwr_pda)->numSector = raidPtr->numSectorsPerLog;
        !           203:
        !           204:        /* Initialize DAG parameters. */
        !           205:        RF_Malloc(tracerec, sizeof(RF_AccTraceEntry_t), (RF_AccTraceEntry_t *));
        !           206:        bzero((char *) tracerec, sizeof(RF_AccTraceEntry_t));
        !           207:        (*fwr_dag_h)->tracerec = tracerec;
        !           208:        fwr_wrNode = (*fwr_dag_h)->succedents[0]->succedents[0];
        !           209:        fwr_wrNode->params[0].p = *fwr_pda;
        !           210:        /* fwr_wrNode->params[1] = log->bufPtr; */
        !           211:        fwr_wrNode->params[2].v = 0;
        !           212:        fwr_wrNode->params[3].v =
        !           213:            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, 0);
        !           214:
        !           215:        /* Launch the dag to write the core log to disk. */
        !           216:        rf_DispatchDAG(*fwr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
        !           217:            (void *) fwr_mcpair);
        !           218: }
        !           219:
        !           220:
        !           221: void
        !           222: rf_ReadRegionParity(RF_RegionId_t regionID, RF_MCPair_t *prd_mcpair,
        !           223:     caddr_t parityBuffer, RF_Raid_t *raidPtr, RF_DagHeader_t **prd_dag_h,
        !           224:     RF_AllocListElem_t **prd_alloclist, RF_PhysDiskAddr_t **prd_pda)
        !           225: {
        !           226:        /*
        !           227:         * Initiate the read region parity from disk. Once initiated, return
        !           228:         * to the calling routine.
        !           229:         *
        !           230:         * NON-BLOCKING
        !           231:         */
        !           232:
        !           233:        RF_AccTraceEntry_t *tracerec;
        !           234:        RF_DagNode_t *prd_rdNode;
        !           235:
        !           236:        /* Create DAG to read region parity from disk. */
        !           237:        rf_MakeAllocList(*prd_alloclist);
        !           238:        *prd_dag_h = rf_MakeSimpleDAG(raidPtr, 1, 0, NULL, rf_DiskReadFunc,
        !           239:            rf_DiskReadUndoFunc, "Rrp", *prd_alloclist, RF_DAG_FLAGS_NONE,
        !           240:            RF_IO_NORMAL_PRIORITY);
        !           241:
        !           242:        /* Create and initialize PDA for region parity. */
        !           243:        /* RF_Malloc(*prd_pda, sizeof(RF_PhysDiskAddr_t),
        !           244:         * (RF_PhysDiskAddr_t *)); */
        !           245:        *prd_pda = rf_AllocPDAList(1);
        !           246:        rf_MapRegionParity(raidPtr, regionID, &((*prd_pda)->row),
        !           247:            &((*prd_pda)->col), &((*prd_pda)->startSector),
        !           248:            &((*prd_pda)->numSector));
        !           249:        if (rf_parityLogDebug)
        !           250:                printf("[reading %d sectors of parity from region %d]\n",
        !           251:                    (int) (*prd_pda)->numSector, regionID);
        !           252:        if ((*prd_pda)->next) {
        !           253:                (*prd_pda)->next = NULL;
        !           254:                printf("set prd_pda->next to NULL\n");
        !           255:        }
        !           256:        /* Initialize DAG parameters. */
        !           257:        RF_Malloc(tracerec, sizeof(RF_AccTraceEntry_t), (RF_AccTraceEntry_t *));
        !           258:        bzero((char *) tracerec, sizeof(RF_AccTraceEntry_t));
        !           259:        (*prd_dag_h)->tracerec = tracerec;
        !           260:        prd_rdNode = (*prd_dag_h)->succedents[0]->succedents[0];
        !           261:        prd_rdNode->params[0].p = *prd_pda;
        !           262:        prd_rdNode->params[1].p = parityBuffer;
        !           263:        prd_rdNode->params[2].v = 0;
        !           264:        prd_rdNode->params[3].v =
        !           265:            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, 0);
        !           266:        if (rf_validateDAGDebug)
        !           267:                rf_ValidateDAG(*prd_dag_h);
        !           268:        /* Launch region parity read dag. */
        !           269:        rf_DispatchDAG(*prd_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
        !           270:            (void *) prd_mcpair);
        !           271: }
        !           272:
        !           273: void
        !           274: rf_WriteRegionParity(RF_RegionId_t regionID, RF_MCPair_t *pwr_mcpair,
        !           275:     caddr_t parityBuffer, RF_Raid_t *raidPtr, RF_DagHeader_t **pwr_dag_h,
        !           276:     RF_AllocListElem_t **pwr_alloclist, RF_PhysDiskAddr_t **pwr_pda)
        !           277: {
        !           278:        /*
        !           279:         * Initiate the write of region parity to disk. Once initiated, return
        !           280:         * to the calling routine.
        !           281:         *
        !           282:         * NON-BLOCKING
        !           283:         */
        !           284:
        !           285:        RF_AccTraceEntry_t *tracerec;
        !           286:        RF_DagNode_t *pwr_wrNode;
        !           287:
        !           288:        /* Create DAG to write region log from disk. */
        !           289:        rf_MakeAllocList(*pwr_alloclist);
        !           290:        *pwr_dag_h = rf_MakeSimpleDAG(raidPtr, 1, 0, parityBuffer,
        !           291:            rf_DiskWriteFunc, rf_DiskWriteUndoFunc, "Wrp", *pwr_alloclist,
        !           292:            RF_DAG_FLAGS_NONE, RF_IO_NORMAL_PRIORITY);
        !           293:
        !           294:        /* Create and initialize PDA for region parity. */
        !           295:        /* RF_Malloc(*pwr_pda, sizeof(RF_PhysDiskAddr_t),
        !           296:         * (RF_PhysDiskAddr_t *)); */
        !           297:        *pwr_pda = rf_AllocPDAList(1);
        !           298:        rf_MapRegionParity(raidPtr, regionID, &((*pwr_pda)->row),
        !           299:            &((*pwr_pda)->col), &((*pwr_pda)->startSector),
        !           300:            &((*pwr_pda)->numSector));
        !           301:
        !           302:        /* Initialize DAG parameters. */
        !           303:        RF_Malloc(tracerec, sizeof(RF_AccTraceEntry_t), (RF_AccTraceEntry_t *));
        !           304:        bzero((char *) tracerec, sizeof(RF_AccTraceEntry_t));
        !           305:        (*pwr_dag_h)->tracerec = tracerec;
        !           306:        pwr_wrNode = (*pwr_dag_h)->succedents[0]->succedents[0];
        !           307:        pwr_wrNode->params[0].p = *pwr_pda;
        !           308:        /* pwr_wrNode->params[1] = parityBuffer; */
        !           309:        pwr_wrNode->params[2].v = 0;
        !           310:        pwr_wrNode->params[3].v =
        !           311:            RF_CREATE_PARAM3(RF_IO_NORMAL_PRIORITY, 0, 0, 0);
        !           312:
        !           313:        /* Launch the dag to write region parity to disk. */
        !           314:        rf_DispatchDAG(*pwr_dag_h, (void (*) (void *)) rf_MCPairWakeupFunc,
        !           315:            (void *) pwr_mcpair);
        !           316: }
        !           317:
        !           318: void
        !           319: rf_FlushLogsToDisk(RF_Raid_t *raidPtr, RF_ParityLog_t *logList)
        !           320: {
        !           321:        /*
        !           322:         * Flush a linked list of core logs to the log disk. Logs contain the
        !           323:         * disk location where they should be written. Logs were written in
        !           324:         * FIFO order and that order must be preserved.
        !           325:         *
        !           326:         * Recommended optimizations:
        !           327:         * 1) Allow multiple flushes to occur simultaneously.
        !           328:         * 2) Coalesce contiguous flush operations.
        !           329:         *
        !           330:         * BLOCKING
        !           331:         */
        !           332:
        !           333:        RF_ParityLog_t *log;
        !           334:        RF_RegionId_t regionID;
        !           335:        RF_MCPair_t *fwr_mcpair;
        !           336:        RF_DagHeader_t *fwr_dag_h;
        !           337:        RF_AllocListElem_t *fwr_alloclist;
        !           338:        RF_PhysDiskAddr_t *fwr_pda;
        !           339:
        !           340:        fwr_mcpair = rf_AllocMCPair();
        !           341:        RF_LOCK_MUTEX(fwr_mcpair->mutex);
        !           342:
        !           343:        RF_ASSERT(logList);
        !           344:        log = logList;
        !           345:        while (log) {
        !           346:                regionID = log->regionID;
        !           347:
        !           348:                /* Create and launch a DAG to write the core log. */
        !           349:                if (rf_parityLogDebug)
        !           350:                        printf("[initiating write of core log for region"
        !           351:                            " %d]\n", regionID);
        !           352:                fwr_mcpair->flag = RF_FALSE;
        !           353:                rf_WriteCoreLog(log, fwr_mcpair, raidPtr, &fwr_dag_h,
        !           354:                    &fwr_alloclist, &fwr_pda);
        !           355:
        !           356:                /* Wait for the DAG to complete. */
        !           357:                while (!fwr_mcpair->flag)
        !           358:                        RF_WAIT_COND(fwr_mcpair->cond, fwr_mcpair->mutex);
        !           359:                if (fwr_dag_h->status != rf_enable) {
        !           360:                        RF_ERRORMSG1("Unable to write core log to disk"
        !           361:                            " (region %d)\n", regionID);
        !           362:                        RF_ASSERT(0);
        !           363:                }
        !           364:                /* RF_Free(fwr_pda, sizeof(RF_PhysDiskAddr_t)); */
        !           365:                rf_FreePhysDiskAddr(fwr_pda);
        !           366:                rf_FreeDAG(fwr_dag_h);
        !           367:                rf_FreeAllocList(fwr_alloclist);
        !           368:
        !           369:                log = log->next;
        !           370:        }
        !           371:        RF_UNLOCK_MUTEX(fwr_mcpair->mutex);
        !           372:        rf_FreeMCPair(fwr_mcpair);
        !           373:        rf_ReleaseParityLogs(raidPtr, logList);
        !           374: }
        !           375:
        !           376: void
        !           377: rf_ReintegrateRegion(RF_Raid_t *raidPtr, RF_RegionId_t regionID,
        !           378:     RF_ParityLog_t *coreLog)
        !           379: {
        !           380:        RF_MCPair_t *rrd_mcpair = NULL, *prd_mcpair, *pwr_mcpair;
        !           381:        RF_DagHeader_t *rrd_dag_h, *prd_dag_h, *pwr_dag_h;
        !           382:        RF_AllocListElem_t *rrd_alloclist, *prd_alloclist, *pwr_alloclist;
        !           383:        RF_PhysDiskAddr_t *rrd_pda, *prd_pda, *pwr_pda;
        !           384:        caddr_t parityBuffer, regionBuffer = NULL;
        !           385:
        !           386:        /*
        !           387:         * Reintegrate a region (regionID).
        !           388:         *
        !           389:         * 1. Acquire region and parity buffers.
        !           390:         * 2. Read log from disk.
        !           391:         * 3. Read parity from disk.
        !           392:         * 4. Apply log to parity.
        !           393:         * 5. Apply core log to parity.
        !           394:         * 6. Write new parity to disk.
        !           395:         *
        !           396:         * BLOCKING
        !           397:         */
        !           398:
        !           399:        if (rf_parityLogDebug)
        !           400:                printf("[reintegrating region %d]\n", regionID);
        !           401:
        !           402:        /* Initiate read of region parity. */
        !           403:        if (rf_parityLogDebug)
        !           404:                printf("[initiating read of parity for region %d]\n", regionID);
        !           405:        parityBuffer = rf_AcquireReintBuffer(&raidPtr->parityBufferPool);
        !           406:        prd_mcpair = rf_AllocMCPair();
        !           407:        RF_LOCK_MUTEX(prd_mcpair->mutex);
        !           408:        prd_mcpair->flag = RF_FALSE;
        !           409:        rf_ReadRegionParity(regionID, prd_mcpair, parityBuffer, raidPtr,
        !           410:                         &prd_dag_h, &prd_alloclist, &prd_pda);
        !           411:
        !           412:        /* If region log nonempty, initiate read. */
        !           413:        if (raidPtr->regionInfo[regionID].diskCount > 0) {
        !           414:                if (rf_parityLogDebug)
        !           415:                        printf("[initiating read of disk log for region %d]\n",
        !           416:                            regionID);
        !           417:                regionBuffer =
        !           418:                    rf_AcquireReintBuffer(&raidPtr->regionBufferPool);
        !           419:                rrd_mcpair = rf_AllocMCPair();
        !           420:                RF_LOCK_MUTEX(rrd_mcpair->mutex);
        !           421:                rrd_mcpair->flag = RF_FALSE;
        !           422:                rf_ReadRegionLog(regionID, rrd_mcpair, regionBuffer, raidPtr,
        !           423:                    &rrd_dag_h, &rrd_alloclist, &rrd_pda);
        !           424:        }
        !           425:        /* Wait on read of region parity to complete. */
        !           426:        while (!prd_mcpair->flag) {
        !           427:                RF_WAIT_COND(prd_mcpair->cond, prd_mcpair->mutex);
        !           428:        }
        !           429:        RF_UNLOCK_MUTEX(prd_mcpair->mutex);
        !           430:        if (prd_dag_h->status != rf_enable) {
        !           431:                RF_ERRORMSG("Unable to read parity from disk\n");
        !           432:                /* Add code to fail the parity disk. */
        !           433:                RF_ASSERT(0);
        !           434:        }
        !           435:        /* Apply core log to parity. */
        !           436:        /* if (coreLog) ApplyLogsToParity(coreLog, parityBuffer); */
        !           437:
        !           438:        if (raidPtr->regionInfo[regionID].diskCount > 0) {
        !           439:                /* Wait on read of region log to complete. */
        !           440:                while (!rrd_mcpair->flag)
        !           441:                        RF_WAIT_COND(rrd_mcpair->cond, rrd_mcpair->mutex);
        !           442:                RF_UNLOCK_MUTEX(rrd_mcpair->mutex);
        !           443:                if (rrd_dag_h->status != rf_enable) {
        !           444:                        RF_ERRORMSG("Unable to read region log from disk\n");
        !           445:                        /* Add code to fail the log disk. */
        !           446:                        RF_ASSERT(0);
        !           447:                }
        !           448:                /* Apply region log to parity. */
        !           449:                /* ApplyRegionToParity(regionID, regionBuffer, parityBuffer); */
        !           450:                /* Release resources associated with region log. */
        !           451:                /* RF_Free(rrd_pda, sizeof(RF_PhysDiskAddr_t)); */
        !           452:                rf_FreePhysDiskAddr(rrd_pda);
        !           453:                rf_FreeDAG(rrd_dag_h);
        !           454:                rf_FreeAllocList(rrd_alloclist);
        !           455:                rf_FreeMCPair(rrd_mcpair);
        !           456:                rf_ReleaseReintBuffer(&raidPtr->regionBufferPool, regionBuffer);
        !           457:        }
        !           458:        /* Write reintegrated parity to disk. */
        !           459:        if (rf_parityLogDebug)
        !           460:                printf("[initiating write of parity for region %d]\n",
        !           461:                    regionID);
        !           462:        pwr_mcpair = rf_AllocMCPair();
        !           463:        RF_LOCK_MUTEX(pwr_mcpair->mutex);
        !           464:        pwr_mcpair->flag = RF_FALSE;
        !           465:        rf_WriteRegionParity(regionID, pwr_mcpair, parityBuffer, raidPtr,
        !           466:            &pwr_dag_h, &pwr_alloclist, &pwr_pda);
        !           467:        while (!pwr_mcpair->flag)
        !           468:                RF_WAIT_COND(pwr_mcpair->cond, pwr_mcpair->mutex);
        !           469:        RF_UNLOCK_MUTEX(pwr_mcpair->mutex);
        !           470:        if (pwr_dag_h->status != rf_enable) {
        !           471:                RF_ERRORMSG("Unable to write parity to disk\n");
        !           472:                /* Add code to fail the parity disk. */
        !           473:                RF_ASSERT(0);
        !           474:        }
        !           475:        /* Release resources associated with read of old parity. */
        !           476:        /* RF_Free(prd_pda, sizeof(RF_PhysDiskAddr_t)); */
        !           477:        rf_FreePhysDiskAddr(prd_pda);
        !           478:        rf_FreeDAG(prd_dag_h);
        !           479:        rf_FreeAllocList(prd_alloclist);
        !           480:        rf_FreeMCPair(prd_mcpair);
        !           481:
        !           482:        /* Release resources associated with write of new parity. */
        !           483:        rf_ReleaseReintBuffer(&raidPtr->parityBufferPool, parityBuffer);
        !           484:        /* RF_Free(pwr_pda, sizeof(RF_PhysDiskAddr_t)); */
        !           485:        rf_FreePhysDiskAddr(pwr_pda);
        !           486:        rf_FreeDAG(pwr_dag_h);
        !           487:        rf_FreeAllocList(pwr_alloclist);
        !           488:        rf_FreeMCPair(pwr_mcpair);
        !           489:
        !           490:        if (rf_parityLogDebug)
        !           491:                printf("[finished reintegrating region %d]\n", regionID);
        !           492: }
        !           493:
        !           494:
        !           495: void
        !           496: rf_ReintegrateLogs(RF_Raid_t *raidPtr, RF_ParityLog_t *logList)
        !           497: {
        !           498:        RF_ParityLog_t *log, *freeLogList = NULL;
        !           499:        RF_ParityLogData_t *logData, *logDataList;
        !           500:        RF_RegionId_t regionID;
        !           501:
        !           502:        RF_ASSERT(logList);
        !           503:        while (logList) {
        !           504:                log = logList;
        !           505:                logList = logList->next;
        !           506:                log->next = NULL;
        !           507:                regionID = log->regionID;
        !           508:                rf_ReintegrateRegion(raidPtr, regionID, log);
        !           509:                log->numRecords = 0;
        !           510:
        !           511:                /*
        !           512:                 * Remove all items which are blocked on reintegration of this
        !           513:                 * region.
        !           514:                 */
        !           515:                RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
        !           516:                logData = rf_SearchAndDequeueParityLogData(raidPtr, regionID,
        !           517:                    &raidPtr->parityLogDiskQueue.reintBlockHead,
        !           518:                    &raidPtr->parityLogDiskQueue.reintBlockTail, RF_TRUE);
        !           519:                logDataList = logData;
        !           520:                while (logData) {
        !           521:                        logData->next =
        !           522:                            rf_SearchAndDequeueParityLogData(raidPtr, regionID,
        !           523:                             &raidPtr->parityLogDiskQueue.reintBlockHead,
        !           524:                             &raidPtr->parityLogDiskQueue.reintBlockTail,
        !           525:                             RF_TRUE);
        !           526:                        logData = logData->next;
        !           527:                }
        !           528:                RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
        !           529:
        !           530:                /*
        !           531:                 * Process blocked log data and clear reintInProgress flag for
        !           532:                 * this region.
        !           533:                 */
        !           534:                if (logDataList)
        !           535:                        rf_ParityLogAppend(logDataList, RF_TRUE, &log, RF_TRUE);
        !           536:                else {
        !           537:                        /*
        !           538:                         * Enable flushing for this region. Holding both
        !           539:                         * locks provides a synchronization barrier with
        !           540:                         * DumpParityLogToDisk.
        !           541:                         */
        !           542:                        RF_LOCK_MUTEX(raidPtr->regionInfo[regionID].mutex);
        !           543:                        RF_LOCK_MUTEX(raidPtr->regionInfo[regionID].reintMutex);
        !           544:                        RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
        !           545:                        raidPtr->regionInfo[regionID].diskCount = 0;
        !           546:                        raidPtr->regionInfo[regionID].reintInProgress =
        !           547:                            RF_FALSE;
        !           548:                        RF_UNLOCK_MUTEX(raidPtr->regionInfo[regionID].mutex);
        !           549:                        RF_UNLOCK_MUTEX(raidPtr->regionInfo[regionID]
        !           550:                            .reintMutex);       /* Flushing is now enabled. */
        !           551:                        RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
        !           552:                }
        !           553:                /*
        !           554:                 * If log wasn't used, attach it to the list of logs to be
        !           555:                 * returned.
        !           556:                 */
        !           557:                if (log) {
        !           558:                        log->next = freeLogList;
        !           559:                        freeLogList = log;
        !           560:                }
        !           561:        }
        !           562:        if (freeLogList)
        !           563:                rf_ReleaseParityLogs(raidPtr, freeLogList);
        !           564: }
        !           565:
        !           566: int
        !           567: rf_ShutdownLogging(RF_Raid_t *raidPtr)
        !           568: {
        !           569:        /*
        !           570:         * Shutdown parity logging:
        !           571:         * 1) Disable parity logging in all regions.
        !           572:         * 2) Reintegrate all regions.
        !           573:         */
        !           574:
        !           575:        RF_SectorCount_t diskCount;
        !           576:        RF_RegionId_t regionID;
        !           577:        RF_ParityLog_t *log;
        !           578:
        !           579:        if (rf_parityLogDebug)
        !           580:                printf("[shutting down parity logging]\n");
        !           581:        /*
        !           582:         * Since parity log maps are volatile, we must reintegrate all
        !           583:         * regions.
        !           584:         */
        !           585:        if (rf_forceParityLogReint) {
        !           586:                for (regionID = 0; regionID < rf_numParityRegions; regionID++) {
        !           587:                        RF_LOCK_MUTEX(raidPtr->regionInfo[regionID].mutex);
        !           588:                        raidPtr->regionInfo[regionID].loggingEnabled = RF_FALSE;
        !           589:                        log = raidPtr->regionInfo[regionID].coreLog;
        !           590:                        raidPtr->regionInfo[regionID].coreLog = NULL;
        !           591:                        diskCount = raidPtr->regionInfo[regionID].diskCount;
        !           592:                        RF_UNLOCK_MUTEX(raidPtr->regionInfo[regionID].mutex);
        !           593:                        if (diskCount > 0 || log != NULL)
        !           594:                                rf_ReintegrateRegion(raidPtr, regionID, log);
        !           595:                        if (log != NULL)
        !           596:                                rf_ReleaseParityLogs(raidPtr, log);
        !           597:                }
        !           598:        }
        !           599:        if (rf_parityLogDebug) {
        !           600:                printf("[parity logging disabled]\n");
        !           601:                printf("[should be done !]\n");
        !           602:        }
        !           603:        return (0);
        !           604: }
        !           605:
        !           606: int
        !           607: rf_ParityLoggingDiskManager(RF_Raid_t *raidPtr)
        !           608: {
        !           609:        RF_ParityLog_t *reintQueue, *flushQueue;
        !           610:        int workNeeded, done = RF_FALSE;
        !           611:        int s;
        !           612:
        !           613:        /*
        !           614:         * Main program for parity logging disk thread. This routine waits
        !           615:         * for work to appear in either the flush or reintegration queues and
        !           616:         * is responsible for flushing core logs to the log disk as well as
        !           617:         * reintegrating parity regions.
        !           618:         *
        !           619:         * BLOCKING
        !           620:         */
        !           621:
        !           622:        s = splbio();
        !           623:
        !           624:        RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
        !           625:
        !           626:        /*
        !           627:         * Inform our creator that we're running. Don't bother doing the
        !           628:         * mutex lock/unlock dance: we locked above, and we'll unlock
        !           629:         * below with nothing to do, yet.
        !           630:         */
        !           631:        raidPtr->parityLogDiskQueue.threadState |= RF_PLOG_RUNNING;
        !           632:        RF_SIGNAL_COND(raidPtr->parityLogDiskQueue.cond);
        !           633:
        !           634:        /* Empty the work queues. */
        !           635:        flushQueue = raidPtr->parityLogDiskQueue.flushQueue;
        !           636:        raidPtr->parityLogDiskQueue.flushQueue = NULL;
        !           637:        reintQueue = raidPtr->parityLogDiskQueue.reintQueue;
        !           638:        raidPtr->parityLogDiskQueue.reintQueue = NULL;
        !           639:        workNeeded = (flushQueue || reintQueue);
        !           640:
        !           641:        while (!done) {
        !           642:                while (workNeeded) {
        !           643:                        /*
        !           644:                         * First, flush all logs in the flush queue, freeing
        !           645:                         * buffers. Second, reintegrate all regions that are
        !           646:                         * reported as full. Third, append queued log data
        !           647:                         * until blocked.
        !           648:                         *
        !           649:                         * Note: Incoming appends (ParityLogAppend) can block
        !           650:                         * on either 1. empty buffer pool 2. region under
        !           651:                         * reintegration. To preserve a global FIFO ordering of
        !           652:                         * appends, buffers are not released to the world
        !           653:                         * until those appends blocked on buffers are removed
        !           654:                         * from the append queue. Similarly, regions that are
        !           655:                         * reintegrated are not opened for general use until
        !           656:                         * the append queue has been emptied.
        !           657:                         */
        !           658:
        !           659:                        RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
        !           660:
        !           661:                        /*
        !           662:                         * Empty flushQueue, using free'd log buffers to
        !           663:                         * process bufTail.
        !           664:                         */
        !           665:                        if (flushQueue)
        !           666:                                rf_FlushLogsToDisk(raidPtr, flushQueue);
        !           667:
        !           668:                        /*
        !           669:                         * Empty reintQueue, flushing from reintTail as we go.
        !           670:                         */
        !           671:                        if (reintQueue)
        !           672:                                rf_ReintegrateLogs(raidPtr, reintQueue);
        !           673:
        !           674:                        RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
        !           675:                        flushQueue = raidPtr->parityLogDiskQueue.flushQueue;
        !           676:                        raidPtr->parityLogDiskQueue.flushQueue = NULL;
        !           677:                        reintQueue = raidPtr->parityLogDiskQueue.reintQueue;
        !           678:                        raidPtr->parityLogDiskQueue.reintQueue = NULL;
        !           679:                        workNeeded = (flushQueue || reintQueue);
        !           680:                }
        !           681:                /* No work is needed at this point. */
        !           682:                if (raidPtr->parityLogDiskQueue.threadState & RF_PLOG_TERMINATE) {
        !           683:                        /*
        !           684:                         * Shutdown parity logging:
        !           685:                         * 1. Disable parity logging in all regions.
        !           686:                         * 2. Reintegrate all regions.
        !           687:                         */
        !           688:                        done = RF_TRUE; /* Thread disabled, no work needed. */
        !           689:                        RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
        !           690:                        rf_ShutdownLogging(raidPtr);
        !           691:                }
        !           692:                if (!done) {
        !           693:                        /* Thread enabled, no work needed, so sleep. */
        !           694:                        if (rf_parityLogDebug)
        !           695:                                printf("[parity logging disk manager"
        !           696:                                    " sleeping]\n");
        !           697:                        RF_WAIT_COND(raidPtr->parityLogDiskQueue.cond,
        !           698:                            raidPtr->parityLogDiskQueue.mutex);
        !           699:                        if (rf_parityLogDebug)
        !           700:                                printf("[parity logging disk manager just"
        !           701:                                    " woke up]\n");
        !           702:                        flushQueue = raidPtr->parityLogDiskQueue.flushQueue;
        !           703:                        raidPtr->parityLogDiskQueue.flushQueue = NULL;
        !           704:                        reintQueue = raidPtr->parityLogDiskQueue.reintQueue;
        !           705:                        raidPtr->parityLogDiskQueue.reintQueue = NULL;
        !           706:                        workNeeded = (flushQueue || reintQueue);
        !           707:                }
        !           708:        }
        !           709:        /*
        !           710:         * Announce that we're done.
        !           711:         */
        !           712:        RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
        !           713:        raidPtr->parityLogDiskQueue.threadState |= RF_PLOG_SHUTDOWN;
        !           714:        RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
        !           715:        RF_SIGNAL_COND(raidPtr->parityLogDiskQueue.cond);
        !           716:
        !           717:        splx(s);
        !           718:
        !           719:        /*
        !           720:         * In the Net- & OpenBSD kernel, the thread must exit; returning would
        !           721:         * cause the proc trampoline to attempt to return to userspace.
        !           722:         */
        !           723:        kthread_exit(0);        /* does not return */
        !           724: }
        !           725: #endif /* RF_INCLUDE_PARITYLOGGING > 0 */

CVSweb