Annotation of sys/dev/raidframe/rf_declusterPQ.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: rf_declusterPQ.c,v 1.4 2002/12/16 07:01:03 tdeval Exp $ */
! 2: /* $NetBSD: rf_declusterPQ.c,v 1.3 1999/02/05 00:06:09 oster Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1995 Carnegie-Mellon University.
! 6: * All rights reserved.
! 7: *
! 8: * Authors: Daniel Stodolsky, Mark Holland, Jim Zelenka
! 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_declusterPQ.c
! 33: *
! 34: * Mapping code for declustered P & Q or declustered EvenOdd.
! 35: * Much code borrowed from rf_decluster.c
! 36: *
! 37: *****************************************************************************/
! 38:
! 39:
! 40: #include "rf_types.h"
! 41: #include "rf_raid.h"
! 42: #include "rf_configure.h"
! 43: #include "rf_decluster.h"
! 44: #include "rf_declusterPQ.h"
! 45: #include "rf_debugMem.h"
! 46: #include "rf_utils.h"
! 47: #include "rf_alloclist.h"
! 48: #include "rf_general.h"
! 49:
! 50: /* Configuration code. */
! 51:
! 52: int
! 53: rf_ConfigureDeclusteredPQ(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
! 54: RF_Config_t *cfgPtr)
! 55: {
! 56: RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
! 57: int b, v, k, r, lambda; /* block design params */
! 58: int i, j, l;
! 59: int *first_avail_slot;
! 60: int complete_FT_count, SUID;
! 61: RF_DeclusteredConfigInfo_t *info;
! 62: int numCompleteFullTablesPerDisk;
! 63: int PUsPerDisk, spareRegionDepthInPUs, extraPUsPerDisk;
! 64: int numCompleteSpareRegionsPerDisk = 0;
! 65: int totSparePUsPerDisk;
! 66: int diskOffsetOfLastFullTableInSUs, SpareSpaceInSUs;
! 67: char *cfgBuf = (char *)(cfgPtr->layoutSpecific);
! 68:
! 69: cfgBuf += RF_SPAREMAP_NAME_LEN;
! 70:
! 71: b = *((int *) cfgBuf);
! 72: cfgBuf += sizeof(int);
! 73: v = *((int *) cfgBuf);
! 74: cfgBuf += sizeof(int);
! 75: k = *((int *) cfgBuf);
! 76: cfgBuf += sizeof(int);
! 77: r = *((int *) cfgBuf);
! 78: cfgBuf += sizeof(int);
! 79: lambda = *((int *) cfgBuf);
! 80: cfgBuf += sizeof(int);
! 81: raidPtr->noRotate = *((int *) cfgBuf);
! 82: cfgBuf += sizeof(int);
! 83:
! 84: if (k <= 2) {
! 85: #ifdef RAIDDEBUG
! 86: printf("RAIDFRAME: k=%d, minimum value 2\n", k);
! 87: #endif /* RAIDDEBUG */
! 88: return (EINVAL);
! 89: }
! 90: /* 1. Create layout specific structure. */
! 91: RF_MallocAndAdd(info, sizeof(RF_DeclusteredConfigInfo_t),
! 92: (RF_DeclusteredConfigInfo_t *), raidPtr->cleanupList);
! 93: if (info == NULL)
! 94: return (ENOMEM);
! 95: layoutPtr->layoutSpecificInfo = (void *) info;
! 96:
! 97: /*
! 98: * 2. The sparemaps are generated assuming that parity is rotated, so
! 99: * we issue a warning if both distributed sparing and no-rotate are on
! 100: * at the same time.
! 101: */
! 102: if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE) &&
! 103: raidPtr->noRotate) {
! 104: RF_ERRORMSG("Warning: distributed sparing specified without"
! 105: " parity rotation.\n");
! 106: }
! 107: if (raidPtr->numCol != v) {
! 108: RF_ERRORMSG2("RAID: config error: table element count (%d)"
! 109: " not equal to no. of cols (%d).\n", v, raidPtr->numCol);
! 110: return (EINVAL);
! 111: }
! 112: /* 3. Set up the values used in devRaidMap. */
! 113: info->BlocksPerTable = b;
! 114: info->NumParityReps = info->groupSize = k;
! 115: info->PUsPerBlock = k - 2; /* PQ */
! 116: info->SUsPerTable = b * info->PUsPerBlock * layoutPtr->SUsPerPU;
! 117: /* b blks, k-1 SUs each. */
! 118: info->SUsPerFullTable = k * info->SUsPerTable; /* Rot k times. */
! 119: info->SUsPerBlock = info->PUsPerBlock * layoutPtr->SUsPerPU;
! 120: info->TableDepthInPUs = (b * k) / v;
! 121: info->FullTableDepthInPUs = info->TableDepthInPUs * k;
! 122: /* k repetitions. */
! 123:
! 124: /* Used only in distributed sparing case. */
! 125: info->FullTablesPerSpareRegion = (v - 1) / rf_gcd(r, v - 1);
! 126: /* (v-1)/gcd fulltables. */
! 127: info->TablesPerSpareRegion = k * info->FullTablesPerSpareRegion;
! 128: info->SpareSpaceDepthPerRegionInSUs = (r * info->TablesPerSpareRegion
! 129: / (v - 1)) * layoutPtr->SUsPerPU;
! 130:
! 131: /* Check to make sure the block design is sufficiently small. */
! 132: if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
! 133: if (info->FullTableDepthInPUs * layoutPtr->SUsPerPU +
! 134: info->SpareSpaceDepthPerRegionInSUs >
! 135: layoutPtr->stripeUnitsPerDisk) {
! 136: RF_ERRORMSG3("RAID: config error: Full Table depth"
! 137: " (%d) + Spare Space (%d) larger than disk size"
! 138: " (%d) (BD too big).\n",
! 139: (int)info->FullTableDepthInPUs,
! 140: (int)info->SpareSpaceDepthPerRegionInSUs,
! 141: (int)layoutPtr->stripeUnitsPerDisk);
! 142: return (EINVAL);
! 143: }
! 144: } else {
! 145: if (info->TableDepthInPUs * layoutPtr->SUsPerPU >
! 146: layoutPtr->stripeUnitsPerDisk) {
! 147: RF_ERRORMSG2("RAID: config error: Table depth (%d)"
! 148: " larger than disk size (%d) (BD too big).\n",
! 149: (int) (info->TableDepthInPUs * layoutPtr->SUsPerPU),
! 150: (int) layoutPtr->stripeUnitsPerDisk);
! 151: return (EINVAL);
! 152: }
! 153: }
! 154:
! 155: /*
! 156: * Compute the size of each disk, and the number of tables in the last
! 157: * fulltable (which need not be complete).
! 158: */
! 159: if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
! 160:
! 161: PUsPerDisk = layoutPtr->stripeUnitsPerDisk /
! 162: layoutPtr->SUsPerPU;
! 163: spareRegionDepthInPUs = (info->TablesPerSpareRegion *
! 164: info->TableDepthInPUs + (info->TablesPerSpareRegion *
! 165: info->TableDepthInPUs) / (v - 1));
! 166: info->SpareRegionDepthInSUs = spareRegionDepthInPUs *
! 167: layoutPtr->SUsPerPU;
! 168:
! 169: numCompleteSpareRegionsPerDisk = PUsPerDisk /
! 170: spareRegionDepthInPUs;
! 171: info->NumCompleteSRs = numCompleteSpareRegionsPerDisk;
! 172: extraPUsPerDisk = PUsPerDisk % spareRegionDepthInPUs;
! 173:
! 174: /*
! 175: * Assume conservatively that we need the full amount of spare
! 176: * space in one region in order to provide spares for the
! 177: * partial spare region at the end of the array. We set "i"
! 178: * to the number of tables in the partial spare region. This
! 179: * may actually include some fulltables.
! 180: */
! 181: extraPUsPerDisk -= (info->SpareSpaceDepthPerRegionInSUs /
! 182: layoutPtr->SUsPerPU);
! 183: if (extraPUsPerDisk <= 0)
! 184: i = 0;
! 185: else
! 186: i = extraPUsPerDisk / info->TableDepthInPUs;
! 187:
! 188: complete_FT_count = raidPtr->numRow *
! 189: (numCompleteSpareRegionsPerDisk *
! 190: (info->TablesPerSpareRegion / k) + i / k);
! 191: info->FullTableLimitSUID = complete_FT_count *
! 192: info->SUsPerFullTable;
! 193: info->ExtraTablesPerDisk = i % k;
! 194:
! 195: /*
! 196: * Note that in the last spare region, the spare space is
! 197: * complete even though data/parity space is not.
! 198: */
! 199: totSparePUsPerDisk = (numCompleteSpareRegionsPerDisk + 1) *
! 200: (info->SpareSpaceDepthPerRegionInSUs / layoutPtr->SUsPerPU);
! 201: info->TotSparePUsPerDisk = totSparePUsPerDisk;
! 202:
! 203: layoutPtr->stripeUnitsPerDisk =
! 204: ((complete_FT_count / raidPtr->numRow) *
! 205: info->FullTableDepthInPUs + /* data & parity space */
! 206: info->ExtraTablesPerDisk * info->TableDepthInPUs +
! 207: totSparePUsPerDisk /* spare space */
! 208: ) * layoutPtr->SUsPerPU;
! 209: layoutPtr->dataStripeUnitsPerDisk =
! 210: (complete_FT_count * info->FullTableDepthInPUs +
! 211: info->ExtraTablesPerDisk * info->TableDepthInPUs)
! 212: * layoutPtr->SUsPerPU * (k - 1) / k;
! 213:
! 214: } else {
! 215: /*
! 216: * Non-dist spare case: force each disk to contain an
! 217: * integral number of tables.
! 218: */
! 219: layoutPtr->stripeUnitsPerDisk /=
! 220: (info->TableDepthInPUs * layoutPtr->SUsPerPU);
! 221: layoutPtr->stripeUnitsPerDisk *=
! 222: (info->TableDepthInPUs * layoutPtr->SUsPerPU);
! 223:
! 224: /*
! 225: * Compute the number of tables in the last fulltable, which
! 226: * need not be complete.
! 227: */
! 228: complete_FT_count = ((layoutPtr->stripeUnitsPerDisk /
! 229: layoutPtr->SUsPerPU) / info->FullTableDepthInPUs) *
! 230: raidPtr->numRow;
! 231:
! 232: info->FullTableLimitSUID = complete_FT_count *
! 233: info->SUsPerFullTable;
! 234: info->ExtraTablesPerDisk = ((layoutPtr->stripeUnitsPerDisk /
! 235: layoutPtr->SUsPerPU) / info->TableDepthInPUs) % k;
! 236: }
! 237:
! 238: raidPtr->sectorsPerDisk = layoutPtr->stripeUnitsPerDisk *
! 239: layoutPtr->sectorsPerStripeUnit;
! 240:
! 241: /*
! 242: * Find the disk offset of the stripe unit where the last
! 243: * fulltable starts.
! 244: */
! 245: numCompleteFullTablesPerDisk = complete_FT_count / raidPtr->numRow;
! 246: diskOffsetOfLastFullTableInSUs = numCompleteFullTablesPerDisk *
! 247: info->FullTableDepthInPUs * layoutPtr->SUsPerPU;
! 248: if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
! 249: SpareSpaceInSUs = numCompleteSpareRegionsPerDisk *
! 250: info->SpareSpaceDepthPerRegionInSUs;
! 251: diskOffsetOfLastFullTableInSUs += SpareSpaceInSUs;
! 252: info->DiskOffsetOfLastSpareSpaceChunkInSUs =
! 253: diskOffsetOfLastFullTableInSUs + info->ExtraTablesPerDisk *
! 254: info->TableDepthInPUs * layoutPtr->SUsPerPU;
! 255: }
! 256: info->DiskOffsetOfLastFullTableInSUs = diskOffsetOfLastFullTableInSUs;
! 257: info->numCompleteFullTablesPerDisk = numCompleteFullTablesPerDisk;
! 258:
! 259: /* 4. Create and initialize the lookup tables. */
! 260: info->LayoutTable = rf_make_2d_array(b, k, raidPtr->cleanupList);
! 261: if (info->LayoutTable == NULL)
! 262: return (ENOMEM);
! 263:
! 264: info->OffsetTable = rf_make_2d_array(b, k, raidPtr->cleanupList);
! 265: if (info->OffsetTable == NULL)
! 266: return (ENOMEM);
! 267:
! 268: info->BlockTable = rf_make_2d_array(info->TableDepthInPUs *
! 269: layoutPtr->SUsPerPU, raidPtr->numCol, raidPtr->cleanupList);
! 270: if (info->BlockTable == NULL)
! 271: return (ENOMEM);
! 272:
! 273: first_avail_slot = (int *) rf_make_1d_array(v, NULL);
! 274: if (first_avail_slot == NULL)
! 275: return (ENOMEM);
! 276:
! 277: for (i = 0; i < b; i++)
! 278: for (j = 0; j < k; j++)
! 279: info->LayoutTable[i][j] = *cfgBuf++;
! 280:
! 281: /* Initialize offset table. */
! 282: for (i = 0; i < b; i++)
! 283: for (j = 0; j < k; j++) {
! 284: info->OffsetTable[i][j] =
! 285: first_avail_slot[info->LayoutTable[i][j]];
! 286: first_avail_slot[info->LayoutTable[i][j]]++;
! 287: }
! 288:
! 289: /* Initialize block table. */
! 290: for (SUID = l = 0; l < layoutPtr->SUsPerPU; l++) {
! 291: for (i = 0; i < b; i++) {
! 292: for (j = 0; j < k; j++) {
! 293: info->BlockTable[(info->OffsetTable[i][j] *
! 294: layoutPtr->SUsPerPU) + l]
! 295: [info->LayoutTable[i][j]] = SUID;
! 296: }
! 297: SUID++;
! 298: }
! 299: }
! 300:
! 301: rf_free_1d_array(first_avail_slot, v);
! 302:
! 303: /* 5. Set up the remaining redundant-but-useful parameters. */
! 304:
! 305: raidPtr->totalSectors = (k * complete_FT_count + raidPtr->numRow *
! 306: info->ExtraTablesPerDisk) * info->SUsPerTable *
! 307: layoutPtr->sectorsPerStripeUnit;
! 308: layoutPtr->numStripe = (raidPtr->totalSectors /
! 309: layoutPtr->sectorsPerStripeUnit) / (k - 2);
! 310:
! 311: /*
! 312: * Strange evaluation order below to try and minimize overflow
! 313: * problems.
! 314: */
! 315:
! 316: layoutPtr->dataSectorsPerStripe = (k - 2) *
! 317: layoutPtr->sectorsPerStripeUnit;
! 318: layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit <<
! 319: raidPtr->logBytesPerSector;
! 320: layoutPtr->numDataCol = k - 2;
! 321: layoutPtr->numParityCol = 2;
! 322:
! 323: return (0);
! 324: }
! 325:
! 326: int
! 327: rf_GetDefaultNumFloatingReconBuffersPQ(RF_Raid_t *raidPtr)
! 328: {
! 329: int def_decl;
! 330:
! 331: def_decl = rf_GetDefaultNumFloatingReconBuffersDeclustered(raidPtr);
! 332: return (RF_MAX(3 * raidPtr->numCol, def_decl));
! 333: }
! 334:
! 335: void
! 336: rf_MapSectorDeclusteredPQ(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
! 337: RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
! 338: {
! 339: RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
! 340: RF_DeclusteredConfigInfo_t *info =
! 341: (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo;
! 342: RF_StripeNum_t SUID = raidSector / layoutPtr->sectorsPerStripeUnit;
! 343: RF_StripeNum_t FullTableID, FullTableOffset, TableID, TableOffset;
! 344: RF_StripeNum_t BlockID, BlockOffset, RepIndex;
! 345: RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable;
! 346: RF_StripeCount_t fulltable_depth = info->FullTableDepthInPUs *
! 347: layoutPtr->SUsPerPU;
! 348: RF_StripeNum_t base_suid = 0, outSU, SpareRegion = 0, SpareSpace = 0;
! 349:
! 350: rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable,
! 351: &fulltable_depth, &base_suid);
! 352:
! 353: /* Fulltable ID within array (across rows). */
! 354: FullTableID = SUID / sus_per_fulltable;
! 355: *row = FullTableID % raidPtr->numRow;
! 356:
! 357: /* Convert to fulltable ID on this disk. */
! 358: FullTableID /= raidPtr->numRow;
! 359:
! 360: if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
! 361: SpareRegion = FullTableID / info->FullTablesPerSpareRegion;
! 362: SpareSpace = SpareRegion * info->SpareSpaceDepthPerRegionInSUs;
! 363: }
! 364: FullTableOffset = SUID % sus_per_fulltable;
! 365: TableID = FullTableOffset / info->SUsPerTable;
! 366: TableOffset = FullTableOffset - TableID * info->SUsPerTable;
! 367: BlockID = TableOffset / info->PUsPerBlock;
! 368: BlockOffset = TableOffset - BlockID * info->PUsPerBlock;
! 369: BlockID %= info->BlocksPerTable;
! 370: RF_ASSERT(BlockOffset < info->groupSize - 2);
! 371: /*
! 372: * TableIDs go from 0 .. GroupSize-1 inclusive.
! 373: * PUsPerBlock is k-2.
! 374: * We want the tableIDs to rotate from the
! 375: * right, so use GroupSize.
! 376: */
! 377: RepIndex = info->groupSize - 1 - TableID;
! 378: RF_ASSERT(RepIndex >= 0);
! 379: if (!raidPtr->noRotate) {
! 380: if (TableID == 0)
! 381: /* P on last drive, Q on first. */
! 382: BlockOffset++;
! 383: else
! 384: /* Skip over PQ. */
! 385: BlockOffset += ((BlockOffset >= RepIndex) ? 2 : 0);
! 386:
! 387: RF_ASSERT(BlockOffset < info->groupSize);
! 388: *col = info->LayoutTable[BlockID][BlockOffset];
! 389: }
! 390: /* Remap to distributed spare space if indicated. */
! 391: if (remap) {
! 392: rf_remap_to_spare_space(layoutPtr, info, *row, FullTableID,
! 393: TableID, BlockID, (base_suid) ? 1 : 0, SpareRegion, col,
! 394: &outSU);
! 395: } else {
! 396:
! 397: outSU = base_suid;
! 398: outSU += FullTableID * fulltable_depth;
! 399: /* Offset to strt of FT. */
! 400: outSU += SpareSpace;
! 401: /* Skip reserved spare space. */
! 402: outSU += TableID * info->TableDepthInPUs * layoutPtr->SUsPerPU;
! 403: /* Offset to start of table. */
! 404: outSU += info->OffsetTable[BlockID][BlockOffset] *
! 405: layoutPtr->SUsPerPU;
! 406: /* Offset to the PU. */
! 407: }
! 408: outSU += TableOffset / (info->BlocksPerTable * info->PUsPerBlock);
! 409: /* Offset to the SU within a PU. */
! 410:
! 411: /*
! 412: * Convert SUs to sectors, and, if not aligned to SU boundary, add in
! 413: * offset to sector.
! 414: */
! 415: *diskSector = outSU * layoutPtr->sectorsPerStripeUnit +
! 416: (raidSector % layoutPtr->sectorsPerStripeUnit);
! 417: }
! 418:
! 419:
! 420: void
! 421: rf_MapParityDeclusteredPQ(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
! 422: RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
! 423: {
! 424: RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
! 425: RF_DeclusteredConfigInfo_t *info =
! 426: (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo;
! 427: RF_StripeNum_t SUID = raidSector / layoutPtr->sectorsPerStripeUnit;
! 428: RF_StripeNum_t FullTableID, FullTableOffset, TableID, TableOffset;
! 429: RF_StripeNum_t BlockID, BlockOffset, RepIndex;
! 430: RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable;
! 431: RF_StripeCount_t fulltable_depth = info->FullTableDepthInPUs *
! 432: layoutPtr->SUsPerPU;
! 433: RF_StripeNum_t base_suid = 0, outSU, SpareRegion, SpareSpace = 0;
! 434:
! 435: rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable,
! 436: &fulltable_depth, &base_suid);
! 437:
! 438: /* Compute row & (possibly) spare space exactly as before. */
! 439: FullTableID = SUID / sus_per_fulltable;
! 440: *row = FullTableID % raidPtr->numRow;
! 441: /* Convert to fulltable ID on this disk. */
! 442: FullTableID /= raidPtr->numRow;
! 443: if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
! 444: SpareRegion = FullTableID / info->FullTablesPerSpareRegion;
! 445: SpareSpace = SpareRegion * info->SpareSpaceDepthPerRegionInSUs;
! 446: }
! 447: /* Compute BlockID and RepIndex exactly as before. */
! 448: FullTableOffset = SUID % sus_per_fulltable;
! 449: TableID = FullTableOffset / info->SUsPerTable;
! 450: TableOffset = FullTableOffset - TableID * info->SUsPerTable;
! 451: BlockID = TableOffset / info->PUsPerBlock;
! 452: BlockOffset = TableOffset - BlockID * info->PUsPerBlock;
! 453: BlockID %= info->BlocksPerTable;
! 454:
! 455: /* The parity block is in the position indicated by RepIndex. */
! 456: RepIndex = (raidPtr->noRotate) ?
! 457: info->PUsPerBlock : info->groupSize - 1 - TableID;
! 458: *col = info->LayoutTable[BlockID][RepIndex];
! 459:
! 460: if (remap)
! 461: RF_PANIC();
! 462:
! 463: /*
! 464: * Compute sector as before, except use RepIndex instead of
! 465: * BlockOffset.
! 466: */
! 467: outSU = base_suid;
! 468: outSU += FullTableID * fulltable_depth;
! 469: outSU += SpareSpace; /* skip rsvd spare space */
! 470: outSU += TableID * info->TableDepthInPUs * layoutPtr->SUsPerPU;
! 471: outSU += info->OffsetTable[BlockID][RepIndex] * layoutPtr->SUsPerPU;
! 472: outSU += TableOffset / (info->BlocksPerTable * info->PUsPerBlock);
! 473:
! 474: *diskSector = outSU * layoutPtr->sectorsPerStripeUnit +
! 475: (raidSector % layoutPtr->sectorsPerStripeUnit);
! 476: }
! 477:
! 478: void
! 479: rf_MapQDeclusteredPQ(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
! 480: RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
! 481: {
! 482: RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
! 483: RF_DeclusteredConfigInfo_t *info =
! 484: (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo;
! 485: RF_StripeNum_t SUID = raidSector / layoutPtr->sectorsPerStripeUnit;
! 486: RF_StripeNum_t FullTableID, FullTableOffset, TableID, TableOffset;
! 487: RF_StripeNum_t BlockID, BlockOffset, RepIndex, RepIndexQ;
! 488: RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable;
! 489: RF_StripeCount_t fulltable_depth = info->FullTableDepthInPUs *
! 490: layoutPtr->SUsPerPU;
! 491: RF_StripeNum_t base_suid = 0, outSU, SpareRegion, SpareSpace = 0;
! 492:
! 493: rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable,
! 494: &fulltable_depth, &base_suid);
! 495:
! 496: /* Compute row & (possibly) spare space exactly as before. */
! 497: FullTableID = SUID / sus_per_fulltable;
! 498: *row = FullTableID % raidPtr->numRow;
! 499: /* Convert to fulltable ID on this disk. */
! 500: FullTableID /= raidPtr->numRow;
! 501: if ((raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
! 502: SpareRegion = FullTableID / info->FullTablesPerSpareRegion;
! 503: SpareSpace = SpareRegion * info->SpareSpaceDepthPerRegionInSUs;
! 504: }
! 505: /* Compute BlockID and RepIndex exactly as before. */
! 506: FullTableOffset = SUID % sus_per_fulltable;
! 507: TableID = FullTableOffset / info->SUsPerTable;
! 508: TableOffset = FullTableOffset - TableID * info->SUsPerTable;
! 509: BlockID = TableOffset / info->PUsPerBlock;
! 510: BlockOffset = TableOffset - BlockID * info->PUsPerBlock;
! 511: BlockID %= info->BlocksPerTable;
! 512:
! 513: /* The q block is in the position indicated by RepIndex. */
! 514: RepIndex = (raidPtr->noRotate) ?
! 515: info->PUsPerBlock : info->groupSize - 1 - TableID;
! 516: RepIndexQ = ((RepIndex == (info->groupSize - 1)) ? 0 : RepIndex + 1);
! 517: *col = info->LayoutTable[BlockID][RepIndexQ];
! 518:
! 519: if (remap)
! 520: RF_PANIC();
! 521:
! 522: /*
! 523: * Compute sector as before, except use RepIndex instead of
! 524: * BlockOffset.
! 525: */
! 526: outSU = base_suid;
! 527: outSU += FullTableID * fulltable_depth;
! 528: outSU += SpareSpace; /* skip rsvd spare space */
! 529: outSU += TableID * info->TableDepthInPUs * layoutPtr->SUsPerPU;
! 530: outSU += TableOffset / (info->BlocksPerTable * info->PUsPerBlock);
! 531:
! 532: outSU += info->OffsetTable[BlockID][RepIndexQ] * layoutPtr->SUsPerPU;
! 533: *diskSector = outSU * layoutPtr->sectorsPerStripeUnit +
! 534: (raidSector % layoutPtr->sectorsPerStripeUnit);
! 535: }
! 536:
! 537: /*
! 538: * Returns an array of ints identifying the disks that comprise the stripe
! 539: * containing the indicated address.
! 540: * The caller must _never_ attempt to modify this array.
! 541: */
! 542: void
! 543: rf_IdentifyStripeDeclusteredPQ(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
! 544: RF_RowCol_t **diskids, RF_RowCol_t *outRow)
! 545: {
! 546: RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
! 547: RF_DeclusteredConfigInfo_t *info =
! 548: (RF_DeclusteredConfigInfo_t *) layoutPtr->layoutSpecificInfo;
! 549: RF_StripeCount_t sus_per_fulltable = info->SUsPerFullTable;
! 550: RF_StripeCount_t fulltable_depth = info->FullTableDepthInPUs *
! 551: layoutPtr->SUsPerPU;
! 552: RF_StripeNum_t base_suid = 0;
! 553: RF_StripeNum_t SUID = rf_RaidAddressToStripeUnitID(layoutPtr, addr);
! 554: RF_StripeNum_t stripeID, FullTableID;
! 555: int tableOffset;
! 556:
! 557: rf_decluster_adjust_params(layoutPtr, &SUID, &sus_per_fulltable,
! 558: &fulltable_depth, &base_suid);
! 559: /* Fulltable ID within array (across rows). */
! 560: FullTableID = SUID / sus_per_fulltable;
! 561: *outRow = FullTableID % raidPtr->numRow;
! 562: /* Find stripe offset into array. */
! 563: stripeID = rf_StripeUnitIDToStripeID(layoutPtr, SUID);
! 564: /* Find offset into block design table. */
! 565: tableOffset = (stripeID % info->BlocksPerTable);
! 566: *diskids = info->LayoutTable[tableOffset];
! 567: }
CVSweb