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

Annotation of sys/dev/raidframe/rf_raid5.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: rf_raid5.c,v 1.4 2002/12/16 07:01:04 tdeval Exp $     */
                      2: /*     $NetBSD: rf_raid5.c,v 1.4 2000/01/08 22:57:30 oster Exp $       */
                      3:
                      4: /*
                      5:  * Copyright (c) 1995 Carnegie-Mellon University.
                      6:  * All rights reserved.
                      7:  *
                      8:  * Author: Mark Holland
                      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_raid5.c -- Implements RAID Level 5.
                     34:  *
                     35:  *****************************************************************************/
                     36:
                     37: #include "rf_types.h"
                     38: #include "rf_raid.h"
                     39: #include "rf_raid5.h"
                     40: #include "rf_dag.h"
                     41: #include "rf_dagffrd.h"
                     42: #include "rf_dagffwr.h"
                     43: #include "rf_dagdegrd.h"
                     44: #include "rf_dagdegwr.h"
                     45: #include "rf_dagutils.h"
                     46: #include "rf_general.h"
                     47: #include "rf_map.h"
                     48: #include "rf_utils.h"
                     49:
                     50: typedef struct RF_Raid5ConfigInfo_s {
                     51:        RF_RowCol_t **stripeIdentifier; /*
                     52:                                         * Filled in at config time and used
                     53:                                         * by IdentifyStripe.
                     54:                                         */
                     55: } RF_Raid5ConfigInfo_t;
                     56:
                     57:
                     58: int
                     59: rf_ConfigureRAID5(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
                     60:     RF_Config_t *cfgPtr)
                     61: {
                     62:        RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
                     63:        RF_Raid5ConfigInfo_t *info;
                     64:        RF_RowCol_t i, j, startdisk;
                     65:
                     66:        /* Create a RAID level 5 configuration structure. */
                     67:        RF_MallocAndAdd(info, sizeof(RF_Raid5ConfigInfo_t),
                     68:            (RF_Raid5ConfigInfo_t *), raidPtr->cleanupList);
                     69:        if (info == NULL)
                     70:                return (ENOMEM);
                     71:        layoutPtr->layoutSpecificInfo = (void *) info;
                     72:
                     73:        RF_ASSERT(raidPtr->numRow == 1);
                     74:
                     75:        /*
                     76:         * The stripe identifier must identify the disks in each stripe, IN
                     77:         * THE ORDER THAT THEY APPEAR IN THE STRIPE.
                     78:         */
                     79:        info->stripeIdentifier = rf_make_2d_array(raidPtr->numCol,
                     80:            raidPtr->numCol, raidPtr->cleanupList);
                     81:        if (info->stripeIdentifier == NULL)
                     82:                return (ENOMEM);
                     83:        startdisk = 0;
                     84:        for (i = 0; i < raidPtr->numCol; i++) {
                     85:                for (j = 0; j < raidPtr->numCol; j++) {
                     86:                        info->stripeIdentifier[i][j] = (startdisk + j) %
                     87:                            raidPtr->numCol;
                     88:                }
                     89:                if ((--startdisk) < 0)
                     90:                        startdisk = raidPtr->numCol - 1;
                     91:        }
                     92:
                     93:        /* Fill in the remaining layout parameters. */
                     94:        layoutPtr->numStripe = layoutPtr->stripeUnitsPerDisk;
                     95:        layoutPtr->bytesPerStripeUnit = layoutPtr->sectorsPerStripeUnit <<
                     96:            raidPtr->logBytesPerSector;
                     97:        layoutPtr->numDataCol = raidPtr->numCol - 1;
                     98:        layoutPtr->dataSectorsPerStripe = layoutPtr->numDataCol *
                     99:            layoutPtr->sectorsPerStripeUnit;
                    100:        layoutPtr->numParityCol = 1;
                    101:        layoutPtr->dataStripeUnitsPerDisk = layoutPtr->stripeUnitsPerDisk;
                    102:
                    103:        raidPtr->totalSectors = layoutPtr->stripeUnitsPerDisk *
                    104:            layoutPtr->numDataCol * layoutPtr->sectorsPerStripeUnit;
                    105:
                    106:        return (0);
                    107: }
                    108:
                    109: int
                    110: rf_GetDefaultNumFloatingReconBuffersRAID5(RF_Raid_t *raidPtr)
                    111: {
                    112:        return (20);
                    113: }
                    114:
                    115: RF_HeadSepLimit_t
                    116: rf_GetDefaultHeadSepLimitRAID5(RF_Raid_t *raidPtr)
                    117: {
                    118:        return (10);
                    119: }
                    120:
                    121: #if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(_KERNEL)
                    122: /* Not currently used. */
                    123: int
                    124: rf_ShutdownRAID5(RF_Raid_t *raidPtr)
                    125: {
                    126:        return (0);
                    127: }
                    128: #endif
                    129:
                    130: void
                    131: rf_MapSectorRAID5(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
                    132:     RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
                    133: {
                    134:        RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
                    135:        *row = 0;
                    136:        *col = (SUID % raidPtr->numCol);
                    137:        *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
                    138:            raidPtr->Layout.sectorsPerStripeUnit +
                    139:            (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
                    140: }
                    141:
                    142: void
                    143: rf_MapParityRAID5(RF_Raid_t *raidPtr, RF_RaidAddr_t raidSector,
                    144:     RF_RowCol_t *row, RF_RowCol_t *col, RF_SectorNum_t *diskSector, int remap)
                    145: {
                    146:        RF_StripeNum_t SUID = raidSector / raidPtr->Layout.sectorsPerStripeUnit;
                    147:
                    148:        *row = 0;
                    149:        *col = raidPtr->Layout.numDataCol -
                    150:            (SUID / raidPtr->Layout.numDataCol) % raidPtr->numCol;
                    151:        *diskSector = (SUID / (raidPtr->Layout.numDataCol)) *
                    152:            raidPtr->Layout.sectorsPerStripeUnit +
                    153:            (raidSector % raidPtr->Layout.sectorsPerStripeUnit);
                    154: }
                    155:
                    156: void
                    157: rf_IdentifyStripeRAID5(RF_Raid_t *raidPtr, RF_RaidAddr_t addr,
                    158:     RF_RowCol_t **diskids, RF_RowCol_t *outRow)
                    159: {
                    160:        RF_StripeNum_t stripeID =
                    161:            rf_RaidAddressToStripeID(&raidPtr->Layout, addr);
                    162:        RF_Raid5ConfigInfo_t *info =
                    163:            (RF_Raid5ConfigInfo_t *) raidPtr->Layout.layoutSpecificInfo;
                    164:
                    165:        *outRow = 0;
                    166:        *diskids = info->stripeIdentifier[stripeID % raidPtr->numCol];
                    167: }
                    168:
                    169: void
                    170: rf_MapSIDToPSIDRAID5(RF_RaidLayout_t *layoutPtr, RF_StripeNum_t stripeID,
                    171:     RF_StripeNum_t *psID, RF_ReconUnitNum_t *which_ru)
                    172: {
                    173:        *which_ru = 0;
                    174:        *psID = stripeID;
                    175: }
                    176:
                    177:
                    178: /*
                    179:  * Select an algorithm for performing an access.  Returns two pointers,
                    180:  * one to a function that will return information about the DAG, and
                    181:  * another to a function that will create the dag.
                    182:  */
                    183: void
                    184: rf_RaidFiveDagSelect(RF_Raid_t *raidPtr, RF_IoType_t type,
                    185:     RF_AccessStripeMap_t *asmap, RF_VoidFuncPtr *createFunc)
                    186: {
                    187:        RF_RaidLayout_t *layoutPtr = &(raidPtr->Layout);
                    188:        RF_PhysDiskAddr_t *failedPDA = NULL;
                    189:        RF_RowCol_t frow, fcol;
                    190:        RF_RowStatus_t rstat;
                    191:        int prior_recon;
                    192:
                    193:        RF_ASSERT(RF_IO_IS_R_OR_W(type));
                    194:
                    195:        if (asmap->numDataFailed + asmap->numParityFailed > 1) {
                    196:                RF_ERRORMSG("Multiple disks failed in a single group !"
                    197:                            "  Aborting I/O operation.\n");
                    198:                 /* *infoFunc = */ *createFunc = NULL;
                    199:                return;
                    200:        } else
                    201:                if (asmap->numDataFailed + asmap->numParityFailed == 1) {
                    202:
                    203:                        /*
                    204:                         * If under recon & already reconstructed, redirect
                    205:                         * the access to the spare drive and eliminate the
                    206:                         * failure indication.
                    207:                         */
                    208:                        failedPDA = asmap->failedPDAs[0];
                    209:                        frow = failedPDA->row;
                    210:                        fcol = failedPDA->col;
                    211:                        rstat = raidPtr->status[failedPDA->row];
                    212:                        prior_recon = (rstat == rf_rs_reconfigured) || (
                    213:                            (rstat == rf_rs_reconstructing) ?
                    214:                            rf_CheckRUReconstructed(raidPtr
                    215:                             ->reconControl[frow]->reconMap,
                    216:                             failedPDA->startSector) : 0);
                    217:                        if (prior_recon) {
                    218:                                RF_RowCol_t or = failedPDA->row;
                    219:                                RF_RowCol_t oc = failedPDA->col;
                    220:                                RF_SectorNum_t oo = failedPDA->startSector;
                    221:
                    222:                                if (layoutPtr->map->flags &
                    223:                                    RF_DISTRIBUTE_SPARE) {
                    224:                                        /* Redirect to dist spare space. */
                    225:
                    226:                                        if (failedPDA == asmap->parityInfo) {
                    227:
                    228:                                                /* Parity has failed. */
                    229:                                                (layoutPtr->map->MapParity)
                    230:                                                    (raidPtr,
                    231:                                                     failedPDA->raidAddress,
                    232:                                                     &failedPDA->row,
                    233:                                                     &failedPDA->col,
                    234:                                                     &failedPDA->startSector,
                    235:                                                     RF_REMAP);
                    236:
                    237:                                                if (asmap->parityInfo->next) {
                    238:                                                        /*
                    239:                                                         * Redir 2nd component,
                    240:                                                         * if any.
                    241:                                                         */
                    242:                                                        RF_PhysDiskAddr_t *p =
                    243:                                                            asmap
                    244:                                                             ->parityInfo->next;
                    245:                                                        RF_SectorNum_t SUoffs =
                    246:                                                            p->startSector %
                    247:                                                layoutPtr->sectorsPerStripeUnit;
                    248:                                                        p->row = failedPDA->row;
                    249:                                                        p->col = failedPDA->col;
                    250:                                                        /*
                    251:                                                         * Cheating:
                    252:                                                         * startSector is not
                    253:                                                         * really a RAID
                    254:                                                         * address.
                    255:                                                         */
                    256:                                                        p->startSector =
                    257:                                        rf_RaidAddressOfPrevStripeUnitBoundary(
                    258:                                            layoutPtr, failedPDA->startSector) +
                    259:                                                            SUoffs;
                    260:                                                }
                    261:                                        } else
                    262:                                                if (asmap->parityInfo->next &&
                    263:                                                    failedPDA ==
                    264:                                                    asmap->parityInfo->next) {
                    265:                                                        /*
                    266:                                                         * Should never happen.
                    267:                                                         */
                    268:                                                        RF_ASSERT(0);
                    269:                                                } else {
                    270:                                                        /* Data has failed. */
                    271:                                                        (layoutPtr->map
                    272:                                                         ->MapSector) (raidPtr,
                    273:                                                         failedPDA->raidAddress,
                    274:                                                            &failedPDA->row,
                    275:                                                            &failedPDA->col,
                    276:                                                        &failedPDA->startSector,
                    277:                                                            RF_REMAP);
                    278:                                                }
                    279:
                    280:                                } else {
                    281:                                        /* Redirect to dedicated spare space. */
                    282:
                    283:                                        failedPDA->row =
                    284:                                            raidPtr->Disks[frow][fcol].spareRow;
                    285:                                        failedPDA->col =
                    286:                                            raidPtr->Disks[frow][fcol].spareCol;
                    287:
                    288:                                        /*
                    289:                                         * The parity may have two distinct
                    290:                                         * components, both of which may need
                    291:                                         * to be redirected.
                    292:                                         */
                    293:                                        if (asmap->parityInfo->next) {
                    294:                                                if (failedPDA ==
                    295:                                                    asmap->parityInfo) {
                    296:                                                        failedPDA->next->row =
                    297:                                                            failedPDA->row;
                    298:                                                        failedPDA->next->col =
                    299:                                                            failedPDA->col;
                    300:                                                } else {
                    301:                                                        if (failedPDA ==
                    302:                                                            asmap->parityInfo
                    303:                                                             ->next) {
                    304:                                                                /*
                    305:                                                                 * Paranoid:
                    306:                                                                 * Should never
                    307:                                                                 * occur.
                    308:                                                                 */
                    309:                                                                asmap
                    310:                                                                 ->parityInfo
                    311:                                                                 ->row =
                    312:                                                                 failedPDA->row;
                    313:                                                                asmap
                    314:                                                                 ->parityInfo
                    315:                                                                 ->col =
                    316:                                                                 failedPDA->col;
                    317:                                                        }
                    318:                                                }
                    319:                                        }
                    320:                                }
                    321:
                    322:                                RF_ASSERT(failedPDA->col != -1);
                    323:
                    324:                                if (rf_dagDebug || rf_mapDebug) {
                    325:                                        printf("raid%d: Redirected type '%c'"
                    326:                                               " r %d c %d o %ld -> r %d c %d"
                    327:                                               " o %ld\n", raidPtr->raidid,
                    328:                                               type, or, oc, (long) oo,
                    329:                                               failedPDA->row, failedPDA->col,
                    330:                                               (long) failedPDA->startSector);
                    331:                                }
                    332:                                asmap->numDataFailed = asmap->numParityFailed
                    333:                                                     = 0;
                    334:                        }
                    335:                }
                    336:        /*
                    337:         * All DAGs begin/end with block/unblock node. Therefore, hdrSucc &
                    338:         * termAnt counts should always be 1. Also, these counts should not be
                    339:         * visible outside DAG creation routines - manipulating the counts
                    340:         * here should be removed.
                    341:         */
                    342:        if (type == RF_IO_TYPE_READ) {
                    343:                if (asmap->numDataFailed == 0)
                    344:                        *createFunc = (RF_VoidFuncPtr)
                    345:                            rf_CreateFaultFreeReadDAG;
                    346:                else
                    347:                        *createFunc = (RF_VoidFuncPtr)
                    348:                            rf_CreateRaidFiveDegradedReadDAG;
                    349:        } else {
                    350:                /*
                    351:                 * If mirroring, always use large writes. If the access
                    352:                 * requires two distinct parity updates, always do a small
                    353:                 * write. If the stripe contains a failure but the access
                    354:                 * does not, do a small write. The first conditional
                    355:                 * (numStripeUnitsAccessed <= numDataCol/2) uses a
                    356:                 * less-than-or-equal rather than just a less-than because
                    357:                 * when G is 3 or 4, numDataCol/2 is 1, and I want
                    358:                 * single-stripe-unit updates to use just one disk.
                    359:                 */
                    360:                if ((asmap->numDataFailed + asmap->numParityFailed) == 0) {
                    361:                        if (rf_suppressLocksAndLargeWrites ||
                    362:                            (((asmap->numStripeUnitsAccessed <=
                    363:                               (layoutPtr->numDataCol / 2)) &&
                    364:                              (layoutPtr->numDataCol != 1)) ||
                    365:                             (asmap->parityInfo->next != NULL) ||
                    366:                             rf_CheckStripeForFailures(raidPtr, asmap))) {
                    367:                                *createFunc = (RF_VoidFuncPtr)
                    368:                                    rf_CreateSmallWriteDAG;
                    369:                        } else
                    370:                                *createFunc = (RF_VoidFuncPtr)
                    371:                                    rf_CreateLargeWriteDAG;
                    372:                } else {
                    373:                        if (asmap->numParityFailed == 1)
                    374:                                *createFunc = (RF_VoidFuncPtr)
                    375:                                    rf_CreateNonRedundantWriteDAG;
                    376:                        else
                    377:                                if (asmap->numStripeUnitsAccessed != 1 &&
                    378:                                    failedPDA->numSector !=
                    379:                                    layoutPtr->sectorsPerStripeUnit)
                    380:                                        *createFunc = NULL;
                    381:                                else
                    382:                                        *createFunc = (RF_VoidFuncPtr)
                    383:                                            rf_CreateDegradedWriteDAG;
                    384:                }
                    385:        }
                    386: }

CVSweb