Home | History | Annotate | Line # | Download | only in raidframe
      1 /*	$NetBSD: rf_layout.c,v 1.20 2008/05/04 20:57:23 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 <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: rf_layout.c,v 1.20 2008/05/04 20:57:23 oster Exp $");
     34 
     35 #include <dev/raidframe/raidframevar.h>
     36 
     37 #include "rf_archs.h"
     38 #include "rf_raid.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
     74  *    sector, map parity, identify stripe, dag selection, map stripeid
     75  *    to parity stripe id (optional), num faults tolerated, special
     76  *    flags.
     77  *
     78  ***********************************************************************/
     79 
     80 static const RF_AccessState_t DefaultStates[] = {
     81 					   rf_QuiesceState,
     82 					   rf_IncrAccessesCountState,
     83 					   rf_MapState,
     84 					   rf_LockState,
     85 					   rf_CreateDAGState,
     86 					   rf_ExecuteDAGState,
     87 					   rf_ProcessDAGState,
     88 					   rf_CleanupState,
     89 					   rf_DecrAccessesCountState,
     90 					   rf_LastState};
     91 
     92 #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
     93 
     94 /* Note that if you add any new RAID types to this list, that you must
     95    also update the mapsw[] table in the raidctl sources */
     96 
     97 static const RF_LayoutSW_t mapsw[] = {
     98 #if RF_INCLUDE_PARITY_DECLUSTERING > 0
     99 	/* parity declustering */
    100 	{'T', "Parity declustering",
    101 		RF_NU(
    102 		    rf_ConfigureDeclustered,
    103 		    rf_MapSectorDeclustered, rf_MapParityDeclustered, NULL,
    104 		    rf_IdentifyStripeDeclustered,
    105 		    rf_RaidFiveDagSelect,
    106 		    rf_MapSIDToPSIDDeclustered,
    107 		    rf_GetDefaultHeadSepLimitDeclustered,
    108 		    rf_GetDefaultNumFloatingReconBuffersDeclustered,
    109 		    NULL, NULL,
    110 		    rf_SubmitReconBufferBasic,
    111 		    rf_VerifyParityBasic,
    112 		    1,
    113 		    DefaultStates,
    114 		    0)
    115 	},
    116 #endif
    117 
    118 #if RF_INCLUDE_PARITY_DECLUSTERING_DS > 0
    119 	/* parity declustering with distributed sparing */
    120 	{'D', "Distributed sparing parity declustering",
    121 		RF_NU(
    122 		    rf_ConfigureDeclusteredDS,
    123 		    rf_MapSectorDeclustered, rf_MapParityDeclustered, NULL,
    124 		    rf_IdentifyStripeDeclustered,
    125 		    rf_RaidFiveDagSelect,
    126 		    rf_MapSIDToPSIDDeclustered,
    127 		    rf_GetDefaultHeadSepLimitDeclustered,
    128 		    rf_GetDefaultNumFloatingReconBuffersDeclustered,
    129 		    rf_GetNumSpareRUsDeclustered, rf_InstallSpareTable,
    130 		    rf_SubmitReconBufferBasic,
    131 		    rf_VerifyParityBasic,
    132 		    1,
    133 		    DefaultStates,
    134 		    RF_DISTRIBUTE_SPARE | RF_BD_DECLUSTERED)
    135 	},
    136 #endif
    137 
    138 #if RF_INCLUDE_DECL_PQ > 0
    139 	/* declustered P+Q */
    140 	{'Q', "Declustered P+Q",
    141 		RF_NU(
    142 		    rf_ConfigureDeclusteredPQ,
    143 		    rf_MapSectorDeclusteredPQ, rf_MapParityDeclusteredPQ, rf_MapQDeclusteredPQ,
    144 		    rf_IdentifyStripeDeclusteredPQ,
    145 		    rf_PQDagSelect,
    146 		    rf_MapSIDToPSIDDeclustered,
    147 		    rf_GetDefaultHeadSepLimitDeclustered,
    148 		    rf_GetDefaultNumFloatingReconBuffersPQ,
    149 		    NULL, NULL,
    150 		    NULL,
    151 		    rf_VerifyParityBasic,
    152 		    2,
    153 		    DefaultStates,
    154 		    0)
    155 	},
    156 #endif				/* RF_INCLUDE_DECL_PQ > 0 */
    157 
    158 #if RF_INCLUDE_RAID5_RS > 0
    159 	/* RAID 5 with rotated sparing */
    160 	{'R', "RAID Level 5 rotated sparing",
    161 		RF_NU(
    162 		    rf_ConfigureRAID5_RS,
    163 		    rf_MapSectorRAID5_RS, rf_MapParityRAID5_RS, NULL,
    164 		    rf_IdentifyStripeRAID5_RS,
    165 		    rf_RaidFiveDagSelect,
    166 		    rf_MapSIDToPSIDRAID5_RS,
    167 		    rf_GetDefaultHeadSepLimitRAID5,
    168 		    rf_GetDefaultNumFloatingReconBuffersRAID5,
    169 		    rf_GetNumSpareRUsRAID5_RS, NULL,
    170 		    rf_SubmitReconBufferBasic,
    171 		    rf_VerifyParityBasic,
    172 		    1,
    173 		    DefaultStates,
    174 		    RF_DISTRIBUTE_SPARE)
    175 	},
    176 #endif				/* RF_INCLUDE_RAID5_RS > 0 */
    177 
    178 #if RF_INCLUDE_CHAINDECLUSTER > 0
    179 	/* Chained Declustering */
    180 	{'C', "Chained Declustering",
    181 		RF_NU(
    182 		    rf_ConfigureChainDecluster,
    183 		    rf_MapSectorChainDecluster, rf_MapParityChainDecluster, NULL,
    184 		    rf_IdentifyStripeChainDecluster,
    185 		    rf_RAIDCDagSelect,
    186 		    rf_MapSIDToPSIDChainDecluster,
    187 		    NULL,
    188 		    NULL,
    189 		    rf_GetNumSpareRUsChainDecluster, NULL,
    190 		    rf_SubmitReconBufferBasic,
    191 		    rf_VerifyParityBasic,
    192 		    1,
    193 		    DefaultStates,
    194 		    0)
    195 	},
    196 #endif				/* RF_INCLUDE_CHAINDECLUSTER > 0 */
    197 
    198 #if RF_INCLUDE_INTERDECLUSTER > 0
    199 	/* Interleaved Declustering */
    200 	{'I', "Interleaved Declustering",
    201 		RF_NU(
    202 		    rf_ConfigureInterDecluster,
    203 		    rf_MapSectorInterDecluster, rf_MapParityInterDecluster, NULL,
    204 		    rf_IdentifyStripeInterDecluster,
    205 		    rf_RAIDIDagSelect,
    206 		    rf_MapSIDToPSIDInterDecluster,
    207 		    rf_GetDefaultHeadSepLimitInterDecluster,
    208 		    rf_GetDefaultNumFloatingReconBuffersInterDecluster,
    209 		    rf_GetNumSpareRUsInterDecluster, NULL,
    210 		    rf_SubmitReconBufferBasic,
    211 		    rf_VerifyParityBasic,
    212 		    1,
    213 		    DefaultStates,
    214 		    RF_DISTRIBUTE_SPARE)
    215 	},
    216 #endif				/* RF_INCLUDE_INTERDECLUSTER > 0 */
    217 
    218 #if RF_INCLUDE_RAID0 > 0
    219 	/* RAID level 0 */
    220 	{'0', "RAID Level 0",
    221 		RF_NU(
    222 		    rf_ConfigureRAID0,
    223 		    rf_MapSectorRAID0, rf_MapParityRAID0, NULL,
    224 		    rf_IdentifyStripeRAID0,
    225 		    rf_RAID0DagSelect,
    226 		    rf_MapSIDToPSIDRAID0,
    227 		    NULL,
    228 		    NULL,
    229 		    NULL, NULL,
    230 		    NULL,
    231 		    rf_VerifyParityRAID0,
    232 		    0,
    233 		    DefaultStates,
    234 		    0)
    235 	},
    236 #endif				/* RF_INCLUDE_RAID0 > 0 */
    237 
    238 #if RF_INCLUDE_RAID1 > 0
    239 	/* RAID level 1 */
    240 	{'1', "RAID Level 1",
    241 		RF_NU(
    242 		    rf_ConfigureRAID1,
    243 		    rf_MapSectorRAID1, rf_MapParityRAID1, NULL,
    244 		    rf_IdentifyStripeRAID1,
    245 		    rf_RAID1DagSelect,
    246 		    rf_MapSIDToPSIDRAID1,
    247 		    rf_GetDefaultHeadSepLimitRAID1,
    248 		    NULL,
    249 		    NULL, NULL,
    250 		    rf_SubmitReconBufferRAID1,
    251 		    rf_VerifyParityRAID1,
    252 		    1,
    253 		    DefaultStates,
    254 		    0)
    255 	},
    256 #endif				/* RF_INCLUDE_RAID1 > 0 */
    257 
    258 #if RF_INCLUDE_RAID4 > 0
    259 	/* RAID level 4 */
    260 	{'4', "RAID Level 4",
    261 		RF_NU(
    262 		    rf_ConfigureRAID4,
    263 		    rf_MapSectorRAID4, rf_MapParityRAID4, NULL,
    264 		    rf_IdentifyStripeRAID4,
    265 		    rf_RaidFiveDagSelect,
    266 		    rf_MapSIDToPSIDRAID4,
    267 		    rf_GetDefaultHeadSepLimitRAID4,
    268 		    rf_GetDefaultNumFloatingReconBuffersRAID4,
    269 		    NULL, NULL,
    270 		    rf_SubmitReconBufferBasic,
    271 		    rf_VerifyParityBasic,
    272 		    1,
    273 		    DefaultStates,
    274 		    0)
    275 	},
    276 #endif				/* RF_INCLUDE_RAID4 > 0 */
    277 
    278 #if RF_INCLUDE_RAID5 > 0
    279 	/* RAID level 5 */
    280 	{'5', "RAID Level 5",
    281 		RF_NU(
    282 		    rf_ConfigureRAID5,
    283 		    rf_MapSectorRAID5, rf_MapParityRAID5, NULL,
    284 		    rf_IdentifyStripeRAID5,
    285 		    rf_RaidFiveDagSelect,
    286 		    rf_MapSIDToPSIDRAID5,
    287 		    rf_GetDefaultHeadSepLimitRAID5,
    288 		    rf_GetDefaultNumFloatingReconBuffersRAID5,
    289 		    NULL, NULL,
    290 		    rf_SubmitReconBufferBasic,
    291 		    rf_VerifyParityBasic,
    292 		    1,
    293 		    DefaultStates,
    294 		    0)
    295 	},
    296 #endif				/* RF_INCLUDE_RAID5 > 0 */
    297 
    298 #if RF_INCLUDE_EVENODD > 0
    299 	/* Evenodd */
    300 	{'E', "EvenOdd",
    301 		RF_NU(
    302 		    rf_ConfigureEvenOdd,
    303 		    rf_MapSectorRAID5, rf_MapParityEvenOdd, rf_MapEEvenOdd,
    304 		    rf_IdentifyStripeEvenOdd,
    305 		    rf_EODagSelect,
    306 		    rf_MapSIDToPSIDRAID5,
    307 		    NULL,
    308 		    NULL,
    309 		    NULL, NULL,
    310 		    NULL,	/* no reconstruction, yet */
    311 		    rf_VerifyParityEvenOdd,
    312 		    2,
    313 		    DefaultStates,
    314 		    0)
    315 	},
    316 #endif				/* RF_INCLUDE_EVENODD > 0 */
    317 
    318 #if RF_INCLUDE_EVENODD > 0
    319 	/* Declustered Evenodd */
    320 	{'e', "Declustered EvenOdd",
    321 		RF_NU(
    322 		    rf_ConfigureDeclusteredPQ,
    323 		    rf_MapSectorDeclusteredPQ, rf_MapParityDeclusteredPQ, rf_MapQDeclusteredPQ,
    324 		    rf_IdentifyStripeDeclusteredPQ,
    325 		    rf_EODagSelect,
    326 		    rf_MapSIDToPSIDRAID5,
    327 		    rf_GetDefaultHeadSepLimitDeclustered,
    328 		    rf_GetDefaultNumFloatingReconBuffersPQ,
    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_PARITYLOGGING > 0
    339 	/* parity logging */
    340 	{'L', "Parity logging",
    341 		RF_NU(
    342 		    rf_ConfigureParityLogging,
    343 		    rf_MapSectorParityLogging, rf_MapParityParityLogging, NULL,
    344 		    rf_IdentifyStripeParityLogging,
    345 		    rf_ParityLoggingDagSelect,
    346 		    rf_MapSIDToPSIDParityLogging,
    347 		    rf_GetDefaultHeadSepLimitParityLogging,
    348 		    rf_GetDefaultNumFloatingReconBuffersParityLogging,
    349 		    NULL, NULL,
    350 		    rf_SubmitReconBufferBasic,
    351 		    NULL,
    352 		    1,
    353 		    DefaultStates,
    354 		    0)
    355 	},
    356 #endif				/* RF_INCLUDE_PARITYLOGGING > 0 */
    357 
    358 	/* end-of-list marker */
    359 	{'\0', NULL,
    360 		RF_NU(
    361 		    NULL,
    362 		    NULL, NULL, NULL,
    363 		    NULL,
    364 		    NULL,
    365 		    NULL,
    366 		    NULL,
    367 		    NULL,
    368 		    NULL, NULL,
    369 		    NULL,
    370 		    NULL,
    371 		    0,
    372 		    NULL,
    373 		    0)
    374 	}
    375 };
    376 
    377 const RF_LayoutSW_t *
    378 rf_GetLayout(RF_ParityConfig_t parityConfig)
    379 {
    380 	const RF_LayoutSW_t *p;
    381 
    382 	/* look up the specific layout */
    383 	for (p = &mapsw[0]; p->parityConfig; p++)
    384 		if (p->parityConfig == parityConfig)
    385 			break;
    386 	if (!p->parityConfig)
    387 		return (NULL);
    388 	RF_ASSERT(p->parityConfig == parityConfig);
    389 	return (p);
    390 }
    391 
    392 /*****************************************************************************
    393  *
    394  * ConfigureLayout --
    395  *
    396  * read the configuration file and set up the RAID layout parameters.
    397  * After reading common params, invokes the layout-specific
    398  * configuration routine to finish the configuration.
    399  *
    400  ****************************************************************************/
    401 int
    402 rf_ConfigureLayout(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
    403 		   RF_Config_t *cfgPtr)
    404 {
    405 	RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
    406 	RF_ParityConfig_t parityConfig;
    407 	const RF_LayoutSW_t *p;
    408 	int     retval;
    409 
    410 	layoutPtr->sectorsPerStripeUnit = cfgPtr->sectPerSU;
    411 	layoutPtr->SUsPerPU = cfgPtr->SUsPerPU;
    412 	layoutPtr->SUsPerRU = cfgPtr->SUsPerRU;
    413 	parityConfig = cfgPtr->parityConfig;
    414 
    415 	if (layoutPtr->sectorsPerStripeUnit <= 0) {
    416 		RF_ERRORMSG2("raid%d: Invalid sectorsPerStripeUnit: %d\n",
    417 			     raidPtr->raidid,
    418 			     (int)layoutPtr->sectorsPerStripeUnit);
    419 		return (EINVAL);
    420 	}
    421 
    422 	if (layoutPtr->SUsPerPU <= 0) {
    423 		RF_ERRORMSG2("raid%d: Invalid StripeUnitsPerParityUnit: %d\n",
    424 			     raidPtr->raidid,
    425 			     (int)layoutPtr->SUsPerPU);
    426 		return (EINVAL);
    427 	}
    428 
    429 	if (layoutPtr->SUsPerRU <= 0) {
    430 		RF_ERRORMSG2("raid%d: Invalid StripeUnitsPerReconstructUnit: %d\n",
    431 			     raidPtr->raidid,
    432 			     (int)layoutPtr->SUsPerRU);
    433 		return (EINVAL);
    434 	}
    435 
    436 	layoutPtr->stripeUnitsPerDisk = raidPtr->sectorsPerDisk / layoutPtr->sectorsPerStripeUnit;
    437 
    438 	p = rf_GetLayout(parityConfig);
    439 	if (p == NULL) {
    440 		RF_ERRORMSG1("Unknown parity configuration '%c'", parityConfig);
    441 		return (EINVAL);
    442 	}
    443 	RF_ASSERT(p->parityConfig == parityConfig);
    444 	layoutPtr->map = p;
    445 
    446 	/* initialize the specific layout */
    447 
    448 	retval = (p->Configure) (listp, raidPtr, cfgPtr);
    449 
    450 	if (retval)
    451 		return (retval);
    452 
    453 	raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
    454 
    455 	if (rf_forceNumFloatingReconBufs >= 0) {
    456 		raidPtr->numFloatingReconBufs = rf_forceNumFloatingReconBufs;
    457 	} else {
    458 		raidPtr->numFloatingReconBufs = rf_GetDefaultNumFloatingReconBuffers(raidPtr);
    459 	}
    460 
    461 	if (rf_forceHeadSepLimit >= 0) {
    462 		raidPtr->headSepLimit = rf_forceHeadSepLimit;
    463 	} else {
    464 		raidPtr->headSepLimit = rf_GetDefaultHeadSepLimit(raidPtr);
    465 	}
    466 	return (0);
    467 }
    468 /* typically there is a 1-1 mapping between stripes and parity stripes.
    469  * however, the declustering code supports packing multiple stripes into
    470  * a single parity stripe, so as to increase the size of the reconstruction
    471  * unit without affecting the size of the stripe unit.  This routine finds
    472  * the parity stripe identifier associated with a stripe ID.  There is also
    473  * a RaidAddressToParityStripeID macro in layout.h
    474  */
    475 RF_StripeNum_t
    476 rf_MapStripeIDToParityStripeID(RF_RaidLayout_t *layoutPtr,
    477 			       RF_StripeNum_t stripeID,
    478 			       RF_ReconUnitNum_t *which_ru)
    479 {
    480 	RF_StripeNum_t parityStripeID;
    481 
    482 	/* quick exit in the common case of SUsPerPU==1 */
    483 	if ((layoutPtr->SUsPerPU == 1) || !layoutPtr->map->MapSIDToPSID) {
    484 		*which_ru = 0;
    485 		return (stripeID);
    486 	} else {
    487 		(layoutPtr->map->MapSIDToPSID) (layoutPtr, stripeID, &parityStripeID, which_ru);
    488 	}
    489 	return (parityStripeID);
    490 }
    491