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