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

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

1.1       nbrk        1: /*     $OpenBSD: rf_disks.c,v 1.12 2007/06/05 00:38:22 deraadt Exp $   */
                      2: /*     $NetBSD: rf_disks.c,v 1.31 2000/06/02 01:17:14 oster Exp $      */
                      3:
                      4: /*
                      5:  * Copyright (c) 1999 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by Greg Oster
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *     This product includes software developed by the NetBSD
                     22:  *     Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
                     39: /*
                     40:  * Copyright (c) 1995 Carnegie-Mellon University.
                     41:  * All rights reserved.
                     42:  *
                     43:  * Author: Mark Holland
                     44:  *
                     45:  * Permission to use, copy, modify and distribute this software and
                     46:  * its documentation is hereby granted, provided that both the copyright
                     47:  * notice and this permission notice appear in all copies of the
                     48:  * software, derivative works or modified versions, and any portions
                     49:  * thereof, and that both notices appear in supporting documentation.
                     50:  *
                     51:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     52:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
                     53:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     54:  *
                     55:  * Carnegie Mellon requests users of this software to return to
                     56:  *
                     57:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
                     58:  *  School of Computer Science
                     59:  *  Carnegie Mellon University
                     60:  *  Pittsburgh PA 15213-3890
                     61:  *
                     62:  * any improvements or extensions that they make and grant Carnegie the
                     63:  * rights to redistribute these changes.
                     64:  */
                     65:
                     66: /***************************************************************
                     67:  * rf_disks.c -- Code to perform operations on the actual disks.
                     68:  ***************************************************************/
                     69:
                     70: #include "rf_types.h"
                     71: #include "rf_raid.h"
                     72: #include "rf_alloclist.h"
                     73: #include "rf_utils.h"
                     74: #include "rf_configure.h"
                     75: #include "rf_general.h"
                     76: #include "rf_options.h"
                     77: #include "rf_kintf.h"
                     78:
                     79: #if defined(__NetBSD__)
                     80: #include "rf_netbsd.h"
                     81: #elif defined(__OpenBSD__)
                     82: #include "rf_openbsd.h"
                     83: #endif
                     84:
                     85: #include <sys/types.h>
                     86: #include <sys/param.h>
                     87: #include <sys/systm.h>
                     88: #include <sys/proc.h>
                     89: #include <sys/ioctl.h>
                     90: #include <sys/fcntl.h>
                     91: #ifdef __NETBSD__
                     92: #include <sys/vnode.h>
                     93: #endif /* __NETBSD__ */
                     94:
                     95: int  rf_AllocDiskStructures(RF_Raid_t *, RF_Config_t *);
                     96: void rf_print_label_status(RF_Raid_t *, int, int, char *,
                     97:        RF_ComponentLabel_t *);
                     98: int  rf_check_label_vitals(RF_Raid_t *, int, int, char *,
                     99:        RF_ComponentLabel_t *, int, int);
                    100:
                    101: #define        DPRINTF6(a,b,c,d,e,f)   if (rf_diskDebug) printf(a,b,c,d,e,f)
                    102: #define        DPRINTF7(a,b,c,d,e,f,g) if (rf_diskDebug) printf(a,b,c,d,e,f,g)
                    103:
                    104: /****************************************************************************
                    105:  *
                    106:  * Initialize the disks comprising the array.
                    107:  *
                    108:  * We want the spare disks to have regular row,col numbers so that we can
                    109:  * easily substitue a spare for a failed disk. But, the driver code assumes
                    110:  * throughout that the array contains numRow by numCol _non-spare_ disks, so
                    111:  * it's not clear how to fit in the spares. This is an unfortunate holdover
                    112:  * from raidSim. The quick and dirty fix is to make row zero bigger than the
                    113:  * rest, and put all the spares in it. This probably needs to get changed
                    114:  * eventually.
                    115:  *
                    116:  ****************************************************************************/
                    117: int
                    118: rf_ConfigureDisks(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
                    119:     RF_Config_t *cfgPtr)
                    120: {
                    121:        RF_RaidDisk_t **disks;
                    122:        RF_SectorCount_t min_numblks = (RF_SectorCount_t) 0x7FFFFFFFFFFFLL;
                    123:        RF_RowCol_t r, c;
                    124:        int bs, ret;
                    125:        unsigned i, count, foundone = 0, numFailuresThisRow;
                    126:        int force;
                    127:
                    128:        force = cfgPtr->force;
                    129:
                    130:        ret = rf_AllocDiskStructures(raidPtr, cfgPtr);
                    131:        if (ret)
                    132:                goto fail;
                    133:
                    134:        disks = raidPtr->Disks;
                    135:
                    136:        for (r = 0; r < raidPtr->numRow; r++) {
                    137:                numFailuresThisRow = 0;
                    138:                for (c = 0; c < raidPtr->numCol; c++) {
                    139:                        ret = rf_ConfigureDisk(raidPtr,
                    140:                            &cfgPtr->devnames[r][c][0], &disks[r][c], r, c);
                    141:
                    142:                        if (ret)
                    143:                                goto fail;
                    144:
                    145:                        if (disks[r][c].status == rf_ds_optimal) {
                    146:                                raidread_component_label(
                    147:                                         raidPtr->raid_cinfo[r][c].ci_dev,
                    148:                                         raidPtr->raid_cinfo[r][c].ci_vp,
                    149:                                         &raidPtr->raid_cinfo[r][c].ci_label);
                    150:                        }
                    151:
                    152:                        if (disks[r][c].status != rf_ds_optimal) {
                    153:                                numFailuresThisRow++;
                    154:                        } else {
                    155:                                if (disks[r][c].numBlocks < min_numblks)
                    156:                                        min_numblks = disks[r][c].numBlocks;
                    157:                                DPRINTF7("Disk at row %d col %d: dev %s"
                    158:                                    " numBlocks %ld blockSize %d (%ld MB)\n",
                    159:                                    r, c, disks[r][c].devname,
                    160:                                    (long int) disks[r][c].numBlocks,
                    161:                                    disks[r][c].blockSize,
                    162:                                    (long int) disks[r][c].numBlocks *
                    163:                                     disks[r][c].blockSize / 1024 / 1024);
                    164:                        }
                    165:                }
                    166:                /* XXX Fix for n-fault tolerant. */
                    167:                /*
                    168:                 * XXX This should probably check to see how many failures
                    169:                 * we can handle for this configuration !
                    170:                 */
                    171:                if (numFailuresThisRow > 0)
                    172:                        raidPtr->status[r] = rf_rs_degraded;
                    173:        }
                    174:        /*
                    175:         * All disks must be the same size & have the same block size, bs must
                    176:         * be a power of 2.
                    177:         */
                    178:        bs = 0;
                    179:        for (foundone = r = 0; !foundone && r < raidPtr->numRow; r++) {
                    180:                for (c = 0; !foundone && c < raidPtr->numCol; c++) {
                    181:                        if (disks[r][c].status == rf_ds_optimal) {
                    182:                                bs = disks[r][c].blockSize;
                    183:                                foundone = 1;
                    184:                        }
                    185:                }
                    186:        }
                    187:        if (!foundone) {
                    188:                RF_ERRORMSG("RAIDFRAME: Did not find any live disks in"
                    189:                    " the array.\n");
                    190:                ret = EINVAL;
                    191:                goto fail;
                    192:        }
                    193:        for (count = 0, i = 1; i; i <<= 1)
                    194:                if (bs & i)
                    195:                        count++;
                    196:        if (count != 1) {
                    197:                RF_ERRORMSG1("Error: block size on disks (%d) must be a"
                    198:                    " power of 2.\n", bs);
                    199:                ret = EINVAL;
                    200:                goto fail;
                    201:        }
                    202:
                    203:        if (rf_CheckLabels(raidPtr, cfgPtr)) {
                    204:                printf("raid%d: There were fatal errors\n", raidPtr->raidid);
                    205:                if (force != 0) {
                    206:                        printf("raid%d: Fatal errors being ignored.\n",
                    207:                            raidPtr->raidid);
                    208:                } else {
                    209:                        ret = EINVAL;
                    210:                        goto fail;
                    211:                }
                    212:        }
                    213:
                    214:        for (r = 0; r < raidPtr->numRow; r++) {
                    215:                for (c = 0; c < raidPtr->numCol; c++) {
                    216:                        if (disks[r][c].status == rf_ds_optimal) {
                    217:                                if (disks[r][c].blockSize != bs) {
                    218:                                        RF_ERRORMSG2("Error: block size of"
                    219:                                            " disk at r %d c %d different from"
                    220:                                            " disk at r 0 c 0.\n", r, c);
                    221:                                        ret = EINVAL;
                    222:                                        goto fail;
                    223:                                }
                    224:                                if (disks[r][c].numBlocks != min_numblks) {
                    225:                                        RF_ERRORMSG3("WARNING: truncating disk"
                    226:                                            " at r %d c %d to %d blocks.\n",
                    227:                                            r, c, (int) min_numblks);
                    228:                                        disks[r][c].numBlocks = min_numblks;
                    229:                                }
                    230:                        }
                    231:                }
                    232:        }
                    233:
                    234:        raidPtr->sectorsPerDisk = min_numblks;
                    235:        raidPtr->logBytesPerSector = ffs(bs) - 1;
                    236:        raidPtr->bytesPerSector = bs;
                    237:        raidPtr->sectorMask = bs - 1;
                    238:        return (0);
                    239:
                    240: fail:
                    241:        rf_UnconfigureVnodes(raidPtr);
                    242:
                    243:        return (ret);
                    244: }
                    245:
                    246:
                    247: /****************************************************************************
                    248:  * Set up the data structures describing the spare disks in the array.
                    249:  * Recall from the above comment that the spare disk descriptors are stored
                    250:  * in row zero, which is specially expanded to hold them.
                    251:  ****************************************************************************/
                    252: int
                    253: rf_ConfigureSpareDisks(RF_ShutdownList_t ** listp, RF_Raid_t * raidPtr,
                    254:     RF_Config_t * cfgPtr)
                    255: {
                    256:        int i, ret;
                    257:        unsigned int bs;
                    258:        RF_RaidDisk_t *disks;
                    259:        int num_spares_done;
                    260:
                    261:        num_spares_done = 0;
                    262:
                    263:        /*
                    264:         * The space for the spares should have already been allocated by
                    265:         * ConfigureDisks().
                    266:         */
                    267:
                    268:        disks = &raidPtr->Disks[0][raidPtr->numCol];
                    269:        for (i = 0; i < raidPtr->numSpare; i++) {
                    270:                ret = rf_ConfigureDisk(raidPtr, &cfgPtr->spare_names[i][0],
                    271:                    &disks[i], 0, raidPtr->numCol + i);
                    272:                if (ret)
                    273:                        goto fail;
                    274:                if (disks[i].status != rf_ds_optimal) {
                    275:                        RF_ERRORMSG1("Warning: spare disk %s failed TUR\n",
                    276:                            &cfgPtr->spare_names[i][0]);
                    277:                } else {
                    278:                        /* Change status to spare. */
                    279:                        disks[i].status = rf_ds_spare;
                    280:                        DPRINTF6("Spare Disk %d: dev %s numBlocks %ld"
                    281:                            " blockSize %d (%ld MB).\n", i, disks[i].devname,
                    282:                            (long int) disks[i].numBlocks, disks[i].blockSize,
                    283:                            (long int) disks[i].numBlocks *
                    284:                            disks[i].blockSize / 1024 / 1024);
                    285:                }
                    286:                num_spares_done++;
                    287:        }
                    288:
                    289:        /* Check sizes and block sizes on spare disks. */
                    290:        bs = 1 << raidPtr->logBytesPerSector;
                    291:        for (i = 0; i < raidPtr->numSpare; i++) {
                    292:                if (disks[i].blockSize != bs) {
                    293:                        RF_ERRORMSG3("Block size of %d on spare disk %s is"
                    294:                            " not the same as on other disks (%d).\n",
                    295:                            disks[i].blockSize, disks[i].devname, bs);
                    296:                        ret = EINVAL;
                    297:                        goto fail;
                    298:                }
                    299:                if (disks[i].numBlocks < raidPtr->sectorsPerDisk) {
                    300:                        RF_ERRORMSG3("Spare disk %s (%llu blocks) is too small"
                    301:                            " to serve as a spare (need %llu blocks).\n",
                    302:                            disks[i].devname, disks[i].numBlocks,
                    303:                            raidPtr->sectorsPerDisk);
                    304:                        ret = EINVAL;
                    305:                        goto fail;
                    306:                } else
                    307:                        if (disks[i].numBlocks > raidPtr->sectorsPerDisk) {
                    308:                                RF_ERRORMSG2("Warning: truncating spare disk"
                    309:                                    " %s to %llu blocks.\n", disks[i].devname,
                    310:                                    raidPtr->sectorsPerDisk);
                    311:
                    312:                                disks[i].numBlocks = raidPtr->sectorsPerDisk;
                    313:                        }
                    314:        }
                    315:
                    316:        return (0);
                    317:
                    318: fail:
                    319:
                    320:        /*
                    321:         * Release the hold on the main components. We've failed to allocate
                    322:         * a spare, and since we're failing, we need to free things...
                    323:         *
                    324:         * XXX Failing to allocate a spare is *not* that big of a deal...
                    325:         * We *can* survive without it, if need be, esp. if we get hot
                    326:         * adding working.
                    327:         * If we don't fail out here, then we need a way to remove this spare...
                    328:         * That should be easier to do here than if we are "live"...
                    329:         */
                    330:
                    331:        rf_UnconfigureVnodes(raidPtr);
                    332:
                    333:        return (ret);
                    334: }
                    335:
                    336: int
                    337: rf_AllocDiskStructures(RF_Raid_t *raidPtr, RF_Config_t *cfgPtr)
                    338: {
                    339:        RF_RaidDisk_t **disks;
                    340:        int ret;
                    341:        int r;
                    342:
                    343:        RF_CallocAndAdd(disks, raidPtr->numRow, sizeof(RF_RaidDisk_t *),
                    344:            (RF_RaidDisk_t **), raidPtr->cleanupList);
                    345:        if (disks == NULL) {
                    346:                ret = ENOMEM;
                    347:                goto fail;
                    348:        }
                    349:        raidPtr->Disks = disks;
                    350:        /* Get space for the device-specific stuff... */
                    351:        RF_CallocAndAdd(raidPtr->raid_cinfo, raidPtr->numRow,
                    352:            sizeof(struct raidcinfo *), (struct raidcinfo **),
                    353:            raidPtr->cleanupList);
                    354:        if (raidPtr->raid_cinfo == NULL) {
                    355:                ret = ENOMEM;
                    356:                goto fail;
                    357:        }
                    358:
                    359:        for (r = 0; r < raidPtr->numRow; r++) {
                    360:                /*
                    361:                 * We allocate RF_MAXSPARE on the first row so that we
                    362:                 * have room to do hot-swapping of spares.
                    363:                 */
                    364:                RF_CallocAndAdd(disks[r], raidPtr->numCol +
                    365:                    ((r == 0) ? RF_MAXSPARE : 0), sizeof(RF_RaidDisk_t),
                    366:                    (RF_RaidDisk_t *), raidPtr->cleanupList);
                    367:                if (disks[r] == NULL) {
                    368:                        ret = ENOMEM;
                    369:                        goto fail;
                    370:                }
                    371:                /* Get more space for device specific stuff... */
                    372:                RF_CallocAndAdd(raidPtr->raid_cinfo[r], raidPtr->numCol +
                    373:                    ((r == 0) ? raidPtr->numSpare : 0),
                    374:                    sizeof(struct raidcinfo), (struct raidcinfo *),
                    375:                    raidPtr->cleanupList);
                    376:                if (raidPtr->raid_cinfo[r] == NULL) {
                    377:                        ret = ENOMEM;
                    378:                        goto fail;
                    379:                }
                    380:        }
                    381:        return(0);
                    382: fail:
                    383:        rf_UnconfigureVnodes(raidPtr);
                    384:
                    385:        return(ret);
                    386: }
                    387:
                    388:
                    389: /* Configure a single disk during auto-configuration at boot. */
                    390: int
                    391: rf_AutoConfigureDisks(RF_Raid_t *raidPtr, RF_Config_t *cfgPtr,
                    392:     RF_AutoConfig_t *auto_config)
                    393: {
                    394:        RF_RaidDisk_t **disks;
                    395:        RF_RaidDisk_t *diskPtr;
                    396:        RF_RowCol_t r, c;
                    397:        RF_SectorCount_t min_numblks = (RF_SectorCount_t) 0x7FFFFFFFFFFFLL;
                    398:        int bs, ret;
                    399:        int numFailuresThisRow;
                    400:        int force;
                    401:        RF_AutoConfig_t *ac;
                    402:        int parity_good;
                    403:        int mod_counter;
                    404:        int mod_counter_found;
                    405:
                    406: #if    DEBUG
                    407:        printf("Starting autoconfiguration of RAID set...\n");
                    408: #endif /* DEBUG */
                    409:        force = cfgPtr->force;
                    410:
                    411:        ret = rf_AllocDiskStructures(raidPtr, cfgPtr);
                    412:        if (ret)
                    413:                goto fail;
                    414:
                    415:        disks = raidPtr->Disks;
                    416:
                    417:        /* Assume the parity will be fine... */
                    418:        parity_good = RF_RAID_CLEAN;
                    419:
                    420:        /* Check for mod_counters that are too low. */
                    421:        mod_counter_found = 0;
                    422:        ac = auto_config;
                    423:        while(ac!=NULL) {
                    424:                if (mod_counter_found == 0) {
                    425:                        mod_counter = ac->clabel->mod_counter;
                    426:                        mod_counter_found = 1;
                    427:                } else {
                    428:                        if (ac->clabel->mod_counter > mod_counter) {
                    429:                                mod_counter = ac->clabel->mod_counter;
                    430:                        }
                    431:                }
                    432:                ac->flag = 0; /* Clear the general purpose flag. */
                    433:                ac = ac->next;
                    434:        }
                    435:
                    436:        for (r = 0; r < raidPtr->numRow; r++) {
                    437:                numFailuresThisRow = 0;
                    438:                for (c = 0; c < raidPtr->numCol; c++) {
                    439:                        diskPtr = &disks[r][c];
                    440:
                    441:                        /* Find this row/col in the autoconfig. */
                    442: #if    DEBUG
                    443:                        printf("Looking for %d,%d in autoconfig.\n", r, c);
                    444: #endif /* DEBUG */
                    445:                        ac = auto_config;
                    446:                        while(ac!=NULL) {
                    447:                                if (ac->clabel == NULL) {
                    448:                                        /* Big-time bad news. */
                    449:                                        goto fail;
                    450:                                }
                    451:                                if ((ac->clabel->row == r) &&
                    452:                                    (ac->clabel->column == c) &&
                    453:                                    (ac->clabel->mod_counter == mod_counter)) {
                    454:                                        /* It's this one... */
                    455:                                        /*
                    456:                                         * Flag it as 'used', so we don't
                    457:                                         * free it later.
                    458:                                         */
                    459:                                        ac->flag = 1;
                    460: #if    DEBUG
                    461:                                        printf("Found: %s at %d,%d.\n",
                    462:                                            ac->devname, r, c);
                    463: #endif /* DEBUG */
                    464:
                    465:                                        break;
                    466:                                }
                    467:                                ac = ac->next;
                    468:                        }
                    469:
                    470:                        if (ac == NULL) {
                    471:                                /*
                    472:                                 * We didn't find an exact match with a
                    473:                                 * correct mod_counter above...  Can we
                    474:                                 * find one with an incorrect mod_counter
                    475:                                 * to use instead ?  (This one, if we find
                    476:                                 * it, will be marked as failed once the
                    477:                                 * set configures)
                    478:                                 */
                    479:
                    480:                                ac = auto_config;
                    481:                                while(ac!=NULL) {
                    482:                                        if (ac->clabel == NULL) {
                    483:                                                /* Big-time bad news. */
                    484:                                                goto fail;
                    485:                                        }
                    486:                                        if ((ac->clabel->row == r) &&
                    487:                                            (ac->clabel->column == c)) {
                    488:                                                /*
                    489:                                                 * It's this one...
                    490:                                                 * Flag it as 'used', so we
                    491:                                                 * don't free it later.
                    492:                                                 */
                    493:                                                ac->flag = 1;
                    494: #if    DEBUG
                    495:                                                printf("Found(low mod_counter)"
                    496:                                                    ": %s at %d,%d.\n",
                    497:                                                    ac->devname, r, c);
                    498: #endif /* DEBUG */
                    499:
                    500:                                                break;
                    501:                                        }
                    502:                                        ac = ac->next;
                    503:                                }
                    504:                        }
                    505:
                    506:
                    507:
                    508:                        if (ac!=NULL) {
                    509:                                /* Found it. Configure it... */
                    510:                                diskPtr->blockSize = ac->clabel->blockSize;
                    511:                                diskPtr->numBlocks = ac->clabel->numBlocks;
                    512:                                /*
                    513:                                 * Note: rf_protectedSectors is already
                    514:                                 * factored into numBlocks here.
                    515:                                 */
                    516:                                raidPtr->raid_cinfo[r][c].ci_vp = ac->vp;
                    517:                                raidPtr->raid_cinfo[r][c].ci_dev = ac->dev;
                    518:
                    519:                                memcpy(&raidPtr->raid_cinfo[r][c].ci_label,
                    520:                                    ac->clabel, sizeof(*ac->clabel));
                    521:                                snprintf(diskPtr->devname,
                    522:                                    sizeof diskPtr->devname, "/dev/%s",
                    523:                                    ac->devname);
                    524:
                    525:                                /*
                    526:                                 * Note the fact that this component was
                    527:                                 * autoconfigured. You'll need this info
                    528:                                 * later. Trust me :)
                    529:                                 */
                    530:                                diskPtr->auto_configured = 1;
                    531:                                diskPtr->dev = ac->dev;
                    532:
                    533:                                /*
                    534:                                 * We allow the user to specify that
                    535:                                 * only a fraction of the disks should
                    536:                                 * be used. This is just for debug: it
                    537:                                 * speeds up the parity scan.
                    538:                                 */
                    539:
                    540:                                diskPtr->numBlocks = diskPtr->numBlocks *
                    541:                                        rf_sizePercentage / 100;
                    542:
                    543:                                /*
                    544:                                 * XXX These will get set multiple times,
                    545:                                 * but since we're autoconfiguring, they'd
                    546:                                 * better be always the same each time !
                    547:                                 * If not, this is the least of your worries.
                    548:                                 */
                    549:
                    550:                                bs = diskPtr->blockSize;
                    551:                                min_numblks = diskPtr->numBlocks;
                    552:
                    553:                                /*
                    554:                                 * This gets done multiple times, but that's
                    555:                                 * fine -- the serial number will be the same
                    556:                                 * for all components, guaranteed.
                    557:                                 */
                    558:                                raidPtr->serial_number =
                    559:                                    ac->clabel->serial_number;
                    560:                                /*
                    561:                                 * Check the last time the label
                    562:                                 * was modified.
                    563:                                 */
                    564:                                if (ac->clabel->mod_counter != mod_counter) {
                    565:                                        /*
                    566:                                         * Even though we've filled in all
                    567:                                         * of the above, we don't trust
                    568:                                         * this component since it's
                    569:                                         * modification counter is not
                    570:                                         * in sync with the rest, and we really
                    571:                                         * consider it to be failed.
                    572:                                         */
                    573:                                        disks[r][c].status = rf_ds_failed;
                    574:                                        numFailuresThisRow++;
                    575:                                } else {
                    576:                                        if (ac->clabel->clean != RF_RAID_CLEAN)
                    577:                                        {
                    578:                                                parity_good = RF_RAID_DIRTY;
                    579:                                        }
                    580:                                }
                    581:                        } else {
                    582:                                /*
                    583:                                 * Didn't find it at all !!!
                    584:                                 * Component must really be dead.
                    585:                                 */
                    586:                                disks[r][c].status = rf_ds_failed;
                    587:                                snprintf(disks[r][c].devname,
                    588:                                    sizeof disks[r][c].devname, "component%d",
                    589:                                    r * raidPtr->numCol + c);
                    590:                                numFailuresThisRow++;
                    591:                        }
                    592:                }
                    593:                /* XXX Fix for n-fault tolerant. */
                    594:                /*
                    595:                 * XXX This should probably check to see how many failures
                    596:                 * we can handle for this configuration !
                    597:                 */
                    598:                if (numFailuresThisRow > 0)
                    599:                        raidPtr->status[r] = rf_rs_degraded;
                    600:        }
                    601:
                    602:        /* Close the device for the ones that didn't get used. */
                    603:
                    604:        ac = auto_config;
                    605:        while(ac != NULL) {
                    606:                if (ac->flag == 0) {
                    607:                        VOP_CLOSE(ac->vp, FREAD, NOCRED, 0);
                    608:                        vput(ac->vp);
                    609:                        ac->vp = NULL;
                    610: #if    DEBUG
                    611:                        printf("Released %s from auto-config set.\n",
                    612:                            ac->devname);
                    613: #endif  /* DEBUG */
                    614:                }
                    615:                ac = ac->next;
                    616:        }
                    617:
                    618:        raidPtr->mod_counter = mod_counter;
                    619:
                    620:        /* Note the state of the parity, if any. */
                    621:        raidPtr->parity_good = parity_good;
                    622:        raidPtr->sectorsPerDisk = min_numblks;
                    623:        raidPtr->logBytesPerSector = ffs(bs) - 1;
                    624:        raidPtr->bytesPerSector = bs;
                    625:        raidPtr->sectorMask = bs - 1;
                    626:        return (0);
                    627:
                    628: fail:
                    629:
                    630:        rf_UnconfigureVnodes(raidPtr);
                    631:
                    632:        return (ret);
                    633:
                    634: }
                    635:
                    636: /* Configure a single disk in the array. */
                    637: int
                    638: rf_ConfigureDisk(RF_Raid_t *raidPtr, char *buf, RF_RaidDisk_t *diskPtr,
                    639:     RF_RowCol_t row, RF_RowCol_t col)
                    640: {
                    641:        char *p;
                    642:        int retcode;
                    643:
                    644:        struct partinfo dpart;
                    645:        struct vnode *vp;
                    646:        struct vattr va;
                    647:        struct proc *proc;
                    648:        int error;
                    649:
                    650:        retcode = 0;
                    651:        p = rf_find_non_white(buf);
                    652:        if (*buf != '\0' && p[strlen(p) - 1] == '\n') {
                    653:                /* Strip off the newline. */
                    654:                p[strlen(p) - 1] = '\0';
                    655:        }
                    656:        (void) strlcpy(diskPtr->devname, p, sizeof diskPtr->devname);
                    657:
                    658:        proc = raidPtr->engine_thread;
                    659:
                    660:        /* Let's start by claiming the component is fine and well... */
                    661:        diskPtr->status = rf_ds_optimal;
                    662:
                    663:        raidPtr->raid_cinfo[row][col].ci_vp = NULL;
                    664:        raidPtr->raid_cinfo[row][col].ci_dev = NULL;
                    665:
                    666:        error = raidlookup(diskPtr->devname, curproc, &vp);
                    667:        if (error) {
                    668:                printf("raidlookup on device: %s failed !\n", diskPtr->devname);
                    669:                if (error == ENXIO) {
                    670:                        /* The component isn't there...  Must be dead :-( */
                    671:                        diskPtr->status = rf_ds_failed;
                    672:                } else {
                    673:                        return (error);
                    674:                }
                    675:        }
                    676:        if (diskPtr->status == rf_ds_optimal) {
                    677:
                    678:                if ((error = VOP_GETATTR(vp, &va, proc->p_ucred, proc)) != 0) {
                    679:                        return (error);
                    680:                }
                    681:                error = VOP_IOCTL(vp, DIOCGPART, (caddr_t) & dpart, FREAD,
                    682:                    proc->p_ucred, proc);
                    683:                if (error) {
                    684:                        return (error);
                    685:                }
                    686:                diskPtr->blockSize = dpart.disklab->d_secsize;
                    687:
                    688:                diskPtr->numBlocks = DL_GETPSIZE(dpart.part) - rf_protectedSectors;
                    689:                diskPtr->partitionSize = DL_GETPSIZE(dpart.part);
                    690:
                    691:                raidPtr->raid_cinfo[row][col].ci_vp = vp;
                    692:                raidPtr->raid_cinfo[row][col].ci_dev = va.va_rdev;
                    693:
                    694:                /* This component was not automatically configured. */
                    695:                diskPtr->auto_configured = 0;
                    696:                diskPtr->dev = va.va_rdev;
                    697:
                    698:                /*
                    699:                 * We allow the user to specify that only a fraction of the
                    700:                 * disks should be used. This is just for debug: it speeds up
                    701:                 * the parity scan.
                    702:                 */
                    703:                diskPtr->numBlocks = diskPtr->numBlocks * rf_sizePercentage
                    704:                    / 100;
                    705:        }
                    706:        return (0);
                    707: }
                    708:
                    709: void
                    710: rf_print_label_status(RF_Raid_t *raidPtr, int row, int column, char *dev_name,
                    711:     RF_ComponentLabel_t *ci_label)
                    712: {
                    713:
                    714:        printf("raid%d: Component %s being configured at row: %d col: %d\n",
                    715:            raidPtr->raidid, dev_name, row, column);
                    716:        printf("         Row: %d Column: %d Num Rows: %d Num Columns: %d\n",
                    717:            ci_label->row, ci_label->column, ci_label->num_rows,
                    718:            ci_label->num_columns);
                    719:        printf("         Version: %d Serial Number: %d Mod Counter: %d\n",
                    720:            ci_label->version, ci_label->serial_number, ci_label->mod_counter);
                    721:        printf("         Clean: %s Status: %d\n",
                    722:            ci_label->clean ? "Yes" : "No", ci_label->status);
                    723: }
                    724:
                    725: int
                    726: rf_check_label_vitals(RF_Raid_t *raidPtr, int row, int column, char *dev_name,
                    727:     RF_ComponentLabel_t *ci_label, int serial_number, int mod_counter)
                    728: {
                    729:        int fatal_error = 0;
                    730:
                    731:        if (serial_number != ci_label->serial_number) {
                    732:                printf("%s has a different serial number: %d %d.\n",
                    733:                    dev_name, serial_number, ci_label->serial_number);
                    734:                fatal_error = 1;
                    735:        }
                    736:        if (mod_counter != ci_label->mod_counter) {
                    737:                printf("%s has a different modfication count: %d %d.\n",
                    738:                    dev_name, mod_counter, ci_label->mod_counter);
                    739:        }
                    740:
                    741:        if (row != ci_label->row) {
                    742:                printf("Row out of alignment for: %s.\n", dev_name);
                    743:                fatal_error = 1;
                    744:        }
                    745:        if (column != ci_label->column) {
                    746:                printf("Column out of alignment for: %s.\n", dev_name);
                    747:                fatal_error = 1;
                    748:        }
                    749:        if (raidPtr->numRow != ci_label->num_rows) {
                    750:                printf("Number of rows do not match for: %s.\n", dev_name);
                    751:                fatal_error = 1;
                    752:        }
                    753:        if (raidPtr->numCol != ci_label->num_columns) {
                    754:                printf("Number of columns do not match for: %s.\n", dev_name);
                    755:                fatal_error = 1;
                    756:        }
                    757:        if (ci_label->clean == 0) {
                    758:                /* It's not clean, but that's not fatal. */
                    759:                printf("%s is not clean !\n", dev_name);
                    760:        }
                    761:        return(fatal_error);
                    762: }
                    763:
                    764:
                    765: /*
                    766:  *
                    767:  * rf_CheckLabels() - Check all the component labels for consistency.
                    768:  * Return an error if there is anything major amiss.
                    769:  *
                    770:  */
                    771:
                    772: int
                    773: rf_CheckLabels(RF_Raid_t *raidPtr, RF_Config_t *cfgPtr)
                    774: {
                    775:        int r, c;
                    776:        char *dev_name;
                    777:        RF_ComponentLabel_t *ci_label;
                    778:        int serial_number = 0;
                    779:        int mod_number = 0;
                    780:        int fatal_error = 0;
                    781:        int mod_values[4];
                    782:        int mod_count[4];
                    783:        int ser_values[4];
                    784:        int ser_count[4];
                    785:        int num_ser;
                    786:        int num_mod;
                    787:        int i;
                    788:        int found;
                    789:        int hosed_row;
                    790:        int hosed_column;
                    791:        int too_fatal;
                    792:        int parity_good;
                    793:        int force;
                    794:
                    795:        hosed_row = -1;
                    796:        hosed_column = -1;
                    797:        too_fatal = 0;
                    798:        force = cfgPtr->force;
                    799:
                    800:        /*
                    801:         * We're going to try to be a little intelligent here. If one
                    802:         * component's label is bogus, and we can identify that it's the
                    803:         * *only* one that's gone, we'll mark it as "failed" and allow
                    804:         * the configuration to proceed. This will be the *only* case
                    805:         * that we'll proceed if there would be (otherwise) fatal errors.
                    806:         *
                    807:         * Basically we simply keep a count of how many components had
                    808:         * what serial number. If all but one agree, we simply mark
                    809:         * the disagreeing component as being failed, and allow
                    810:         * things to come up "normally".
                    811:         *
                    812:         * We do this first for serial numbers, and then for "mod_counter".
                    813:         *
                    814:         */
                    815:
                    816:        num_ser = 0;
                    817:        num_mod = 0;
                    818:        for (r = 0; r < raidPtr->numRow && !fatal_error; r++) {
                    819:                for (c = 0; c < raidPtr->numCol; c++) {
                    820:                        ci_label = &raidPtr->raid_cinfo[r][c].ci_label;
                    821:                        found = 0;
                    822:                        for(i = 0; i < num_ser; i++) {
                    823:                                if (ser_values[i] == ci_label->serial_number) {
                    824:                                        ser_count[i]++;
                    825:                                        found = 1;
                    826:                                        break;
                    827:                                }
                    828:                        }
                    829:                        if (!found) {
                    830:                                ser_values[num_ser] = ci_label->serial_number;
                    831:                                ser_count[num_ser] = 1;
                    832:                                num_ser++;
                    833:                                if (num_ser > 2) {
                    834:                                        fatal_error = 1;
                    835:                                        break;
                    836:                                }
                    837:                        }
                    838:                        found = 0;
                    839:                        for(i = 0; i < num_mod; i++) {
                    840:                                if (mod_values[i] == ci_label->mod_counter) {
                    841:                                        mod_count[i]++;
                    842:                                        found = 1;
                    843:                                        break;
                    844:                                }
                    845:                        }
                    846:                        if (!found) {
                    847:                                mod_values[num_mod] = ci_label->mod_counter;
                    848:                                mod_count[num_mod] = 1;
                    849:                                num_mod++;
                    850:                                if (num_mod > 2) {
                    851:                                        fatal_error = 1;
                    852:                                        break;
                    853:                                }
                    854:                        }
                    855:                }
                    856:        }
                    857: #if    DEBUG
                    858:        printf("raid%d: Summary of serial numbers:\n", raidPtr->raidid);
                    859:        for(i = 0; i < num_ser; i++) {
                    860:                printf("%d %d\n", ser_values[i], ser_count[i]);
                    861:        }
                    862:        printf("raid%d: Summary of mod counters:\n", raidPtr->raidid);
                    863:        for(i = 0; i < num_mod; i++) {
                    864:                printf("%d %d\n", mod_values[i], mod_count[i]);
                    865:        }
                    866: #endif  /* DEBUG */
                    867:        serial_number = ser_values[0];
                    868:        if (num_ser == 2) {
                    869:                if ((ser_count[0] == 1) || (ser_count[1] == 1)) {
                    870:                        /* Locate the maverick component. */
                    871:                        if (ser_count[1] > ser_count[0]) {
                    872:                                serial_number = ser_values[1];
                    873:                        }
                    874:                        for (r = 0; r < raidPtr->numRow; r++) {
                    875:                                for (c = 0; c < raidPtr->numCol; c++) {
                    876:                                        ci_label =
                    877:                                            &raidPtr->raid_cinfo[r][c].ci_label;
                    878:                                        if (serial_number !=
                    879:                                            ci_label->serial_number) {
                    880:                                                hosed_row = r;
                    881:                                                hosed_column = c;
                    882:                                                break;
                    883:                                        }
                    884:                                }
                    885:                        }
                    886:                        printf("Hosed component: %s.\n",
                    887:                            &cfgPtr->devnames[hosed_row][hosed_column][0]);
                    888:                        if (!force) {
                    889:                                /*
                    890:                                 * We'll fail this component, as if there are
                    891:                                 * other major errors, we aren't forcing things
                    892:                                 * and we'll abort the config anyways.
                    893:                                 */
                    894:                                raidPtr->Disks[hosed_row][hosed_column].status
                    895:                                    = rf_ds_failed;
                    896:                                raidPtr->numFailures++;
                    897:                                raidPtr->status[hosed_row] = rf_rs_degraded;
                    898:                        }
                    899:                } else {
                    900:                        too_fatal = 1;
                    901:                }
                    902:                if (cfgPtr->parityConfig == '0') {
                    903:                        /*
                    904:                         * We've identified two different serial numbers.
                    905:                         * RAID 0 can't cope with that, so we'll punt.
                    906:                         */
                    907:                        too_fatal = 1;
                    908:                }
                    909:
                    910:        }
                    911:
                    912:        /*
                    913:         * Record the serial number for later. If we bail later, setting
                    914:         * this doesn't matter, otherwise we've got the best guess at the
                    915:         * correct serial number.
                    916:         */
                    917:        raidPtr->serial_number = serial_number;
                    918:
                    919:        mod_number = mod_values[0];
                    920:        if (num_mod == 2) {
                    921:                if ((mod_count[0] == 1) || (mod_count[1] == 1)) {
                    922:                        /* Locate the maverick component. */
                    923:                        if (mod_count[1] > mod_count[0]) {
                    924:                                mod_number = mod_values[1];
                    925:                        } else if (mod_count[1] < mod_count[0]) {
                    926:                                mod_number = mod_values[0];
                    927:                        } else {
                    928:                                /*
                    929:                                 * Counts of different modification values
                    930:                                 * are the same. Assume greater value is
                    931:                                 * the correct one, all other things
                    932:                                 * considered.
                    933:                                 */
                    934:                                if (mod_values[0] > mod_values[1]) {
                    935:                                        mod_number = mod_values[0];
                    936:                                } else {
                    937:                                        mod_number = mod_values[1];
                    938:                                }
                    939:
                    940:                        }
                    941:                        for (r = 0; r < raidPtr->numRow && !too_fatal; r++) {
                    942:                                for (c = 0; c < raidPtr->numCol; c++) {
                    943:                                        ci_label =
                    944:                                            &raidPtr->raid_cinfo[r][c].ci_label;
                    945:                                        if (mod_number !=
                    946:                                            ci_label->mod_counter) {
                    947:                                                if ((hosed_row == r) &&
                    948:                                                    (hosed_column == c)) {
                    949:                                                        /*
                    950:                                                         * Same one. Can
                    951:                                                         * deal with it.
                    952:                                                         */
                    953:                                                } else {
                    954:                                                        hosed_row = r;
                    955:                                                        hosed_column = c;
                    956:                                                        if (num_ser != 1) {
                    957:                                                                too_fatal = 1;
                    958:                                                                break;
                    959:                                                        }
                    960:                                                }
                    961:                                        }
                    962:                                }
                    963:                        }
                    964:                        printf("Hosed component: %s.\n",
                    965:                            &cfgPtr->devnames[hosed_row][hosed_column][0]);
                    966:                        if (!force) {
                    967:                                /*
                    968:                                 * We'll fail this component, as if there are
                    969:                                 * other major errors, we aren't forcing things
                    970:                                 * and we'll abort the config anyways.
                    971:                                 */
                    972:                                if (raidPtr
                    973:                                    ->Disks[hosed_row][hosed_column].status !=
                    974:                                    rf_ds_failed) {
                    975:                                        raidPtr->Disks[hosed_row]
                    976:                                            [hosed_column].status =
                    977:                                            rf_ds_failed;
                    978:                                        raidPtr->numFailures++;
                    979:                                        raidPtr->status[hosed_row] =
                    980:                                            rf_rs_degraded;
                    981:                                }
                    982:                        }
                    983:                } else {
                    984:                        too_fatal = 1;
                    985:                }
                    986:                if (cfgPtr->parityConfig == '0') {
                    987:                        /*
                    988:                         * We've identified two different mod counters.
                    989:                         * RAID 0 can't cope with that, so we'll punt.
                    990:                         */
                    991:                        too_fatal = 1;
                    992:                }
                    993:        }
                    994:
                    995:        raidPtr->mod_counter = mod_number;
                    996:
                    997:        if (too_fatal) {
                    998:                /*
                    999:                 * We've had both a serial number mismatch, and a mod_counter
                   1000:                 * mismatch -- and they involved two different components !!!
                   1001:                 * Bail -- make things fail so that the user must force
                   1002:                 * the issue...
                   1003:                 */
                   1004:                hosed_row = -1;
                   1005:                hosed_column = -1;
                   1006:        }
                   1007:
                   1008:        if (num_ser > 2) {
                   1009:                printf("raid%d: Too many different serial numbers !\n",
                   1010:                    raidPtr->raidid);
                   1011:        }
                   1012:
                   1013:        if (num_mod > 2) {
                   1014:                printf("raid%d: Too many different mod counters !\n",
                   1015:                    raidPtr->raidid);
                   1016:        }
                   1017:
                   1018:        /*
                   1019:         * We start by assuming the parity will be good, and flee from
                   1020:         * that notion at the slightest sign of trouble.
                   1021:         */
                   1022:
                   1023:        parity_good = RF_RAID_CLEAN;
                   1024:        for (r = 0; r < raidPtr->numRow; r++) {
                   1025:                for (c = 0; c < raidPtr->numCol; c++) {
                   1026:                        dev_name = &cfgPtr->devnames[r][c][0];
                   1027:                        ci_label = &raidPtr->raid_cinfo[r][c].ci_label;
                   1028:
                   1029:                        if ((r == hosed_row) && (c == hosed_column)) {
                   1030:                                printf("raid%d: Ignoring %s.\n",
                   1031:                                    raidPtr->raidid, dev_name);
                   1032:                        } else {
                   1033:                                rf_print_label_status(raidPtr, r, c, dev_name,
                   1034:                                    ci_label);
                   1035:                                if (rf_check_label_vitals(raidPtr, r, c,
                   1036:                                     dev_name, ci_label, serial_number,
                   1037:                                     mod_number)) {
                   1038:                                        fatal_error = 1;
                   1039:                                }
                   1040:                                if (ci_label->clean != RF_RAID_CLEAN) {
                   1041:                                        parity_good = RF_RAID_DIRTY;
                   1042:                                }
                   1043:                        }
                   1044:                }
                   1045:        }
                   1046:        if (fatal_error) {
                   1047:                parity_good = RF_RAID_DIRTY;
                   1048:        }
                   1049:
                   1050:        /* We note the state of the parity. */
                   1051:        raidPtr->parity_good = parity_good;
                   1052:
                   1053:        return(fatal_error);
                   1054: }
                   1055:
                   1056: int
                   1057: rf_add_hot_spare(RF_Raid_t *raidPtr, RF_SingleComponent_t *sparePtr)
                   1058: {
                   1059:        RF_RaidDisk_t *disks;
                   1060:        RF_DiskQueue_t *spareQueues;
                   1061:        int ret;
                   1062:        unsigned int bs;
                   1063:        int spare_number;
                   1064:
                   1065: #if 0
                   1066:        printf("Just in rf_add_hot_spare: %d.\n", raidPtr->numSpare);
                   1067:        printf("Num col: %d.\n", raidPtr->numCol);
                   1068: #endif
                   1069:        if (raidPtr->numSpare >= RF_MAXSPARE) {
                   1070:                RF_ERRORMSG1("Too many spares: %d.\n", raidPtr->numSpare);
                   1071:                return(EINVAL);
                   1072:        }
                   1073:
                   1074:        RF_LOCK_MUTEX(raidPtr->mutex);
                   1075:
                   1076:        /* The beginning of the spares... */
                   1077:        disks = &raidPtr->Disks[0][raidPtr->numCol];
                   1078:
                   1079:        spare_number = raidPtr->numSpare;
                   1080:
                   1081:        ret = rf_ConfigureDisk(raidPtr, sparePtr->component_name,
                   1082:            &disks[spare_number], 0, raidPtr->numCol + spare_number);
                   1083:
                   1084:        if (ret)
                   1085:                goto fail;
                   1086:        if (disks[spare_number].status != rf_ds_optimal) {
                   1087:                RF_ERRORMSG1("Warning: spare disk %s failed TUR.\n",
                   1088:                    sparePtr->component_name);
                   1089:                ret = EINVAL;
                   1090:                goto fail;
                   1091:        } else {
                   1092:                disks[spare_number].status = rf_ds_spare;
                   1093:                DPRINTF6("Spare Disk %d: dev %s numBlocks %ld blockSize %d"
                   1094:                    " (%ld MB).\n", spare_number, disks[spare_number].devname,
                   1095:                    (long int) disks[spare_number].numBlocks,
                   1096:                    disks[spare_number].blockSize,
                   1097:                    (long int) disks[spare_number].numBlocks *
                   1098:                     disks[spare_number].blockSize / 1024 / 1024);
                   1099:        }
                   1100:
                   1101:
                   1102:        /* Check sizes and block sizes on the spare disk. */
                   1103:        bs = 1 << raidPtr->logBytesPerSector;
                   1104:        if (disks[spare_number].blockSize != bs) {
                   1105:                RF_ERRORMSG3("Block size of %d on spare disk %s is not"
                   1106:                    " the same as on other disks (%d).\n",
                   1107:                    disks[spare_number].blockSize,
                   1108:                    disks[spare_number].devname, bs);
                   1109:                ret = EINVAL;
                   1110:                goto fail;
                   1111:        }
                   1112:        if (disks[spare_number].numBlocks < raidPtr->sectorsPerDisk) {
                   1113:                RF_ERRORMSG3("Spare disk %s (%llu blocks) is too small to serve"
                   1114:                    " as a spare (need %llu blocks).\n",
                   1115:                    disks[spare_number].devname, disks[spare_number].numBlocks,
                   1116:                    raidPtr->sectorsPerDisk);
                   1117:                ret = EINVAL;
                   1118:                goto fail;
                   1119:        } else {
                   1120:                if (disks[spare_number].numBlocks >
                   1121:                    raidPtr->sectorsPerDisk) {
                   1122:                        RF_ERRORMSG2("Warning: truncating spare disk %s to %llu"
                   1123:                            " blocks.\n", disks[spare_number].devname,
                   1124:                            raidPtr->sectorsPerDisk);
                   1125:
                   1126:                        disks[spare_number].numBlocks = raidPtr->sectorsPerDisk;
                   1127:                }
                   1128:        }
                   1129:
                   1130:        spareQueues = &raidPtr->Queues[0][raidPtr->numCol];
                   1131:        ret = rf_ConfigureDiskQueue(raidPtr, &spareQueues[spare_number],
                   1132:            0, raidPtr->numCol + spare_number, raidPtr->qType,
                   1133:            raidPtr->sectorsPerDisk, raidPtr->Disks[0][raidPtr->numCol +
                   1134:             spare_number].dev, raidPtr->maxOutstanding,
                   1135:            &raidPtr->shutdownList, raidPtr->cleanupList);
                   1136:
                   1137:
                   1138:        raidPtr->numSpare++;
                   1139:        RF_UNLOCK_MUTEX(raidPtr->mutex);
                   1140:        return (0);
                   1141:
                   1142: fail:
                   1143:        RF_UNLOCK_MUTEX(raidPtr->mutex);
                   1144:        return(ret);
                   1145: }
                   1146:
                   1147: int
                   1148: rf_remove_hot_spare(RF_Raid_t *raidPtr, RF_SingleComponent_t *sparePtr)
                   1149: {
                   1150:        int spare_number;
                   1151:
                   1152:        if (raidPtr->numSpare == 0) {
                   1153:                printf("No spares to remove !\n");
                   1154:                return(EINVAL);
                   1155:        }
                   1156:
                   1157:        spare_number = sparePtr->column;
                   1158:
                   1159:        return(EINVAL); /* XXX Not implemented yet. */
                   1160: #if 0
                   1161:        if (spare_number < 0 || spare_number > raidPtr->numSpare) {
                   1162:                return(EINVAL);
                   1163:        }
                   1164:
                   1165:        /* Verify that this spare isn't in use... */
                   1166:
                   1167:        /* It's gone... */
                   1168:
                   1169:        raidPtr->numSpare--;
                   1170:
                   1171:        return (0);
                   1172: #endif
                   1173: }
                   1174:
                   1175: int
                   1176: rf_delete_component(RF_Raid_t *raidPtr, RF_SingleComponent_t *component)
                   1177: {
                   1178:        RF_RaidDisk_t *disks;
                   1179:
                   1180:        if ((component->row < 0) ||
                   1181:            (component->row >= raidPtr->numRow) ||
                   1182:            (component->column < 0) ||
                   1183:            (component->column >= raidPtr->numCol)) {
                   1184:                return(EINVAL);
                   1185:        }
                   1186:
                   1187:        disks = &raidPtr->Disks[component->row][component->column];
                   1188:
                   1189:        /* 1. This component must be marked as 'failed'. */
                   1190:
                   1191:        return(EINVAL); /* Not implemented yet. */
                   1192: }
                   1193:
                   1194: int
                   1195: rf_incorporate_hot_spare(RF_Raid_t *raidPtr, RF_SingleComponent_t *component)
                   1196: {
                   1197:
                   1198:        /*
                   1199:         * Issues here include how to 'move' this in if there is IO
                   1200:         * taking place (e.g. component queues and such).
                   1201:         */
                   1202:
                   1203:        return(EINVAL); /* Not implemented yet. */
                   1204: }

CVSweb