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