rf_layout.c revision 1.4 1 /* $NetBSD: rf_layout.c,v 1.4 1999/07/19 01:35:19 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 /* 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