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

Annotation of sys/dev/raidframe/rf_chaindecluster.c, Revision 1.1

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

CVSweb