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