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