rf_chaindecluster.c revision 1.5
1/* $NetBSD: rf_chaindecluster.c,v 1.5 2001/01/26 04:14:14 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_general.h" 46#include "rf_utils.h" 47 48typedef struct RF_ChaindeclusterConfigInfo_s { 49 RF_RowCol_t **stripeIdentifier; /* filled in at config time and used 50 * by IdentifyStripe */ 51 RF_StripeCount_t numSparingRegions; 52 RF_StripeCount_t stripeUnitsPerSparingRegion; 53 RF_SectorNum_t mirrorStripeOffset; 54} RF_ChaindeclusterConfigInfo_t; 55 56int 57rf_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 110rf_GetNumSpareRUsChainDecluster(raidPtr) 111 RF_Raid_t *raidPtr; 112{ 113 RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo; 114 115 /* 116 * The layout uses two stripe units per disk as spare within each 117 * sparing region. 118 */ 119 return (2 * info->numSparingRegions); 120} 121 122 123/* Maps to the primary copy of the data, i.e. the first mirror pair */ 124void 125rf_MapSectorChainDecluster( 126 RF_Raid_t * raidPtr, 127 RF_RaidAddr_t raidSector, 128 RF_RowCol_t * row, 129 RF_RowCol_t * col, 130 RF_SectorNum_t * diskSector, 131 int remap) 132{ 133 RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo; 134 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit; 135 RF_SectorNum_t index_within_region, index_within_disk; 136 RF_StripeNum_t sparing_region_id; 137 int col_before_remap; 138 139 *row = 0; 140 sparing_region_id = SUID / info->stripeUnitsPerSparingRegion; 141 index_within_region = SUID % info->stripeUnitsPerSparingRegion; 142 index_within_disk = index_within_region / raidPtr->numCol; 143 col_before_remap = SUID % raidPtr->numCol; 144 145 if (!remap) { 146 *col = col_before_remap; 147 *diskSector = (index_within_disk + ((raidPtr->numCol - 1) * sparing_region_id)) * 148 raidPtr->Layout.sectorsPerStripeUnit; 149 *diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit); 150 } else { 151 /* remap sector to spare space... */ 152 *diskSector = sparing_region_id * (raidPtr->numCol + 1) * raidPtr->Layout.sectorsPerStripeUnit; 153 *diskSector += (raidPtr->numCol - 1) * raidPtr->Layout.sectorsPerStripeUnit; 154 *diskSector += (raidSector % raidPtr->Layout.sectorsPerStripeUnit); 155 index_within_disk = index_within_region / raidPtr->numCol; 156 if (index_within_disk < col_before_remap) 157 *col = index_within_disk; 158 else 159 if (index_within_disk == raidPtr->numCol - 2) { 160 *col = (col_before_remap + raidPtr->numCol - 1) % raidPtr->numCol; 161 *diskSector += raidPtr->Layout.sectorsPerStripeUnit; 162 } else 163 *col = (index_within_disk + 2) % raidPtr->numCol; 164 } 165 166} 167 168 169 170/* Maps to the second copy of the mirror pair, which is chain declustered. The second copy is contained 171 in the next disk (mod numCol) after the disk containing the primary copy. 172 The offset into the disk is one-half disk down */ 173void 174rf_MapParityChainDecluster( 175 RF_Raid_t * raidPtr, 176 RF_RaidAddr_t raidSector, 177 RF_RowCol_t * row, 178 RF_RowCol_t * col, 179 RF_SectorNum_t * diskSector, 180 int remap) 181{ 182 RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo; 183 RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit; 184 RF_SectorNum_t index_within_region, index_within_disk; 185 RF_StripeNum_t sparing_region_id; 186 int col_before_remap; 187 188 *row = 0; 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 216void 217rf_IdentifyStripeChainDecluster( 218 RF_Raid_t * raidPtr, 219 RF_RaidAddr_t addr, 220 RF_RowCol_t ** diskids, 221 RF_RowCol_t * outRow) 222{ 223 RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo; 224 RF_StripeNum_t SUID; 225 RF_RowCol_t col; 226 227 SUID = addr / raidPtr->Layout.sectorsPerStripeUnit; 228 col = SUID % raidPtr->numCol; 229 *outRow = 0; 230 *diskids = info->stripeIdentifier[col]; 231} 232 233void 234rf_MapSIDToPSIDChainDecluster( 235 RF_RaidLayout_t * layoutPtr, 236 RF_StripeNum_t stripeID, 237 RF_StripeNum_t * psID, 238 RF_ReconUnitNum_t * which_ru) 239{ 240 *which_ru = 0; 241 *psID = stripeID; 242} 243/****************************************************************************** 244 * select a graph to perform a single-stripe access 245 * 246 * Parameters: raidPtr - description of the physical array 247 * type - type of operation (read or write) requested 248 * asmap - logical & physical addresses for this access 249 * createFunc - function to use to create the graph (return value) 250 *****************************************************************************/ 251 252void 253rf_RAIDCDagSelect( 254 RF_Raid_t * raidPtr, 255 RF_IoType_t type, 256 RF_AccessStripeMap_t * asmap, 257 RF_VoidFuncPtr * createFunc) 258#if 0 259 void (**createFunc) (RF_Raid_t *, RF_AccessStripeMap_t *, 260 RF_DagHeader_t *, void *, RF_RaidAccessFlags_t, 261 RF_AllocListElem_t *) 262#endif 263{ 264 RF_ASSERT(RF_IO_IS_R_OR_W(type)); 265 RF_ASSERT(raidPtr->numRow == 1); 266 267 if (asmap->numDataFailed + asmap->numParityFailed > 1) { 268 RF_ERRORMSG("Multiple disks failed in a single group! Aborting I/O operation.\n"); 269 *createFunc = NULL; 270 return; 271 } 272 *createFunc = (type == RF_IO_TYPE_READ) ? (RF_VoidFuncPtr) rf_CreateFaultFreeReadDAG : (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG; 273 274 if (type == RF_IO_TYPE_READ) { 275 if ((raidPtr->status[0] == rf_rs_degraded) || (raidPtr->status[0] == rf_rs_reconstructing)) 276 *createFunc = (RF_VoidFuncPtr) rf_CreateRaidCDegradedReadDAG; /* array status is 277 * degraded, implement 278 * workload shifting */ 279 else 280 *createFunc = (RF_VoidFuncPtr) rf_CreateMirrorPartitionReadDAG; /* array status not 281 * degraded, so use 282 * mirror partition dag */ 283 } else 284 *createFunc = (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG; 285} 286