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@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