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