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