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