#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rf_layout.c,v 1.20 2008/05/04 20:57:23 oster Exp $");
#include <dev/raidframe/raidframevar.h>
#include "rf_archs.h"
#include "rf_raid.h"
#include "rf_dag.h"
#include "rf_desc.h"
#include "rf_decluster.h"
#include "rf_pq.h"
#include "rf_declusterPQ.h"
#include "rf_raid0.h"
#include "rf_raid1.h"
#include "rf_raid4.h"
#include "rf_raid5.h"
#include "rf_states.h"
#if RF_INCLUDE_RAID5_RS > 0
#include "rf_raid5_rotatedspare.h"
#endif
#if RF_INCLUDE_CHAINDECLUSTER > 0
#include "rf_chaindecluster.h"
#endif
#if RF_INCLUDE_INTERDECLUSTER > 0
#include "rf_interdecluster.h"
#endif
#if RF_INCLUDE_PARITYLOGGING > 0
#include "rf_paritylogging.h"
#endif
#if RF_INCLUDE_EVENODD > 0
#include "rf_evenodd.h"
#endif
#include "rf_general.h"
#include "rf_driver.h"
#include "rf_parityscan.h"
#include "rf_reconbuffer.h"
#include "rf_reconutil.h"
static const RF_AccessState_t DefaultStates[] = {
rf_QuiesceState,
rf_IncrAccessesCountState,
rf_MapState,
rf_LockState,
rf_CreateDAGState,
rf_ExecuteDAGState,
rf_ProcessDAGState,
rf_CleanupState,
rf_DecrAccessesCountState,
rf_LastState};
#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
static const RF_LayoutSW_t mapsw[] = {
#if RF_INCLUDE_PARITY_DECLUSTERING > 0
{'T', "Parity declustering",
RF_NU(
rf_ConfigureDeclustered,
rf_MapSectorDeclustered, rf_MapParityDeclustered, NULL,
rf_IdentifyStripeDeclustered,
rf_RaidFiveDagSelect,
rf_MapSIDToPSIDDeclustered,
rf_GetDefaultHeadSepLimitDeclustered,
rf_GetDefaultNumFloatingReconBuffersDeclustered,
NULL, NULL,
rf_SubmitReconBufferBasic,
rf_VerifyParityBasic,
1,
DefaultStates,
0)
},
#endif
#if RF_INCLUDE_PARITY_DECLUSTERING_DS > 0
{'D', "Distributed sparing parity declustering",
RF_NU(
rf_ConfigureDeclusteredDS,
rf_MapSectorDeclustered, rf_MapParityDeclustered, NULL,
rf_IdentifyStripeDeclustered,
rf_RaidFiveDagSelect,
rf_MapSIDToPSIDDeclustered,
rf_GetDefaultHeadSepLimitDeclustered,
rf_GetDefaultNumFloatingReconBuffersDeclustered,
rf_GetNumSpareRUsDeclustered, rf_InstallSpareTable,
rf_SubmitReconBufferBasic,
rf_VerifyParityBasic,
1,
DefaultStates,
RF_DISTRIBUTE_SPARE | RF_BD_DECLUSTERED)
},
#endif
#if RF_INCLUDE_DECL_PQ > 0
{'Q', "Declustered P+Q",
RF_NU(
rf_ConfigureDeclusteredPQ,
rf_MapSectorDeclusteredPQ, rf_MapParityDeclusteredPQ, rf_MapQDeclusteredPQ,
rf_IdentifyStripeDeclusteredPQ,
rf_PQDagSelect,
rf_MapSIDToPSIDDeclustered,
rf_GetDefaultHeadSepLimitDeclustered,
rf_GetDefaultNumFloatingReconBuffersPQ,
NULL, NULL,
NULL,
rf_VerifyParityBasic,
2,
DefaultStates,
0)
},
#endif
#if RF_INCLUDE_RAID5_RS > 0
{'R', "RAID Level 5 rotated sparing",
RF_NU(
rf_ConfigureRAID5_RS,
rf_MapSectorRAID5_RS, rf_MapParityRAID5_RS, NULL,
rf_IdentifyStripeRAID5_RS,
rf_RaidFiveDagSelect,
rf_MapSIDToPSIDRAID5_RS,
rf_GetDefaultHeadSepLimitRAID5,
rf_GetDefaultNumFloatingReconBuffersRAID5,
rf_GetNumSpareRUsRAID5_RS, NULL,
rf_SubmitReconBufferBasic,
rf_VerifyParityBasic,
1,
DefaultStates,
RF_DISTRIBUTE_SPARE)
},
#endif
#if RF_INCLUDE_CHAINDECLUSTER > 0
{'C', "Chained Declustering",
RF_NU(
rf_ConfigureChainDecluster,
rf_MapSectorChainDecluster, rf_MapParityChainDecluster, NULL,
rf_IdentifyStripeChainDecluster,
rf_RAIDCDagSelect,
rf_MapSIDToPSIDChainDecluster,
NULL,
NULL,
rf_GetNumSpareRUsChainDecluster, NULL,
rf_SubmitReconBufferBasic,
rf_VerifyParityBasic,
1,
DefaultStates,
0)
},
#endif
#if RF_INCLUDE_INTERDECLUSTER > 0
{'I', "Interleaved Declustering",
RF_NU(
rf_ConfigureInterDecluster,
rf_MapSectorInterDecluster, rf_MapParityInterDecluster, NULL,
rf_IdentifyStripeInterDecluster,
rf_RAIDIDagSelect,
rf_MapSIDToPSIDInterDecluster,
rf_GetDefaultHeadSepLimitInterDecluster,
rf_GetDefaultNumFloatingReconBuffersInterDecluster,
rf_GetNumSpareRUsInterDecluster, NULL,
rf_SubmitReconBufferBasic,
rf_VerifyParityBasic,
1,
DefaultStates,
RF_DISTRIBUTE_SPARE)
},
#endif
#if RF_INCLUDE_RAID0 > 0
{'0', "RAID Level 0",
RF_NU(
rf_ConfigureRAID0,
rf_MapSectorRAID0, rf_MapParityRAID0, NULL,
rf_IdentifyStripeRAID0,
rf_RAID0DagSelect,
rf_MapSIDToPSIDRAID0,
NULL,
NULL,
NULL, NULL,
NULL,
rf_VerifyParityRAID0,
0,
DefaultStates,
0)
},
#endif
#if RF_INCLUDE_RAID1 > 0
{'1', "RAID Level 1",
RF_NU(
rf_ConfigureRAID1,
rf_MapSectorRAID1, rf_MapParityRAID1, NULL,
rf_IdentifyStripeRAID1,
rf_RAID1DagSelect,
rf_MapSIDToPSIDRAID1,
rf_GetDefaultHeadSepLimitRAID1,
NULL,
NULL, NULL,
rf_SubmitReconBufferRAID1,
rf_VerifyParityRAID1,
1,
DefaultStates,
0)
},
#endif
#if RF_INCLUDE_RAID4 > 0
{'4', "RAID Level 4",
RF_NU(
rf_ConfigureRAID4,
rf_MapSectorRAID4, rf_MapParityRAID4, NULL,
rf_IdentifyStripeRAID4,
rf_RaidFiveDagSelect,
rf_MapSIDToPSIDRAID4,
rf_GetDefaultHeadSepLimitRAID4,
rf_GetDefaultNumFloatingReconBuffersRAID4,
NULL, NULL,
rf_SubmitReconBufferBasic,
rf_VerifyParityBasic,
1,
DefaultStates,
0)
},
#endif
#if RF_INCLUDE_RAID5 > 0
{'5', "RAID Level 5",
RF_NU(
rf_ConfigureRAID5,
rf_MapSectorRAID5, rf_MapParityRAID5, NULL,
rf_IdentifyStripeRAID5,
rf_RaidFiveDagSelect,
rf_MapSIDToPSIDRAID5,
rf_GetDefaultHeadSepLimitRAID5,
rf_GetDefaultNumFloatingReconBuffersRAID5,
NULL, NULL,
rf_SubmitReconBufferBasic,
rf_VerifyParityBasic,
1,
DefaultStates,
0)
},
#endif
#if RF_INCLUDE_EVENODD > 0
{'E', "EvenOdd",
RF_NU(
rf_ConfigureEvenOdd,
rf_MapSectorRAID5, rf_MapParityEvenOdd, rf_MapEEvenOdd,
rf_IdentifyStripeEvenOdd,
rf_EODagSelect,
rf_MapSIDToPSIDRAID5,
NULL,
NULL,
NULL, NULL,
NULL,
rf_VerifyParityEvenOdd,
2,
DefaultStates,
0)
},
#endif
#if RF_INCLUDE_EVENODD > 0
{'e', "Declustered EvenOdd",
RF_NU(
rf_ConfigureDeclusteredPQ,
rf_MapSectorDeclusteredPQ, rf_MapParityDeclusteredPQ, rf_MapQDeclusteredPQ,
rf_IdentifyStripeDeclusteredPQ,
rf_EODagSelect,
rf_MapSIDToPSIDRAID5,
rf_GetDefaultHeadSepLimitDeclustered,
rf_GetDefaultNumFloatingReconBuffersPQ,
NULL, NULL,
NULL,
rf_VerifyParityEvenOdd,
2,
DefaultStates,
0)
},
#endif
#if RF_INCLUDE_PARITYLOGGING > 0
{'L', "Parity logging",
RF_NU(
rf_ConfigureParityLogging,
rf_MapSectorParityLogging, rf_MapParityParityLogging, NULL,
rf_IdentifyStripeParityLogging,
rf_ParityLoggingDagSelect,
rf_MapSIDToPSIDParityLogging,
rf_GetDefaultHeadSepLimitParityLogging,
rf_GetDefaultNumFloatingReconBuffersParityLogging,
NULL, NULL,
rf_SubmitReconBufferBasic,
NULL,
1,
DefaultStates,
0)
},
#endif
{'\0', NULL,
RF_NU(
NULL,
NULL, NULL, NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL, NULL,
NULL,
NULL,
0,
NULL,
0)
}
};
const RF_LayoutSW_t *
rf_GetLayout(RF_ParityConfig_t parityConfig)
{
const RF_LayoutSW_t *p;
for (p = &mapsw[0]; p->parityConfig; p++)
if (p->parityConfig == parityConfig)
break;
if (!p->parityConfig)
return (NULL);
RF_ASSERT(p->parityConfig == parityConfig);
return (p);
}
int
rf_ConfigureLayout(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
RF_Config_t *cfgPtr)
{
RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
RF_ParityConfig_t parityConfig;
const RF_LayoutSW_t *p;
int retval;
layoutPtr->sectorsPerStripeUnit = cfgPtr->sectPerSU;
layoutPtr->SUsPerPU = cfgPtr->SUsPerPU;
layoutPtr->SUsPerRU = cfgPtr->SUsPerRU;
parityConfig = cfgPtr->parityConfig;
if (layoutPtr->sectorsPerStripeUnit <= 0) {
RF_ERRORMSG2("raid%d: Invalid sectorsPerStripeUnit: %d\n",
raidPtr->raidid,
(int)layoutPtr->sectorsPerStripeUnit);
return (EINVAL);
}
if (layoutPtr->SUsPerPU <= 0) {
RF_ERRORMSG2("raid%d: Invalid StripeUnitsPerParityUnit: %d\n",
raidPtr->raidid,
(int)layoutPtr->SUsPerPU);
return (EINVAL);
}
if (layoutPtr->SUsPerRU <= 0) {
RF_ERRORMSG2("raid%d: Invalid StripeUnitsPerReconstructUnit: %d\n",
raidPtr->raidid,
(int)layoutPtr->SUsPerRU);
return (EINVAL);
}
layoutPtr->stripeUnitsPerDisk = raidPtr->sectorsPerDisk / layoutPtr->sectorsPerStripeUnit;
p = rf_GetLayout(parityConfig);
if (p == NULL) {
RF_ERRORMSG1("Unknown parity configuration '%c'", parityConfig);
return (EINVAL);
}
RF_ASSERT(p->parityConfig == parityConfig);
layoutPtr->map = p;
retval = (p->Configure) (listp, raidPtr, cfgPtr);
if (retval)
return (retval);
raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
if (rf_forceNumFloatingReconBufs >= 0) {
raidPtr->numFloatingReconBufs = rf_forceNumFloatingReconBufs;
} else {
raidPtr->numFloatingReconBufs = rf_GetDefaultNumFloatingReconBuffers(raidPtr);
}
if (rf_forceHeadSepLimit >= 0) {
raidPtr->headSepLimit = rf_forceHeadSepLimit;
} else {
raidPtr->headSepLimit = rf_GetDefaultHeadSepLimit(raidPtr);
}
return (0);
}
RF_StripeNum_t
rf_MapStripeIDToParityStripeID(RF_RaidLayout_t *layoutPtr,
RF_StripeNum_t stripeID,
RF_ReconUnitNum_t *which_ru)
{
RF_StripeNum_t parityStripeID;
if ((layoutPtr->SUsPerPU == 1) || !layoutPtr->map->MapSIDToPSID) {
*which_ru = 0;
return (stripeID);
} else {
(layoutPtr->map->MapSIDToPSID) (layoutPtr, stripeID, &parityStripeID, which_ru);
}
return (parityStripeID);
}