Annotation of sys/dev/raidframe/rf_reconutil.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: rf_reconutil.c,v 1.3 2002/12/16 07:01:05 tdeval Exp $ */
! 2: /* $NetBSD: rf_reconutil.c,v 1.3 1999/02/05 00:06:17 oster Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1995 Carnegie-Mellon University.
! 6: * All rights reserved.
! 7: *
! 8: * Author: Mark Holland
! 9: *
! 10: * Permission to use, copy, modify and distribute this software and
! 11: * its documentation is hereby granted, provided that both the copyright
! 12: * notice and this permission notice appear in all copies of the
! 13: * software, derivative works or modified versions, and any portions
! 14: * thereof, and that both notices appear in supporting documentation.
! 15: *
! 16: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 17: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
! 18: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 19: *
! 20: * Carnegie Mellon requests users of this software to return to
! 21: *
! 22: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 23: * School of Computer Science
! 24: * Carnegie Mellon University
! 25: * Pittsburgh PA 15213-3890
! 26: *
! 27: * any improvements or extensions that they make and grant Carnegie the
! 28: * rights to redistribute these changes.
! 29: */
! 30:
! 31: /**********************************************
! 32: * rf_reconutil.c -- Reconstruction utilities.
! 33: **********************************************/
! 34:
! 35: #include "rf_types.h"
! 36: #include "rf_raid.h"
! 37: #include "rf_desc.h"
! 38: #include "rf_reconutil.h"
! 39: #include "rf_reconbuffer.h"
! 40: #include "rf_general.h"
! 41: #include "rf_decluster.h"
! 42: #include "rf_raid5_rotatedspare.h"
! 43: #include "rf_interdecluster.h"
! 44: #include "rf_chaindecluster.h"
! 45:
! 46:
! 47: /*********************************************************************
! 48: * Allocates/frees the reconstruction control information structures.
! 49: *********************************************************************/
! 50: RF_ReconCtrl_t *
! 51: rf_MakeReconControl(
! 52: RF_RaidReconDesc_t *reconDesc,
! 53: RF_RowCol_t frow, /* Failed row and column. */
! 54: RF_RowCol_t fcol,
! 55: RF_RowCol_t srow, /* Identifies which spare we're using. */
! 56: RF_RowCol_t scol
! 57: )
! 58: {
! 59: RF_Raid_t *raidPtr = reconDesc->raidPtr;
! 60: RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
! 61: RF_ReconUnitCount_t RUsPerPU = layoutPtr->SUsPerPU /
! 62: layoutPtr->SUsPerRU;
! 63: RF_ReconUnitCount_t numSpareRUs;
! 64: RF_ReconCtrl_t *reconCtrlPtr;
! 65: RF_ReconBuffer_t *rbuf;
! 66: RF_LayoutSW_t *lp;
! 67: int retcode, rc;
! 68: RF_RowCol_t i;
! 69:
! 70: lp = raidPtr->Layout.map;
! 71:
! 72: /*
! 73: * Make and zero the global reconstruction structure and the per-disk
! 74: * structure.
! 75: */
! 76: RF_Calloc(reconCtrlPtr, 1, sizeof(RF_ReconCtrl_t), (RF_ReconCtrl_t *));
! 77: /* This zeros it. */
! 78: RF_Calloc(reconCtrlPtr->perDiskInfo, raidPtr->numCol,
! 79: sizeof(RF_PerDiskReconCtrl_t), (RF_PerDiskReconCtrl_t *));
! 80: reconCtrlPtr->reconDesc = reconDesc;
! 81: reconCtrlPtr->fcol = fcol;
! 82: reconCtrlPtr->spareRow = srow;
! 83: reconCtrlPtr->spareCol = scol;
! 84: reconCtrlPtr->lastPSID = layoutPtr->numStripe / layoutPtr->SUsPerPU;
! 85: reconCtrlPtr->percentComplete = 0;
! 86:
! 87: /* Initialize each per-disk recon information structure. */
! 88: for (i = 0; i < raidPtr->numCol; i++) {
! 89: reconCtrlPtr->perDiskInfo[i].reconCtrl = reconCtrlPtr;
! 90: reconCtrlPtr->perDiskInfo[i].row = frow;
! 91: reconCtrlPtr->perDiskInfo[i].col = i;
! 92: /* Make it appear as if we just finished an RU. */
! 93: reconCtrlPtr->perDiskInfo[i].curPSID = -1;
! 94: reconCtrlPtr->perDiskInfo[i].ru_count = RUsPerPU - 1;
! 95: }
! 96:
! 97: /*
! 98: * Get the number of spare units per disk and the sparemap in case
! 99: * spare is distributed.
! 100: */
! 101:
! 102: if (lp->GetNumSpareRUs) {
! 103: numSpareRUs = lp->GetNumSpareRUs(raidPtr);
! 104: } else {
! 105: numSpareRUs = 0;
! 106: }
! 107:
! 108: /*
! 109: * Not all distributed sparing archs need dynamic mappings.
! 110: */
! 111: if (lp->InstallSpareTable) {
! 112: retcode = rf_InstallSpareTable(raidPtr, frow, fcol);
! 113: if (retcode) {
! 114: RF_PANIC(); /* XXX Fix this. */
! 115: }
! 116: }
! 117: /* Make the reconstruction map. */
! 118: reconCtrlPtr->reconMap = rf_MakeReconMap(raidPtr,
! 119: (int) (layoutPtr->SUsPerRU * layoutPtr->sectorsPerStripeUnit),
! 120: raidPtr->sectorsPerDisk, numSpareRUs);
! 121:
! 122: /* Make the per-disk reconstruction buffers. */
! 123: for (i = 0; i < raidPtr->numCol; i++) {
! 124: reconCtrlPtr->perDiskInfo[i].rbuf = (i == fcol) ? NULL :
! 125: rf_MakeReconBuffer(raidPtr, frow, i,
! 126: RF_RBUF_TYPE_EXCLUSIVE);
! 127: }
! 128:
! 129: /* Initialize the event queue. */
! 130: rc = rf_mutex_init(&reconCtrlPtr->eq_mutex);
! 131: if (rc) {
! 132: /* XXX Deallocate, cleanup. */
! 133: RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d.\n",
! 134: __FILE__, __LINE__, rc);
! 135: return (NULL);
! 136: }
! 137: rc = rf_cond_init(&reconCtrlPtr->eq_cond);
! 138: if (rc) {
! 139: /* XXX Deallocate, cleanup. */
! 140: RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d.\n",
! 141: __FILE__, __LINE__, rc);
! 142: return (NULL);
! 143: }
! 144: reconCtrlPtr->eventQueue = NULL;
! 145: reconCtrlPtr->eq_count = 0;
! 146:
! 147: /* Make the floating recon buffers and append them to the free list. */
! 148: rc = rf_mutex_init(&reconCtrlPtr->rb_mutex);
! 149: if (rc) {
! 150: /* XXX Deallocate, cleanup. */
! 151: RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d.\n",
! 152: __FILE__, __LINE__, rc);
! 153: return (NULL);
! 154: }
! 155: reconCtrlPtr->fullBufferList = NULL;
! 156: reconCtrlPtr->priorityList = NULL;
! 157: reconCtrlPtr->floatingRbufs = NULL;
! 158: reconCtrlPtr->committedRbufs = NULL;
! 159: for (i = 0; i < raidPtr->numFloatingReconBufs; i++) {
! 160: rbuf = rf_MakeReconBuffer(raidPtr, frow, fcol,
! 161: RF_RBUF_TYPE_FLOATING);
! 162: rbuf->next = reconCtrlPtr->floatingRbufs;
! 163: reconCtrlPtr->floatingRbufs = rbuf;
! 164: }
! 165:
! 166: /* Create the parity stripe status table. */
! 167: reconCtrlPtr->pssTable = rf_MakeParityStripeStatusTable(raidPtr);
! 168:
! 169: /* Set the initial min head sep counter val. */
! 170: reconCtrlPtr->minHeadSepCounter = 0;
! 171:
! 172: return (reconCtrlPtr);
! 173: }
! 174:
! 175: void
! 176: rf_FreeReconControl(RF_Raid_t *raidPtr, RF_RowCol_t row)
! 177: {
! 178: RF_ReconCtrl_t *reconCtrlPtr = raidPtr->reconControl[row];
! 179: RF_ReconBuffer_t *t;
! 180: RF_ReconUnitNum_t i;
! 181:
! 182: RF_ASSERT(reconCtrlPtr);
! 183: for (i = 0; i < raidPtr->numCol; i++)
! 184: if (reconCtrlPtr->perDiskInfo[i].rbuf)
! 185: rf_FreeReconBuffer(reconCtrlPtr->perDiskInfo[i].rbuf);
! 186: for (i = 0; i < raidPtr->numFloatingReconBufs; i++) {
! 187: t = reconCtrlPtr->floatingRbufs;
! 188: RF_ASSERT(t);
! 189: reconCtrlPtr->floatingRbufs = t->next;
! 190: rf_FreeReconBuffer(t);
! 191: }
! 192: rf_mutex_destroy(&reconCtrlPtr->rb_mutex);
! 193: rf_mutex_destroy(&reconCtrlPtr->eq_mutex);
! 194: rf_cond_destroy(&reconCtrlPtr->eq_cond);
! 195: rf_FreeReconMap(reconCtrlPtr->reconMap);
! 196: rf_FreeParityStripeStatusTable(raidPtr, reconCtrlPtr->pssTable);
! 197: RF_Free(reconCtrlPtr->perDiskInfo, raidPtr->numCol *
! 198: sizeof(RF_PerDiskReconCtrl_t));
! 199: RF_Free(reconCtrlPtr, sizeof(*reconCtrlPtr));
! 200: }
! 201:
! 202:
! 203: /*****************************************************************************
! 204: * Computes the default head separation limit.
! 205: *****************************************************************************/
! 206: RF_HeadSepLimit_t
! 207: rf_GetDefaultHeadSepLimit(RF_Raid_t *raidPtr)
! 208: {
! 209: RF_HeadSepLimit_t hsl;
! 210: RF_LayoutSW_t *lp;
! 211:
! 212: lp = raidPtr->Layout.map;
! 213: if (lp->GetDefaultHeadSepLimit == NULL)
! 214: return (-1);
! 215: hsl = lp->GetDefaultHeadSepLimit(raidPtr);
! 216: return (hsl);
! 217: }
! 218:
! 219:
! 220: /*****************************************************************************
! 221: * Computes the default number of floating recon buffers.
! 222: *****************************************************************************/
! 223: int
! 224: rf_GetDefaultNumFloatingReconBuffers(RF_Raid_t *raidPtr)
! 225: {
! 226: RF_LayoutSW_t *lp;
! 227: int nrb;
! 228:
! 229: lp = raidPtr->Layout.map;
! 230: if (lp->GetDefaultNumFloatingReconBuffers == NULL)
! 231: return (3 * raidPtr->numCol);
! 232: nrb = lp->GetDefaultNumFloatingReconBuffers(raidPtr);
! 233: return (nrb);
! 234: }
! 235:
! 236:
! 237: /*****************************************************************************
! 238: * Creates and initializes a reconstruction buffer.
! 239: *****************************************************************************/
! 240: RF_ReconBuffer_t *
! 241: rf_MakeReconBuffer(RF_Raid_t *raidPtr, RF_RowCol_t row, RF_RowCol_t col,
! 242: RF_RbufType_t type)
! 243: {
! 244: RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
! 245: RF_ReconBuffer_t *t;
! 246: u_int recon_buffer_size = rf_RaidAddressToByte(raidPtr,
! 247: layoutPtr->SUsPerRU * layoutPtr->sectorsPerStripeUnit);
! 248:
! 249: RF_Malloc(t, sizeof(RF_ReconBuffer_t), (RF_ReconBuffer_t *));
! 250: RF_Malloc(t->buffer, recon_buffer_size, (caddr_t));
! 251: RF_Malloc(t->arrived, raidPtr->numCol * sizeof(char), (char *));
! 252: t->raidPtr = raidPtr;
! 253: t->row = row;
! 254: t->col = col;
! 255: t->priority = RF_IO_RECON_PRIORITY;
! 256: t->type = type;
! 257: t->pssPtr = NULL;
! 258: t->next = NULL;
! 259: return (t);
! 260: }
! 261:
! 262:
! 263: /*****************************************************************************
! 264: * Frees a reconstruction buffer.
! 265: *****************************************************************************/
! 266: void
! 267: rf_FreeReconBuffer(RF_ReconBuffer_t *rbuf)
! 268: {
! 269: RF_Raid_t *raidPtr = rbuf->raidPtr;
! 270: u_int recon_buffer_size = rf_RaidAddressToByte(raidPtr,
! 271: raidPtr->Layout.SUsPerRU * raidPtr->Layout.sectorsPerStripeUnit);
! 272:
! 273: RF_Free(rbuf->arrived, raidPtr->numCol * sizeof(char));
! 274: RF_Free(rbuf->buffer, recon_buffer_size);
! 275: RF_Free(rbuf, sizeof(*rbuf));
! 276: }
! 277:
! 278:
! 279: /*****************************************************************************
! 280: * Debug only: Sanity check the number of floating recon bufs in use.
! 281: *****************************************************************************/
! 282: void
! 283: rf_CheckFloatingRbufCount(RF_Raid_t *raidPtr, int dolock)
! 284: {
! 285: RF_ReconParityStripeStatus_t *p;
! 286: RF_PSStatusHeader_t *pssTable;
! 287: RF_ReconBuffer_t *rbuf;
! 288: int i, j, sum = 0;
! 289: RF_RowCol_t frow = 0;
! 290:
! 291: for (i = 0; i < raidPtr->numRow; i++)
! 292: if (raidPtr->reconControl[i]) {
! 293: frow = i;
! 294: break;
! 295: }
! 296: RF_ASSERT(frow >= 0);
! 297:
! 298: if (dolock)
! 299: RF_LOCK_MUTEX(raidPtr->reconControl[frow]->rb_mutex);
! 300: pssTable = raidPtr->reconControl[frow]->pssTable;
! 301:
! 302: for (i = 0; i < raidPtr->pssTableSize; i++) {
! 303: RF_LOCK_MUTEX(pssTable[i].mutex);
! 304: for (p = pssTable[i].chain; p; p = p->next) {
! 305: rbuf = (RF_ReconBuffer_t *) p->rbuf;
! 306: if (rbuf && rbuf->type == RF_RBUF_TYPE_FLOATING)
! 307: sum++;
! 308:
! 309: rbuf = (RF_ReconBuffer_t *) p->writeRbuf;
! 310: if (rbuf && rbuf->type == RF_RBUF_TYPE_FLOATING)
! 311: sum++;
! 312:
! 313: for (j = 0; j < p->xorBufCount; j++) {
! 314: rbuf = (RF_ReconBuffer_t *) p->rbufsForXor[j];
! 315: RF_ASSERT(rbuf);
! 316: if (rbuf->type == RF_RBUF_TYPE_FLOATING)
! 317: sum++;
! 318: }
! 319: }
! 320: RF_UNLOCK_MUTEX(pssTable[i].mutex);
! 321: }
! 322:
! 323: for (rbuf = raidPtr->reconControl[frow]->floatingRbufs; rbuf;
! 324: rbuf = rbuf->next) {
! 325: if (rbuf->type == RF_RBUF_TYPE_FLOATING)
! 326: sum++;
! 327: }
! 328: for (rbuf = raidPtr->reconControl[frow]->committedRbufs; rbuf;
! 329: rbuf = rbuf->next) {
! 330: if (rbuf->type == RF_RBUF_TYPE_FLOATING)
! 331: sum++;
! 332: }
! 333: for (rbuf = raidPtr->reconControl[frow]->fullBufferList; rbuf;
! 334: rbuf = rbuf->next) {
! 335: if (rbuf->type == RF_RBUF_TYPE_FLOATING)
! 336: sum++;
! 337: }
! 338: for (rbuf = raidPtr->reconControl[frow]->priorityList; rbuf;
! 339: rbuf = rbuf->next) {
! 340: if (rbuf->type == RF_RBUF_TYPE_FLOATING)
! 341: sum++;
! 342: }
! 343:
! 344: RF_ASSERT(sum == raidPtr->numFloatingReconBufs);
! 345:
! 346: if (dolock)
! 347: RF_UNLOCK_MUTEX(raidPtr->reconControl[frow]->rb_mutex);
! 348: }
CVSweb