xref: /netbsd/sys/dev/raidframe/rf_layout.c (revision c4a72b64)
1 /*	$NetBSD: rf_layout.c,v 1.13 2002/09/23 02:35:24 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 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: rf_layout.c,v 1.13 2002/09/23 02:35:24 oster Exp $");
34 
35 #include <dev/raidframe/raidframevar.h>
36 
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"
69 
70 /***********************************************************************
71  *
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.
77  *
78  ***********************************************************************/
79 
80 static RF_AccessState_t DefaultStates[] = {rf_QuiesceState,
81 					   rf_IncrAccessesCountState,
82 					   rf_MapState,
83 					   rf_LockState,
84 					   rf_CreateDAGState,
85 					   rf_ExecuteDAGState,
86 					   rf_ProcessDAGState,
87 					   rf_DecrAccessesCountState,
88 					   rf_CleanupState,
89 					   rf_LastState};
90 
91 #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
92 
93 /* Note that if you add any new RAID types to this list, that you must
94    also update the mapsw[] table in the raidctl sources */
95 
96 static RF_LayoutSW_t mapsw[] = {
97 #if RF_INCLUDE_PARITY_DECLUSTERING > 0
98 	/* parity declustering */
99 	{'T', "Parity declustering",
100 		RF_NU(
101 		    rf_ConfigureDeclustered,
102 		    rf_MapSectorDeclustered, rf_MapParityDeclustered, NULL,
103 		    rf_IdentifyStripeDeclustered,
104 		    rf_RaidFiveDagSelect,
105 		    rf_MapSIDToPSIDDeclustered,
106 		    rf_GetDefaultHeadSepLimitDeclustered,
107 		    rf_GetDefaultNumFloatingReconBuffersDeclustered,
108 		    NULL, NULL,
109 		    rf_SubmitReconBufferBasic,
110 		    rf_VerifyParityBasic,
111 		    1,
112 		    DefaultStates,
113 		    0)
114 	},
115 #endif
116 
117 #if RF_INCLUDE_PARITY_DECLUSTERING_DS > 0
118 	/* parity declustering with distributed sparing */
119 	{'D', "Distributed sparing parity declustering",
120 		RF_NU(
121 		    rf_ConfigureDeclusteredDS,
122 		    rf_MapSectorDeclustered, rf_MapParityDeclustered, NULL,
123 		    rf_IdentifyStripeDeclustered,
124 		    rf_RaidFiveDagSelect,
125 		    rf_MapSIDToPSIDDeclustered,
126 		    rf_GetDefaultHeadSepLimitDeclustered,
127 		    rf_GetDefaultNumFloatingReconBuffersDeclustered,
128 		    rf_GetNumSpareRUsDeclustered, rf_InstallSpareTable,
129 		    rf_SubmitReconBufferBasic,
130 		    rf_VerifyParityBasic,
131 		    1,
132 		    DefaultStates,
133 		    RF_DISTRIBUTE_SPARE | RF_BD_DECLUSTERED)
134 	},
135 #endif
136 
137 #if RF_INCLUDE_DECL_PQ > 0
138 	/* declustered P+Q */
139 	{'Q', "Declustered P+Q",
140 		RF_NU(
141 		    rf_ConfigureDeclusteredPQ,
142 		    rf_MapSectorDeclusteredPQ, rf_MapParityDeclusteredPQ, rf_MapQDeclusteredPQ,
143 		    rf_IdentifyStripeDeclusteredPQ,
144 		    rf_PQDagSelect,
145 		    rf_MapSIDToPSIDDeclustered,
146 		    rf_GetDefaultHeadSepLimitDeclustered,
147 		    rf_GetDefaultNumFloatingReconBuffersPQ,
148 		    NULL, NULL,
149 		    NULL,
150 		    rf_VerifyParityBasic,
151 		    2,
152 		    DefaultStates,
153 		    0)
154 	},
155 #endif				/* RF_INCLUDE_DECL_PQ > 0 */
156 
157 #if RF_INCLUDE_RAID5_RS > 0
158 	/* RAID 5 with rotated sparing */
159 	{'R', "RAID Level 5 rotated sparing",
160 		RF_NU(
161 		    rf_ConfigureRAID5_RS,
162 		    rf_MapSectorRAID5_RS, rf_MapParityRAID5_RS, NULL,
163 		    rf_IdentifyStripeRAID5_RS,
164 		    rf_RaidFiveDagSelect,
165 		    rf_MapSIDToPSIDRAID5_RS,
166 		    rf_GetDefaultHeadSepLimitRAID5,
167 		    rf_GetDefaultNumFloatingReconBuffersRAID5,
168 		    rf_GetNumSpareRUsRAID5_RS, NULL,
169 		    rf_SubmitReconBufferBasic,
170 		    rf_VerifyParityBasic,
171 		    1,
172 		    DefaultStates,
173 		    RF_DISTRIBUTE_SPARE)
174 	},
175 #endif				/* RF_INCLUDE_RAID5_RS > 0 */
176 
177 #if RF_INCLUDE_CHAINDECLUSTER > 0
178 	/* Chained Declustering */
179 	{'C', "Chained Declustering",
180 		RF_NU(
181 		    rf_ConfigureChainDecluster,
182 		    rf_MapSectorChainDecluster, rf_MapParityChainDecluster, NULL,
183 		    rf_IdentifyStripeChainDecluster,
184 		    rf_RAIDCDagSelect,
185 		    rf_MapSIDToPSIDChainDecluster,
186 		    NULL,
187 		    NULL,
188 		    rf_GetNumSpareRUsChainDecluster, NULL,
189 		    rf_SubmitReconBufferBasic,
190 		    rf_VerifyParityBasic,
191 		    1,
192 		    DefaultStates,
193 		    0)
194 	},
195 #endif				/* RF_INCLUDE_CHAINDECLUSTER > 0 */
196 
197 #if RF_INCLUDE_INTERDECLUSTER > 0
198 	/* Interleaved Declustering */
199 	{'I', "Interleaved Declustering",
200 		RF_NU(
201 		    rf_ConfigureInterDecluster,
202 		    rf_MapSectorInterDecluster, rf_MapParityInterDecluster, NULL,
203 		    rf_IdentifyStripeInterDecluster,
204 		    rf_RAIDIDagSelect,
205 		    rf_MapSIDToPSIDInterDecluster,
206 		    rf_GetDefaultHeadSepLimitInterDecluster,
207 		    rf_GetDefaultNumFloatingReconBuffersInterDecluster,
208 		    rf_GetNumSpareRUsInterDecluster, NULL,
209 		    rf_SubmitReconBufferBasic,
210 		    rf_VerifyParityBasic,
211 		    1,
212 		    DefaultStates,
213 		    RF_DISTRIBUTE_SPARE)
214 	},
215 #endif				/* RF_INCLUDE_INTERDECLUSTER > 0 */
216 
217 #if RF_INCLUDE_RAID0 > 0
218 	/* RAID level 0 */
219 	{'0', "RAID Level 0",
220 		RF_NU(
221 		    rf_ConfigureRAID0,
222 		    rf_MapSectorRAID0, rf_MapParityRAID0, NULL,
223 		    rf_IdentifyStripeRAID0,
224 		    rf_RAID0DagSelect,
225 		    rf_MapSIDToPSIDRAID0,
226 		    NULL,
227 		    NULL,
228 		    NULL, NULL,
229 		    NULL,
230 		    rf_VerifyParityRAID0,
231 		    0,
232 		    DefaultStates,
233 		    0)
234 	},
235 #endif				/* RF_INCLUDE_RAID0 > 0 */
236 
237 #if RF_INCLUDE_RAID1 > 0
238 	/* RAID level 1 */
239 	{'1', "RAID Level 1",
240 		RF_NU(
241 		    rf_ConfigureRAID1,
242 		    rf_MapSectorRAID1, rf_MapParityRAID1, NULL,
243 		    rf_IdentifyStripeRAID1,
244 		    rf_RAID1DagSelect,
245 		    rf_MapSIDToPSIDRAID1,
246 		    NULL,
247 		    NULL,
248 		    NULL, NULL,
249 		    rf_SubmitReconBufferRAID1,
250 		    rf_VerifyParityRAID1,
251 		    1,
252 		    DefaultStates,
253 		    0)
254 	},
255 #endif				/* RF_INCLUDE_RAID1 > 0 */
256 
257 #if RF_INCLUDE_RAID4 > 0
258 	/* RAID level 4 */
259 	{'4', "RAID Level 4",
260 		RF_NU(
261 		    rf_ConfigureRAID4,
262 		    rf_MapSectorRAID4, rf_MapParityRAID4, NULL,
263 		    rf_IdentifyStripeRAID4,
264 		    rf_RaidFiveDagSelect,
265 		    rf_MapSIDToPSIDRAID4,
266 		    rf_GetDefaultHeadSepLimitRAID4,
267 		    rf_GetDefaultNumFloatingReconBuffersRAID4,
268 		    NULL, NULL,
269 		    rf_SubmitReconBufferBasic,
270 		    rf_VerifyParityBasic,
271 		    1,
272 		    DefaultStates,
273 		    0)
274 	},
275 #endif				/* RF_INCLUDE_RAID4 > 0 */
276 
277 #if RF_INCLUDE_RAID5 > 0
278 	/* RAID level 5 */
279 	{'5', "RAID Level 5",
280 		RF_NU(
281 		    rf_ConfigureRAID5,
282 		    rf_MapSectorRAID5, rf_MapParityRAID5, NULL,
283 		    rf_IdentifyStripeRAID5,
284 		    rf_RaidFiveDagSelect,
285 		    rf_MapSIDToPSIDRAID5,
286 		    rf_GetDefaultHeadSepLimitRAID5,
287 		    rf_GetDefaultNumFloatingReconBuffersRAID5,
288 		    NULL, NULL,
289 		    rf_SubmitReconBufferBasic,
290 		    rf_VerifyParityBasic,
291 		    1,
292 		    DefaultStates,
293 		    0)
294 	},
295 #endif				/* RF_INCLUDE_RAID5 > 0 */
296 
297 #if RF_INCLUDE_EVENODD > 0
298 	/* Evenodd */
299 	{'E', "EvenOdd",
300 		RF_NU(
301 		    rf_ConfigureEvenOdd,
302 		    rf_MapSectorRAID5, rf_MapParityEvenOdd, rf_MapEEvenOdd,
303 		    rf_IdentifyStripeEvenOdd,
304 		    rf_EODagSelect,
305 		    rf_MapSIDToPSIDRAID5,
306 		    NULL,
307 		    NULL,
308 		    NULL, NULL,
309 		    NULL,	/* no reconstruction, yet */
310 		    rf_VerifyParityEvenOdd,
311 		    2,
312 		    DefaultStates,
313 		    0)
314 	},
315 #endif				/* RF_INCLUDE_EVENODD > 0 */
316 
317 #if RF_INCLUDE_EVENODD > 0
318 	/* Declustered Evenodd */
319 	{'e', "Declustered EvenOdd",
320 		RF_NU(
321 		    rf_ConfigureDeclusteredPQ,
322 		    rf_MapSectorDeclusteredPQ, rf_MapParityDeclusteredPQ, rf_MapQDeclusteredPQ,
323 		    rf_IdentifyStripeDeclusteredPQ,
324 		    rf_EODagSelect,
325 		    rf_MapSIDToPSIDRAID5,
326 		    rf_GetDefaultHeadSepLimitDeclustered,
327 		    rf_GetDefaultNumFloatingReconBuffersPQ,
328 		    NULL, NULL,
329 		    NULL,	/* no reconstruction, yet */
330 		    rf_VerifyParityEvenOdd,
331 		    2,
332 		    DefaultStates,
333 		    0)
334 	},
335 #endif				/* RF_INCLUDE_EVENODD > 0 */
336 
337 #if RF_INCLUDE_PARITYLOGGING > 0
338 	/* parity logging */
339 	{'L', "Parity logging",
340 		RF_NU(
341 		    rf_ConfigureParityLogging,
342 		    rf_MapSectorParityLogging, rf_MapParityParityLogging, NULL,
343 		    rf_IdentifyStripeParityLogging,
344 		    rf_ParityLoggingDagSelect,
345 		    rf_MapSIDToPSIDParityLogging,
346 		    rf_GetDefaultHeadSepLimitParityLogging,
347 		    rf_GetDefaultNumFloatingReconBuffersParityLogging,
348 		    NULL, NULL,
349 		    rf_SubmitReconBufferBasic,
350 		    NULL,
351 		    1,
352 		    DefaultStates,
353 		    0)
354 	},
355 #endif				/* RF_INCLUDE_PARITYLOGGING > 0 */
356 
357 	/* end-of-list marker */
358 	{'\0', NULL,
359 		RF_NU(
360 		    NULL,
361 		    NULL, NULL, NULL,
362 		    NULL,
363 		    NULL,
364 		    NULL,
365 		    NULL,
366 		    NULL,
367 		    NULL, NULL,
368 		    NULL,
369 		    NULL,
370 		    0,
371 		    NULL,
372 		    0)
373 	}
374 };
375 
376 RF_LayoutSW_t *
377 rf_GetLayout(RF_ParityConfig_t parityConfig)
378 {
379 	RF_LayoutSW_t *p;
380 
381 	/* look up the specific layout */
382 	for (p = &mapsw[0]; p->parityConfig; p++)
383 		if (p->parityConfig == parityConfig)
384 			break;
385 	if (!p->parityConfig)
386 		return (NULL);
387 	RF_ASSERT(p->parityConfig == parityConfig);
388 	return (p);
389 }
390 
391 /*****************************************************************************
392  *
393  * ConfigureLayout --
394  *
395  * read the configuration file and set up the RAID layout parameters.
396  * After reading common params, invokes the layout-specific
397  * configuration routine to finish the configuration.
398  *
399  ****************************************************************************/
400 int
401 rf_ConfigureLayout(
402     RF_ShutdownList_t ** listp,
403     RF_Raid_t * raidPtr,
404     RF_Config_t * cfgPtr)
405 {
406 	RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
407 	RF_ParityConfig_t parityConfig;
408 	RF_LayoutSW_t *p;
409 	int     retval;
410 
411 	layoutPtr->sectorsPerStripeUnit = cfgPtr->sectPerSU;
412 	layoutPtr->SUsPerPU = cfgPtr->SUsPerPU;
413 	layoutPtr->SUsPerRU = cfgPtr->SUsPerRU;
414 	parityConfig = cfgPtr->parityConfig;
415 
416 	if (layoutPtr->sectorsPerStripeUnit <= 0) {
417 		RF_ERRORMSG2("raid%d: Invalid sectorsPerStripeUnit: %d\n",
418 			     raidPtr->raidid,
419 			     (int)layoutPtr->sectorsPerStripeUnit );
420 		return (EINVAL);
421 	}
422 
423 	layoutPtr->stripeUnitsPerDisk = raidPtr->sectorsPerDisk / layoutPtr->sectorsPerStripeUnit;
424 
425 	p = rf_GetLayout(parityConfig);
426 	if (p == NULL) {
427 		RF_ERRORMSG1("Unknown parity configuration '%c'", parityConfig);
428 		return (EINVAL);
429 	}
430 	RF_ASSERT(p->parityConfig == parityConfig);
431 	layoutPtr->map = p;
432 
433 	/* initialize the specific layout */
434 
435 	retval = (p->Configure) (listp, raidPtr, cfgPtr);
436 
437 	if (retval)
438 		return (retval);
439 
440 	raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
441 
442 	if (rf_forceNumFloatingReconBufs >= 0) {
443 		raidPtr->numFloatingReconBufs = rf_forceNumFloatingReconBufs;
444 	} else {
445 		raidPtr->numFloatingReconBufs = rf_GetDefaultNumFloatingReconBuffers(raidPtr);
446 	}
447 
448 	if (rf_forceHeadSepLimit >= 0) {
449 		raidPtr->headSepLimit = rf_forceHeadSepLimit;
450 	} else {
451 		raidPtr->headSepLimit = rf_GetDefaultHeadSepLimit(raidPtr);
452 	}
453 	return (0);
454 }
455 /* typically there is a 1-1 mapping between stripes and parity stripes.
456  * however, the declustering code supports packing multiple stripes into
457  * a single parity stripe, so as to increase the size of the reconstruction
458  * unit without affecting the size of the stripe unit.  This routine finds
459  * the parity stripe identifier associated with a stripe ID.  There is also
460  * a RaidAddressToParityStripeID macro in layout.h
461  */
462 RF_StripeNum_t
463 rf_MapStripeIDToParityStripeID(layoutPtr, stripeID, which_ru)
464 	RF_RaidLayout_t *layoutPtr;
465 	RF_StripeNum_t stripeID;
466 	RF_ReconUnitNum_t *which_ru;
467 {
468 	RF_StripeNum_t parityStripeID;
469 
470 	/* quick exit in the common case of SUsPerPU==1 */
471 	if ((layoutPtr->SUsPerPU == 1) || !layoutPtr->map->MapSIDToPSID) {
472 		*which_ru = 0;
473 		return (stripeID);
474 	} else {
475 		(layoutPtr->map->MapSIDToPSID) (layoutPtr, stripeID, &parityStripeID, which_ru);
476 	}
477 	return (parityStripeID);
478 }
479