Annotation of sys/dev/raidframe/rf_layout.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: rf_layout.c,v 1.7 2007/04/10 17:47:55 miod Exp $ */
2: /* $NetBSD: rf_layout.c,v 1.6 2000/04/17 19:35:12 oster Exp $ */
3:
4: /*
5: * Copyright (c) 1995 Carnegie-Mellon University.
6: * All rights reserved.
7: *
8: * Author: Mark Holland
9: *
10: * Permission to use, copy, modify and distribute this software and
11: * its documentation is hereby granted, provided that both the copyright
12: * notice and this permission notice appear in all copies of the
13: * software, derivative works or modified versions, and any portions
14: * thereof, and that both notices appear in supporting documentation.
15: *
16: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
18: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19: *
20: * Carnegie Mellon requests users of this software to return to
21: *
22: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
23: * School of Computer Science
24: * Carnegie Mellon University
25: * Pittsburgh PA 15213-3890
26: *
27: * any improvements or extensions that they make and grant Carnegie the
28: * rights to redistribute these changes.
29: */
30:
31: /*
32: * rf_layout.c -- Driver code dealing with layout and mapping issues.
33: */
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 sector,
74: * map parity, identify stripe, dag selection, map stripeid
75: * to parity stripe id (optional), num faults tolerated,
76: * special flags.
77: *
78: *****************************************************************************/
79:
80: static RF_AccessState_t DefaultStates[] = {
81: rf_QuiesceState, rf_IncrAccessesCountState, rf_MapState,
82: rf_LockState, rf_CreateDAGState, rf_ExecuteDAGState,
83: rf_ProcessDAGState, rf_DecrAccessesCountState,
84: rf_CleanupState, rf_LastState
85: };
86:
87: #if (defined(__NetBSD__) || defined(__OpenBSD__)) && !defined(_KERNEL)
88: /*
89: * XXX Gross hack to shutup gcc -- It complains that DefaultStates is not
90: * used when compiling this in userland... I hate to burst its bubble, but
91: * DefaultStates is used all over the place here in the initialization of
92: * lots of data structures. GO
93: */
94: RF_AccessState_t *NothingAtAll = DefaultStates;
95: #endif
96:
97: #if (defined(__NetBSD__) || defined(__OpenBSD__)) && defined(_KERNEL)
98: /* XXX Remove static so GCC doesn't complain about these being unused ! */
99: int distSpareYes = 1;
100: int distSpareNo = 0;
101: #else
102: static int distSpareYes = 1;
103: static int distSpareNo = 0;
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: /* Parity declustering. */
120: {'T', "Parity declustering",
121: RF_NK2(rf_MakeLayoutSpecificDeclustered, &distSpareNo)
122: RF_NU(
123: rf_ConfigureDeclustered,
124: rf_MapSectorDeclustered, rf_MapParityDeclustered, NULL,
125: rf_IdentifyStripeDeclustered,
126: rf_RaidFiveDagSelect,
127: rf_MapSIDToPSIDDeclustered,
128: rf_GetDefaultHeadSepLimitDeclustered,
129: rf_GetDefaultNumFloatingReconBuffersDeclustered,
130: NULL, NULL,
131: rf_SubmitReconBufferBasic,
132: rf_VerifyParityBasic,
133: 1,
134: DefaultStates,
135: 0)
136: },
137:
138: /* Parity declustering with distributed sparing. */
139: {'D', "Distributed sparing parity declustering",
140: RF_NK2(rf_MakeLayoutSpecificDeclustered, &distSpareYes)
141: RF_NU(
142: rf_ConfigureDeclusteredDS,
143: rf_MapSectorDeclustered, rf_MapParityDeclustered, NULL,
144: rf_IdentifyStripeDeclustered,
145: rf_RaidFiveDagSelect,
146: rf_MapSIDToPSIDDeclustered,
147: rf_GetDefaultHeadSepLimitDeclustered,
148: rf_GetDefaultNumFloatingReconBuffersDeclustered,
149: rf_GetNumSpareRUsDeclustered, rf_InstallSpareTable,
150: rf_SubmitReconBufferBasic,
151: rf_VerifyParityBasic,
152: 1,
153: DefaultStates,
154: RF_DISTRIBUTE_SPARE | RF_BD_DECLUSTERED)
155: },
156:
157: #if RF_INCLUDE_DECL_PQ > 0
158: /* Declustered P+Q. */
159: {'Q', "Declustered P+Q",
160: RF_NK2(rf_MakeLayoutSpecificDeclustered, &distSpareNo)
161: RF_NU(
162: rf_ConfigureDeclusteredPQ,
163: rf_MapSectorDeclusteredPQ, rf_MapParityDeclusteredPQ,
164: rf_MapQDeclusteredPQ,
165: rf_IdentifyStripeDeclusteredPQ,
166: rf_PQDagSelect,
167: rf_MapSIDToPSIDDeclustered,
168: rf_GetDefaultHeadSepLimitDeclustered,
169: rf_GetDefaultNumFloatingReconBuffersPQ,
170: NULL, NULL,
171: NULL,
172: rf_VerifyParityBasic,
173: 2,
174: DefaultStates,
175: 0)
176: },
177: #endif /* RF_INCLUDE_DECL_PQ > 0 */
178:
179: #if RF_INCLUDE_RAID5_RS > 0
180: /* RAID 5 with rotated sparing. */
181: {'R', "RAID Level 5 rotated sparing",
182: RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
183: RF_NU(
184: rf_ConfigureRAID5_RS,
185: rf_MapSectorRAID5_RS, rf_MapParityRAID5_RS, NULL,
186: rf_IdentifyStripeRAID5_RS,
187: rf_RaidFiveDagSelect,
188: rf_MapSIDToPSIDRAID5_RS,
189: rf_GetDefaultHeadSepLimitRAID5,
190: rf_GetDefaultNumFloatingReconBuffersRAID5,
191: rf_GetNumSpareRUsRAID5_RS, NULL,
192: rf_SubmitReconBufferBasic,
193: rf_VerifyParityBasic,
194: 1,
195: DefaultStates,
196: RF_DISTRIBUTE_SPARE)
197: },
198: #endif /* RF_INCLUDE_RAID5_RS > 0 */
199:
200: #if RF_INCLUDE_CHAINDECLUSTER > 0
201: /* Chained Declustering. */
202: {'C', "Chained Declustering",
203: RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
204: RF_NU(
205: rf_ConfigureChainDecluster,
206: rf_MapSectorChainDecluster, rf_MapParityChainDecluster,
207: NULL,
208: rf_IdentifyStripeChainDecluster,
209: rf_RAIDCDagSelect,
210: rf_MapSIDToPSIDChainDecluster,
211: NULL,
212: NULL,
213: rf_GetNumSpareRUsChainDecluster, NULL,
214: rf_SubmitReconBufferBasic,
215: rf_VerifyParityBasic,
216: 1,
217: DefaultStates,
218: 0)
219: },
220: #endif /* RF_INCLUDE_CHAINDECLUSTER > 0 */
221:
222: #if RF_INCLUDE_INTERDECLUSTER > 0
223: /* Interleaved Declustering. */
224: {'I', "Interleaved Declustering",
225: RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
226: RF_NU(
227: rf_ConfigureInterDecluster,
228: rf_MapSectorInterDecluster, rf_MapParityInterDecluster,
229: NULL,
230: rf_IdentifyStripeInterDecluster,
231: rf_RAIDIDagSelect,
232: rf_MapSIDToPSIDInterDecluster,
233: rf_GetDefaultHeadSepLimitInterDecluster,
234: rf_GetDefaultNumFloatingReconBuffersInterDecluster,
235: rf_GetNumSpareRUsInterDecluster, NULL,
236: rf_SubmitReconBufferBasic,
237: rf_VerifyParityBasic,
238: 1,
239: DefaultStates,
240: RF_DISTRIBUTE_SPARE)
241: },
242: #endif /* RF_INCLUDE_INTERDECLUSTER > 0 */
243:
244: #if RF_INCLUDE_RAID0 > 0
245: /* RAID level 0. */
246: {'0', "RAID Level 0",
247: RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
248: RF_NU(
249: rf_ConfigureRAID0,
250: rf_MapSectorRAID0, rf_MapParityRAID0, NULL,
251: rf_IdentifyStripeRAID0,
252: rf_RAID0DagSelect,
253: rf_MapSIDToPSIDRAID0,
254: NULL,
255: NULL,
256: NULL, NULL,
257: NULL,
258: rf_VerifyParityRAID0,
259: 0,
260: DefaultStates,
261: 0)
262: },
263: #endif /* RF_INCLUDE_RAID0 > 0 */
264:
265: #if RF_INCLUDE_RAID1 > 0
266: /* RAID level 1. */
267: {'1', "RAID Level 1",
268: RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
269: RF_NU(
270: rf_ConfigureRAID1,
271: rf_MapSectorRAID1, rf_MapParityRAID1, NULL,
272: rf_IdentifyStripeRAID1,
273: rf_RAID1DagSelect,
274: rf_MapSIDToPSIDRAID1,
275: NULL,
276: NULL,
277: NULL, NULL,
278: rf_SubmitReconBufferRAID1,
279: rf_VerifyParityRAID1,
280: 1,
281: DefaultStates,
282: 0)
283: },
284: #endif /* RF_INCLUDE_RAID1 > 0 */
285:
286: #if RF_INCLUDE_RAID4 > 0
287: /* RAID level 4. */
288: {'4', "RAID Level 4",
289: RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
290: RF_NU(
291: rf_ConfigureRAID4,
292: rf_MapSectorRAID4, rf_MapParityRAID4, NULL,
293: rf_IdentifyStripeRAID4,
294: rf_RaidFiveDagSelect,
295: rf_MapSIDToPSIDRAID4,
296: rf_GetDefaultHeadSepLimitRAID4,
297: rf_GetDefaultNumFloatingReconBuffersRAID4,
298: NULL, NULL,
299: rf_SubmitReconBufferBasic,
300: rf_VerifyParityBasic,
301: 1,
302: DefaultStates,
303: 0)
304: },
305: #endif /* RF_INCLUDE_RAID4 > 0 */
306:
307: #if RF_INCLUDE_RAID5 > 0
308: /* RAID level 5. */
309: {'5', "RAID Level 5",
310: RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
311: RF_NU(
312: rf_ConfigureRAID5,
313: rf_MapSectorRAID5, rf_MapParityRAID5, NULL,
314: rf_IdentifyStripeRAID5,
315: rf_RaidFiveDagSelect,
316: rf_MapSIDToPSIDRAID5,
317: rf_GetDefaultHeadSepLimitRAID5,
318: rf_GetDefaultNumFloatingReconBuffersRAID5,
319: NULL, NULL,
320: rf_SubmitReconBufferBasic,
321: rf_VerifyParityBasic,
322: 1,
323: DefaultStates,
324: 0)
325: },
326: #endif /* RF_INCLUDE_RAID5 > 0 */
327:
328: #if RF_INCLUDE_EVENODD > 0
329: /* Evenodd. */
330: {'E', "EvenOdd",
331: RF_NK2(rf_MakeLayoutSpecificNULL, NULL)
332: RF_NU(
333: rf_ConfigureEvenOdd,
334: rf_MapSectorRAID5, rf_MapParityEvenOdd, rf_MapEEvenOdd,
335: rf_IdentifyStripeEvenOdd,
336: rf_EODagSelect,
337: rf_MapSIDToPSIDRAID5,
338: NULL,
339: NULL,
340: NULL, NULL,
341: NULL, /* No reconstruction, yet. */
342: rf_VerifyParityEvenOdd,
343: 2,
344: DefaultStates,
345: 0)
346: },
347: #endif /* RF_INCLUDE_EVENODD > 0 */
348:
349: #if RF_INCLUDE_EVENODD > 0
350: /* Declustered Evenodd. */
351: {'e', "Declustered EvenOdd",
352: RF_NK2(rf_MakeLayoutSpecificDeclustered, &distSpareNo)
353: RF_NU(
354: rf_ConfigureDeclusteredPQ,
355: rf_MapSectorDeclusteredPQ, rf_MapParityDeclusteredPQ,
356: 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:
427: #if RF_UTILITY == 0
428: /*****************************************************************************
429: *
430: * ConfigureLayout
431: *
432: * Read the configuration file and set up the RAID layout parameters.
433: * After reading common params, invokes the layout-specific configuration
434: * routine to finish the configuration.
435: *
436: *****************************************************************************/
437: int
438: rf_ConfigureLayout(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
439: RF_Config_t *cfgPtr)
440: {
441: RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
442: RF_ParityConfig_t parityConfig;
443: RF_LayoutSW_t *p;
444: int retval;
445:
446: layoutPtr->sectorsPerStripeUnit = cfgPtr->sectPerSU;
447: layoutPtr->SUsPerPU = cfgPtr->SUsPerPU;
448: layoutPtr->SUsPerRU = cfgPtr->SUsPerRU;
449: parityConfig = cfgPtr->parityConfig;
450:
451: if (layoutPtr->sectorsPerStripeUnit <= 0) {
452: RF_ERRORMSG2("raid%d: Invalid sectorsPerStripeUnit: %d.\n",
453: raidPtr->raidid, (int)layoutPtr->sectorsPerStripeUnit);
454: return (EINVAL);
455: }
456:
457: layoutPtr->stripeUnitsPerDisk = raidPtr->sectorsPerDisk /
458: layoutPtr->sectorsPerStripeUnit;
459:
460: p = rf_GetLayout(parityConfig);
461: if (p == NULL) {
462: RF_ERRORMSG1("Unknown parity configuration '%c'", parityConfig);
463: return (EINVAL);
464: }
465: RF_ASSERT(p->parityConfig == parityConfig);
466: layoutPtr->map = p;
467:
468: /* Initialize the specific layout. */
469:
470: retval = (p->Configure) (listp, raidPtr, cfgPtr);
471:
472: if (retval)
473: return (retval);
474:
475: layoutPtr->dataBytesPerStripe = layoutPtr->dataSectorsPerStripe <<
476: raidPtr->logBytesPerSector;
477: raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk *
478: layoutPtr->sectorsPerStripeUnit;
479:
480: if (rf_forceNumFloatingReconBufs >= 0) {
481: raidPtr->numFloatingReconBufs = rf_forceNumFloatingReconBufs;
482: } else {
483: raidPtr->numFloatingReconBufs =
484: rf_GetDefaultNumFloatingReconBuffers(raidPtr);
485: }
486:
487: if (rf_forceHeadSepLimit >= 0) {
488: raidPtr->headSepLimit = rf_forceHeadSepLimit;
489: } else {
490: raidPtr->headSepLimit = rf_GetDefaultHeadSepLimit(raidPtr);
491: }
492:
493: #ifdef RAIDDEBUG
494: if (raidPtr->headSepLimit >= 0) {
495: printf("RAIDFRAME(%s): Using %ld floating recon bufs"
496: " with head sep limit %ld.\n", layoutPtr->map->configName,
497: (long) raidPtr->numFloatingReconBufs,
498: (long) raidPtr->headSepLimit);
499: } else {
500: printf("RAIDFRAME(%s): Using %ld floating recon bufs"
501: " with no head sep limit.\n", layoutPtr->map->configName,
502: (long) raidPtr->numFloatingReconBufs);
503: }
504: #endif /* RAIDDEBUG */
505:
506: return (0);
507: }
508:
509: /*
510: * Typically there is a 1-1 mapping between stripes and parity stripes.
511: * However, the declustering code supports packing multiple stripes into
512: * a single parity stripe, so as to increase the size of the reconstruction
513: * unit without affecting the size of the stripe unit. This routine finds
514: * the parity stripe identifier associated with a stripe ID. There is also
515: * a RaidAddressToParityStripeID macro in layout.h
516: */
517: RF_StripeNum_t
518: rf_MapStripeIDToParityStripeID(RF_RaidLayout_t *layoutPtr,
519: RF_StripeNum_t stripeID, RF_ReconUnitNum_t *which_ru)
520: {
521: RF_StripeNum_t parityStripeID;
522:
523: /* Quick exit in the common case of SUsPerPU == 1. */
524: if ((layoutPtr->SUsPerPU == 1) || !layoutPtr->map->MapSIDToPSID) {
525: *which_ru = 0;
526: return (stripeID);
527: } else {
528: (layoutPtr->map->MapSIDToPSID) (layoutPtr, stripeID,
529: &parityStripeID, which_ru);
530: }
531: return (parityStripeID);
532: }
533: #endif /* RF_UTILITY == 0 */
CVSweb