1 /* $NetBSD: rf_layout.c,v 1.19 2008/04/20 20:42:32 oster Exp $ */
3 * Copyright (c) 1995 Carnegie-Mellon University.
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.
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.
18 * Carnegie Mellon requests users of this software to return to
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
29 /* rf_layout.c -- driver code dealing with layout and mapping issues
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: rf_layout.c,v 1.19 2008/04/20 20:42:32 oster Exp $");
35 #include <dev/raidframe/raidframevar.h>
41 #include "rf_decluster.h"
43 #include "rf_declusterPQ.h"
48 #include "rf_states.h"
49 #if RF_INCLUDE_RAID5_RS > 0
50 #include "rf_raid5_rotatedspare.h"
51 #endif /* RF_INCLUDE_RAID5_RS > 0 */
52 #if RF_INCLUDE_CHAINDECLUSTER > 0
53 #include "rf_chaindecluster.h"
54 #endif /* RF_INCLUDE_CHAINDECLUSTER > 0 */
55 #if RF_INCLUDE_INTERDECLUSTER > 0
56 #include "rf_interdecluster.h"
57 #endif /* RF_INCLUDE_INTERDECLUSTER > 0 */
58 #if RF_INCLUDE_PARITYLOGGING > 0
59 #include "rf_paritylogging.h"
60 #endif /* RF_INCLUDE_PARITYLOGGING > 0 */
61 #if RF_INCLUDE_EVENODD > 0
62 #include "rf_evenodd.h"
63 #endif /* RF_INCLUDE_EVENODD > 0 */
64 #include "rf_general.h"
65 #include "rf_driver.h"
66 #include "rf_parityscan.h"
67 #include "rf_reconbuffer.h"
68 #include "rf_reconutil.h"
70 /***********************************************************************
72 * the layout switch defines all the layouts that are supported.
73 * fields are: layout ID, init routine, shutdown routine, map
74 * sector, map parity, identify stripe, dag selection, map stripeid
75 * to parity stripe id (optional), num faults tolerated, special
78 ***********************************************************************/
80 static const RF_AccessState_t DefaultStates
[] = {
82 rf_IncrAccessesCountState
,
89 rf_DecrAccessesCountState
,
92 #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
94 /* Note that if you add any new RAID types to this list, that you must
95 also update the mapsw[] table in the raidctl sources */
97 static const RF_LayoutSW_t mapsw
[] = {
98 #if RF_INCLUDE_PARITY_DECLUSTERING > 0
99 /* parity declustering */
100 {'T', "Parity declustering",
102 rf_ConfigureDeclustered
,
103 rf_MapSectorDeclustered
, rf_MapParityDeclustered
, NULL
,
104 rf_IdentifyStripeDeclustered
,
105 rf_RaidFiveDagSelect
,
106 rf_MapSIDToPSIDDeclustered
,
107 rf_GetDefaultHeadSepLimitDeclustered
,
108 rf_GetDefaultNumFloatingReconBuffersDeclustered
,
110 rf_SubmitReconBufferBasic
,
111 rf_VerifyParityBasic
,
118 #if RF_INCLUDE_PARITY_DECLUSTERING_DS > 0
119 /* parity declustering with distributed sparing */
120 {'D', "Distributed sparing parity declustering",
122 rf_ConfigureDeclusteredDS
,
123 rf_MapSectorDeclustered
, rf_MapParityDeclustered
, NULL
,
124 rf_IdentifyStripeDeclustered
,
125 rf_RaidFiveDagSelect
,
126 rf_MapSIDToPSIDDeclustered
,
127 rf_GetDefaultHeadSepLimitDeclustered
,
128 rf_GetDefaultNumFloatingReconBuffersDeclustered
,
129 rf_GetNumSpareRUsDeclustered
, rf_InstallSpareTable
,
130 rf_SubmitReconBufferBasic
,
131 rf_VerifyParityBasic
,
134 RF_DISTRIBUTE_SPARE
| RF_BD_DECLUSTERED
)
138 #if RF_INCLUDE_DECL_PQ > 0
139 /* declustered P+Q */
140 {'Q', "Declustered P+Q",
142 rf_ConfigureDeclusteredPQ
,
143 rf_MapSectorDeclusteredPQ
, rf_MapParityDeclusteredPQ
, rf_MapQDeclusteredPQ
,
144 rf_IdentifyStripeDeclusteredPQ
,
146 rf_MapSIDToPSIDDeclustered
,
147 rf_GetDefaultHeadSepLimitDeclustered
,
148 rf_GetDefaultNumFloatingReconBuffersPQ
,
151 rf_VerifyParityBasic
,
156 #endif /* RF_INCLUDE_DECL_PQ > 0 */
158 #if RF_INCLUDE_RAID5_RS > 0
159 /* RAID 5 with rotated sparing */
160 {'R', "RAID Level 5 rotated sparing",
162 rf_ConfigureRAID5_RS
,
163 rf_MapSectorRAID5_RS
, rf_MapParityRAID5_RS
, NULL
,
164 rf_IdentifyStripeRAID5_RS
,
165 rf_RaidFiveDagSelect
,
166 rf_MapSIDToPSIDRAID5_RS
,
167 rf_GetDefaultHeadSepLimitRAID5
,
168 rf_GetDefaultNumFloatingReconBuffersRAID5
,
169 rf_GetNumSpareRUsRAID5_RS
, NULL
,
170 rf_SubmitReconBufferBasic
,
171 rf_VerifyParityBasic
,
176 #endif /* RF_INCLUDE_RAID5_RS > 0 */
178 #if RF_INCLUDE_CHAINDECLUSTER > 0
179 /* Chained Declustering */
180 {'C', "Chained Declustering",
182 rf_ConfigureChainDecluster
,
183 rf_MapSectorChainDecluster
, rf_MapParityChainDecluster
, NULL
,
184 rf_IdentifyStripeChainDecluster
,
186 rf_MapSIDToPSIDChainDecluster
,
189 rf_GetNumSpareRUsChainDecluster
, NULL
,
190 rf_SubmitReconBufferBasic
,
191 rf_VerifyParityBasic
,
196 #endif /* RF_INCLUDE_CHAINDECLUSTER > 0 */
198 #if RF_INCLUDE_INTERDECLUSTER > 0
199 /* Interleaved Declustering */
200 {'I', "Interleaved Declustering",
202 rf_ConfigureInterDecluster
,
203 rf_MapSectorInterDecluster
, rf_MapParityInterDecluster
, NULL
,
204 rf_IdentifyStripeInterDecluster
,
206 rf_MapSIDToPSIDInterDecluster
,
207 rf_GetDefaultHeadSepLimitInterDecluster
,
208 rf_GetDefaultNumFloatingReconBuffersInterDecluster
,
209 rf_GetNumSpareRUsInterDecluster
, NULL
,
210 rf_SubmitReconBufferBasic
,
211 rf_VerifyParityBasic
,
216 #endif /* RF_INCLUDE_INTERDECLUSTER > 0 */
218 #if RF_INCLUDE_RAID0 > 0
220 {'0', "RAID Level 0",
223 rf_MapSectorRAID0
, rf_MapParityRAID0
, NULL
,
224 rf_IdentifyStripeRAID0
,
226 rf_MapSIDToPSIDRAID0
,
231 rf_VerifyParityRAID0
,
236 #endif /* RF_INCLUDE_RAID0 > 0 */
238 #if RF_INCLUDE_RAID1 > 0
240 {'1', "RAID Level 1",
243 rf_MapSectorRAID1
, rf_MapParityRAID1
, NULL
,
244 rf_IdentifyStripeRAID1
,
246 rf_MapSIDToPSIDRAID1
,
247 rf_GetDefaultHeadSepLimitRAID1
,
250 rf_SubmitReconBufferRAID1
,
251 rf_VerifyParityRAID1
,
256 #endif /* RF_INCLUDE_RAID1 > 0 */
258 #if RF_INCLUDE_RAID4 > 0
260 {'4', "RAID Level 4",
263 rf_MapSectorRAID4
, rf_MapParityRAID4
, NULL
,
264 rf_IdentifyStripeRAID4
,
265 rf_RaidFiveDagSelect
,
266 rf_MapSIDToPSIDRAID4
,
267 rf_GetDefaultHeadSepLimitRAID4
,
268 rf_GetDefaultNumFloatingReconBuffersRAID4
,
270 rf_SubmitReconBufferBasic
,
271 rf_VerifyParityBasic
,
276 #endif /* RF_INCLUDE_RAID4 > 0 */
278 #if RF_INCLUDE_RAID5 > 0
280 {'5', "RAID Level 5",
283 rf_MapSectorRAID5
, rf_MapParityRAID5
, NULL
,
284 rf_IdentifyStripeRAID5
,
285 rf_RaidFiveDagSelect
,
286 rf_MapSIDToPSIDRAID5
,
287 rf_GetDefaultHeadSepLimitRAID5
,
288 rf_GetDefaultNumFloatingReconBuffersRAID5
,
290 rf_SubmitReconBufferBasic
,
291 rf_VerifyParityBasic
,
296 #endif /* RF_INCLUDE_RAID5 > 0 */
298 #if RF_INCLUDE_EVENODD > 0
303 rf_MapSectorRAID5
, rf_MapParityEvenOdd
, rf_MapEEvenOdd
,
304 rf_IdentifyStripeEvenOdd
,
306 rf_MapSIDToPSIDRAID5
,
310 NULL
, /* no reconstruction, yet */
311 rf_VerifyParityEvenOdd
,
316 #endif /* RF_INCLUDE_EVENODD > 0 */
318 #if RF_INCLUDE_EVENODD > 0
319 /* Declustered Evenodd */
320 {'e', "Declustered EvenOdd",
322 rf_ConfigureDeclusteredPQ
,
323 rf_MapSectorDeclusteredPQ
, rf_MapParityDeclusteredPQ
, rf_MapQDeclusteredPQ
,
324 rf_IdentifyStripeDeclusteredPQ
,
326 rf_MapSIDToPSIDRAID5
,
327 rf_GetDefaultHeadSepLimitDeclustered
,
328 rf_GetDefaultNumFloatingReconBuffersPQ
,
330 NULL
, /* no reconstruction, yet */
331 rf_VerifyParityEvenOdd
,
336 #endif /* RF_INCLUDE_EVENODD > 0 */
338 #if RF_INCLUDE_PARITYLOGGING > 0
340 {'L', "Parity logging",
342 rf_ConfigureParityLogging
,
343 rf_MapSectorParityLogging
, rf_MapParityParityLogging
, NULL
,
344 rf_IdentifyStripeParityLogging
,
345 rf_ParityLoggingDagSelect
,
346 rf_MapSIDToPSIDParityLogging
,
347 rf_GetDefaultHeadSepLimitParityLogging
,
348 rf_GetDefaultNumFloatingReconBuffersParityLogging
,
350 rf_SubmitReconBufferBasic
,
356 #endif /* RF_INCLUDE_PARITYLOGGING > 0 */
358 /* end-of-list marker */
377 const RF_LayoutSW_t
*
378 rf_GetLayout(RF_ParityConfig_t parityConfig
)
380 const RF_LayoutSW_t
*p
;
382 /* look up the specific layout */
383 for (p
= &mapsw
[0]; p
->parityConfig
; p
++)
384 if (p
->parityConfig
== parityConfig
)
386 if (!p
->parityConfig
)
388 RF_ASSERT(p
->parityConfig
== parityConfig
);
392 /*****************************************************************************
396 * read the configuration file and set up the RAID layout parameters.
397 * After reading common params, invokes the layout-specific
398 * configuration routine to finish the configuration.
400 ****************************************************************************/
402 rf_ConfigureLayout(RF_ShutdownList_t
**listp
, RF_Raid_t
*raidPtr
,
405 RF_RaidLayout_t
*layoutPtr
= &(raidPtr
->Layout
);
406 RF_ParityConfig_t parityConfig
;
407 const RF_LayoutSW_t
*p
;
410 layoutPtr
->sectorsPerStripeUnit
= cfgPtr
->sectPerSU
;
411 layoutPtr
->SUsPerPU
= cfgPtr
->SUsPerPU
;
412 layoutPtr
->SUsPerRU
= cfgPtr
->SUsPerRU
;
413 parityConfig
= cfgPtr
->parityConfig
;
415 if (layoutPtr
->sectorsPerStripeUnit
<= 0) {
416 RF_ERRORMSG2("raid%d: Invalid sectorsPerStripeUnit: %d\n",
418 (int)layoutPtr
->sectorsPerStripeUnit
);
422 if (layoutPtr
->SUsPerPU
<= 0) {
423 RF_ERRORMSG2("raid%d: Invalid StripeUnitsPerParityUnit: %d\n",
425 (int)layoutPtr
->SUsPerPU
);
429 if (layoutPtr
->SUsPerRU
<= 0) {
430 RF_ERRORMSG2("raid%d: Invalid StripeUnitsPerReconstructUnit: %d\n",
432 (int)layoutPtr
->SUsPerRU
);
436 layoutPtr
->stripeUnitsPerDisk
= raidPtr
->sectorsPerDisk
/ layoutPtr
->sectorsPerStripeUnit
;
438 p
= rf_GetLayout(parityConfig
);
440 RF_ERRORMSG1("Unknown parity configuration '%c'", parityConfig
);
443 RF_ASSERT(p
->parityConfig
== parityConfig
);
446 /* initialize the specific layout */
448 retval
= (p
->Configure
) (listp
, raidPtr
, cfgPtr
);
453 raidPtr
->sectorsPerDisk
= layoutPtr
->stripeUnitsPerDisk
* layoutPtr
->sectorsPerStripeUnit
;
455 if (rf_forceNumFloatingReconBufs
>= 0) {
456 raidPtr
->numFloatingReconBufs
= rf_forceNumFloatingReconBufs
;
458 raidPtr
->numFloatingReconBufs
= rf_GetDefaultNumFloatingReconBuffers(raidPtr
);
461 if (rf_forceHeadSepLimit
>= 0) {
462 raidPtr
->headSepLimit
= rf_forceHeadSepLimit
;
464 raidPtr
->headSepLimit
= rf_GetDefaultHeadSepLimit(raidPtr
);
468 /* typically there is a 1-1 mapping between stripes and parity stripes.
469 * however, the declustering code supports packing multiple stripes into
470 * a single parity stripe, so as to increase the size of the reconstruction
471 * unit without affecting the size of the stripe unit. This routine finds
472 * the parity stripe identifier associated with a stripe ID. There is also
473 * a RaidAddressToParityStripeID macro in layout.h
476 rf_MapStripeIDToParityStripeID(RF_RaidLayout_t
*layoutPtr
,
477 RF_StripeNum_t stripeID
,
478 RF_ReconUnitNum_t
*which_ru
)
480 RF_StripeNum_t parityStripeID
;
482 /* quick exit in the common case of SUsPerPU==1 */
483 if ((layoutPtr
->SUsPerPU
== 1) || !layoutPtr
->map
->MapSIDToPSID
) {
487 (layoutPtr
->map
->MapSIDToPSID
) (layoutPtr
, stripeID
, &parityStripeID
, which_ru
);
489 return (parityStripeID
);