Home | History | Annotate | Line # | Download | only in raidframe
rf_chaindecluster.c revision 1.10
      1 /*	$NetBSD: rf_chaindecluster.c,v 1.10 2003/12/29 02:38:17 oster 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.10 2003/12/29 02:38:17 oster 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 	/* fill in the remaining layout parameters */
     90 	num_used_stripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk - (layoutPtr->stripeUnitsPerDisk %
     91 	    (2 * raidPtr->numCol - 2));
     92 	info->numSparingRegions = num_used_stripeUnitsPerDisk / (2 * raidPtr->numCol - 2);
     93 	info->stripeUnitsPerSparingRegion = raidPtr->numCol * (raidPtr->numCol - 1);
     94 	info->mirrorStripeOffset = info->numSparingRegions * (raidPtr->numCol - 1);
     95 	layoutPtr->numStripe = info->numSparingRegions * info->stripeUnitsPerSparingRegion;
     96 	layoutPtr->numDataCol = 1;
     97 	layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
     98 	layoutPtr->numParityCol = 1;
     99 
    100 	layoutPtr->dataStripeUnitsPerDisk = num_used_stripeUnitsPerDisk;
    101 
    102 	raidPtr->sectorsPerDisk =
    103 	    num_used_stripeUnitsPerDisk * layoutPtr->sectorsPerStripeUnit;
    104 
    105 	raidPtr->totalSectors =
    106 	    (layoutPtr->numStripe) * layoutPtr->sectorsPerStripeUnit;
    107 
    108 	layoutPtr->stripeUnitsPerDisk = raidPtr->sectorsPerDisk / layoutPtr->sectorsPerStripeUnit;
    109 
    110 	return (0);
    111 }
    112 
    113 RF_ReconUnitCount_t
    114 rf_GetNumSpareRUsChainDecluster(raidPtr)
    115 	RF_Raid_t *raidPtr;
    116 {
    117 	RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
    118 
    119 	/*
    120          * The layout uses two stripe units per disk as spare within each
    121          * sparing region.
    122          */
    123 	return (2 * info->numSparingRegions);
    124 }
    125 
    126 
    127 /* Maps to the primary copy of the data, i.e. the first mirror pair */
    128 void
    129 rf_MapSectorChainDecluster(
    130     RF_Raid_t * raidPtr,
    131     RF_RaidAddr_t raidSector,
    132     RF_RowCol_t * col,
    133     RF_SectorNum_t * diskSector,
    134     int remap)
    135 {
    136 	RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
    137 	RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
    138 	RF_SectorNum_t index_within_region, index_within_disk;
    139 	RF_StripeNum_t sparing_region_id;
    140 	int     col_before_remap;
    141 
    142 	sparing_region_id = SUID / info->stripeUnitsPerSparingRegion;
    143 	index_within_region = SUID % info->stripeUnitsPerSparingRegion;
    144 	index_within_disk = index_within_region / raidPtr->numCol;
    145 	col_before_remap = SUID % raidPtr->numCol;
    146 
    147 	if (!remap) {
    148 		*col = col_before_remap;
    149 		*diskSector = (index_within_disk + ((raidPtr->numCol - 1) * sparing_region_id)) *
    150 		    raidPtr->Layout.sectorsPerStripeUnit;
    151 		*diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
    152 	} else {
    153 		/* remap sector to spare space... */
    154 		*diskSector = sparing_region_id * (raidPtr->numCol + 1) * raidPtr->Layout.sectorsPerStripeUnit;
    155 		*diskSector += (raidPtr->numCol - 1) * raidPtr->Layout.sectorsPerStripeUnit;
    156 		*diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
    157 		index_within_disk = index_within_region / raidPtr->numCol;
    158 		if (index_within_disk < col_before_remap)
    159 			*col = index_within_disk;
    160 		else
    161 			if (index_within_disk == raidPtr->numCol - 2) {
    162 				*col = (col_before_remap + raidPtr->numCol - 1) % raidPtr->numCol;
    163 				*diskSector += raidPtr->Layout.sectorsPerStripeUnit;
    164 			} else
    165 				*col = (index_within_disk + 2) % raidPtr->numCol;
    166 	}
    167 
    168 }
    169 
    170 
    171 
    172 /* Maps to the second copy of the mirror pair, which is chain declustered. The second copy is contained
    173    in the next disk (mod numCol) after the disk containing the primary copy.
    174    The offset into the disk is one-half disk down */
    175 void
    176 rf_MapParityChainDecluster(
    177     RF_Raid_t * raidPtr,
    178     RF_RaidAddr_t raidSector,
    179     RF_RowCol_t * col,
    180     RF_SectorNum_t * diskSector,
    181     int remap)
    182 {
    183 	RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
    184 	RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
    185 	RF_SectorNum_t index_within_region, index_within_disk;
    186 	RF_StripeNum_t sparing_region_id;
    187 	int     col_before_remap;
    188 
    189 	if (!remap) {
    190 		*col = SUID % raidPtr->numCol;
    191 		*col = (*col + 1) % raidPtr->numCol;
    192 		*diskSector = info->mirrorStripeOffset * raidPtr->Layout.sectorsPerStripeUnit;
    193 		*diskSector += (SUID / raidPtr->numCol) * raidPtr->Layout.sectorsPerStripeUnit;
    194 		*diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
    195 	} else {
    196 		/* remap parity to spare space ... */
    197 		sparing_region_id = SUID / info->stripeUnitsPerSparingRegion;
    198 		index_within_region = SUID % info->stripeUnitsPerSparingRegion;
    199 		index_within_disk = index_within_region / raidPtr->numCol;
    200 		*diskSector = sparing_region_id * (raidPtr->numCol + 1) * raidPtr->Layout.sectorsPerStripeUnit;
    201 		*diskSector += (raidPtr->numCol) * raidPtr->Layout.sectorsPerStripeUnit;
    202 		*diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
    203 		col_before_remap = SUID % raidPtr->numCol;
    204 		if (index_within_disk < col_before_remap)
    205 			*col = index_within_disk;
    206 		else
    207 			if (index_within_disk == raidPtr->numCol - 2) {
    208 				*col = (col_before_remap + 2) % raidPtr->numCol;
    209 				*diskSector -= raidPtr->Layout.sectorsPerStripeUnit;
    210 			} else
    211 				*col = (index_within_disk + 2) % raidPtr->numCol;
    212 	}
    213 
    214 }
    215 
    216 void
    217 rf_IdentifyStripeChainDecluster(
    218     RF_Raid_t * raidPtr,
    219     RF_RaidAddr_t addr,
    220     RF_RowCol_t ** diskids)
    221 {
    222 	RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
    223 	RF_StripeNum_t SUID;
    224 	RF_RowCol_t col;
    225 
    226 	SUID = addr / raidPtr->Layout.sectorsPerStripeUnit;
    227 	col = SUID % raidPtr->numCol;
    228 	*diskids = info->stripeIdentifier[col];
    229 }
    230 
    231 void
    232 rf_MapSIDToPSIDChainDecluster(
    233     RF_RaidLayout_t * layoutPtr,
    234     RF_StripeNum_t stripeID,
    235     RF_StripeNum_t * psID,
    236     RF_ReconUnitNum_t * which_ru)
    237 {
    238 	*which_ru = 0;
    239 	*psID = stripeID;
    240 }
    241 /******************************************************************************
    242  * select a graph to perform a single-stripe access
    243  *
    244  * Parameters:  raidPtr    - description of the physical array
    245  *              type       - type of operation (read or write) requested
    246  *              asmap      - logical & physical addresses for this access
    247  *              createFunc - function to use to create the graph (return value)
    248  *****************************************************************************/
    249 
    250 void
    251 rf_RAIDCDagSelect(
    252     RF_Raid_t * raidPtr,
    253     RF_IoType_t type,
    254     RF_AccessStripeMap_t * asmap,
    255     RF_VoidFuncPtr * createFunc)
    256 #if 0
    257 	void    (**createFunc) (RF_Raid_t *, RF_AccessStripeMap_t *,
    258             RF_DagHeader_t *, void *, RF_RaidAccessFlags_t,
    259             RF_AllocListElem_t *)
    260 #endif
    261 {
    262 	RF_ASSERT(RF_IO_IS_R_OR_W(type));
    263 
    264 	if (asmap->numDataFailed + asmap->numParityFailed > 1) {
    265 		RF_ERRORMSG("Multiple disks failed in a single group!  Aborting I/O operation.\n");
    266 		*createFunc = NULL;
    267 		return;
    268 	}
    269 	*createFunc = (type == RF_IO_TYPE_READ) ? (RF_VoidFuncPtr) rf_CreateFaultFreeReadDAG : (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
    270 
    271 	if (type == RF_IO_TYPE_READ) {
    272 		if ((raidPtr->status == rf_rs_degraded) || (raidPtr->status == rf_rs_reconstructing))
    273 			*createFunc = (RF_VoidFuncPtr) rf_CreateRaidCDegradedReadDAG;	/* array status is
    274 											 * degraded, implement
    275 											 * workload shifting */
    276 		else
    277 			*createFunc = (RF_VoidFuncPtr) rf_CreateMirrorPartitionReadDAG;	/* array status not
    278 											 * degraded, so use
    279 											 * mirror partition dag */
    280 	} else
    281 		*createFunc = (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
    282 }
    283 #endif /* (RF_INCLUDE_CHAINDECLUSTER > 0) */
    284