[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

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