rf_reconutil.c revision 1.2
1/* $NetBSD: rf_reconutil.c,v 1.2 1999/01/26 02:34:02 oster Exp $ */ 2/* 3 * Copyright (c) 1995 Carnegie-Mellon University. 4 * All rights reserved. 5 * 6 * Author: Mark Holland 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 * rf_reconutil.c -- reconstruction utilities 31 ********************************************/ 32 33#include "rf_types.h" 34#include "rf_raid.h" 35#include "rf_desc.h" 36#include "rf_reconutil.h" 37#include "rf_reconbuffer.h" 38#include "rf_general.h" 39#include "rf_decluster.h" 40#include "rf_raid5_rotatedspare.h" 41#include "rf_interdecluster.h" 42#include "rf_chaindecluster.h" 43 44/******************************************************************* 45 * allocates/frees the reconstruction control information structures 46 *******************************************************************/ 47RF_ReconCtrl_t *rf_MakeReconControl(reconDesc, frow, fcol, srow, scol) 48 RF_RaidReconDesc_t *reconDesc; 49 RF_RowCol_t frow; /* failed row and column */ 50 RF_RowCol_t fcol; 51 RF_RowCol_t srow; /* identifies which spare we're using */ 52 RF_RowCol_t scol; 53{ 54 RF_Raid_t *raidPtr = reconDesc->raidPtr; 55 RF_RaidLayout_t *layoutPtr = &raidPtr->Layout; 56 RF_ReconUnitCount_t RUsPerPU = layoutPtr->SUsPerPU / layoutPtr->SUsPerRU; 57 RF_ReconUnitCount_t numSpareRUs; 58 RF_ReconCtrl_t *reconCtrlPtr; 59 RF_ReconBuffer_t *rbuf; 60 RF_LayoutSW_t *lp; 61 int retcode, rc; 62 RF_RowCol_t i; 63 64 lp = raidPtr->Layout.map; 65 66 /* make and zero the global reconstruction structure and the per-disk structure */ 67 RF_Calloc(reconCtrlPtr, 1, sizeof(RF_ReconCtrl_t), (RF_ReconCtrl_t *)); 68 RF_Calloc(reconCtrlPtr->perDiskInfo, raidPtr->numCol, sizeof(RF_PerDiskReconCtrl_t), (RF_PerDiskReconCtrl_t *)); /* this zeros it */ 69 reconCtrlPtr->reconDesc = reconDesc; 70 reconCtrlPtr->fcol = fcol; 71 reconCtrlPtr->spareRow = srow; 72 reconCtrlPtr->spareCol = scol; 73 reconCtrlPtr->lastPSID = layoutPtr->numStripe/layoutPtr->SUsPerPU; 74 reconCtrlPtr->percentComplete = 0; 75 76 /* initialize each per-disk recon information structure */ 77 for (i=0; i<raidPtr->numCol; i++) { 78 reconCtrlPtr->perDiskInfo[i].reconCtrl = reconCtrlPtr; 79 reconCtrlPtr->perDiskInfo[i].row = frow; 80 reconCtrlPtr->perDiskInfo[i].col = i; 81 reconCtrlPtr->perDiskInfo[i].curPSID = -1; /* make it appear as if we just finished an RU */ 82 reconCtrlPtr->perDiskInfo[i].ru_count = RUsPerPU-1; 83 } 84 85 /* Get the number of spare units per disk and the sparemap in case spare is distributed */ 86 87 if (lp->GetNumSpareRUs) { 88 numSpareRUs = lp->GetNumSpareRUs(raidPtr); 89 } 90 else { 91 numSpareRUs = 0; 92 } 93 94 /* 95 * Not all distributed sparing archs need dynamic mappings 96 */ 97 if (lp->InstallSpareTable) { 98 retcode = rf_InstallSpareTable(raidPtr, frow, fcol); 99 if (retcode) { 100 RF_PANIC(); /* XXX fix this*/ 101 } 102 } 103 104 /* make the reconstruction map */ 105 reconCtrlPtr->reconMap = rf_MakeReconMap(raidPtr, (int) (layoutPtr->SUsPerRU * layoutPtr->sectorsPerStripeUnit), 106 raidPtr->sectorsPerDisk, numSpareRUs); 107 108 /* make the per-disk reconstruction buffers */ 109 for (i=0; i<raidPtr->numCol; i++) { 110 reconCtrlPtr->perDiskInfo[i].rbuf = (i==fcol) ? NULL : rf_MakeReconBuffer(raidPtr, frow, i, RF_RBUF_TYPE_EXCLUSIVE); 111 } 112 113 /* initialize the event queue */ 114 rc = rf_mutex_init(&reconCtrlPtr->eq_mutex); 115 if (rc) { 116 /* XXX deallocate, cleanup */ 117 RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n", __FILE__, 118 __LINE__, rc); 119 return(NULL); 120 } 121 rc = rf_cond_init(&reconCtrlPtr->eq_cond); 122 if (rc) { 123 /* XXX deallocate, cleanup */ 124 RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d\n", __FILE__, 125 __LINE__, rc); 126 return(NULL); 127 } 128 reconCtrlPtr->eventQueue = NULL; 129 reconCtrlPtr->eq_count = 0; 130 131 /* make the floating recon buffers and append them to the free list */ 132 rc = rf_mutex_init(&reconCtrlPtr->rb_mutex); 133 if (rc) { 134 /* XXX deallocate, cleanup */ 135 RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n", __FILE__, 136 __LINE__, rc); 137 return(NULL); 138 } 139 reconCtrlPtr->fullBufferList= NULL; 140 reconCtrlPtr->priorityList = NULL; 141 reconCtrlPtr->floatingRbufs = NULL; 142 reconCtrlPtr->committedRbufs= NULL; 143 for (i=0; i<raidPtr->numFloatingReconBufs; i++) { 144 rbuf = rf_MakeReconBuffer(raidPtr, frow, fcol, RF_RBUF_TYPE_FLOATING); 145 rbuf->next = reconCtrlPtr->floatingRbufs; 146 reconCtrlPtr->floatingRbufs = rbuf; 147 } 148 149 /* create the parity stripe status table */ 150 reconCtrlPtr->pssTable = rf_MakeParityStripeStatusTable(raidPtr); 151 152 /* set the initial min head sep counter val */ 153 reconCtrlPtr->minHeadSepCounter = 0; 154 155 return(reconCtrlPtr); 156} 157 158void rf_FreeReconControl(raidPtr, row) 159 RF_Raid_t *raidPtr; 160 RF_RowCol_t row; 161{ 162 RF_ReconCtrl_t *reconCtrlPtr = raidPtr->reconControl[row]; 163 RF_ReconBuffer_t *t; 164 RF_ReconUnitNum_t i; 165 166 RF_ASSERT(reconCtrlPtr); 167 for (i=0; i<raidPtr->numCol; i++) if (reconCtrlPtr->perDiskInfo[i].rbuf) rf_FreeReconBuffer(reconCtrlPtr->perDiskInfo[i].rbuf); 168 for (i=0; i<raidPtr->numFloatingReconBufs; i++) { 169 t = reconCtrlPtr->floatingRbufs; 170 RF_ASSERT(t); 171 reconCtrlPtr->floatingRbufs = t->next; 172 rf_FreeReconBuffer(t); 173 } 174 rf_mutex_destroy(&reconCtrlPtr->rb_mutex); 175 rf_mutex_destroy(&reconCtrlPtr->eq_mutex); 176 rf_cond_destroy(&reconCtrlPtr->eq_cond); 177 rf_FreeReconMap(reconCtrlPtr->reconMap); 178 rf_FreeParityStripeStatusTable(raidPtr, reconCtrlPtr->pssTable); 179 RF_Free(reconCtrlPtr->perDiskInfo, raidPtr->numCol * sizeof(RF_PerDiskReconCtrl_t)); 180 RF_Free(reconCtrlPtr, sizeof(*reconCtrlPtr)); 181} 182 183 184/****************************************************************************** 185 * computes the default head separation limit 186 *****************************************************************************/ 187RF_HeadSepLimit_t rf_GetDefaultHeadSepLimit(raidPtr) 188 RF_Raid_t *raidPtr; 189{ 190 RF_HeadSepLimit_t hsl; 191 RF_LayoutSW_t *lp; 192 193 lp = raidPtr->Layout.map; 194 if (lp->GetDefaultHeadSepLimit == NULL) 195 return(-1); 196 hsl = lp->GetDefaultHeadSepLimit(raidPtr); 197 return(hsl); 198} 199 200 201/****************************************************************************** 202 * computes the default number of floating recon buffers 203 *****************************************************************************/ 204int rf_GetDefaultNumFloatingReconBuffers(raidPtr) 205 RF_Raid_t *raidPtr; 206{ 207 RF_LayoutSW_t *lp; 208 int nrb; 209 210 lp = raidPtr->Layout.map; 211 if (lp->GetDefaultNumFloatingReconBuffers == NULL) 212 return(3 * raidPtr->numCol); 213 nrb = lp->GetDefaultNumFloatingReconBuffers(raidPtr); 214 return(nrb); 215} 216 217 218/****************************************************************************** 219 * creates and initializes a reconstruction buffer 220 *****************************************************************************/ 221RF_ReconBuffer_t *rf_MakeReconBuffer( 222 RF_Raid_t *raidPtr, 223 RF_RowCol_t row, 224 RF_RowCol_t col, 225 RF_RbufType_t type) 226{ 227 RF_RaidLayout_t *layoutPtr = &raidPtr->Layout; 228 RF_ReconBuffer_t *t; 229 u_int recon_buffer_size = rf_RaidAddressToByte(raidPtr, layoutPtr->SUsPerRU * layoutPtr->sectorsPerStripeUnit); 230 231 RF_Malloc(t, sizeof(RF_ReconBuffer_t), (RF_ReconBuffer_t *)); 232 RF_Malloc(t->buffer, recon_buffer_size, (caddr_t)); 233 RF_Malloc(t->arrived, raidPtr->numCol * sizeof(char), (char *)); 234 t->raidPtr = raidPtr; 235 t->row = row; t->col = col; 236 t->priority = RF_IO_RECON_PRIORITY; 237 t->type = type; 238 t->pssPtr = NULL; 239 t->next = NULL; 240 return(t); 241} 242 243/****************************************************************************** 244 * frees a reconstruction buffer 245 *****************************************************************************/ 246void rf_FreeReconBuffer(rbuf) 247 RF_ReconBuffer_t *rbuf; 248{ 249 RF_Raid_t *raidPtr = rbuf->raidPtr; 250 u_int recon_buffer_size = rf_RaidAddressToByte(raidPtr, raidPtr->Layout.SUsPerRU * raidPtr->Layout.sectorsPerStripeUnit); 251 252 RF_Free(rbuf->arrived, raidPtr->numCol * sizeof(char)); 253 RF_Free(rbuf->buffer, recon_buffer_size); 254 RF_Free(rbuf, sizeof(*rbuf)); 255} 256 257 258/****************************************************************************** 259 * debug only: sanity check the number of floating recon bufs in use 260 *****************************************************************************/ 261void rf_CheckFloatingRbufCount(raidPtr, dolock) 262 RF_Raid_t *raidPtr; 263 int dolock; 264{ 265 RF_ReconParityStripeStatus_t *p; 266 RF_PSStatusHeader_t *pssTable; 267 RF_ReconBuffer_t *rbuf; 268 int i, j, sum = 0; 269 RF_RowCol_t frow=0; 270 271 for (i=0; i<raidPtr->numRow; i++) 272 if (raidPtr->reconControl[i]) { 273 frow = i; 274 break; 275 } 276 RF_ASSERT(frow >= 0); 277 278 if (dolock) 279 RF_LOCK_MUTEX(raidPtr->reconControl[frow]->rb_mutex); 280 pssTable = raidPtr->reconControl[frow]->pssTable; 281 282 for (i=0; i<raidPtr->pssTableSize; i++) { 283 RF_LOCK_MUTEX(pssTable[i].mutex); 284 for (p = pssTable[i].chain; p; p=p->next) { 285 rbuf = (RF_ReconBuffer_t *) p->rbuf; 286 if (rbuf && rbuf->type == RF_RBUF_TYPE_FLOATING) 287 sum++; 288 289 rbuf = (RF_ReconBuffer_t *) p->writeRbuf; 290 if (rbuf && rbuf->type == RF_RBUF_TYPE_FLOATING) 291 sum++; 292 293 for (j=0; j<p->xorBufCount; j++) { 294 rbuf = (RF_ReconBuffer_t *) p->rbufsForXor[j]; 295 RF_ASSERT(rbuf); 296 if (rbuf->type == RF_RBUF_TYPE_FLOATING) 297 sum++; 298 } 299 } 300 RF_UNLOCK_MUTEX(pssTable[i].mutex); 301 } 302 303 for (rbuf = raidPtr->reconControl[frow]->floatingRbufs; rbuf; rbuf = rbuf->next) { 304 if (rbuf->type == RF_RBUF_TYPE_FLOATING) 305 sum++; 306 } 307 for (rbuf = raidPtr->reconControl[frow]->committedRbufs; rbuf; rbuf = rbuf->next) { 308 if (rbuf->type == RF_RBUF_TYPE_FLOATING) 309 sum++; 310 } 311 for (rbuf = raidPtr->reconControl[frow]->fullBufferList; rbuf; rbuf = rbuf->next) { 312 if (rbuf->type == RF_RBUF_TYPE_FLOATING) 313 sum++; 314 } 315 for (rbuf = raidPtr->reconControl[frow]->priorityList; rbuf; rbuf = rbuf->next) { 316 if (rbuf->type == RF_RBUF_TYPE_FLOATING) 317 sum++; 318 } 319 320 RF_ASSERT(sum == raidPtr->numFloatingReconBufs); 321 322 if (dolock) 323 RF_UNLOCK_MUTEX(raidPtr->reconControl[frow]->rb_mutex); 324} 325