root/dev/raidframe/rf_disks.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rf_ConfigureDisks
  2. rf_ConfigureSpareDisks
  3. rf_AllocDiskStructures
  4. rf_AutoConfigureDisks
  5. rf_ConfigureDisk
  6. rf_print_label_status
  7. rf_check_label_vitals
  8. rf_CheckLabels
  9. rf_add_hot_spare
  10. rf_remove_hot_spare
  11. rf_delete_component
  12. rf_incorporate_hot_spare

    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 }

/* [<][>][^][v][top][bottom][index][help] */