rf_layout.c revision 1.9.2.1 1 /* $NetBSD: rf_layout.c,v 1.9.2.1 2001/10/22 20:41:36 nathanw 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 <dev/raidframe/raidframevar.h>
33
34 #include "rf_archs.h"
35 #include "rf_raid.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