Home | History | Annotate | Line # | Download | only in raidframe
rf_layout.c revision 1.1
      1 /*	$NetBSD: rf_layout.c,v 1.1 1998/11/13 04:20:30 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 /*
     33  * :
     34  * Log: rf_layout.c,v
     35  * Revision 1.71  1996/08/20 22:41:30  jimz
     36  * add declustered evenodd
     37  *
     38  * Revision 1.70  1996/07/31  16:56:18  jimz
     39  * dataBytesPerStripe, sectorsPerDisk init arch-indep.
     40  *
     41  * Revision 1.69  1996/07/31  15:34:46  jimz
     42  * add EvenOdd
     43  *
     44  * Revision 1.68  1996/07/29  14:05:12  jimz
     45  * fix numPUs/numRUs confusion (everything is now numRUs)
     46  * clean up some commenting, return values
     47  *
     48  * Revision 1.67  1996/07/27  23:36:08  jimz
     49  * Solaris port of simulator
     50  *
     51  * Revision 1.66  1996/07/27  18:40:24  jimz
     52  * cleanup sweep
     53  *
     54  * Revision 1.65  1996/07/18  22:57:14  jimz
     55  * port simulator to AIX
     56  *
     57  * Revision 1.64  1996/07/15  17:22:18  jimz
     58  * nit-pick code cleanup
     59  * resolve stdlib problems on DEC OSF
     60  *
     61  * Revision 1.63  1996/07/13  00:00:59  jimz
     62  * sanitized generalized reconstruction architecture
     63  * cleaned up head sep, rbuf problems
     64  *
     65  * Revision 1.62  1996/07/11  19:08:00  jimz
     66  * generalize reconstruction mechanism
     67  * allow raid1 reconstructs via copyback (done with array
     68  * quiesced, not online, therefore not disk-directed)
     69  *
     70  * Revision 1.61  1996/06/19  22:23:01  jimz
     71  * parity verification is now a layout-configurable thing
     72  * not all layouts currently support it (correctly, anyway)
     73  *
     74  * Revision 1.60  1996/06/19  17:53:48  jimz
     75  * move GetNumSparePUs, InstallSpareTable ops into layout switch
     76  *
     77  * Revision 1.59  1996/06/19  14:57:58  jimz
     78  * move layout-specific config parsing hooks into RF_LayoutSW_t
     79  * table in rf_layout.c
     80  *
     81  * Revision 1.58  1996/06/10  11:55:47  jimz
     82  * Straightened out some per-array/not-per-array distinctions, fixed
     83  * a couple bugs related to confusion. Added shutdown lists. Removed
     84  * layout shutdown function (now subsumed by shutdown lists).
     85  *
     86  * Revision 1.57  1996/06/07  22:26:27  jimz
     87  * type-ify which_ru (RF_ReconUnitNum_t)
     88  *
     89  * Revision 1.56  1996/06/07  21:33:04  jimz
     90  * begin using consistent types for sector numbers,
     91  * stripe numbers, row+col numbers, recon unit numbers
     92  *
     93  * Revision 1.55  1996/06/06  18:41:35  jimz
     94  * change interleaved declustering dag selection to an
     95  * interleaved-declustering-specific routine (so we can
     96  * use the partitioned mirror node)
     97  *
     98  * Revision 1.54  1996/06/05  18:06:02  jimz
     99  * Major code cleanup. The Great Renaming is now done.
    100  * Better modularity. Better typing. Fixed a bunch of
    101  * synchronization bugs. Made a lot of global stuff
    102  * per-desc or per-array. Removed dead code.
    103  *
    104  * Revision 1.53  1996/06/03  23:28:26  jimz
    105  * more bugfixes
    106  * check in tree to sync for IPDS runs with current bugfixes
    107  * there still may be a problem with threads in the script test
    108  * getting I/Os stuck- not trivially reproducible (runs ~50 times
    109  * in a row without getting stuck)
    110  *
    111  * Revision 1.52  1996/06/02  17:31:48  jimz
    112  * Moved a lot of global stuff into array structure, where it belongs.
    113  * Fixed up paritylogging, pss modules in this manner. Some general
    114  * code cleanup. Removed lots of dead code, some dead files.
    115  *
    116  * Revision 1.51  1996/05/31  22:26:54  jimz
    117  * fix a lot of mapping problems, memory allocation problems
    118  * found some weird lock issues, fixed 'em
    119  * more code cleanup
    120  *
    121  * Revision 1.50  1996/05/30  23:22:16  jimz
    122  * bugfixes of serialization, timing problems
    123  * more cleanup
    124  *
    125  * Revision 1.49  1996/05/30  11:29:41  jimz
    126  * Numerous bug fixes. Stripe lock release code disagreed with the taking code
    127  * about when stripes should be locked (I made it consistent: no parity, no lock)
    128  * There was a lot of extra serialization of I/Os which I've removed- a lot of
    129  * it was to calculate values for the cache code, which is no longer with us.
    130  * More types, function, macro cleanup. Added code to properly quiesce the array
    131  * on shutdown. Made a lot of stuff array-specific which was (bogusly) general
    132  * before. Fixed memory allocation, freeing bugs.
    133  *
    134  * Revision 1.48  1996/05/27  18:56:37  jimz
    135  * more code cleanup
    136  * better typing
    137  * compiles in all 3 environments
    138  *
    139  * Revision 1.47  1996/05/24  22:17:04  jimz
    140  * continue code + namespace cleanup
    141  * typed a bunch of flags
    142  *
    143  * Revision 1.46  1996/05/24  01:59:45  jimz
    144  * another checkpoint in code cleanup for release
    145  * time to sync kernel tree
    146  *
    147  * Revision 1.45  1996/05/23  21:46:35  jimz
    148  * checkpoint in code cleanup (release prep)
    149  * lots of types, function names have been fixed
    150  *
    151  * Revision 1.44  1996/05/18  19:51:34  jimz
    152  * major code cleanup- fix syntax, make some types consistent,
    153  * add prototypes, clean out dead code, et cetera
    154  *
    155  * Revision 1.43  1996/02/22  16:46:35  amiri
    156  * modified chained declustering to use a seperate DAG selection routine
    157  *
    158  * Revision 1.42  1995/12/01  19:16:11  root
    159  * added copyright info
    160  *
    161  * Revision 1.41  1995/11/28  21:31:02  amiri
    162  * added Interleaved Declustering to switch table
    163  *
    164  * Revision 1.40  1995/11/20  14:35:17  arw
    165  * moved rf_StartThroughputStats in DefaultWrite and DefaultRead
    166  *
    167  * Revision 1.39  1995/11/19  16:28:46  wvcii
    168  * replaced LaunchDAGState with CreateDAGState, ExecuteDAGState
    169  *
    170  * Revision 1.38  1995/11/17  19:00:41  wvcii
    171  * added MapQ entries to switch table
    172  *
    173  * Revision 1.37  1995/11/17  16:58:13  amiri
    174  * Added the Chained Declustering architecture ('C'),
    175  * essentially a variant of mirroring.
    176  *
    177  * Revision 1.36  1995/11/16  16:16:10  amiri
    178  * Added RAID5 with rotated sparing ('R' configuration)
    179  *
    180  * Revision 1.35  1995/11/07  15:41:17  wvcii
    181  * modified state lists: DefaultStates, VSReadStates
    182  * necessary to support new states (LaunchDAGState, ProcessDAGState)
    183  *
    184  * Revision 1.34  1995/10/18  01:23:20  amiri
    185  * added ifndef SIMULATE wrapper around rf_StartThroughputStats()
    186  *
    187  * Revision 1.33  1995/10/13  15:05:46  arw
    188  * added rf_StartThroughputStats to DefaultRead and DefaultWrite
    189  *
    190  * Revision 1.32  1995/10/12  16:04:23  jimz
    191  * added config names to mapsw entires
    192  *
    193  * Revision 1.31  1995/10/04  03:57:48  wvcii
    194  * added raid level 1 to mapsw
    195  *
    196  * Revision 1.30  1995/09/07  01:26:55  jimz
    197  * Achive basic compilation in kernel. Kernel functionality
    198  * is not guaranteed at all, but it'll compile. Mostly. I hope.
    199  *
    200  * Revision 1.29  1995/07/28  21:43:42  robby
    201  * checkin after leaving for Rice. Bye
    202  *
    203  * Revision 1.28  1995/07/26  03:26:14  robby
    204  * *** empty log message ***
    205  *
    206  * Revision 1.27  1995/07/21  19:47:52  rachad
    207  * Added raid 0 /5 with caching architectures
    208  *
    209  * Revision 1.26  1995/07/21  19:29:27  robby
    210  * added virtual striping states
    211  *
    212  * Revision 1.25  1995/07/10  21:41:47  robby
    213  * switched to have my own virtual stripng write function from the cache
    214  *
    215  * Revision 1.24  1995/07/10  20:51:59  robby
    216  * added virtual striping states
    217  *
    218  * Revision 1.23  1995/07/10  16:57:42  robby
    219  * updated alloclistelem struct to the correct struct name
    220  *
    221  * Revision 1.22  1995/07/08  20:06:11  rachad
    222  * *** empty log message ***
    223  *
    224  * Revision 1.21  1995/07/08  19:43:16  cfb
    225  * *** empty log message ***
    226  *
    227  * Revision 1.20  1995/07/08  18:05:39  rachad
    228  * Linked up Claudsons code with the real cache
    229  *
    230  * Revision 1.19  1995/07/06  14:29:36  robby
    231  * added defaults states list to the layout switch
    232  *
    233  * Revision 1.18  1995/06/23  13:40:34  robby
    234  * updeated to prototypes in rf_layout.h
    235  *
    236  */
    237 
    238 #include "rf_types.h"
    239 #include "rf_archs.h"
    240 #include "rf_raid.h"
    241 #include "rf_configure.h"
    242 #include "rf_dag.h"
    243 #include "rf_desc.h"
    244 #include "rf_decluster.h"
    245 #include "rf_pq.h"
    246 #include "rf_declusterPQ.h"
    247 #include "rf_raid0.h"
    248 #include "rf_raid1.h"
    249 #include "rf_raid4.h"
    250 #include "rf_raid5.h"
    251 #include "rf_states.h"
    252 #if RF_INCLUDE_RAID5_RS > 0
    253 #include "rf_raid5_rotatedspare.h"
    254 #endif /* RF_INCLUDE_RAID5_RS > 0 */
    255 #if RF_INCLUDE_CHAINDECLUSTER > 0
    256 #include "rf_chaindecluster.h"
    257 #endif /* RF_INCLUDE_CHAINDECLUSTER > 0 */
    258 #if RF_INCLUDE_INTERDECLUSTER > 0
    259 #include "rf_interdecluster.h"
    260 #endif /* RF_INCLUDE_INTERDECLUSTER > 0 */
    261 #if RF_INCLUDE_PARITYLOGGING > 0
    262 #include "rf_paritylogging.h"
    263 #endif /* RF_INCLUDE_PARITYLOGGING > 0 */
    264 #if RF_INCLUDE_EVENODD > 0
    265 #include "rf_evenodd.h"
    266 #endif /* RF_INCLUDE_EVENODD > 0 */
    267 #include "rf_general.h"
    268 #include "rf_driver.h"
    269 #include "rf_parityscan.h"
    270 #include "rf_reconbuffer.h"
    271 #include "rf_reconutil.h"
    272 
    273 /***********************************************************************
    274  *
    275  * the layout switch defines all the layouts that are supported.
    276  *    fields are: layout ID, init routine, shutdown routine, map
    277  *    sector, map parity, identify stripe, dag selection, map stripeid
    278  *    to parity stripe id (optional), num faults tolerated, special
    279  *    flags.
    280  *
    281  ***********************************************************************/
    282 
    283 static RF_AccessState_t DefaultStates[] = {rf_QuiesceState,
    284 	rf_IncrAccessesCountState, rf_MapState, rf_LockState, rf_CreateDAGState,
    285 	rf_ExecuteDAGState, rf_ProcessDAGState, rf_DecrAccessesCountState,
    286 	rf_CleanupState, rf_LastState};
    287 
    288 #if defined(__NetBSD__) && !defined(_KERNEL)
    289 /* XXX Gross hack to shutup gcc -- it complains that DefaultStates is not
    290 used when compiling this in userland..  I hate to burst it's bubble, but
    291 DefaultStates is used all over the place here in the initialization of
    292 lots of data structures.  GO */
    293 RF_AccessState_t *NothingAtAll = DefaultStates;
    294 #endif
    295 
    296 #if defined(__NetBSD__) && defined(_KERNEL)
    297 /* XXX Remove static so GCC doesn't complain about these being unused! */
    298 int distSpareYes = 1;
    299 int distSpareNo  = 0;
    300 #else
    301 static int distSpareYes = 1;
    302 static int distSpareNo  = 0;
    303 #endif
    304 #ifdef KERNEL
    305 #define RF_NK2(a,b)
    306 #else /* KERNEL */
    307 #define RF_NK2(a,b) a,b,
    308 #endif /* KERNEL */
    309 
    310 #if RF_UTILITY > 0
    311 #define RF_NU(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)
    312 #else /* RF_UTILITY > 0 */
    313 #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
    314 #endif /* RF_UTILITY > 0 */
    315 
    316 static RF_LayoutSW_t mapsw[] = {
    317 	/* parity declustering */
    318 	{'T', "Parity declustering",
    319 	RF_NK2(rf_MakeLayoutSpecificDeclustered, &distSpareNo)
    320 	RF_NU(
    321 	rf_ConfigureDeclustered,
    322 	rf_MapSectorDeclustered, rf_MapParityDeclustered, NULL,
    323 	rf_IdentifyStripeDeclustered,
    324 	rf_RaidFiveDagSelect,
    325 	rf_MapSIDToPSIDDeclustered,
    326 	rf_GetDefaultHeadSepLimitDeclustered,
    327 	rf_GetDefaultNumFloatingReconBuffersDeclustered,
    328 	NULL, NULL,
    329 	rf_SubmitReconBufferBasic,
    330 	rf_VerifyParityBasic,
    331 	1,
    332 	DefaultStates,
    333 	0)
    334 	},
    335 
    336 	/* parity declustering with distributed sparing */
    337 	{'D', "Distributed sparing parity declustering",
    338 	RF_NK2(rf_MakeLayoutSpecificDeclustered, &distSpareYes)
    339 	RF_NU(
    340 	rf_ConfigureDeclusteredDS,
    341 	rf_MapSectorDeclustered, rf_MapParityDeclustered, NULL,
    342 	rf_IdentifyStripeDeclustered,
    343 	rf_RaidFiveDagSelect,
    344 	rf_MapSIDToPSIDDeclustered,
    345 	rf_GetDefaultHeadSepLimitDeclustered,
    346 	rf_GetDefaultNumFloatingReconBuffersDeclustered,
    347 	rf_GetNumSpareRUsDeclustered, rf_InstallSpareTable,
    348 	rf_SubmitReconBufferBasic,
    349 	rf_VerifyParityBasic,
    350 	1,
    351 	DefaultStates,
    352 	RF_DISTRIBUTE_SPARE|RF_BD_DECLUSTERED)
    353 	},
    354 
    355 #if RF_INCLUDE_DECL_PQ > 0
    356 	/* declustered P+Q */
    357 	{'Q', "Declustered P+Q",
    358 	RF_NK2(rf_MakeLayoutSpecificDeclustered, &distSpareNo)
    359 	RF_NU(
    360 	rf_ConfigureDeclusteredPQ,
    361 	rf_MapSectorDeclusteredPQ, rf_MapParityDeclusteredPQ, rf_MapQDeclusteredPQ,
    362 	rf_IdentifyStripeDeclusteredPQ,
    363 	rf_PQDagSelect,
    364 	rf_MapSIDToPSIDDeclustered,
    365 	rf_GetDefaultHeadSepLimitDeclustered,
    366 	rf_GetDefaultNumFloatingReconBuffersPQ,
    367 	NULL, NULL,
    368 	NULL,
    369 	rf_VerifyParityBasic,
    370 	2,
    371 	DefaultStates,
    372 	0)
    373 	},
    374 #endif /* RF_INCLUDE_DECL_PQ > 0 */
    375 
    376 #if RF_INCLUDE_RAID5_RS > 0
    377 	/* RAID 5 with rotated sparing */
    378 	{'R', "RAID Level 5 rotated sparing",
    379 	RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    380 	RF_NU(
    381 	rf_ConfigureRAID5_RS,
    382 	rf_MapSectorRAID5_RS, rf_MapParityRAID5_RS, NULL,
    383 	rf_IdentifyStripeRAID5_RS,
    384 	rf_RaidFiveDagSelect,
    385 	rf_MapSIDToPSIDRAID5_RS,
    386 	rf_GetDefaultHeadSepLimitRAID5,
    387 	rf_GetDefaultNumFloatingReconBuffersRAID5,
    388 	rf_GetNumSpareRUsRAID5_RS, NULL,
    389 	rf_SubmitReconBufferBasic,
    390 	rf_VerifyParityBasic,
    391 	1,
    392 	DefaultStates,
    393 	RF_DISTRIBUTE_SPARE)
    394 	},
    395 #endif /* RF_INCLUDE_RAID5_RS > 0 */
    396 
    397 #if RF_INCLUDE_CHAINDECLUSTER > 0
    398 	/* Chained Declustering */
    399 	{'C', "Chained Declustering",
    400 	RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    401 	RF_NU(
    402 	rf_ConfigureChainDecluster,
    403 	rf_MapSectorChainDecluster, rf_MapParityChainDecluster, NULL,
    404 	rf_IdentifyStripeChainDecluster,
    405 	rf_RAIDCDagSelect,
    406 	rf_MapSIDToPSIDChainDecluster,
    407 	NULL,
    408 	NULL,
    409 	rf_GetNumSpareRUsChainDecluster, NULL,
    410 	rf_SubmitReconBufferBasic,
    411 	rf_VerifyParityBasic,
    412 	1,
    413 	DefaultStates,
    414 	0)
    415 	},
    416 #endif /* RF_INCLUDE_CHAINDECLUSTER > 0 */
    417 
    418 #if RF_INCLUDE_INTERDECLUSTER > 0
    419 	/* Interleaved Declustering */
    420 	{'I', "Interleaved Declustering",
    421 	RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    422 	RF_NU(
    423 	rf_ConfigureInterDecluster,
    424 	rf_MapSectorInterDecluster, rf_MapParityInterDecluster, NULL,
    425 	rf_IdentifyStripeInterDecluster,
    426 	rf_RAIDIDagSelect,
    427 	rf_MapSIDToPSIDInterDecluster,
    428 	rf_GetDefaultHeadSepLimitInterDecluster,
    429 	rf_GetDefaultNumFloatingReconBuffersInterDecluster,
    430 	rf_GetNumSpareRUsInterDecluster, NULL,
    431 	rf_SubmitReconBufferBasic,
    432 	rf_VerifyParityBasic,
    433 	1,
    434 	DefaultStates,
    435 	RF_DISTRIBUTE_SPARE)
    436 	},
    437 #endif /* RF_INCLUDE_INTERDECLUSTER > 0 */
    438 
    439 #if RF_INCLUDE_RAID0 > 0
    440 	/* RAID level 0 */
    441 	{'0', "RAID Level 0",
    442 	RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    443 	RF_NU(
    444 	rf_ConfigureRAID0,
    445 	rf_MapSectorRAID0, rf_MapParityRAID0, NULL,
    446 	rf_IdentifyStripeRAID0,
    447 	rf_RAID0DagSelect,
    448 	rf_MapSIDToPSIDRAID0,
    449 	NULL,
    450 	NULL,
    451 	NULL, NULL,
    452 	NULL,
    453 	rf_VerifyParityRAID0,
    454 	0,
    455 	DefaultStates,
    456 	0)
    457 	},
    458 #endif /* RF_INCLUDE_RAID0 > 0 */
    459 
    460 #if RF_INCLUDE_RAID1 > 0
    461 	/* RAID level 1 */
    462 	{'1', "RAID Level 1",
    463 	RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    464 	RF_NU(
    465 	rf_ConfigureRAID1,
    466 	rf_MapSectorRAID1, rf_MapParityRAID1, NULL,
    467 	rf_IdentifyStripeRAID1,
    468 	rf_RAID1DagSelect,
    469 	rf_MapSIDToPSIDRAID1,
    470 	NULL,
    471 	NULL,
    472 	NULL, NULL,
    473 	rf_SubmitReconBufferRAID1,
    474 	rf_VerifyParityRAID1,
    475 	1,
    476 	DefaultStates,
    477 	0)
    478 	},
    479 #endif /* RF_INCLUDE_RAID1 > 0 */
    480 
    481 #if RF_INCLUDE_RAID4 > 0
    482 	/* RAID level 4 */
    483 	{'4', "RAID Level 4",
    484 	RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    485 	RF_NU(
    486 	rf_ConfigureRAID4,
    487 	rf_MapSectorRAID4, rf_MapParityRAID4, NULL,
    488 	rf_IdentifyStripeRAID4,
    489 	rf_RaidFiveDagSelect,
    490 	rf_MapSIDToPSIDRAID4,
    491 	rf_GetDefaultHeadSepLimitRAID4,
    492 	rf_GetDefaultNumFloatingReconBuffersRAID4,
    493 	NULL, NULL,
    494 	rf_SubmitReconBufferBasic,
    495 	rf_VerifyParityBasic,
    496 	1,
    497 	DefaultStates,
    498 	0)
    499 	},
    500 #endif /* RF_INCLUDE_RAID4 > 0 */
    501 
    502 #if RF_INCLUDE_RAID5 > 0
    503 	/* RAID level 5 */
    504 	{'5', "RAID Level 5",
    505 	RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    506 	RF_NU(
    507 	rf_ConfigureRAID5,
    508 	rf_MapSectorRAID5, rf_MapParityRAID5, NULL,
    509 	rf_IdentifyStripeRAID5,
    510 	rf_RaidFiveDagSelect,
    511 	rf_MapSIDToPSIDRAID5,
    512 	rf_GetDefaultHeadSepLimitRAID5,
    513 	rf_GetDefaultNumFloatingReconBuffersRAID5,
    514 	NULL, NULL,
    515 	rf_SubmitReconBufferBasic,
    516 	rf_VerifyParityBasic,
    517 	1,
    518 	DefaultStates,
    519 	0)
    520 	},
    521 #endif /* RF_INCLUDE_RAID5 > 0 */
    522 
    523 #if RF_INCLUDE_EVENODD > 0
    524 	/* Evenodd */
    525 	{'E', "EvenOdd",
    526 	RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    527 	RF_NU(
    528 	rf_ConfigureEvenOdd,
    529 	rf_MapSectorRAID5, rf_MapParityEvenOdd, rf_MapEEvenOdd,
    530 	rf_IdentifyStripeEvenOdd,
    531 	rf_EODagSelect,
    532 	rf_MapSIDToPSIDRAID5,
    533 	NULL,
    534 	NULL,
    535 	NULL, NULL,
    536 	NULL, /* no reconstruction, yet */
    537 	rf_VerifyParityEvenOdd,
    538 	2,
    539 	DefaultStates,
    540 	0)
    541 	},
    542 #endif /* RF_INCLUDE_EVENODD > 0 */
    543 
    544 #if RF_INCLUDE_EVENODD > 0
    545 	/* Declustered Evenodd */
    546 	{'e', "Declustered EvenOdd",
    547 	RF_NK2(rf_MakeLayoutSpecificDeclustered, &distSpareNo)
    548 	RF_NU(
    549 	rf_ConfigureDeclusteredPQ,
    550 	rf_MapSectorDeclusteredPQ, rf_MapParityDeclusteredPQ, rf_MapQDeclusteredPQ,
    551 	rf_IdentifyStripeDeclusteredPQ,
    552 	rf_EODagSelect,
    553 	rf_MapSIDToPSIDRAID5,
    554 	rf_GetDefaultHeadSepLimitDeclustered,
    555 	rf_GetDefaultNumFloatingReconBuffersPQ,
    556 	NULL, NULL,
    557 	NULL, /* no reconstruction, yet */
    558 	rf_VerifyParityEvenOdd,
    559 	2,
    560 	DefaultStates,
    561 	0)
    562 	},
    563 #endif /* RF_INCLUDE_EVENODD > 0 */
    564 
    565 #if RF_INCLUDE_PARITYLOGGING > 0
    566 	/* parity logging */
    567 	{'L', "Parity logging",
    568 	RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
    569 	RF_NU(
    570 	rf_ConfigureParityLogging,
    571 	rf_MapSectorParityLogging, rf_MapParityParityLogging, NULL,
    572 	rf_IdentifyStripeParityLogging,
    573 	rf_ParityLoggingDagSelect,
    574 	rf_MapSIDToPSIDParityLogging,
    575 	rf_GetDefaultHeadSepLimitParityLogging,
    576 	rf_GetDefaultNumFloatingReconBuffersParityLogging,
    577 	NULL, NULL,
    578 	rf_SubmitReconBufferBasic,
    579 	NULL,
    580 	1,
    581 	DefaultStates,
    582 	0)
    583 	},
    584 #endif /* RF_INCLUDE_PARITYLOGGING > 0 */
    585 
    586 	/* end-of-list marker */
    587 	{ '\0', NULL,
    588 	RF_NK2(NULL, NULL)
    589 	RF_NU(
    590 	NULL,
    591 	NULL, NULL, NULL,
    592 	NULL,
    593 	NULL,
    594 	NULL,
    595 	NULL,
    596 	NULL,
    597 	NULL, NULL,
    598 	NULL,
    599 	NULL,
    600 	0,
    601 	NULL,
    602 	0)
    603 	}
    604 };
    605 
    606 RF_LayoutSW_t *rf_GetLayout(RF_ParityConfig_t parityConfig)
    607 {
    608   RF_LayoutSW_t *p;
    609 
    610   /* look up the specific layout */
    611   for (p=&mapsw[0]; p->parityConfig; p++)
    612     if (p->parityConfig == parityConfig)
    613       break;
    614   if (!p->parityConfig)
    615     return(NULL);
    616   RF_ASSERT(p->parityConfig == parityConfig);
    617   return(p);
    618 }
    619 
    620 #if RF_UTILITY == 0
    621 /*****************************************************************************************
    622  *
    623  * ConfigureLayout --
    624  *
    625  * read the configuration file and set up the RAID layout parameters.  After reading
    626  * common params, invokes the layout-specific configuration routine to finish
    627  * the configuration.
    628  *
    629  ****************************************************************************************/
    630 int rf_ConfigureLayout(
    631   RF_ShutdownList_t  **listp,
    632   RF_Raid_t           *raidPtr,
    633   RF_Config_t         *cfgPtr)
    634 {
    635   RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
    636   RF_ParityConfig_t parityConfig;
    637   RF_LayoutSW_t *p;
    638   int retval;
    639 
    640   layoutPtr->sectorsPerStripeUnit = cfgPtr->sectPerSU;
    641   layoutPtr->SUsPerPU             = cfgPtr->SUsPerPU;
    642   layoutPtr->SUsPerRU             = cfgPtr->SUsPerRU;
    643   parityConfig                    = cfgPtr->parityConfig;
    644 
    645   layoutPtr->stripeUnitsPerDisk = raidPtr->sectorsPerDisk / layoutPtr->sectorsPerStripeUnit;
    646 
    647   p = rf_GetLayout(parityConfig);
    648   if (p == NULL) {
    649     RF_ERRORMSG1("Unknown parity configuration '%c'", parityConfig);
    650     return(EINVAL);
    651   }
    652   RF_ASSERT(p->parityConfig == parityConfig);
    653   layoutPtr->map = p;
    654 
    655   /* initialize the specific layout */
    656 
    657   retval = (p->Configure)(listp, raidPtr, cfgPtr);
    658 
    659   if (retval)
    660     return(retval);
    661 
    662   layoutPtr->dataBytesPerStripe = layoutPtr->dataSectorsPerStripe << raidPtr->logBytesPerSector;
    663   raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
    664 
    665   if (rf_forceNumFloatingReconBufs >= 0) {
    666     raidPtr->numFloatingReconBufs = rf_forceNumFloatingReconBufs;
    667   }
    668   else {
    669     raidPtr->numFloatingReconBufs = rf_GetDefaultNumFloatingReconBuffers(raidPtr);
    670   }
    671 
    672   if (rf_forceHeadSepLimit >= 0) {
    673     raidPtr->headSepLimit = rf_forceHeadSepLimit;
    674   }
    675   else {
    676     raidPtr->headSepLimit = rf_GetDefaultHeadSepLimit(raidPtr);
    677   }
    678 
    679   printf("RAIDFRAME: Configure (%s): total number of sectors is %lu (%lu MB)\n",
    680      layoutPtr->map->configName,
    681      (unsigned long)raidPtr->totalSectors,
    682      (unsigned long)(raidPtr->totalSectors / 1024 * (1<<raidPtr->logBytesPerSector) / 1024));
    683   if (raidPtr->headSepLimit >= 0) {
    684     printf("RAIDFRAME(%s): Using %ld floating recon bufs with head sep limit %ld\n",
    685       layoutPtr->map->configName, (long)raidPtr->numFloatingReconBufs, (long)raidPtr->headSepLimit);
    686   }
    687   else {
    688     printf("RAIDFRAME(%s): Using %ld floating recon bufs with no head sep limit\n",
    689       layoutPtr->map->configName, (long)raidPtr->numFloatingReconBufs);
    690   }
    691 
    692   return(0);
    693 }
    694 
    695 /* typically there is a 1-1 mapping between stripes and parity stripes.
    696  * however, the declustering code supports packing multiple stripes into
    697  * a single parity stripe, so as to increase the size of the reconstruction
    698  * unit without affecting the size of the stripe unit.  This routine finds
    699  * the parity stripe identifier associated with a stripe ID.  There is also
    700  * a RaidAddressToParityStripeID macro in layout.h
    701  */
    702 RF_StripeNum_t rf_MapStripeIDToParityStripeID(layoutPtr, stripeID, which_ru)
    703   RF_RaidLayout_t    *layoutPtr;
    704   RF_StripeNum_t      stripeID;
    705   RF_ReconUnitNum_t  *which_ru;
    706 {
    707   RF_StripeNum_t parityStripeID;
    708 
    709   /* quick exit in the common case of SUsPerPU==1 */
    710   if ((layoutPtr->SUsPerPU == 1) || !layoutPtr->map->MapSIDToPSID) {
    711     *which_ru = 0;
    712     return(stripeID);
    713   }
    714   else {
    715     (layoutPtr->map->MapSIDToPSID)(layoutPtr, stripeID, &parityStripeID, which_ru);
    716   }
    717   return(parityStripeID);
    718 }
    719 #endif /* RF_UTILITY == 0 */
    720