Home | History | Annotate | Line # | Download | only in raidframe
rf_layout.c revision 1.8
      1 /*	$NetBSD: rf_layout.c,v 1.8 2001/01/27 02:13:34 oster Exp $	*/
      2 /*
      3  * Copyright (c) 1995 Carnegie-Mellon University.
      4  * All rights reserved.
      5  *
      6  * Author: Mark Holland
      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 /* rf_layout.c -- driver code dealing with layout and mapping issues
     30  */
     31 
     32 #include "rf_types.h"
     33 #include "rf_archs.h"
     34 #include "rf_raid.h"
     35 #include "rf_configure.h"
     36 #include "rf_dag.h"
     37 #include "rf_desc.h"
     38 #include "rf_decluster.h"
     39 #include "rf_pq.h"
     40 #include "rf_declusterPQ.h"
     41 #include "rf_raid0.h"
     42 #include "rf_raid1.h"
     43 #include "rf_raid4.h"
     44 #include "rf_raid5.h"
     45 #include "rf_states.h"
     46 #if RF_INCLUDE_RAID5_RS > 0
     47 #include "rf_raid5_rotatedspare.h"
     48 #endif				/* RF_INCLUDE_RAID5_RS > 0 */
     49 #if RF_INCLUDE_CHAINDECLUSTER > 0
     50 #include "rf_chaindecluster.h"
     51 #endif				/* RF_INCLUDE_CHAINDECLUSTER > 0 */
     52 #if RF_INCLUDE_INTERDECLUSTER > 0
     53 #include "rf_interdecluster.h"
     54 #endif				/* RF_INCLUDE_INTERDECLUSTER > 0 */
     55 #if RF_INCLUDE_PARITYLOGGING > 0
     56 #include "rf_paritylogging.h"
     57 #endif				/* RF_INCLUDE_PARITYLOGGING > 0 */
     58 #if RF_INCLUDE_EVENODD > 0
     59 #include "rf_evenodd.h"
     60 #endif				/* RF_INCLUDE_EVENODD > 0 */
     61 #include "rf_general.h"
     62 #include "rf_driver.h"
     63 #include "rf_parityscan.h"
     64 #include "rf_reconbuffer.h"
     65 #include "rf_reconutil.h"
     66 
     67 /***********************************************************************
     68  *
     69  * the layout switch defines all the layouts that are supported.
     70  *    fields are: layout ID, init routine, shutdown routine, map
     71  *    sector, map parity, identify stripe, dag selection, map stripeid
     72  *    to parity stripe id (optional), num faults tolerated, special
     73  *    flags.
     74  *
     75  ***********************************************************************/
     76 
     77 static RF_AccessState_t DefaultStates[] = {rf_QuiesceState,
     78 	rf_IncrAccessesCountState, rf_MapState, rf_LockState, rf_CreateDAGState,
     79 	rf_ExecuteDAGState, rf_ProcessDAGState, rf_DecrAccessesCountState,
     80 rf_CleanupState, rf_LastState};
     81 #if defined(__NetBSD__) && !defined(_KERNEL)
     82 /* XXX Gross hack to shutup gcc -- it complains that DefaultStates is not
     83 used when compiling this in userland..  I hate to burst it's bubble, but
     84 DefaultStates is used all over the place here in the initialization of
     85 lots of data structures.  GO */
     86 RF_AccessState_t *NothingAtAll = DefaultStates;
     87 #endif
     88 
     89 #if defined(__NetBSD__) && defined(_KERNEL)
     90 /* XXX Remove static so GCC doesn't complain about these being unused! */
     91 #if RF_INCLUDE_PARITY_DECLUSTERING_DS > 0
     92 int     distSpareYes = 1;
     93 #endif
     94 #if (RF_INCLUDE_PARITY_DECLUSTERING > 0) || (RF_INCLUDE_DECL_PQ > 0) || (RF_INCLUDE_EVENODD > 0)
     95 int     distSpareNo = 0;
     96 #endif
     97 #else
     98 #if RF_INCLUDE_PARITY_DECLUSTERING_DS > 0
     99 static int distSpareYes = 1;
    100 #endif
    101 #if  (RF_INCLUDE_PARITY_DECLUSTERING > 0) || (RF_INCLUDE_DECL_PQ > 0) || (RF_INCLUDE_EVENODD > 0)
    102 static int distSpareNo = 0;
    103 #endif
    104 #endif
    105 
    106 #ifdef _KERNEL
    107 #define RF_NK2(a,b)
    108 #else				/* _KERNEL */
    109 #define RF_NK2(a,b) a,b,
    110 #endif				/* _KERNEL */
    111 
    112 #if RF_UTILITY > 0
    113 #define RF_NU(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)
    114 #else				/* RF_UTILITY > 0 */
    115 #define RF_NU(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p
    116 #endif				/* RF_UTILITY > 0 */
    117 
    118 static RF_LayoutSW_t mapsw[] = {
    119 #if RF_INCLUDE_PARITY_DECLUSTERING > 0
    120 	/* parity declustering */
    121 	{'T', "Parity declustering",
    122 		RF_NK2(rf_MakeLayoutSpecificDeclustered, &distSpareNo)
    123 		RF_NU(
    124 		    rf_ConfigureDeclustered,
    125 		    rf_MapSectorDeclustered, rf_MapParityDeclustered, NULL,
    126 		    rf_IdentifyStripeDeclustered,
    127 		    rf_RaidFiveDagSelect,
    128 		    rf_MapSIDToPSIDDeclustered,
    129 		    rf_GetDefaultHeadSepLimitDeclustered,
    130 		    rf_GetDefaultNumFloatingReconBuffersDeclustered,
    131 		    NULL, NULL,
    132 		    rf_SubmitReconBufferBasic,
    133 		    rf_VerifyParityBasic,
    134 		    1,
    135 		    DefaultStates,
    136 		    0)
    137 	},
    138 #endif
    139 
    140 #if RF_INCLUDE_PARITY_DECLUSTERING_DS > 0
    141 	/* parity declustering with distributed sparing */
    142 	{'D', "Distributed sparing parity declustering",
    143 		RF_NK2(rf_MakeLayoutSpecificDeclustered, &distSpareYes)
    144 		RF_NU(
    145 		    rf_ConfigureDeclusteredDS,
    146 		    rf_MapSectorDeclustered, rf_MapParityDeclustered, NULL,
    147 		    rf_IdentifyStripeDeclustered,
    148 		    rf_RaidFiveDagSelect,
    149 		    rf_MapSIDToPSIDDeclustered,
    150 		    rf_GetDefaultHeadSepLimitDeclustered,
    151 		    rf_GetDefaultNumFloatingReconBuffersDeclustered,
    152 		    rf_GetNumSpareRUsDeclustered, rf_InstallSpareTable,
    153 		    rf_SubmitReconBufferBasic,
    154 		    rf_VerifyParityBasic,
    155 		    1,
    156 		    DefaultStates,
    157 		    RF_DISTRIBUTE_SPARE | RF_BD_DECLUSTERED)
    158 	},
    159 #endif
    160 
    161 #if RF_INCLUDE_DECL_PQ > 0
    162 	/* declustered P+Q */
    163 	{'Q', "Declustered P+Q",
    164 		RF_NK2(rf_MakeLayoutSpecificDeclustered, &distSpareNo)
    165 		RF_NU(
    166 		    rf_ConfigureDeclusteredPQ,
    167 		    rf_MapSectorDeclusteredPQ, rf_MapParityDeclusteredPQ, rf_MapQDeclusteredPQ,
    168 		    rf_IdentifyStripeDeclusteredPQ,
    169 		    rf_PQDagSelect,
    170 		    rf_MapSIDToPSIDDeclustered,
    171 		    rf_GetDefaultHeadSepLimitDeclustered,
    172 		    rf_GetDefaultNumFloatingReconBuffersPQ,
    173 		    NULL, NULL,
    174 		    NULL,
    175 		    rf_VerifyParityBasic,
    176 		    2,
    177 		    DefaultStates,
    178 		    0)
    179 	},
    180 #endif				/* RF_INCLUDE_DECL_PQ > 0 */
    181 
    182 #if RF_INCLUDE_RAID5_RS > 0
    183 	/* RAID 5 with rotated sparing */
    184 	{'R', "RAID Level 5 rotated sparing",
    185 		RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    186 		RF_NU(
    187 		    rf_ConfigureRAID5_RS,
    188 		    rf_MapSectorRAID5_RS, rf_MapParityRAID5_RS, NULL,
    189 		    rf_IdentifyStripeRAID5_RS,
    190 		    rf_RaidFiveDagSelect,
    191 		    rf_MapSIDToPSIDRAID5_RS,
    192 		    rf_GetDefaultHeadSepLimitRAID5,
    193 		    rf_GetDefaultNumFloatingReconBuffersRAID5,
    194 		    rf_GetNumSpareRUsRAID5_RS, NULL,
    195 		    rf_SubmitReconBufferBasic,
    196 		    rf_VerifyParityBasic,
    197 		    1,
    198 		    DefaultStates,
    199 		    RF_DISTRIBUTE_SPARE)
    200 	},
    201 #endif				/* RF_INCLUDE_RAID5_RS > 0 */
    202 
    203 #if RF_INCLUDE_CHAINDECLUSTER > 0
    204 	/* Chained Declustering */
    205 	{'C', "Chained Declustering",
    206 		RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    207 		RF_NU(
    208 		    rf_ConfigureChainDecluster,
    209 		    rf_MapSectorChainDecluster, rf_MapParityChainDecluster, NULL,
    210 		    rf_IdentifyStripeChainDecluster,
    211 		    rf_RAIDCDagSelect,
    212 		    rf_MapSIDToPSIDChainDecluster,
    213 		    NULL,
    214 		    NULL,
    215 		    rf_GetNumSpareRUsChainDecluster, NULL,
    216 		    rf_SubmitReconBufferBasic,
    217 		    rf_VerifyParityBasic,
    218 		    1,
    219 		    DefaultStates,
    220 		    0)
    221 	},
    222 #endif				/* RF_INCLUDE_CHAINDECLUSTER > 0 */
    223 
    224 #if RF_INCLUDE_INTERDECLUSTER > 0
    225 	/* Interleaved Declustering */
    226 	{'I', "Interleaved Declustering",
    227 		RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    228 		RF_NU(
    229 		    rf_ConfigureInterDecluster,
    230 		    rf_MapSectorInterDecluster, rf_MapParityInterDecluster, NULL,
    231 		    rf_IdentifyStripeInterDecluster,
    232 		    rf_RAIDIDagSelect,
    233 		    rf_MapSIDToPSIDInterDecluster,
    234 		    rf_GetDefaultHeadSepLimitInterDecluster,
    235 		    rf_GetDefaultNumFloatingReconBuffersInterDecluster,
    236 		    rf_GetNumSpareRUsInterDecluster, NULL,
    237 		    rf_SubmitReconBufferBasic,
    238 		    rf_VerifyParityBasic,
    239 		    1,
    240 		    DefaultStates,
    241 		    RF_DISTRIBUTE_SPARE)
    242 	},
    243 #endif				/* RF_INCLUDE_INTERDECLUSTER > 0 */
    244 
    245 #if RF_INCLUDE_RAID0 > 0
    246 	/* RAID level 0 */
    247 	{'0', "RAID Level 0",
    248 		RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    249 		RF_NU(
    250 		    rf_ConfigureRAID0,
    251 		    rf_MapSectorRAID0, rf_MapParityRAID0, NULL,
    252 		    rf_IdentifyStripeRAID0,
    253 		    rf_RAID0DagSelect,
    254 		    rf_MapSIDToPSIDRAID0,
    255 		    NULL,
    256 		    NULL,
    257 		    NULL, NULL,
    258 		    NULL,
    259 		    rf_VerifyParityRAID0,
    260 		    0,
    261 		    DefaultStates,
    262 		    0)
    263 	},
    264 #endif				/* RF_INCLUDE_RAID0 > 0 */
    265 
    266 #if RF_INCLUDE_RAID1 > 0
    267 	/* RAID level 1 */
    268 	{'1', "RAID Level 1",
    269 		RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    270 		RF_NU(
    271 		    rf_ConfigureRAID1,
    272 		    rf_MapSectorRAID1, rf_MapParityRAID1, NULL,
    273 		    rf_IdentifyStripeRAID1,
    274 		    rf_RAID1DagSelect,
    275 		    rf_MapSIDToPSIDRAID1,
    276 		    NULL,
    277 		    NULL,
    278 		    NULL, NULL,
    279 		    rf_SubmitReconBufferRAID1,
    280 		    rf_VerifyParityRAID1,
    281 		    1,
    282 		    DefaultStates,
    283 		    0)
    284 	},
    285 #endif				/* RF_INCLUDE_RAID1 > 0 */
    286 
    287 #if RF_INCLUDE_RAID4 > 0
    288 	/* RAID level 4 */
    289 	{'4', "RAID Level 4",
    290 		RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    291 		RF_NU(
    292 		    rf_ConfigureRAID4,
    293 		    rf_MapSectorRAID4, rf_MapParityRAID4, NULL,
    294 		    rf_IdentifyStripeRAID4,
    295 		    rf_RaidFiveDagSelect,
    296 		    rf_MapSIDToPSIDRAID4,
    297 		    rf_GetDefaultHeadSepLimitRAID4,
    298 		    rf_GetDefaultNumFloatingReconBuffersRAID4,
    299 		    NULL, NULL,
    300 		    rf_SubmitReconBufferBasic,
    301 		    rf_VerifyParityBasic,
    302 		    1,
    303 		    DefaultStates,
    304 		    0)
    305 	},
    306 #endif				/* RF_INCLUDE_RAID4 > 0 */
    307 
    308 #if RF_INCLUDE_RAID5 > 0
    309 	/* RAID level 5 */
    310 	{'5', "RAID Level 5",
    311 		RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    312 		RF_NU(
    313 		    rf_ConfigureRAID5,
    314 		    rf_MapSectorRAID5, rf_MapParityRAID5, NULL,
    315 		    rf_IdentifyStripeRAID5,
    316 		    rf_RaidFiveDagSelect,
    317 		    rf_MapSIDToPSIDRAID5,
    318 		    rf_GetDefaultHeadSepLimitRAID5,
    319 		    rf_GetDefaultNumFloatingReconBuffersRAID5,
    320 		    NULL, NULL,
    321 		    rf_SubmitReconBufferBasic,
    322 		    rf_VerifyParityBasic,
    323 		    1,
    324 		    DefaultStates,
    325 		    0)
    326 	},
    327 #endif				/* RF_INCLUDE_RAID5 > 0 */
    328 
    329 #if RF_INCLUDE_EVENODD > 0
    330 	/* Evenodd */
    331 	{'E', "EvenOdd",
    332 		RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    333 		RF_NU(
    334 		    rf_ConfigureEvenOdd,
    335 		    rf_MapSectorRAID5, rf_MapParityEvenOdd, rf_MapEEvenOdd,
    336 		    rf_IdentifyStripeEvenOdd,
    337 		    rf_EODagSelect,
    338 		    rf_MapSIDToPSIDRAID5,
    339 		    NULL,
    340 		    NULL,
    341 		    NULL, NULL,
    342 		    NULL,	/* no reconstruction, yet */
    343 		    rf_VerifyParityEvenOdd,
    344 		    2,
    345 		    DefaultStates,
    346 		    0)
    347 	},
    348 #endif				/* RF_INCLUDE_EVENODD > 0 */
    349 
    350 #if RF_INCLUDE_EVENODD > 0
    351 	/* Declustered Evenodd */
    352 	{'e', "Declustered EvenOdd",
    353 		RF_NK2(rf_MakeLayoutSpecificDeclustered, &distSpareNo)
    354 		RF_NU(
    355 		    rf_ConfigureDeclusteredPQ,
    356 		    rf_MapSectorDeclusteredPQ, rf_MapParityDeclusteredPQ, rf_MapQDeclusteredPQ,
    357 		    rf_IdentifyStripeDeclusteredPQ,
    358 		    rf_EODagSelect,
    359 		    rf_MapSIDToPSIDRAID5,
    360 		    rf_GetDefaultHeadSepLimitDeclustered,
    361 		    rf_GetDefaultNumFloatingReconBuffersPQ,
    362 		    NULL, NULL,
    363 		    NULL,	/* no reconstruction, yet */
    364 		    rf_VerifyParityEvenOdd,
    365 		    2,
    366 		    DefaultStates,
    367 		    0)
    368 	},
    369 #endif				/* RF_INCLUDE_EVENODD > 0 */
    370 
    371 #if RF_INCLUDE_PARITYLOGGING > 0
    372 	/* parity logging */
    373 	{'L', "Parity logging",
    374 		RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    375 		RF_NU(
    376 		    rf_ConfigureParityLogging,
    377 		    rf_MapSectorParityLogging, rf_MapParityParityLogging, NULL,
    378 		    rf_IdentifyStripeParityLogging,
    379 		    rf_ParityLoggingDagSelect,
    380 		    rf_MapSIDToPSIDParityLogging,
    381 		    rf_GetDefaultHeadSepLimitParityLogging,
    382 		    rf_GetDefaultNumFloatingReconBuffersParityLogging,
    383 		    NULL, NULL,
    384 		    rf_SubmitReconBufferBasic,
    385 		    NULL,
    386 		    1,
    387 		    DefaultStates,
    388 		    0)
    389 	},
    390 #endif				/* RF_INCLUDE_PARITYLOGGING > 0 */
    391 
    392 	/* end-of-list marker */
    393 	{'\0', NULL,
    394 		RF_NK2(NULL, NULL)
    395 		RF_NU(
    396 		    NULL,
    397 		    NULL, NULL, NULL,
    398 		    NULL,
    399 		    NULL,
    400 		    NULL,
    401 		    NULL,
    402 		    NULL,
    403 		    NULL, NULL,
    404 		    NULL,
    405 		    NULL,
    406 		    0,
    407 		    NULL,
    408 		    0)
    409 	}
    410 };
    411 
    412 RF_LayoutSW_t *
    413 rf_GetLayout(RF_ParityConfig_t parityConfig)
    414 {
    415 	RF_LayoutSW_t *p;
    416 
    417 	/* look up the specific layout */
    418 	for (p = &mapsw[0]; p->parityConfig; p++)
    419 		if (p->parityConfig == parityConfig)
    420 			break;
    421 	if (!p->parityConfig)
    422 		return (NULL);
    423 	RF_ASSERT(p->parityConfig == parityConfig);
    424 	return (p);
    425 }
    426 #if RF_UTILITY == 0
    427 /*****************************************************************************************
    428  *
    429  * ConfigureLayout --
    430  *
    431  * read the configuration file and set up the RAID layout parameters.  After reading
    432  * common params, invokes the layout-specific configuration routine to finish
    433  * the configuration.
    434  *
    435  ****************************************************************************************/
    436 int
    437 rf_ConfigureLayout(
    438     RF_ShutdownList_t ** listp,
    439     RF_Raid_t * raidPtr,
    440     RF_Config_t * cfgPtr)
    441 {
    442 	RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
    443 	RF_ParityConfig_t parityConfig;
    444 	RF_LayoutSW_t *p;
    445 	int     retval;
    446 
    447 	layoutPtr->sectorsPerStripeUnit = cfgPtr->sectPerSU;
    448 	layoutPtr->SUsPerPU = cfgPtr->SUsPerPU;
    449 	layoutPtr->SUsPerRU = cfgPtr->SUsPerRU;
    450 	parityConfig = cfgPtr->parityConfig;
    451 
    452 	if (layoutPtr->sectorsPerStripeUnit <= 0) {
    453 		RF_ERRORMSG2("raid%d: Invalid sectorsPerStripeUnit: %d\n",
    454 			     raidPtr->raidid,
    455 			     (int)layoutPtr->sectorsPerStripeUnit );
    456 		return (EINVAL);
    457 	}
    458 
    459 	layoutPtr->stripeUnitsPerDisk = raidPtr->sectorsPerDisk / layoutPtr->sectorsPerStripeUnit;
    460 
    461 	p = rf_GetLayout(parityConfig);
    462 	if (p == NULL) {
    463 		RF_ERRORMSG1("Unknown parity configuration '%c'", parityConfig);
    464 		return (EINVAL);
    465 	}
    466 	RF_ASSERT(p->parityConfig == parityConfig);
    467 	layoutPtr->map = p;
    468 
    469 	/* initialize the specific layout */
    470 
    471 	retval = (p->Configure) (listp, raidPtr, cfgPtr);
    472 
    473 	if (retval)
    474 		return (retval);
    475 
    476 	layoutPtr->dataBytesPerStripe = layoutPtr->dataSectorsPerStripe << raidPtr->logBytesPerSector;
    477 	raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
    478 
    479 	if (rf_forceNumFloatingReconBufs >= 0) {
    480 		raidPtr->numFloatingReconBufs = rf_forceNumFloatingReconBufs;
    481 	} else {
    482 		raidPtr->numFloatingReconBufs = rf_GetDefaultNumFloatingReconBuffers(raidPtr);
    483 	}
    484 
    485 	if (rf_forceHeadSepLimit >= 0) {
    486 		raidPtr->headSepLimit = rf_forceHeadSepLimit;
    487 	} else {
    488 		raidPtr->headSepLimit = rf_GetDefaultHeadSepLimit(raidPtr);
    489 	}
    490 
    491 	printf("RAIDFRAME: Configure (%s): total number of sectors is %lu (%lu MB)\n",
    492 	    layoutPtr->map->configName,
    493 	    (unsigned long) raidPtr->totalSectors,
    494 	    (unsigned long) (raidPtr->totalSectors / 1024 * (1 << raidPtr->logBytesPerSector) / 1024));
    495 	if (raidPtr->headSepLimit >= 0) {
    496 		printf("RAIDFRAME(%s): Using %ld floating recon bufs with head sep limit %ld\n",
    497 		    layoutPtr->map->configName, (long) raidPtr->numFloatingReconBufs, (long) raidPtr->headSepLimit);
    498 	} else {
    499 		printf("RAIDFRAME(%s): Using %ld floating recon bufs with no head sep limit\n",
    500 		    layoutPtr->map->configName, (long) raidPtr->numFloatingReconBufs);
    501 	}
    502 
    503 	return (0);
    504 }
    505 /* typically there is a 1-1 mapping between stripes and parity stripes.
    506  * however, the declustering code supports packing multiple stripes into
    507  * a single parity stripe, so as to increase the size of the reconstruction
    508  * unit without affecting the size of the stripe unit.  This routine finds
    509  * the parity stripe identifier associated with a stripe ID.  There is also
    510  * a RaidAddressToParityStripeID macro in layout.h
    511  */
    512 RF_StripeNum_t
    513 rf_MapStripeIDToParityStripeID(layoutPtr, stripeID, which_ru)
    514 	RF_RaidLayout_t *layoutPtr;
    515 	RF_StripeNum_t stripeID;
    516 	RF_ReconUnitNum_t *which_ru;
    517 {
    518 	RF_StripeNum_t parityStripeID;
    519 
    520 	/* quick exit in the common case of SUsPerPU==1 */
    521 	if ((layoutPtr->SUsPerPU == 1) || !layoutPtr->map->MapSIDToPSID) {
    522 		*which_ru = 0;
    523 		return (stripeID);
    524 	} else {
    525 		(layoutPtr->map->MapSIDToPSID) (layoutPtr, stripeID, &parityStripeID, which_ru);
    526 	}
    527 	return (parityStripeID);
    528 }
    529 #endif				/* RF_UTILITY == 0 */
    530