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