rf_layout.c revision 1.11 1 /* $NetBSD: rf_layout.c,v 1.11 2001/11/13 07:11:14 lukem 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 (at) 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.11 2001/11/13 07:11:14 lukem 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 layoutPtr->dataBytesPerStripe = layoutPtr->dataSectorsPerStripe << raidPtr->logBytesPerSector;
441 raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
442
443 if (rf_forceNumFloatingReconBufs >= 0) {
444 raidPtr->numFloatingReconBufs = rf_forceNumFloatingReconBufs;
445 } else {
446 raidPtr->numFloatingReconBufs = rf_GetDefaultNumFloatingReconBuffers(raidPtr);
447 }
448
449 if (rf_forceHeadSepLimit >= 0) {
450 raidPtr->headSepLimit = rf_forceHeadSepLimit;
451 } else {
452 raidPtr->headSepLimit = rf_GetDefaultHeadSepLimit(raidPtr);
453 }
454
455 printf("RAIDFRAME: Configure (%s): total number of sectors is %lu (%lu MB)\n",
456 layoutPtr->map->configName,
457 (unsigned long) raidPtr->totalSectors,
458 (unsigned long) (raidPtr->totalSectors / 1024 * (1 << raidPtr->logBytesPerSector) / 1024));
459 if (raidPtr->headSepLimit >= 0) {
460 printf("RAIDFRAME(%s): Using %ld floating recon bufs with head sep limit %ld\n",
461 layoutPtr->map->configName, (long) raidPtr->numFloatingReconBufs, (long) raidPtr->headSepLimit);
462 } else {
463 printf("RAIDFRAME(%s): Using %ld floating recon bufs with no head sep limit\n",
464 layoutPtr->map->configName, (long) raidPtr->numFloatingReconBufs);
465 }
466
467 return (0);
468 }
469 /* typically there is a 1-1 mapping between stripes and parity stripes.
470 * however, the declustering code supports packing multiple stripes into
471 * a single parity stripe, so as to increase the size of the reconstruction
472 * unit without affecting the size of the stripe unit. This routine finds
473 * the parity stripe identifier associated with a stripe ID. There is also
474 * a RaidAddressToParityStripeID macro in layout.h
475 */
476 RF_StripeNum_t
477 rf_MapStripeIDToParityStripeID(layoutPtr, stripeID, which_ru)
478 RF_RaidLayout_t *layoutPtr;
479 RF_StripeNum_t stripeID;
480 RF_ReconUnitNum_t *which_ru;
481 {
482 RF_StripeNum_t parityStripeID;
483
484 /* quick exit in the common case of SUsPerPU==1 */
485 if ((layoutPtr->SUsPerPU == 1) || !layoutPtr->map->MapSIDToPSID) {
486 *which_ru = 0;
487 return (stripeID);
488 } else {
489 (layoutPtr->map->MapSIDToPSID) (layoutPtr, stripeID, &parityStripeID, which_ru);
490 }
491 return (parityStripeID);
492 }
493