[BACK]Return to rf_declusterPQ.c CVS log [TXT][DIR] Up to [local] / sys / dev / raidframe

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