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