xref: /netbsd-src/sys/dev/raidframe/rf_layout.c (revision dc306354b0b29af51801a7632f1e95265a68cd81)
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@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