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