Home | History | Annotate | Line # | Download | only in raidframe
rf_chaindecluster.c revision 1.6.2.3
      1 /*	$NetBSD: rf_chaindecluster.c,v 1.6.2.3 2002/10/18 02:43:42 nathanw Exp $	*/
      2 /*
      3  * Copyright (c) 1995 Carnegie-Mellon University.
      4  * All rights reserved.
      5  *
      6  * Author: Khalil Amiri
      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 /******************************************************************************
     30  *
     31  * rf_chaindecluster.c -- implements chained declustering
     32  *
     33  *****************************************************************************/
     34 
     35 #include <sys/cdefs.h>
     36 __KERNEL_RCSID(0, "$NetBSD: rf_chaindecluster.c,v 1.6.2.3 2002/10/18 02:43:42 nathanw Exp $");
     37 
     38 #include "rf_archs.h"
     39 
     40 #if (RF_INCLUDE_CHAINDECLUSTER > 0)
     41 
     42 #include <dev/raidframe/raidframevar.h>
     43 
     44 #include "rf_raid.h"
     45 #include "rf_chaindecluster.h"
     46 #include "rf_dag.h"
     47 #include "rf_dagutils.h"
     48 #include "rf_dagffrd.h"
     49 #include "rf_dagffwr.h"
     50 #include "rf_dagdegrd.h"
     51 #include "rf_dagfuncs.h"
     52 #include "rf_general.h"
     53 #include "rf_utils.h"
     54 
     55 typedef struct RF_ChaindeclusterConfigInfo_s {
     56 	RF_RowCol_t **stripeIdentifier;	/* filled in at config time and used
     57 					 * by IdentifyStripe */
     58 	RF_StripeCount_t numSparingRegions;
     59 	RF_StripeCount_t stripeUnitsPerSparingRegion;
     60 	RF_SectorNum_t mirrorStripeOffset;
     61 }       RF_ChaindeclusterConfigInfo_t;
     62 
     63 int
     64 rf_ConfigureChainDecluster(
     65     RF_ShutdownList_t ** listp,
     66     RF_Raid_t * raidPtr,
     67     RF_Config_t * cfgPtr)
     68 {
     69 	RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
     70 	RF_StripeCount_t num_used_stripeUnitsPerDisk;
     71 	RF_ChaindeclusterConfigInfo_t *info;
     72 	RF_RowCol_t i;
     73 
     74 	/* create a Chained Declustering configuration structure */
     75 	RF_MallocAndAdd(info, sizeof(RF_ChaindeclusterConfigInfo_t), (RF_ChaindeclusterConfigInfo_t *), raidPtr->cleanupList);
     76 	if (info == NULL)
     77 		return (ENOMEM);
     78 	layoutPtr->layoutSpecificInfo = (void *) info;
     79 
     80 	/* fill in the config structure.  */
     81 	info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol, 2, raidPtr->cleanupList);
     82 	if (info->stripeIdentifier == NULL)
     83 		return (ENOMEM);
     84 	for (i = 0; i < raidPtr->numCol; i++) {
     85 		info->stripeIdentifier[i][0] = i % raidPtr->numCol;
     86 		info->stripeIdentifier[i][1] = (i + 1) % raidPtr->numCol;
     87 	}
     88 
     89 	RF_ASSERT(raidPtr->numRow == 1);
     90 
     91 	/* fill in the remaining layout parameters */
     92 	num_used_stripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk - (layoutPtr->stripeUnitsPerDisk %
     93 	    (2 * raidPtr->numCol - 2));
     94 	info->numSparingRegions = num_used_stripeUnitsPerDisk / (2 * raidPtr->numCol - 2);
     95 	info->stripeUnitsPerSparingRegion = raidPtr->numCol * (raidPtr->numCol - 1);
     96 	info->mirrorStripeOffset = info->numSparingRegions * (raidPtr->numCol - 1);
     97 	layoutPtr->numStripe = info->numSparingRegions * info->stripeUnitsPerSparingRegion;
     98 	layoutPtr->numDataCol = 1;
     99 	layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
    100 	layoutPtr->numParityCol = 1;
    101 
    102 	layoutPtr->dataStripeUnitsPerDisk = num_used_stripeUnitsPerDisk;
    103 
    104 	raidPtr->sectorsPerDisk =
    105 	    num_used_stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
    106 
    107 	raidPtr->totalSectors =
    108 	    (layoutPtr->numStripe) * layoutPtr->sectorsPerStripeUnit;
    109 
    110 	layoutPtr->stripeUnitsPerDisk = raidPtr->sectorsPerDisk / layoutPtr->sectorsPerStripeUnit;
    111 
    112 	return (0);
    113 }
    114 
    115 RF_ReconUnitCount_t
    116 rf_GetNumSpareRUsChainDecluster(raidPtr)
    117 	RF_Raid_t *raidPtr;
    118 {
    119 	RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
    120 
    121 	/*
    122          * The layout uses two stripe units per disk as spare within each
    123          * sparing region.
    124          */
    125 	return (2 * info->numSparingRegions);
    126 }
    127 
    128 
    129 /* Maps to the primary copy of the data, i.e. the first mirror pair */
    130 void
    131 rf_MapSectorChainDecluster(
    132     RF_Raid_t * raidPtr,
    133     RF_RaidAddr_t raidSector,
    134     RF_RowCol_t * row,
    135     RF_RowCol_t * col,
    136     RF_SectorNum_t * diskSector,
    137     int remap)
    138 {
    139 	RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
    140 	RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
    141 	RF_SectorNum_t index_within_region, index_within_disk;
    142 	RF_StripeNum_t sparing_region_id;
    143 	int     col_before_remap;
    144 
    145 	*row = 0;
    146 	sparing_region_id = SUID / info->stripeUnitsPerSparingRegion;
    147 	index_within_region = SUID % info->stripeUnitsPerSparingRegion;
    148 	index_within_disk = index_within_region / raidPtr->numCol;
    149 	col_before_remap = SUID % raidPtr->numCol;
    150 
    151 	if (!remap) {
    152 		*col = col_before_remap;
    153 		*diskSector = (index_within_disk + ((raidPtr->numCol - 1) * sparing_region_id)) *
    154 		    raidPtr->Layout.sectorsPerStripeUnit;
    155 		*diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
    156 	} else {
    157 		/* remap sector to spare space... */
    158 		*diskSector = sparing_region_id * (raidPtr->numCol + 1) * raidPtr->Layout.sectorsPerStripeUnit;
    159 		*diskSector += (raidPtr->numCol - 1) * raidPtr->Layout.sectorsPerStripeUnit;
    160 		*diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
    161 		index_within_disk = index_within_region / raidPtr->numCol;
    162 		if (index_within_disk < col_before_remap)
    163 			*col = index_within_disk;
    164 		else
    165 			if (index_within_disk == raidPtr->numCol - 2) {
    166 				*col = (col_before_remap + raidPtr->numCol - 1) % raidPtr->numCol;
    167 				*diskSector += raidPtr->Layout.sectorsPerStripeUnit;
    168 			} else
    169 				*col = (index_within_disk + 2) % raidPtr->numCol;
    170 	}
    171 
    172 }
    173 
    174 
    175 
    176 /* Maps to the second copy of the mirror pair, which is chain declustered. The second copy is contained
    177    in the next disk (mod numCol) after the disk containing the primary copy.
    178    The offset into the disk is one-half disk down */
    179 void
    180 rf_MapParityChainDecluster(
    181     RF_Raid_t * raidPtr,
    182     RF_RaidAddr_t raidSector,
    183     RF_RowCol_t * row,
    184     RF_RowCol_t * col,
    185     RF_SectorNum_t * diskSector,
    186     int remap)
    187 {
    188 	RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
    189 	RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
    190 	RF_SectorNum_t index_within_region, index_within_disk;
    191 	RF_StripeNum_t sparing_region_id;
    192 	int     col_before_remap;
    193 
    194 	*row = 0;
    195 	if (!remap) {
    196 		*col = SUID % raidPtr->numCol;
    197 		*col = (*col + 1) % raidPtr->numCol;
    198 		*diskSector = info->mirrorStripeOffset * raidPtr->Layout.sectorsPerStripeUnit;
    199 		*diskSector += (SUID / raidPtr->numCol) * raidPtr->Layout.sectorsPerStripeUnit;
    200 		*diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
    201 	} else {
    202 		/* remap parity to spare space ... */
    203 		sparing_region_id = SUID / info->stripeUnitsPerSparingRegion;
    204 		index_within_region = SUID % info->stripeUnitsPerSparingRegion;
    205 		index_within_disk = index_within_region / raidPtr->numCol;
    206 		*diskSector = sparing_region_id * (raidPtr->numCol + 1) * raidPtr->Layout.sectorsPerStripeUnit;
    207 		*diskSector += (raidPtr->numCol) * raidPtr->Layout.sectorsPerStripeUnit;
    208 		*diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
    209 		col_before_remap = SUID % raidPtr->numCol;
    210 		if (index_within_disk < col_before_remap)
    211 			*col = index_within_disk;
    212 		else
    213 			if (index_within_disk == raidPtr->numCol - 2) {
    214 				*col = (col_before_remap + 2) % raidPtr->numCol;
    215 				*diskSector -= raidPtr->Layout.sectorsPerStripeUnit;
    216 			} else
    217 				*col = (index_within_disk + 2) % raidPtr->numCol;
    218 	}
    219 
    220 }
    221 
    222 void
    223 rf_IdentifyStripeChainDecluster(
    224     RF_Raid_t * raidPtr,
    225     RF_RaidAddr_t addr,
    226     RF_RowCol_t ** diskids,
    227     RF_RowCol_t * outRow)
    228 {
    229 	RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
    230 	RF_StripeNum_t SUID;
    231 	RF_RowCol_t col;
    232 
    233 	SUID = addr / raidPtr->Layout.sectorsPerStripeUnit;
    234 	col = SUID % raidPtr->numCol;
    235 	*outRow = 0;
    236 	*diskids = info->stripeIdentifier[col];
    237 }
    238 
    239 void
    240 rf_MapSIDToPSIDChainDecluster(
    241     RF_RaidLayout_t * layoutPtr,
    242     RF_StripeNum_t stripeID,
    243     RF_StripeNum_t * psID,
    244     RF_ReconUnitNum_t * which_ru)
    245 {
    246 	*which_ru = 0;
    247 	*psID = stripeID;
    248 }
    249 /******************************************************************************
    250  * select a graph to perform a single-stripe access
    251  *
    252  * Parameters:  raidPtr    - description of the physical array
    253  *              type       - type of operation (read or write) requested
    254  *              asmap      - logical & physical addresses for this access
    255  *              createFunc - function to use to create the graph (return value)
    256  *****************************************************************************/
    257 
    258 void
    259 rf_RAIDCDagSelect(
    260     RF_Raid_t * raidPtr,
    261     RF_IoType_t type,
    262     RF_AccessStripeMap_t * asmap,
    263     RF_VoidFuncPtr * createFunc)
    264 #if 0
    265 	void    (**createFunc) (RF_Raid_t *, RF_AccessStripeMap_t *,
    266             RF_DagHeader_t *, void *, RF_RaidAccessFlags_t,
    267             RF_AllocListElem_t *)
    268 #endif
    269 {
    270 	RF_ASSERT(RF_IO_IS_R_OR_W(type));
    271 	RF_ASSERT(raidPtr->numRow == 1);
    272 
    273 	if (asmap->numDataFailed + asmap->numParityFailed > 1) {
    274 		RF_ERRORMSG("Multiple disks failed in a single group!  Aborting I/O operation.\n");
    275 		*createFunc = NULL;
    276 		return;
    277 	}
    278 	*createFunc = (type == RF_IO_TYPE_READ) ? (RF_VoidFuncPtr) rf_CreateFaultFreeReadDAG : (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
    279 
    280 	if (type == RF_IO_TYPE_READ) {
    281 		if ((raidPtr->status[0] == rf_rs_degraded) || (raidPtr->status[0] == rf_rs_reconstructing))
    282 			*createFunc = (RF_VoidFuncPtr) rf_CreateRaidCDegradedReadDAG;	/* array status is
    283 											 * degraded, implement
    284 											 * workload shifting */
    285 		else
    286 			*createFunc = (RF_VoidFuncPtr) rf_CreateMirrorPartitionReadDAG;	/* array status not
    287 											 * degraded, so use
    288 											 * mirror partition dag */
    289 	} else
    290 		*createFunc = (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
    291 }
    292 #endif /* (RF_INCLUDE_CHAINDECLUSTER > 0) */
    293