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