[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

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