root/dev/raidframe/rf_paritylogDiskMgr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rf_AcquireReintBuffer
  2. rf_ReleaseReintBuffer
  3. rf_ReadRegionLog
  4. rf_WriteCoreLog
  5. rf_ReadRegionParity
  6. rf_WriteRegionParity
  7. rf_FlushLogsToDisk
  8. rf_ReintegrateRegion
  9. rf_ReintegrateLogs
  10. rf_ShutdownLogging
  11. rf_ParityLoggingDiskManager

    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 */

/* [<][>][^][v][top][bottom][index][help] */