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