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