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