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