Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / raidframe / rf_layout.c
blobddc192c973006b2e1381aded7686d9637310610f
1 /* $NetBSD: rf_layout.c,v 1.19 2008/04/20 20:42:32 oster Exp $ */
2 /*
3 * Copyright (c) 1995 Carnegie-Mellon University.
4 * All rights reserved.
6 * Author: Mark Holland
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>
37 #include "rf_archs.h"
38 #include "rf_raid.h"
39 #include "rf_dag.h"
40 #include "rf_desc.h"
41 #include "rf_decluster.h"
42 #include "rf_pq.h"
43 #include "rf_declusterPQ.h"
44 #include "rf_raid0.h"
45 #include "rf_raid1.h"
46 #include "rf_raid4.h"
47 #include "rf_raid5.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
76 * flags.
78 ***********************************************************************/
80 static const RF_AccessState_t DefaultStates[] = {
81 rf_QuiesceState,
82 rf_IncrAccessesCountState,
83 rf_MapState,
84 rf_LockState,
85 rf_CreateDAGState,
86 rf_ExecuteDAGState,
87 rf_ProcessDAGState,
88 rf_CleanupState,
89 rf_DecrAccessesCountState,
90 rf_LastState};
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",
101 RF_NU(
102 rf_ConfigureDeclustered,
103 rf_MapSectorDeclustered, rf_MapParityDeclustered, NULL,
104 rf_IdentifyStripeDeclustered,
105 rf_RaidFiveDagSelect,
106 rf_MapSIDToPSIDDeclustered,
107 rf_GetDefaultHeadSepLimitDeclustered,
108 rf_GetDefaultNumFloatingReconBuffersDeclustered,
109 NULL, NULL,
110 rf_SubmitReconBufferBasic,
111 rf_VerifyParityBasic,
113 DefaultStates,
116 #endif
118 #if RF_INCLUDE_PARITY_DECLUSTERING_DS > 0
119 /* parity declustering with distributed sparing */
120 {'D', "Distributed sparing parity declustering",
121 RF_NU(
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,
133 DefaultStates,
134 RF_DISTRIBUTE_SPARE | RF_BD_DECLUSTERED)
136 #endif
138 #if RF_INCLUDE_DECL_PQ > 0
139 /* declustered P+Q */
140 {'Q', "Declustered P+Q",
141 RF_NU(
142 rf_ConfigureDeclusteredPQ,
143 rf_MapSectorDeclusteredPQ, rf_MapParityDeclusteredPQ, rf_MapQDeclusteredPQ,
144 rf_IdentifyStripeDeclusteredPQ,
145 rf_PQDagSelect,
146 rf_MapSIDToPSIDDeclustered,
147 rf_GetDefaultHeadSepLimitDeclustered,
148 rf_GetDefaultNumFloatingReconBuffersPQ,
149 NULL, NULL,
150 NULL,
151 rf_VerifyParityBasic,
153 DefaultStates,
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",
161 RF_NU(
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,
173 DefaultStates,
174 RF_DISTRIBUTE_SPARE)
176 #endif /* RF_INCLUDE_RAID5_RS > 0 */
178 #if RF_INCLUDE_CHAINDECLUSTER > 0
179 /* Chained Declustering */
180 {'C', "Chained Declustering",
181 RF_NU(
182 rf_ConfigureChainDecluster,
183 rf_MapSectorChainDecluster, rf_MapParityChainDecluster, NULL,
184 rf_IdentifyStripeChainDecluster,
185 rf_RAIDCDagSelect,
186 rf_MapSIDToPSIDChainDecluster,
187 NULL,
188 NULL,
189 rf_GetNumSpareRUsChainDecluster, NULL,
190 rf_SubmitReconBufferBasic,
191 rf_VerifyParityBasic,
193 DefaultStates,
196 #endif /* RF_INCLUDE_CHAINDECLUSTER > 0 */
198 #if RF_INCLUDE_INTERDECLUSTER > 0
199 /* Interleaved Declustering */
200 {'I', "Interleaved Declustering",
201 RF_NU(
202 rf_ConfigureInterDecluster,
203 rf_MapSectorInterDecluster, rf_MapParityInterDecluster, NULL,
204 rf_IdentifyStripeInterDecluster,
205 rf_RAIDIDagSelect,
206 rf_MapSIDToPSIDInterDecluster,
207 rf_GetDefaultHeadSepLimitInterDecluster,
208 rf_GetDefaultNumFloatingReconBuffersInterDecluster,
209 rf_GetNumSpareRUsInterDecluster, NULL,
210 rf_SubmitReconBufferBasic,
211 rf_VerifyParityBasic,
213 DefaultStates,
214 RF_DISTRIBUTE_SPARE)
216 #endif /* RF_INCLUDE_INTERDECLUSTER > 0 */
218 #if RF_INCLUDE_RAID0 > 0
219 /* RAID level 0 */
220 {'0', "RAID Level 0",
221 RF_NU(
222 rf_ConfigureRAID0,
223 rf_MapSectorRAID0, rf_MapParityRAID0, NULL,
224 rf_IdentifyStripeRAID0,
225 rf_RAID0DagSelect,
226 rf_MapSIDToPSIDRAID0,
227 NULL,
228 NULL,
229 NULL, NULL,
230 NULL,
231 rf_VerifyParityRAID0,
233 DefaultStates,
236 #endif /* RF_INCLUDE_RAID0 > 0 */
238 #if RF_INCLUDE_RAID1 > 0
239 /* RAID level 1 */
240 {'1', "RAID Level 1",
241 RF_NU(
242 rf_ConfigureRAID1,
243 rf_MapSectorRAID1, rf_MapParityRAID1, NULL,
244 rf_IdentifyStripeRAID1,
245 rf_RAID1DagSelect,
246 rf_MapSIDToPSIDRAID1,
247 rf_GetDefaultHeadSepLimitRAID1,
248 NULL,
249 NULL, NULL,
250 rf_SubmitReconBufferRAID1,
251 rf_VerifyParityRAID1,
253 DefaultStates,
256 #endif /* RF_INCLUDE_RAID1 > 0 */
258 #if RF_INCLUDE_RAID4 > 0
259 /* RAID level 4 */
260 {'4', "RAID Level 4",
261 RF_NU(
262 rf_ConfigureRAID4,
263 rf_MapSectorRAID4, rf_MapParityRAID4, NULL,
264 rf_IdentifyStripeRAID4,
265 rf_RaidFiveDagSelect,
266 rf_MapSIDToPSIDRAID4,
267 rf_GetDefaultHeadSepLimitRAID4,
268 rf_GetDefaultNumFloatingReconBuffersRAID4,
269 NULL, NULL,
270 rf_SubmitReconBufferBasic,
271 rf_VerifyParityBasic,
273 DefaultStates,
276 #endif /* RF_INCLUDE_RAID4 > 0 */
278 #if RF_INCLUDE_RAID5 > 0
279 /* RAID level 5 */
280 {'5', "RAID Level 5",
281 RF_NU(
282 rf_ConfigureRAID5,
283 rf_MapSectorRAID5, rf_MapParityRAID5, NULL,
284 rf_IdentifyStripeRAID5,
285 rf_RaidFiveDagSelect,
286 rf_MapSIDToPSIDRAID5,
287 rf_GetDefaultHeadSepLimitRAID5,
288 rf_GetDefaultNumFloatingReconBuffersRAID5,
289 NULL, NULL,
290 rf_SubmitReconBufferBasic,
291 rf_VerifyParityBasic,
293 DefaultStates,
296 #endif /* RF_INCLUDE_RAID5 > 0 */
298 #if RF_INCLUDE_EVENODD > 0
299 /* Evenodd */
300 {'E', "EvenOdd",
301 RF_NU(
302 rf_ConfigureEvenOdd,
303 rf_MapSectorRAID5, rf_MapParityEvenOdd, rf_MapEEvenOdd,
304 rf_IdentifyStripeEvenOdd,
305 rf_EODagSelect,
306 rf_MapSIDToPSIDRAID5,
307 NULL,
308 NULL,
309 NULL, NULL,
310 NULL, /* no reconstruction, yet */
311 rf_VerifyParityEvenOdd,
313 DefaultStates,
316 #endif /* RF_INCLUDE_EVENODD > 0 */
318 #if RF_INCLUDE_EVENODD > 0
319 /* Declustered Evenodd */
320 {'e', "Declustered EvenOdd",
321 RF_NU(
322 rf_ConfigureDeclusteredPQ,
323 rf_MapSectorDeclusteredPQ, rf_MapParityDeclusteredPQ, rf_MapQDeclusteredPQ,
324 rf_IdentifyStripeDeclusteredPQ,
325 rf_EODagSelect,
326 rf_MapSIDToPSIDRAID5,
327 rf_GetDefaultHeadSepLimitDeclustered,
328 rf_GetDefaultNumFloatingReconBuffersPQ,
329 NULL, NULL,
330 NULL, /* no reconstruction, yet */
331 rf_VerifyParityEvenOdd,
333 DefaultStates,
336 #endif /* RF_INCLUDE_EVENODD > 0 */
338 #if RF_INCLUDE_PARITYLOGGING > 0
339 /* parity logging */
340 {'L', "Parity logging",
341 RF_NU(
342 rf_ConfigureParityLogging,
343 rf_MapSectorParityLogging, rf_MapParityParityLogging, NULL,
344 rf_IdentifyStripeParityLogging,
345 rf_ParityLoggingDagSelect,
346 rf_MapSIDToPSIDParityLogging,
347 rf_GetDefaultHeadSepLimitParityLogging,
348 rf_GetDefaultNumFloatingReconBuffersParityLogging,
349 NULL, NULL,
350 rf_SubmitReconBufferBasic,
351 NULL,
353 DefaultStates,
356 #endif /* RF_INCLUDE_PARITYLOGGING > 0 */
358 /* end-of-list marker */
359 {'\0', NULL,
360 RF_NU(
361 NULL,
362 NULL, NULL, NULL,
363 NULL,
364 NULL,
365 NULL,
366 NULL,
367 NULL,
368 NULL, NULL,
369 NULL,
370 NULL,
372 NULL,
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)
385 break;
386 if (!p->parityConfig)
387 return (NULL);
388 RF_ASSERT(p->parityConfig == parityConfig);
389 return (p);
392 /*****************************************************************************
394 * ConfigureLayout --
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,
403 RF_Config_t *cfgPtr)
405 RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
406 RF_ParityConfig_t parityConfig;
407 const RF_LayoutSW_t *p;
408 int retval;
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",
417 raidPtr->raidid,
418 (int)layoutPtr->sectorsPerStripeUnit);
419 return (EINVAL);
422 if (layoutPtr->SUsPerPU <= 0) {
423 RF_ERRORMSG2("raid%d: Invalid StripeUnitsPerParityUnit: %d\n",
424 raidPtr->raidid,
425 (int)layoutPtr->SUsPerPU);
426 return (EINVAL);
429 if (layoutPtr->SUsPerRU <= 0) {
430 RF_ERRORMSG2("raid%d: Invalid StripeUnitsPerReconstructUnit: %d\n",
431 raidPtr->raidid,
432 (int)layoutPtr->SUsPerRU);
433 return (EINVAL);
436 layoutPtr->stripeUnitsPerDisk = raidPtr->sectorsPerDisk / layoutPtr->sectorsPerStripeUnit;
438 p = rf_GetLayout(parityConfig);
439 if (p == NULL) {
440 RF_ERRORMSG1("Unknown parity configuration '%c'", parityConfig);
441 return (EINVAL);
443 RF_ASSERT(p->parityConfig == parityConfig);
444 layoutPtr->map = p;
446 /* initialize the specific layout */
448 retval = (p->Configure) (listp, raidPtr, cfgPtr);
450 if (retval)
451 return (retval);
453 raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
455 if (rf_forceNumFloatingReconBufs >= 0) {
456 raidPtr->numFloatingReconBufs = rf_forceNumFloatingReconBufs;
457 } else {
458 raidPtr->numFloatingReconBufs = rf_GetDefaultNumFloatingReconBuffers(raidPtr);
461 if (rf_forceHeadSepLimit >= 0) {
462 raidPtr->headSepLimit = rf_forceHeadSepLimit;
463 } else {
464 raidPtr->headSepLimit = rf_GetDefaultHeadSepLimit(raidPtr);
466 return (0);
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
475 RF_StripeNum_t
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) {
484 *which_ru = 0;
485 return (stripeID);
486 } else {
487 (layoutPtr->map->MapSIDToPSID) (layoutPtr, stripeID, &parityStripeID, which_ru);
489 return (parityStripeID);