Annotation of sys/dev/raidframe/rf_paritylogging.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: rf_paritylogging.c,v 1.6 2002/12/16 07:01:04 tdeval Exp $ */
! 2: /* $NetBSD: rf_paritylogging.c,v 1.10 2000/02/12 16:06:27 oster Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1995 Carnegie-Mellon University.
! 6: * All rights reserved.
! 7: *
! 8: * Author: William V. Courtright II
! 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: /*
! 33: * Parity logging configuration, dag selection, and mapping is implemented here.
! 34: */
! 35:
! 36: #include "rf_archs.h"
! 37:
! 38: #if RF_INCLUDE_PARITYLOGGING > 0
! 39:
! 40: #include "rf_types.h"
! 41: #include "rf_raid.h"
! 42: #include "rf_dag.h"
! 43: #include "rf_dagutils.h"
! 44: #include "rf_dagfuncs.h"
! 45: #include "rf_dagffrd.h"
! 46: #include "rf_dagffwr.h"
! 47: #include "rf_dagdegrd.h"
! 48: #include "rf_dagdegwr.h"
! 49: #include "rf_paritylog.h"
! 50: #include "rf_paritylogDiskMgr.h"
! 51: #include "rf_paritylogging.h"
! 52: #include "rf_parityloggingdags.h"
! 53: #include "rf_general.h"
! 54: #include "rf_map.h"
! 55: #include "rf_utils.h"
! 56: #include "rf_shutdown.h"
! 57:
! 58: typedef struct RF_ParityLoggingConfigInfo_s {
! 59: RF_RowCol_t **stripeIdentifier; /*
! 60: * Filled in at config time & used by
! 61: * IdentifyStripe.
! 62: */
! 63: } RF_ParityLoggingConfigInfo_t;
! 64:
! 65: void rf_FreeRegionInfo(RF_Raid_t *, RF_RegionId_t);
! 66: void rf_FreeParityLogQueue(RF_Raid_t *, RF_ParityLogQueue_t *);
! 67: void rf_FreeRegionBufferQueue(RF_RegionBufferQueue_t *);
! 68: void rf_ShutdownParityLogging(RF_ThreadArg_t);
! 69: void rf_ShutdownParityLoggingRegionInfo(RF_ThreadArg_t);
! 70: void rf_ShutdownParityLoggingPool(RF_ThreadArg_t);
! 71: void rf_ShutdownParityLoggingRegionBufferPool(RF_ThreadArg_t);
! 72: void rf_ShutdownParityLoggingParityBufferPool(RF_ThreadArg_t);
! 73: void rf_ShutdownParityLoggingDiskQueue(RF_ThreadArg_t);
! 74:
! 75:
! 76: int
! 77: rf_ConfigureParityLogging(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
! 78: RF_Config_t *cfgPtr)
! 79: {
! 80: int i, j, startdisk, rc;
! 81: RF_SectorCount_t totalLogCapacity, fragmentation, lastRegionCapacity;
! 82: RF_SectorCount_t parityBufferCapacity, maxRegionParityRange;
! 83: RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
! 84: RF_ParityLoggingConfigInfo_t *info;
! 85: RF_ParityLog_t *l = NULL, *next;
! 86: caddr_t lHeapPtr;
! 87:
! 88: if (rf_numParityRegions <= 0)
! 89: return(EINVAL);
! 90:
! 91: /*
! 92: * We create multiple entries on the shutdown list here, since
! 93: * this configuration routine is fairly complicated in and of
! 94: * itself, and this makes backing out of a failed configuration
! 95: * much simpler.
! 96: */
! 97:
! 98: raidPtr->numSectorsPerLog = RF_DEFAULT_NUM_SECTORS_PER_LOG;
! 99:
! 100: /* Create a parity logging configuration structure. */
! 101: RF_MallocAndAdd(info, sizeof(RF_ParityLoggingConfigInfo_t),
! 102: (RF_ParityLoggingConfigInfo_t *),
! 103: raidPtr->cleanupList);
! 104: if (info == NULL)
! 105: return (ENOMEM);
! 106: layoutPtr->layoutSpecificInfo = (void *) info;
! 107:
! 108: RF_ASSERT(raidPtr->numRow == 1);
! 109:
! 110: /*
! 111: * The stripe identifier must identify the disks in each stripe, IN
! 112: * THE ORDER THAT THEY APPEAR IN THE STRIPE.
! 113: */
! 114: info->stripeIdentifier = rf_make_2d_array((raidPtr->numCol),
! 115: (raidPtr->numCol),
! 116: raidPtr->cleanupList);
! 117: if (info->stripeIdentifier == NULL)
! 118: return (ENOMEM);
! 119:
! 120: startdisk = 0;
! 121: for (i = 0; i < (raidPtr->numCol); i++) {
! 122: for (j = 0; j < (raidPtr->numCol); j++) {
! 123: info->stripeIdentifier[i][j] = (startdisk + j) %
! 124: (raidPtr->numCol - 1);
! 125: }
! 126: if ((--startdisk) < 0)
! 127: startdisk = raidPtr->numCol - 1 - 1;
! 128: }
! 129:
! 130: /* Fill in the remaining layout parameters. */
! 131: layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk;
! 132: layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit <<
! 133: raidPtr->logBytesPerSector;
! 134: layoutPtr->numParityCol = 1;
! 135: layoutPtr->numParityLogCol = 1;
! 136: layoutPtr->numDataCol = raidPtr->numCol - layoutPtr->numParityCol -
! 137: layoutPtr->numParityLogCol;
! 138: layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol *
! 139: layoutPtr->sectorsPerStripeUnit;
! 140: layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk;
! 141: raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk *
! 142: layoutPtr->sectorsPerStripeUnit;
! 143:
! 144: raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk *
! 145: layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
! 146:
! 147: /*
! 148: * Configure parity log parameters.
! 149: *
! 150: * Parameter Comment/constraints
! 151: * ------------------------------------------------
! 152: * numParityRegions* All regions (except possibly last)
! 153: * of equal size.
! 154: * totalInCoreLogCapacity* Amount of memory in bytes available
! 155: * for in-core logs (default 1 MB).
! 156: * numSectorsPerLog# Capacity of an in-core log in sectors
! 157: * (1 * disk track).
! 158: * numParityLogs Total number of in-core logs,
! 159: * should be at least numParityRegions.
! 160: * regionLogCapacity Size of a region log (except possibly
! 161: * last one) in sectors.
! 162: * totalLogCapacity Total amount of log space in sectors.
! 163: *
! 164: * Where '*' denotes a user settable parameter.
! 165: * Note that logs are fixed to be the size of a disk track,
! 166: * value #defined in rf_paritylog.h.
! 167: *
! 168: */
! 169:
! 170: totalLogCapacity = layoutPtr->stripeUnitsPerDisk *
! 171: layoutPtr->sectorsPerStripeUnit * layoutPtr->numParityLogCol;
! 172: raidPtr->regionLogCapacity = totalLogCapacity / rf_numParityRegions;
! 173: if (rf_parityLogDebug)
! 174: printf("bytes per sector %d\n", raidPtr->bytesPerSector);
! 175:
! 176: /*
! 177: * Reduce fragmentation within a disk region by adjusting the number
! 178: * of regions in an attempt to allow an integral number of logs to fit
! 179: * into a disk region.
! 180: */
! 181: fragmentation = raidPtr->regionLogCapacity % raidPtr->numSectorsPerLog;
! 182: if (fragmentation > 0)
! 183: for (i = 1; i < (raidPtr->numSectorsPerLog / 2); i++) {
! 184: if (((totalLogCapacity / (rf_numParityRegions + i)) %
! 185: raidPtr->numSectorsPerLog) < fragmentation) {
! 186: rf_numParityRegions++;
! 187: raidPtr->regionLogCapacity = totalLogCapacity /
! 188: rf_numParityRegions;
! 189: fragmentation = raidPtr->regionLogCapacity %
! 190: raidPtr->numSectorsPerLog;
! 191: }
! 192: if (((totalLogCapacity / (rf_numParityRegions - i)) %
! 193: raidPtr->numSectorsPerLog) < fragmentation) {
! 194: rf_numParityRegions--;
! 195: raidPtr->regionLogCapacity = totalLogCapacity /
! 196: rf_numParityRegions;
! 197: fragmentation = raidPtr->regionLogCapacity %
! 198: raidPtr->numSectorsPerLog;
! 199: }
! 200: }
! 201: /* Ensure integral number of regions per log. */
! 202: raidPtr->regionLogCapacity = (raidPtr->regionLogCapacity /
! 203: raidPtr->numSectorsPerLog) * raidPtr->numSectorsPerLog;
! 204:
! 205: raidPtr->numParityLogs = rf_totalInCoreLogCapacity /
! 206: (raidPtr->bytesPerSector * raidPtr->numSectorsPerLog);
! 207: /*
! 208: * To avoid deadlock, must ensure that enough logs exist for each
! 209: * region to have one simultaneously.
! 210: */
! 211: if (raidPtr->numParityLogs < rf_numParityRegions)
! 212: raidPtr->numParityLogs = rf_numParityRegions;
! 213:
! 214: /* Create region information structs. */
! 215: printf("Allocating %d bytes for in-core parity region info\n",
! 216: (int) (rf_numParityRegions * sizeof(RF_RegionInfo_t)));
! 217: RF_Malloc(raidPtr->regionInfo,
! 218: (rf_numParityRegions * sizeof(RF_RegionInfo_t)),
! 219: (RF_RegionInfo_t *));
! 220: if (raidPtr->regionInfo == NULL)
! 221: return (ENOMEM);
! 222:
! 223: /* Last region may not be full capacity. */
! 224: lastRegionCapacity = raidPtr->regionLogCapacity;
! 225: while ((rf_numParityRegions - 1) * raidPtr->regionLogCapacity +
! 226: lastRegionCapacity > totalLogCapacity)
! 227: lastRegionCapacity = lastRegionCapacity -
! 228: raidPtr->numSectorsPerLog;
! 229:
! 230: raidPtr->regionParityRange = raidPtr->sectorsPerDisk /
! 231: rf_numParityRegions;
! 232: maxRegionParityRange = raidPtr->regionParityRange;
! 233:
! 234: /* I can't remember why this line is in the code -wvcii 6/30/95. */
! 235: /* if (raidPtr->sectorsPerDisk % rf_numParityRegions > 0)
! 236: * regionParityRange++; */
! 237:
! 238: /* Build pool of unused parity logs. */
! 239: printf("Allocating %d bytes for %d parity logs\n",
! 240: raidPtr->numParityLogs * raidPtr->numSectorsPerLog *
! 241: raidPtr->bytesPerSector,
! 242: raidPtr->numParityLogs);
! 243: RF_Malloc(raidPtr->parityLogBufferHeap, raidPtr->numParityLogs *
! 244: raidPtr->numSectorsPerLog * raidPtr->bytesPerSector,
! 245: (caddr_t));
! 246: if (raidPtr->parityLogBufferHeap == NULL)
! 247: return (ENOMEM);
! 248: lHeapPtr = raidPtr->parityLogBufferHeap;
! 249: rc = rf_mutex_init(&raidPtr->parityLogPool.mutex);
! 250: if (rc) {
! 251: RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n",
! 252: __FILE__, __LINE__, rc);
! 253: RF_Free(raidPtr->parityLogBufferHeap, raidPtr->numParityLogs *
! 254: raidPtr->numSectorsPerLog * raidPtr->bytesPerSector);
! 255: return (ENOMEM);
! 256: }
! 257: for (i = 0; i < raidPtr->numParityLogs; i++) {
! 258: if (i == 0) {
! 259: RF_Calloc(raidPtr->parityLogPool.parityLogs, 1,
! 260: sizeof(RF_ParityLog_t), (RF_ParityLog_t *));
! 261: if (raidPtr->parityLogPool.parityLogs == NULL) {
! 262: RF_Free(raidPtr->parityLogBufferHeap,
! 263: raidPtr->numParityLogs *
! 264: raidPtr->numSectorsPerLog *
! 265: raidPtr->bytesPerSector);
! 266: return (ENOMEM);
! 267: }
! 268: l = raidPtr->parityLogPool.parityLogs;
! 269: } else {
! 270: RF_Calloc(l->next, 1, sizeof(RF_ParityLog_t),
! 271: (RF_ParityLog_t *));
! 272: if (l->next == NULL) {
! 273: RF_Free(raidPtr->parityLogBufferHeap,
! 274: raidPtr->numParityLogs *
! 275: raidPtr->numSectorsPerLog *
! 276: raidPtr->bytesPerSector);
! 277: for (l = raidPtr->parityLogPool.parityLogs;
! 278: l;
! 279: l = next) {
! 280: next = l->next;
! 281: if (l->records)
! 282: RF_Free(l->records,
! 283: (raidPtr->numSectorsPerLog *
! 284: sizeof(RF_ParityLogRecord_t)));
! 285: RF_Free(l, sizeof(RF_ParityLog_t));
! 286: }
! 287: return (ENOMEM);
! 288: }
! 289: l = l->next;
! 290: }
! 291: l->bufPtr = lHeapPtr;
! 292: lHeapPtr += raidPtr->numSectorsPerLog *
! 293: raidPtr->bytesPerSector;
! 294: RF_Malloc(l->records, (raidPtr->numSectorsPerLog *
! 295: sizeof(RF_ParityLogRecord_t)),
! 296: (RF_ParityLogRecord_t *));
! 297: if (l->records == NULL) {
! 298: RF_Free(raidPtr->parityLogBufferHeap,
! 299: raidPtr->numParityLogs *
! 300: raidPtr->numSectorsPerLog *
! 301: raidPtr->bytesPerSector);
! 302: for (l = raidPtr->parityLogPool.parityLogs;
! 303: l;
! 304: l = next) {
! 305: next = l->next;
! 306: if (l->records)
! 307: RF_Free(l->records,
! 308: (raidPtr->numSectorsPerLog *
! 309: sizeof(RF_ParityLogRecord_t)));
! 310: RF_Free(l, sizeof(RF_ParityLog_t));
! 311: }
! 312: return (ENOMEM);
! 313: }
! 314: }
! 315: rc = rf_ShutdownCreate(listp, rf_ShutdownParityLoggingPool, raidPtr);
! 316: if (rc) {
! 317: RF_ERRORMSG3("Unable to create shutdown entry file %s line %d"
! 318: " rc=%d\n", __FILE__, __LINE__, rc);
! 319: rf_ShutdownParityLoggingPool(raidPtr);
! 320: return (rc);
! 321: }
! 322: /* Build pool of region buffers. */
! 323: rc = rf_mutex_init(&raidPtr->regionBufferPool.mutex);
! 324: if (rc) {
! 325: RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n",
! 326: __FILE__, __LINE__, rc);
! 327: return (ENOMEM);
! 328: }
! 329: rc = rf_cond_init(&raidPtr->regionBufferPool.cond);
! 330: if (rc) {
! 331: RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d\n",
! 332: __FILE__, __LINE__, rc);
! 333: rf_mutex_destroy(&raidPtr->regionBufferPool.mutex);
! 334: return (ENOMEM);
! 335: }
! 336: raidPtr->regionBufferPool.bufferSize = raidPtr->regionLogCapacity *
! 337: raidPtr->bytesPerSector;
! 338: printf("regionBufferPool.bufferSize %d\n",
! 339: raidPtr->regionBufferPool.bufferSize);
! 340:
! 341: /* For now, only one region at a time may be reintegrated. */
! 342: raidPtr->regionBufferPool.totalBuffers = 1;
! 343:
! 344: raidPtr->regionBufferPool.availableBuffers =
! 345: raidPtr->regionBufferPool.totalBuffers;
! 346: raidPtr->regionBufferPool.availBuffersIndex = 0;
! 347: raidPtr->regionBufferPool.emptyBuffersIndex = 0;
! 348: printf("Allocating %d bytes for regionBufferPool\n",
! 349: (int) (raidPtr->regionBufferPool.totalBuffers *
! 350: sizeof(caddr_t)));
! 351: RF_Malloc(raidPtr->regionBufferPool.buffers,
! 352: raidPtr->regionBufferPool.totalBuffers * sizeof(caddr_t),
! 353: (caddr_t *));
! 354: if (raidPtr->regionBufferPool.buffers == NULL) {
! 355: rf_mutex_destroy(&raidPtr->regionBufferPool.mutex);
! 356: rf_cond_destroy(&raidPtr->regionBufferPool.cond);
! 357: return (ENOMEM);
! 358: }
! 359: for (i = 0; i < raidPtr->regionBufferPool.totalBuffers; i++) {
! 360: printf("Allocating %d bytes for regionBufferPool#%d\n",
! 361: (int) (raidPtr->regionBufferPool.bufferSize *
! 362: sizeof(char)), i);
! 363: RF_Malloc(raidPtr->regionBufferPool.buffers[i],
! 364: raidPtr->regionBufferPool.bufferSize * sizeof(char),
! 365: (caddr_t));
! 366: if (raidPtr->regionBufferPool.buffers[i] == NULL) {
! 367: rf_mutex_destroy(&raidPtr->regionBufferPool.mutex);
! 368: rf_cond_destroy(&raidPtr->regionBufferPool.cond);
! 369: for (j = 0; j < i; j++) {
! 370: RF_Free(raidPtr->regionBufferPool.buffers[i],
! 371: raidPtr->regionBufferPool.bufferSize *
! 372: sizeof(char));
! 373: }
! 374: RF_Free(raidPtr->regionBufferPool.buffers,
! 375: raidPtr->regionBufferPool.totalBuffers *
! 376: sizeof(caddr_t));
! 377: return (ENOMEM);
! 378: }
! 379: printf("raidPtr->regionBufferPool.buffers[%d] = %lx\n", i,
! 380: (long) raidPtr->regionBufferPool.buffers[i]);
! 381: }
! 382: rc = rf_ShutdownCreate(listp,
! 383: rf_ShutdownParityLoggingRegionBufferPool,
! 384: raidPtr);
! 385: if (rc) {
! 386: RF_ERRORMSG3("Unable to create shutdown entry file %s line %d"
! 387: " rc=%d\n", __FILE__, __LINE__, rc);
! 388: rf_ShutdownParityLoggingRegionBufferPool(raidPtr);
! 389: return (rc);
! 390: }
! 391: /* Build pool of parity buffers. */
! 392: parityBufferCapacity = maxRegionParityRange;
! 393: rc = rf_mutex_init(&raidPtr->parityBufferPool.mutex);
! 394: if (rc) {
! 395: RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n",
! 396: __FILE__, __LINE__, rc);
! 397: return (rc);
! 398: }
! 399: rc = rf_cond_init(&raidPtr->parityBufferPool.cond);
! 400: if (rc) {
! 401: RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d\n",
! 402: __FILE__, __LINE__, rc);
! 403: rf_mutex_destroy(&raidPtr->parityBufferPool.mutex);
! 404: return (ENOMEM);
! 405: }
! 406: raidPtr->parityBufferPool.bufferSize = parityBufferCapacity *
! 407: raidPtr->bytesPerSector;
! 408: printf("parityBufferPool.bufferSize %d\n",
! 409: raidPtr->parityBufferPool.bufferSize);
! 410:
! 411: /* For now, only one region at a time may be reintegrated. */
! 412: raidPtr->parityBufferPool.totalBuffers = 1;
! 413:
! 414: raidPtr->parityBufferPool.availableBuffers =
! 415: raidPtr->parityBufferPool.totalBuffers;
! 416: raidPtr->parityBufferPool.availBuffersIndex = 0;
! 417: raidPtr->parityBufferPool.emptyBuffersIndex = 0;
! 418: printf("Allocating %d bytes for parityBufferPool of %d units\n",
! 419: (int) (raidPtr->parityBufferPool.totalBuffers *
! 420: sizeof(caddr_t)),
! 421: raidPtr->parityBufferPool.totalBuffers);
! 422: RF_Malloc(raidPtr->parityBufferPool.buffers,
! 423: raidPtr->parityBufferPool.totalBuffers * sizeof(caddr_t),
! 424: (caddr_t *));
! 425: if (raidPtr->parityBufferPool.buffers == NULL) {
! 426: rf_mutex_destroy(&raidPtr->parityBufferPool.mutex);
! 427: rf_cond_destroy(&raidPtr->parityBufferPool.cond);
! 428: return (ENOMEM);
! 429: }
! 430: for (i = 0; i < raidPtr->parityBufferPool.totalBuffers; i++) {
! 431: printf("Allocating %d bytes for parityBufferPool#%d\n",
! 432: (int) (raidPtr->parityBufferPool.bufferSize *
! 433: sizeof(char)), i);
! 434: RF_Malloc(raidPtr->parityBufferPool.buffers[i],
! 435: raidPtr->parityBufferPool.bufferSize * sizeof(char),
! 436: (caddr_t));
! 437: if (raidPtr->parityBufferPool.buffers == NULL) {
! 438: rf_mutex_destroy(&raidPtr->parityBufferPool.mutex);
! 439: rf_cond_destroy(&raidPtr->parityBufferPool.cond);
! 440: for (j = 0; j < i; j++) {
! 441: RF_Free(raidPtr->parityBufferPool.buffers[i],
! 442: raidPtr->regionBufferPool.bufferSize *
! 443: sizeof(char));
! 444: }
! 445: RF_Free(raidPtr->parityBufferPool.buffers,
! 446: raidPtr->regionBufferPool.totalBuffers *
! 447: sizeof(caddr_t));
! 448: return (ENOMEM);
! 449: }
! 450: printf("parityBufferPool.buffers[%d] = %lx\n", i,
! 451: (long) raidPtr->parityBufferPool.buffers[i]);
! 452: }
! 453: rc = rf_ShutdownCreate(listp,
! 454: rf_ShutdownParityLoggingParityBufferPool,
! 455: raidPtr);
! 456: if (rc) {
! 457: RF_ERRORMSG3("Unable to create shutdown entry file %s line %d"
! 458: " rc=%d\n", __FILE__, __LINE__, rc);
! 459: rf_ShutdownParityLoggingParityBufferPool(raidPtr);
! 460: return (rc);
! 461: }
! 462: /* Initialize parityLogDiskQueue. */
! 463: rc = rf_create_managed_mutex(listp,
! 464: &raidPtr->parityLogDiskQueue.mutex);
! 465: if (rc) {
! 466: RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n",
! 467: __FILE__, __LINE__, rc);
! 468: return (rc);
! 469: }
! 470: rc = rf_create_managed_cond(listp, &raidPtr->parityLogDiskQueue.cond);
! 471: if (rc) {
! 472: RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d\n",
! 473: __FILE__, __LINE__, rc);
! 474: return (rc);
! 475: }
! 476: raidPtr->parityLogDiskQueue.flushQueue = NULL;
! 477: raidPtr->parityLogDiskQueue.reintQueue = NULL;
! 478: raidPtr->parityLogDiskQueue.bufHead = NULL;
! 479: raidPtr->parityLogDiskQueue.bufTail = NULL;
! 480: raidPtr->parityLogDiskQueue.reintHead = NULL;
! 481: raidPtr->parityLogDiskQueue.reintTail = NULL;
! 482: raidPtr->parityLogDiskQueue.logBlockHead = NULL;
! 483: raidPtr->parityLogDiskQueue.logBlockTail = NULL;
! 484: raidPtr->parityLogDiskQueue.reintBlockHead = NULL;
! 485: raidPtr->parityLogDiskQueue.reintBlockTail = NULL;
! 486: raidPtr->parityLogDiskQueue.freeDataList = NULL;
! 487: raidPtr->parityLogDiskQueue.freeCommonList = NULL;
! 488:
! 489: rc = rf_ShutdownCreate(listp,
! 490: rf_ShutdownParityLoggingDiskQueue,
! 491: raidPtr);
! 492: if (rc) {
! 493: RF_ERRORMSG3("Unable to create shutdown entry file %s line %d"
! 494: " rc=%d\n", __FILE__, __LINE__, rc);
! 495: return (rc);
! 496: }
! 497: for (i = 0; i < rf_numParityRegions; i++) {
! 498: rc = rf_mutex_init(&raidPtr->regionInfo[i].mutex);
! 499: if (rc) {
! 500: RF_ERRORMSG3("Unable to init mutex file %s line %d"
! 501: " rc=%d\n", __FILE__, __LINE__, rc);
! 502: for (j = 0; j < i; j++)
! 503: rf_FreeRegionInfo(raidPtr, j);
! 504: RF_Free(raidPtr->regionInfo,
! 505: (rf_numParityRegions *
! 506: sizeof(RF_RegionInfo_t)));
! 507: return (ENOMEM);
! 508: }
! 509: rc = rf_mutex_init(&raidPtr->regionInfo[i].reintMutex);
! 510: if (rc) {
! 511: RF_ERRORMSG3("Unable to init mutex file %s line %d"
! 512: " rc=%d\n", __FILE__, __LINE__, rc);
! 513: rf_mutex_destroy(&raidPtr->regionInfo[i].mutex);
! 514: for (j = 0; j < i; j++)
! 515: rf_FreeRegionInfo(raidPtr, j);
! 516: RF_Free(raidPtr->regionInfo,
! 517: (rf_numParityRegions *
! 518: sizeof(RF_RegionInfo_t)));
! 519: return (ENOMEM);
! 520: }
! 521: raidPtr->regionInfo[i].reintInProgress = RF_FALSE;
! 522: raidPtr->regionInfo[i].regionStartAddr =
! 523: raidPtr->regionLogCapacity * i;
! 524: raidPtr->regionInfo[i].parityStartAddr =
! 525: raidPtr->regionParityRange * i;
! 526: if (i < rf_numParityRegions - 1) {
! 527: raidPtr->regionInfo[i].capacity =
! 528: raidPtr->regionLogCapacity;
! 529: raidPtr->regionInfo[i].numSectorsParity =
! 530: raidPtr->regionParityRange;
! 531: } else {
! 532: raidPtr->regionInfo[i].capacity = lastRegionCapacity;
! 533: raidPtr->regionInfo[i].numSectorsParity =
! 534: raidPtr->sectorsPerDisk -
! 535: raidPtr->regionParityRange * i;
! 536: if (raidPtr->regionInfo[i].numSectorsParity >
! 537: maxRegionParityRange)
! 538: maxRegionParityRange =
! 539: raidPtr->regionInfo[i].numSectorsParity;
! 540: }
! 541: raidPtr->regionInfo[i].diskCount = 0;
! 542: RF_ASSERT(raidPtr->regionInfo[i].capacity +
! 543: raidPtr->regionInfo[i].regionStartAddr <=
! 544: totalLogCapacity);
! 545: RF_ASSERT(raidPtr->regionInfo[i].parityStartAddr +
! 546: raidPtr->regionInfo[i].numSectorsParity <=
! 547: raidPtr->sectorsPerDisk);
! 548: printf("Allocating %d bytes for region %d\n",
! 549: (int) (raidPtr->regionInfo[i].capacity *
! 550: sizeof(RF_DiskMap_t)), i);
! 551: RF_Malloc(raidPtr->regionInfo[i].diskMap,
! 552: (raidPtr->regionInfo[i].capacity *
! 553: sizeof(RF_DiskMap_t)),
! 554: (RF_DiskMap_t *));
! 555: if (raidPtr->regionInfo[i].diskMap == NULL) {
! 556: rf_mutex_destroy(&raidPtr->regionInfo[i].mutex);
! 557: rf_mutex_destroy(&raidPtr->regionInfo[i].reintMutex);
! 558: for (j = 0; j < i; j++)
! 559: rf_FreeRegionInfo(raidPtr, j);
! 560: RF_Free(raidPtr->regionInfo,
! 561: (rf_numParityRegions *
! 562: sizeof(RF_RegionInfo_t)));
! 563: return (ENOMEM);
! 564: }
! 565: raidPtr->regionInfo[i].loggingEnabled = RF_FALSE;
! 566: raidPtr->regionInfo[i].coreLog = NULL;
! 567: }
! 568: rc = rf_ShutdownCreate(listp,
! 569: rf_ShutdownParityLoggingRegionInfo,
! 570: raidPtr);
! 571: if (rc) {
! 572: RF_ERRORMSG3("Unable to create shutdown entry file %s line %d"
! 573: " rc=%d\n", __FILE__, __LINE__, rc);
! 574: rf_ShutdownParityLoggingRegionInfo(raidPtr);
! 575: return (rc);
! 576: }
! 577: RF_ASSERT(raidPtr->parityLogDiskQueue.threadState == 0);
! 578: raidPtr->parityLogDiskQueue.threadState = RF_PLOG_CREATED;
! 579: rc = RF_CREATE_THREAD(raidPtr->pLogDiskThreadHandle,
! 580: rf_ParityLoggingDiskManager, raidPtr, "rf_log");
! 581: if (rc) {
! 582: raidPtr->parityLogDiskQueue.threadState = 0;
! 583: RF_ERRORMSG3("Unable to create parity logging disk thread"
! 584: " file %s line %d rc=%d\n",
! 585: __FILE__, __LINE__, rc);
! 586: return (ENOMEM);
! 587: }
! 588: /* Wait for thread to start. */
! 589: RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
! 590: while (!(raidPtr->parityLogDiskQueue.threadState & RF_PLOG_RUNNING)) {
! 591: RF_WAIT_COND(raidPtr->parityLogDiskQueue.cond,
! 592: raidPtr->parityLogDiskQueue.mutex);
! 593: }
! 594: RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
! 595:
! 596: rc = rf_ShutdownCreate(listp, rf_ShutdownParityLogging, raidPtr);
! 597: if (rc) {
! 598: RF_ERRORMSG1("Got rc=%d adding parity logging shutdown"
! 599: " event.\n", rc);
! 600: rf_ShutdownParityLogging(raidPtr);
! 601: return (rc);
! 602: }
! 603: if (rf_parityLogDebug) {
! 604: printf("\t\t\tsize of disk log in sectors: %d\n",
! 605: (int) totalLogCapacity);
! 606: printf("\t\t\ttotal number of parity regions is %d\n",
! 607: (int) rf_numParityRegions);
! 608: printf("\t\t\tnominal sectors of log per parity region is %d\n",
! 609: (int) raidPtr->regionLogCapacity);
! 610: printf("\t\t\tnominal region fragmentation is %d sectors\n",
! 611: (int) fragmentation);
! 612: printf("\t\t\ttotal number of parity logs is %d\n",
! 613: raidPtr->numParityLogs);
! 614: printf("\t\t\tparity log size is %d sectors\n",
! 615: raidPtr->numSectorsPerLog);
! 616: printf("\t\t\ttotal in-core log space is %d bytes\n",
! 617: (int) rf_totalInCoreLogCapacity);
! 618: }
! 619: rf_EnableParityLogging(raidPtr);
! 620:
! 621: return (0);
! 622: }
! 623:
! 624:
! 625: void
! 626: rf_FreeRegionInfo(RF_Raid_t *raidPtr, RF_RegionId_t regionID)
! 627: {
! 628: RF_LOCK_MUTEX(raidPtr->regionInfo[regionID].mutex);
! 629: RF_Free(raidPtr->regionInfo[regionID].diskMap,
! 630: (raidPtr->regionInfo[regionID].capacity *
! 631: sizeof(RF_DiskMap_t)));
! 632: if (!rf_forceParityLogReint && raidPtr->regionInfo[regionID].coreLog) {
! 633: rf_ReleaseParityLogs(raidPtr,
! 634: raidPtr->regionInfo[regionID].coreLog);
! 635: raidPtr->regionInfo[regionID].coreLog = NULL;
! 636: } else {
! 637: RF_ASSERT(raidPtr->regionInfo[regionID].coreLog == NULL);
! 638: RF_ASSERT(raidPtr->regionInfo[regionID].diskCount == 0);
! 639: }
! 640: RF_UNLOCK_MUTEX(raidPtr->regionInfo[regionID].mutex);
! 641: rf_mutex_destroy(&raidPtr->regionInfo[regionID].mutex);
! 642: rf_mutex_destroy(&raidPtr->regionInfo[regionID].reintMutex);
! 643: }
! 644:
! 645:
! 646: void
! 647: rf_FreeParityLogQueue(RF_Raid_t *raidPtr, RF_ParityLogQueue_t *queue)
! 648: {
! 649: RF_ParityLog_t *l1, *l2;
! 650:
! 651: RF_LOCK_MUTEX(queue->mutex);
! 652: l1 = queue->parityLogs;
! 653: while (l1) {
! 654: l2 = l1;
! 655: l1 = l2->next;
! 656: RF_Free(l2->records, (raidPtr->numSectorsPerLog *
! 657: sizeof(RF_ParityLogRecord_t)));
! 658: RF_Free(l2, sizeof(RF_ParityLog_t));
! 659: }
! 660: RF_UNLOCK_MUTEX(queue->mutex);
! 661: rf_mutex_destroy(&queue->mutex);
! 662: }
! 663:
! 664:
! 665: void
! 666: rf_FreeRegionBufferQueue(RF_RegionBufferQueue_t *queue)
! 667: {
! 668: int i;
! 669:
! 670: RF_LOCK_MUTEX(queue->mutex);
! 671: if (queue->availableBuffers != queue->totalBuffers) {
! 672: printf("Attempt to free region queue that is still in use !\n");
! 673: RF_ASSERT(0);
! 674: }
! 675: for (i = 0; i < queue->totalBuffers; i++)
! 676: RF_Free(queue->buffers[i], queue->bufferSize);
! 677: RF_Free(queue->buffers, queue->totalBuffers * sizeof(caddr_t));
! 678: RF_UNLOCK_MUTEX(queue->mutex);
! 679: rf_mutex_destroy(&queue->mutex);
! 680: }
! 681:
! 682:
! 683: void
! 684: rf_ShutdownParityLoggingRegionInfo(RF_ThreadArg_t arg)
! 685: {
! 686: RF_Raid_t *raidPtr;
! 687: RF_RegionId_t i;
! 688:
! 689: raidPtr = (RF_Raid_t *) arg;
! 690: if (rf_parityLogDebug) {
! 691: printf("raid%d: ShutdownParityLoggingRegionInfo\n",
! 692: raidPtr->raidid);
! 693: }
! 694: /* Free region information structs. */
! 695: for (i = 0; i < rf_numParityRegions; i++)
! 696: rf_FreeRegionInfo(raidPtr, i);
! 697: RF_Free(raidPtr->regionInfo, (rf_numParityRegions *
! 698: sizeof(raidPtr->regionInfo)));
! 699: raidPtr->regionInfo = NULL;
! 700: }
! 701:
! 702:
! 703: void
! 704: rf_ShutdownParityLoggingPool(RF_ThreadArg_t arg)
! 705: {
! 706: RF_Raid_t *raidPtr;
! 707:
! 708: raidPtr = (RF_Raid_t *) arg;
! 709: if (rf_parityLogDebug) {
! 710: printf("raid%d: ShutdownParityLoggingPool\n", raidPtr->raidid);
! 711: }
! 712: /* Free contents of parityLogPool. */
! 713: rf_FreeParityLogQueue(raidPtr, &raidPtr->parityLogPool);
! 714: RF_Free(raidPtr->parityLogBufferHeap, raidPtr->numParityLogs *
! 715: raidPtr->numSectorsPerLog * raidPtr->bytesPerSector);
! 716: }
! 717:
! 718:
! 719: void
! 720: rf_ShutdownParityLoggingRegionBufferPool(RF_ThreadArg_t arg)
! 721: {
! 722: RF_Raid_t *raidPtr;
! 723:
! 724: raidPtr = (RF_Raid_t *) arg;
! 725: if (rf_parityLogDebug) {
! 726: printf("raid%d: ShutdownParityLoggingRegionBufferPool\n",
! 727: raidPtr->raidid);
! 728: }
! 729: rf_FreeRegionBufferQueue(&raidPtr->regionBufferPool);
! 730: }
! 731:
! 732:
! 733: void
! 734: rf_ShutdownParityLoggingParityBufferPool(RF_ThreadArg_t arg)
! 735: {
! 736: RF_Raid_t *raidPtr;
! 737:
! 738: raidPtr = (RF_Raid_t *) arg;
! 739: if (rf_parityLogDebug) {
! 740: printf("raid%d: ShutdownParityLoggingParityBufferPool\n",
! 741: raidPtr->raidid);
! 742: }
! 743: rf_FreeRegionBufferQueue(&raidPtr->parityBufferPool);
! 744: }
! 745:
! 746:
! 747: void
! 748: rf_ShutdownParityLoggingDiskQueue(RF_ThreadArg_t arg)
! 749: {
! 750: RF_ParityLogData_t *d;
! 751: RF_CommonLogData_t *c;
! 752: RF_Raid_t *raidPtr;
! 753:
! 754: raidPtr = (RF_Raid_t *) arg;
! 755: if (rf_parityLogDebug) {
! 756: printf("raid%d: ShutdownParityLoggingDiskQueue\n",
! 757: raidPtr->raidid);
! 758: }
! 759: /* Free disk manager stuff. */
! 760: RF_ASSERT(raidPtr->parityLogDiskQueue.bufHead == NULL);
! 761: RF_ASSERT(raidPtr->parityLogDiskQueue.bufTail == NULL);
! 762: RF_ASSERT(raidPtr->parityLogDiskQueue.reintHead == NULL);
! 763: RF_ASSERT(raidPtr->parityLogDiskQueue.reintTail == NULL);
! 764: while (raidPtr->parityLogDiskQueue.freeDataList) {
! 765: d = raidPtr->parityLogDiskQueue.freeDataList;
! 766: raidPtr->parityLogDiskQueue.freeDataList =
! 767: raidPtr->parityLogDiskQueue.freeDataList->next;
! 768: RF_Free(d, sizeof(RF_ParityLogData_t));
! 769: }
! 770: while (raidPtr->parityLogDiskQueue.freeCommonList) {
! 771: c = raidPtr->parityLogDiskQueue.freeCommonList;
! 772: rf_mutex_destroy(&c->mutex);
! 773: raidPtr->parityLogDiskQueue.freeCommonList =
! 774: raidPtr->parityLogDiskQueue.freeCommonList->next;
! 775: RF_Free(c, sizeof(RF_CommonLogData_t));
! 776: }
! 777: }
! 778:
! 779:
! 780: void
! 781: rf_ShutdownParityLogging(RF_ThreadArg_t arg)
! 782: {
! 783: RF_Raid_t *raidPtr;
! 784:
! 785: raidPtr = (RF_Raid_t *) arg;
! 786: if (rf_parityLogDebug) {
! 787: printf("raid%d: ShutdownParityLogging\n", raidPtr->raidid);
! 788: }
! 789: /* Shutdown disk thread. */
! 790: /*
! 791: * This has the desirable side-effect of forcing all regions to be
! 792: * reintegrated. This is necessary since all parity log maps are
! 793: * currently held in volatile memory.
! 794: */
! 795:
! 796: RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
! 797: raidPtr->parityLogDiskQueue.threadState |= RF_PLOG_TERMINATE;
! 798: RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
! 799: RF_SIGNAL_COND(raidPtr->parityLogDiskQueue.cond);
! 800: /*
! 801: * pLogDiskThread will now terminate when queues are cleared.
! 802: * Now wait for it to be done.
! 803: */
! 804: RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
! 805: while (!(raidPtr->parityLogDiskQueue.threadState & RF_PLOG_SHUTDOWN)) {
! 806: RF_WAIT_COND(raidPtr->parityLogDiskQueue.cond,
! 807: raidPtr->parityLogDiskQueue.mutex);
! 808: }
! 809: RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);
! 810: if (rf_parityLogDebug) {
! 811: printf("raid%d: ShutdownParityLogging done"
! 812: " (thread completed)\n", raidPtr->raidid);
! 813: }
! 814: }
! 815:
! 816:
! 817: int
! 818: rf_GetDefaultNumFloatingReconBuffersParityLogging(RF_Raid_t *raidPtr)
! 819: {
! 820: return (20);
! 821: }
! 822:
! 823:
! 824: RF_HeadSepLimit_t
! 825: rf_GetDefaultHeadSepLimitParityLogging(RF_Raid_t *raidPtr)
! 826: {
! 827: return (10);
! 828: }
! 829:
! 830:
! 831: /* Return the region ID for a given RAID address. */
! 832: RF_RegionId_t
! 833: rf_MapRegionIDParityLogging(RF_Raid_t *raidPtr, RF_SectorNum_t address)
! 834: {
! 835: RF_RegionId_t regionID;
! 836:
! 837: /* regionID = address / (raidPtr->regionParityRange *
! 838: * raidPtr->Layout.numDataCol); */
! 839: regionID = address / raidPtr->regionParityRange;
! 840: if (regionID == rf_numParityRegions) {
! 841: /* Last region may be larger than other regions. */
! 842: regionID--;
! 843: }
! 844: RF_ASSERT(address >= raidPtr->regionInfo[regionID].parityStartAddr);
! 845: RF_ASSERT(address < raidPtr->regionInfo[regionID].parityStartAddr +
! 846: raidPtr->regionInfo[regionID].numSectorsParity);
! 847: RF_ASSERT(regionID < rf_numParityRegions);
! 848: return (regionID);
! 849: }
! 850:
! 851:
! 852: /* Given a logical RAID sector, determine physical disk address of data. */
! 853: void
! 854: rf_MapSectorParityLogging(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
! 855: RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
! 856: {
! 857: RF_StripeNum_t SUID = raidSector /
! 858: raidPtr->Layout.sectorsPerStripeUnit;
! 859: *row = 0;
! 860: /* *col = (SUID % (raidPtr->numCol -
! 861: * raidPtr->Layout.numParityLogCol)); */
! 862: *col = SUID % raidPtr->Layout.numDataCol;
! 863: *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
! 864: raidPtr->Layout.sectorsPerStripeUnit +
! 865: (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
! 866: }
! 867:
! 868:
! 869: /* Given a logical RAID sector, determine physical disk address of parity. */
! 870: void
! 871: rf_MapParityParityLogging(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
! 872: RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
! 873: {
! 874: RF_StripeNum_t SUID = raidSector /
! 875: raidPtr->Layout.sectorsPerStripeUnit;
! 876:
! 877: *row = 0;
! 878: /* *col =
! 879: * raidPtr->Layout.numDataCol-(SUID / raidPtr->Layout.numDataCol) %
! 880: * (raidPtr->numCol - raidPtr->Layout.numParityLogCol); */
! 881: *col = raidPtr->Layout.numDataCol;
! 882: *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
! 883: raidPtr->Layout.sectorsPerStripeUnit +
! 884: (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
! 885: }
! 886:
! 887:
! 888: /*
! 889: * Given a regionID and sector offset, determine the physical disk address
! 890: * of the parity log.
! 891: */
! 892: void
! 893: rf_MapLogParityLogging(RF_Raid_t *raidPtr, RF_RegionId_t regionID,
! 894: RF_SectorNum_t regionOffset, RF_RowCol_t *row, RF_RowCol_t *col,
! 895: RF_SectorNum_t *startSector)
! 896: {
! 897: *row = 0;
! 898: *col = raidPtr->numCol - 1;
! 899: *startSector =
! 900: raidPtr->regionInfo[regionID].regionStartAddr + regionOffset;
! 901: }
! 902:
! 903:
! 904: /*
! 905: * Given a regionID, determine the physical disk address of the logged
! 906: * parity for that region.
! 907: */
! 908: void
! 909: rf_MapRegionParity(RF_Raid_t *raidPtr, RF_RegionId_t regionID,
! 910: RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *startSector,
! 911: RF_SectorCount_t *numSector)
! 912: {
! 913: *row = 0;
! 914: *col = raidPtr->numCol - 2;
! 915: *startSector = raidPtr->regionInfo[regionID].parityStartAddr;
! 916: *numSector = raidPtr->regionInfo[regionID].numSectorsParity;
! 917: }
! 918:
! 919:
! 920: /*
! 921: * Given a logical RAID address, determine the participating disks in
! 922: * the stripe.
! 923: */
! 924: void
! 925: rf_IdentifyStripeParityLogging(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
! 926: RF_RowCol_t **diskids, RF_RowCol_t *outRow)
! 927: {
! 928: RF_StripeNum_t stripeID = rf_RaidAddressToStripeID(&raidPtr->Layout,
! 929: addr);
! 930: RF_ParityLoggingConfigInfo_t *info = (RF_ParityLoggingConfigInfo_t *)
! 931: raidPtr->Layout.layoutSpecificInfo;
! 932: *outRow = 0;
! 933: *diskids = info->stripeIdentifier[stripeID % raidPtr->numCol];
! 934: }
! 935:
! 936:
! 937: void
! 938: rf_MapSIDToPSIDParityLogging(RF_RaidLayout_t *layoutPtr,
! 939: RF_StripeNum_t stripeID, RF_StripeNum_t *psID, RF_ReconUnitNum_t *which_ru)
! 940: {
! 941: *which_ru = 0;
! 942: *psID = stripeID;
! 943: }
! 944:
! 945:
! 946: /*
! 947: * Select an algorithm for performing an access. Returns two pointers,
! 948: * one to a function that will return information about the DAG, and
! 949: * another to a function that will create the dag.
! 950: */
! 951: void
! 952: rf_ParityLoggingDagSelect(RF_Raid_t *raidPtr, RF_IoType_t type,
! 953: RF_AccessStripeMap_t *asmp, RF_VoidFuncPtr *createFunc)
! 954: {
! 955: RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
! 956: RF_PhysDiskAddr_t *failedPDA = NULL;
! 957: RF_RowCol_t frow, fcol;
! 958: RF_RowStatus_t rstat;
! 959: int prior_recon;
! 960:
! 961: RF_ASSERT(RF_IO_IS_R_OR_W(type));
! 962:
! 963: if (asmp->numDataFailed + asmp->numParityFailed > 1) {
! 964: RF_ERRORMSG("Multiple disks failed in a single group !"
! 965: " Aborting I/O operation.\n");
! 966: /* *infoFunc = */ *createFunc = NULL;
! 967: return;
! 968: } else
! 969: if (asmp->numDataFailed + asmp->numParityFailed == 1) {
! 970:
! 971: /*
! 972: * If under recon & already reconstructed, redirect
! 973: * the access to the spare drive and eliminate the
! 974: * failure indication.
! 975: */
! 976: failedPDA = asmp->failedPDAs[0];
! 977: frow = failedPDA->row;
! 978: fcol = failedPDA->col;
! 979: rstat = raidPtr->status[failedPDA->row];
! 980: prior_recon = (rstat == rf_rs_reconfigured) ||
! 981: ((rstat == rf_rs_reconstructing) ?
! 982: rf_CheckRUReconstructed(raidPtr->reconControl[frow]
! 983: ->reconMap, failedPDA->startSector) : 0);
! 984: if (prior_recon) {
! 985: RF_RowCol_t or = failedPDA->row;
! 986: RF_RowCol_t oc = failedPDA->col;
! 987: RF_SectorNum_t oo = failedPDA->startSector;
! 988: if (layoutPtr->map->flags &
! 989: RF_DISTRIBUTE_SPARE) {
! 990: /* Redirect to dist spare space. */
! 991:
! 992: if (failedPDA == asmp->parityInfo) {
! 993:
! 994: /* Parity has failed. */
! 995: (layoutPtr->map->MapParity)
! 996: (raidPtr,
! 997: failedPDA->raidAddress,
! 998: &failedPDA->row,
! 999: &failedPDA->col,
! 1000: &failedPDA->startSector,
! 1001: RF_REMAP);
! 1002:
! 1003: if (asmp->parityInfo->next) {
! 1004: /*
! 1005: * Redir 2nd component,
! 1006: * if any.
! 1007: */
! 1008: RF_PhysDiskAddr_t *p =
! 1009: asmp->parityInfo->next;
! 1010: RF_SectorNum_t SUoffs =
! 1011: p->startSector %
! 1012: layoutPtr->sectorsPerStripeUnit;
! 1013: p->row = failedPDA->row;
! 1014: p->col = failedPDA->col;
! 1015: /*
! 1016: * Cheating:
! 1017: * startSector is not
! 1018: * really a RAID
! 1019: * address.
! 1020: */
! 1021: p->startSector =
! 1022: rf_RaidAddressOfPrevStripeUnitBoundary(layoutPtr,
! 1023: failedPDA->startSector) + SUoffs;
! 1024: }
! 1025: } else
! 1026: if (asmp->parityInfo->next &&
! 1027: failedPDA ==
! 1028: asmp->parityInfo->next) {
! 1029: /*
! 1030: * Should not ever
! 1031: * happen.
! 1032: */
! 1033: RF_ASSERT(0);
! 1034: } else {
! 1035: /* Data has failed. */
! 1036: (layoutPtr->map
! 1037: ->MapSector)
! 1038: (raidPtr,
! 1039: failedPDA->raidAddress,
! 1040: &failedPDA->row,
! 1041: &failedPDA->col,
! 1042: &failedPDA->startSector,
! 1043: RF_REMAP);
! 1044: }
! 1045:
! 1046: } else {
! 1047: /* Redirect to dedicated spare space. */
! 1048:
! 1049: failedPDA->row =
! 1050: raidPtr->Disks[frow][fcol].spareRow;
! 1051: failedPDA->col =
! 1052: raidPtr->Disks[frow][fcol].spareCol;
! 1053:
! 1054: /*
! 1055: * The parity may have two distinct
! 1056: * components, both of which may need
! 1057: * to be redirected.
! 1058: */
! 1059: if (asmp->parityInfo->next) {
! 1060: if (failedPDA ==
! 1061: asmp->parityInfo) {
! 1062: failedPDA->next->row =
! 1063: failedPDA->row;
! 1064: failedPDA->next->col =
! 1065: failedPDA->col;
! 1066: } else {
! 1067: if (failedPDA ==
! 1068: asmp->parityInfo
! 1069: ->next) {
! 1070: /*
! 1071: * Paranoid:
! 1072: * Should never
! 1073: * occur.
! 1074: */
! 1075: asmp->parityInfo
! 1076: ->row =
! 1077: failedPDA->row;
! 1078: asmp->parityInfo
! 1079: ->col =
! 1080: failedPDA->col;
! 1081: }
! 1082: }
! 1083: }
! 1084: }
! 1085:
! 1086: RF_ASSERT(failedPDA->col != -1);
! 1087:
! 1088: if (rf_dagDebug || rf_mapDebug) {
! 1089: printf("raid%d: Redirected type '%c'"
! 1090: " r %d c %d o %ld -> r %d c %d"
! 1091: " o %ld\n", raidPtr->raidid,
! 1092: type, or, oc, (long) oo,
! 1093: failedPDA->row, failedPDA->col,
! 1094: (long) failedPDA->startSector);
! 1095: }
! 1096: asmp->numDataFailed = asmp->numParityFailed = 0;
! 1097: }
! 1098: }
! 1099: if (type == RF_IO_TYPE_READ) {
! 1100:
! 1101: if (asmp->numDataFailed == 0)
! 1102: *createFunc =
! 1103: (RF_VoidFuncPtr) rf_CreateFaultFreeReadDAG;
! 1104: else
! 1105: *createFunc =
! 1106: (RF_VoidFuncPtr) rf_CreateRaidFiveDegradedReadDAG;
! 1107:
! 1108: } else {
! 1109:
! 1110:
! 1111: /*
! 1112: * If mirroring, always use large writes. If the access
! 1113: * requires two distinct parity updates, always do a small
! 1114: * write. If the stripe contains a failure but the access
! 1115: * does not, do a small write. The first conditional
! 1116: * (numStripeUnitsAccessed <= numDataCol/2) uses a
! 1117: * less-than-or-equal rather than just a less-than because
! 1118: * when G is 3 or 4, numDataCol/2 is 1, and I want
! 1119: * single-stripe-unit updates to use just one disk.
! 1120: */
! 1121: if ((asmp->numDataFailed + asmp->numParityFailed) == 0) {
! 1122: if (((asmp->numStripeUnitsAccessed <=
! 1123: (layoutPtr->numDataCol / 2)) &&
! 1124: (layoutPtr->numDataCol != 1)) ||
! 1125: (asmp->parityInfo->next != NULL) ||
! 1126: rf_CheckStripeForFailures(raidPtr, asmp)) {
! 1127: *createFunc = (RF_VoidFuncPtr)
! 1128: rf_CreateParityLoggingSmallWriteDAG;
! 1129: } else
! 1130: *createFunc = (RF_VoidFuncPtr)
! 1131: rf_CreateParityLoggingLargeWriteDAG;
! 1132: } else
! 1133: if (asmp->numParityFailed == 1)
! 1134: *createFunc = (RF_VoidFuncPtr)
! 1135: rf_CreateNonRedundantWriteDAG;
! 1136: else
! 1137: if (asmp->numStripeUnitsAccessed != 1 &&
! 1138: failedPDA->numSector !=
! 1139: layoutPtr->sectorsPerStripeUnit)
! 1140: *createFunc = NULL;
! 1141: else
! 1142: *createFunc = (RF_VoidFuncPtr)
! 1143: rf_CreateDegradedWriteDAG;
! 1144: }
! 1145: }
! 1146: #endif /* RF_INCLUDE_PARITYLOGGING > 0 */
CVSweb