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