Annotation of sys/dev/raidframe/rf_chaindecluster.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: rf_chaindecluster.c,v 1.4 2002/12/16 07:01:03 tdeval Exp $ */
! 2: /* $NetBSD: rf_chaindecluster.c,v 1.4 2000/01/07 03:40:56 oster Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1995 Carnegie-Mellon University.
! 6: * All rights reserved.
! 7: *
! 8: * Author: Khalil Amiri
! 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: * rf_chaindecluster.c -- implements chained declustering
! 34: *
! 35: *****************************************************************************/
! 36:
! 37: #include "rf_archs.h"
! 38: #include "rf_types.h"
! 39: #include "rf_raid.h"
! 40: #include "rf_chaindecluster.h"
! 41: #include "rf_dag.h"
! 42: #include "rf_dagutils.h"
! 43: #include "rf_dagffrd.h"
! 44: #include "rf_dagffwr.h"
! 45: #include "rf_dagdegrd.h"
! 46: #include "rf_dagfuncs.h"
! 47: #include "rf_general.h"
! 48: #include "rf_utils.h"
! 49:
! 50: typedef struct RF_ChaindeclusterConfigInfo_s {
! 51: RF_RowCol_t **stripeIdentifier; /*
! 52: * Filled in at config time and
! 53: * used by IdentifyStripe.
! 54: */
! 55: RF_StripeCount_t numSparingRegions;
! 56: RF_StripeCount_t stripeUnitsPerSparingRegion;
! 57: RF_SectorNum_t mirrorStripeOffset;
! 58: } RF_ChaindeclusterConfigInfo_t;
! 59:
! 60:
! 61: int
! 62: rf_ConfigureChainDecluster(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
! 63: RF_Config_t *cfgPtr)
! 64: {
! 65: RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
! 66: RF_StripeCount_t num_used_stripeUnitsPerDisk;
! 67: RF_ChaindeclusterConfigInfo_t *info;
! 68: RF_RowCol_t i;
! 69:
! 70: /* Create a Chained Declustering configuration structure. */
! 71: RF_MallocAndAdd(info, sizeof(RF_ChaindeclusterConfigInfo_t),
! 72: (RF_ChaindeclusterConfigInfo_t *), raidPtr->cleanupList);
! 73: if (info == NULL)
! 74: return (ENOMEM);
! 75: layoutPtr->layoutSpecificInfo = (void *) info;
! 76:
! 77: /* Fill in the config structure. */
! 78: info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol, 2,
! 79: raidPtr->cleanupList);
! 80: if (info->stripeIdentifier == NULL)
! 81: return (ENOMEM);
! 82: for (i = 0; i < raidPtr->numCol; i++) {
! 83: info->stripeIdentifier[i][0] = i % raidPtr->numCol;
! 84: info->stripeIdentifier[i][1] = (i + 1) % raidPtr->numCol;
! 85: }
! 86:
! 87: RF_ASSERT(raidPtr->numRow == 1);
! 88:
! 89: /* Fill in the remaining layout parameters. */
! 90: num_used_stripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk -
! 91: (layoutPtr->stripeUnitsPerDisk % (2 * raidPtr->numCol - 2));
! 92: info->numSparingRegions = num_used_stripeUnitsPerDisk /
! 93: (2 * raidPtr->numCol - 2);
! 94: info->stripeUnitsPerSparingRegion = raidPtr->numCol *
! 95: (raidPtr->numCol - 1);
! 96: info->mirrorStripeOffset = info->numSparingRegions *
! 97: (raidPtr->numCol - 1);
! 98: layoutPtr->numStripe = info->numSparingRegions *
! 99: info->stripeUnitsPerSparingRegion;
! 100: layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit <<
! 101: raidPtr->logBytesPerSector;
! 102: layoutPtr->numDataCol = 1;
! 103: layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol *
! 104: layoutPtr->sectorsPerStripeUnit;
! 105: layoutPtr->numParityCol = 1;
! 106:
! 107: layoutPtr->dataStripeUnitsPerDisk = num_used_stripeUnitsPerDisk;
! 108:
! 109: raidPtr->sectorsPerDisk = num_used_stripeUnitsPerDisk *
! 110: layoutPtr->sectorsPerStripeUnit;
! 111:
! 112: raidPtr->totalSectors = (layoutPtr->numStripe) *
! 113: layoutPtr->sectorsPerStripeUnit;
! 114:
! 115: layoutPtr->stripeUnitsPerDisk = raidPtr->sectorsPerDisk /
! 116: layoutPtr->sectorsPerStripeUnit;
! 117:
! 118: return (0);
! 119: }
! 120:
! 121: RF_ReconUnitCount_t
! 122: rf_GetNumSpareRUsChainDecluster(RF_Raid_t *raidPtr)
! 123: {
! 124: RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *)
! 125: raidPtr->Layout.layoutSpecificInfo;
! 126:
! 127: /*
! 128: * The layout uses two stripe units per disk as spare within each
! 129: * sparing region.
! 130: */
! 131: return (2 * info->numSparingRegions);
! 132: }
! 133:
! 134:
! 135: /* Maps to the primary copy of the data, i.e. the first mirror pair. */
! 136: void
! 137: rf_MapSectorChainDecluster(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
! 138: RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
! 139: {
! 140: RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *)
! 141: raidPtr->Layout.layoutSpecificInfo;
! 142: RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
! 143: RF_SectorNum_t index_within_region, index_within_disk;
! 144: RF_StripeNum_t sparing_region_id;
! 145: int col_before_remap;
! 146:
! 147: *row = 0;
! 148: sparing_region_id = SUID / info->stripeUnitsPerSparingRegion;
! 149: index_within_region = SUID % info->stripeUnitsPerSparingRegion;
! 150: index_within_disk = index_within_region / raidPtr->numCol;
! 151: col_before_remap = SUID % raidPtr->numCol;
! 152:
! 153: if (!remap) {
! 154: *col = col_before_remap;
! 155: *diskSector = (index_within_disk + ((raidPtr->numCol - 1) *
! 156: sparing_region_id)) * raidPtr->Layout.sectorsPerStripeUnit;
! 157: *diskSector += (raidSector %
! 158: raidPtr->Layout.sectorsPerStripeUnit);
! 159: } else {
! 160: /* Remap sector to spare space... */
! 161: *diskSector = sparing_region_id * (raidPtr->numCol + 1) *
! 162: raidPtr->Layout.sectorsPerStripeUnit;
! 163: *diskSector += (raidPtr->numCol - 1) *
! 164: raidPtr->Layout.sectorsPerStripeUnit;
! 165: *diskSector += (raidSector %
! 166: raidPtr->Layout.sectorsPerStripeUnit);
! 167: index_within_disk = index_within_region / raidPtr->numCol;
! 168: if (index_within_disk < col_before_remap)
! 169: *col = index_within_disk;
! 170: else
! 171: if (index_within_disk == raidPtr->numCol - 2) {
! 172: *col = (col_before_remap + raidPtr->numCol - 1)
! 173: % raidPtr->numCol;
! 174: *diskSector +=
! 175: raidPtr->Layout.sectorsPerStripeUnit;
! 176: } else
! 177: *col = (index_within_disk + 2) %
! 178: raidPtr->numCol;
! 179: }
! 180:
! 181: }
! 182:
! 183:
! 184: /*
! 185: * Maps to the second copy of the mirror pair, which is chain declustered.
! 186: * The second copy is contained in the next disk (mod numCol) after the disk
! 187: * containing the primary copy.
! 188: * The offset into the disk is one-half disk down.
! 189: */
! 190: void
! 191: rf_MapParityChainDecluster(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
! 192: RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
! 193: {
! 194: RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *)
! 195: raidPtr->Layout.layoutSpecificInfo;
! 196: RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
! 197: RF_SectorNum_t index_within_region, index_within_disk;
! 198: RF_StripeNum_t sparing_region_id;
! 199: int col_before_remap;
! 200:
! 201: *row = 0;
! 202: if (!remap) {
! 203: *col = SUID % raidPtr->numCol;
! 204: *col = (*col + 1) % raidPtr->numCol;
! 205: *diskSector = info->mirrorStripeOffset *
! 206: raidPtr->Layout.sectorsPerStripeUnit;
! 207: *diskSector += (SUID / raidPtr->numCol) *
! 208: raidPtr->Layout.sectorsPerStripeUnit;
! 209: *diskSector += (raidSector %
! 210: raidPtr->Layout.sectorsPerStripeUnit);
! 211: } else {
! 212: /* Remap parity to spare space... */
! 213: sparing_region_id = SUID / info->stripeUnitsPerSparingRegion;
! 214: index_within_region = SUID % info->stripeUnitsPerSparingRegion;
! 215: index_within_disk = index_within_region / raidPtr->numCol;
! 216: *diskSector = sparing_region_id * (raidPtr->numCol + 1) *
! 217: raidPtr->Layout.sectorsPerStripeUnit;
! 218: *diskSector += (raidPtr->numCol) *
! 219: raidPtr->Layout.sectorsPerStripeUnit;
! 220: *diskSector += (raidSector %
! 221: raidPtr->Layout.sectorsPerStripeUnit);
! 222: col_before_remap = SUID % raidPtr->numCol;
! 223: if (index_within_disk < col_before_remap)
! 224: *col = index_within_disk;
! 225: else
! 226: if (index_within_disk == raidPtr->numCol - 2) {
! 227: *col = (col_before_remap + 2) % raidPtr->numCol;
! 228: *diskSector -=
! 229: raidPtr->Layout.sectorsPerStripeUnit;
! 230: } else
! 231: *col = (index_within_disk + 2) %
! 232: raidPtr->numCol;
! 233: }
! 234: }
! 235:
! 236: void
! 237: rf_IdentifyStripeChainDecluster(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
! 238: RF_RowCol_t **diskids, RF_RowCol_t *outRow)
! 239: {
! 240: RF_ChaindeclusterConfigInfo_t *info = (RF_ChaindeclusterConfigInfo_t *)
! 241: raidPtr->Layout.layoutSpecificInfo;
! 242: RF_StripeNum_t SUID;
! 243: RF_RowCol_t col;
! 244:
! 245: SUID = addr / raidPtr->Layout.sectorsPerStripeUnit;
! 246: col = SUID % raidPtr->numCol;
! 247: *outRow = 0;
! 248: *diskids = info->stripeIdentifier[col];
! 249: }
! 250:
! 251: void
! 252: rf_MapSIDToPSIDChainDecluster(RF_RaidLayout_t *layoutPtr,
! 253: RF_StripeNum_t stripeID, RF_StripeNum_t *psID, RF_ReconUnitNum_t *which_ru)
! 254: {
! 255: *which_ru = 0;
! 256: *psID = stripeID;
! 257: }
! 258:
! 259:
! 260: /****************************************************************************
! 261: * Select a graph to perform a single-stripe access.
! 262: *
! 263: * Parameters: raidPtr - description of the physical array
! 264: * type - type of operation (read or write) requested
! 265: * asmap - logical & physical addresses for this access
! 266: * createFunc - function to use to create the graph (return value)
! 267: *****************************************************************************/
! 268:
! 269: void
! 270: rf_RAIDCDagSelect(RF_Raid_t *raidPtr, RF_IoType_t type,
! 271: RF_AccessStripeMap_t *asmap, RF_VoidFuncPtr *createFunc)
! 272: {
! 273: RF_ASSERT(RF_IO_IS_R_OR_W(type));
! 274: RF_ASSERT(raidPtr->numRow == 1);
! 275:
! 276: if (asmap->numDataFailed + asmap->numParityFailed > 1) {
! 277: RF_ERRORMSG("Multiple disks failed in a single group !"
! 278: " Aborting I/O operation.\n");
! 279: *createFunc = NULL;
! 280: return;
! 281: }
! 282: *createFunc = (type == RF_IO_TYPE_READ) ?
! 283: (RF_VoidFuncPtr) rf_CreateFaultFreeReadDAG :
! 284: (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
! 285:
! 286: if (type == RF_IO_TYPE_READ) {
! 287: if ((raidPtr->status[0] == rf_rs_degraded) ||
! 288: (raidPtr->status[0] == rf_rs_reconstructing))
! 289: /*
! 290: * Array status is degraded,
! 291: * implement workload shifting.
! 292: */
! 293: *createFunc = (RF_VoidFuncPtr)
! 294: rf_CreateRaidCDegradedReadDAG;
! 295: else
! 296: /*
! 297: * Array status not degraded,
! 298: * so use mirror partition dag.
! 299: */
! 300: *createFunc = (RF_VoidFuncPtr)
! 301: rf_CreateMirrorPartitionReadDAG;
! 302: } else
! 303: *createFunc = (RF_VoidFuncPtr) rf_CreateRaidOneWriteDAG;
! 304: }
CVSweb