Home | History | Annotate | Line # | Download | only in raidframe
rf_disks.c revision 1.1
      1  1.1  oster /*	$NetBSD: rf_disks.c,v 1.1 1998/11/13 04:20:29 oster Exp $	*/
      2  1.1  oster /*
      3  1.1  oster  * Copyright (c) 1995 Carnegie-Mellon University.
      4  1.1  oster  * All rights reserved.
      5  1.1  oster  *
      6  1.1  oster  * Author: Mark Holland
      7  1.1  oster  *
      8  1.1  oster  * Permission to use, copy, modify and distribute this software and
      9  1.1  oster  * its documentation is hereby granted, provided that both the copyright
     10  1.1  oster  * notice and this permission notice appear in all copies of the
     11  1.1  oster  * software, derivative works or modified versions, and any portions
     12  1.1  oster  * thereof, and that both notices appear in supporting documentation.
     13  1.1  oster  *
     14  1.1  oster  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     15  1.1  oster  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
     16  1.1  oster  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     17  1.1  oster  *
     18  1.1  oster  * Carnegie Mellon requests users of this software to return to
     19  1.1  oster  *
     20  1.1  oster  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     21  1.1  oster  *  School of Computer Science
     22  1.1  oster  *  Carnegie Mellon University
     23  1.1  oster  *  Pittsburgh PA 15213-3890
     24  1.1  oster  *
     25  1.1  oster  * any improvements or extensions that they make and grant Carnegie the
     26  1.1  oster  * rights to redistribute these changes.
     27  1.1  oster  */
     28  1.1  oster 
     29  1.1  oster /***************************************************************
     30  1.1  oster  * rf_disks.c -- code to perform operations on the actual disks
     31  1.1  oster  ***************************************************************/
     32  1.1  oster 
     33  1.1  oster /* :
     34  1.1  oster  * Log: rf_disks.c,v
     35  1.1  oster  * Revision 1.32  1996/07/27 18:40:24  jimz
     36  1.1  oster  * cleanup sweep
     37  1.1  oster  *
     38  1.1  oster  * Revision 1.31  1996/07/22  19:52:16  jimz
     39  1.1  oster  * switched node params to RF_DagParam_t, a union of
     40  1.1  oster  * a 64-bit int and a void *, for better portability
     41  1.1  oster  * attempted hpux port, but failed partway through for
     42  1.1  oster  * lack of a single C compiler capable of compiling all
     43  1.1  oster  * source files
     44  1.1  oster  *
     45  1.1  oster  * Revision 1.30  1996/07/19  16:11:21  jimz
     46  1.1  oster  * pass devname to DoReadCapacity
     47  1.1  oster  *
     48  1.1  oster  * Revision 1.29  1996/07/18  22:57:14  jimz
     49  1.1  oster  * port simulator to AIX
     50  1.1  oster  *
     51  1.1  oster  * Revision 1.28  1996/07/10  22:28:38  jimz
     52  1.1  oster  * get rid of obsolete row statuses (dead,degraded2)
     53  1.1  oster  *
     54  1.1  oster  * Revision 1.27  1996/06/10  12:06:14  jimz
     55  1.1  oster  * don't do any SCSI op stuff in simulator at all
     56  1.1  oster  *
     57  1.1  oster  * Revision 1.26  1996/06/10  11:55:47  jimz
     58  1.1  oster  * Straightened out some per-array/not-per-array distinctions, fixed
     59  1.1  oster  * a couple bugs related to confusion. Added shutdown lists. Removed
     60  1.1  oster  * layout shutdown function (now subsumed by shutdown lists).
     61  1.1  oster  *
     62  1.1  oster  * Revision 1.25  1996/06/09  02:36:46  jimz
     63  1.1  oster  * lots of little crufty cleanup- fixup whitespace
     64  1.1  oster  * issues, comment #ifdefs, improve typing in some
     65  1.1  oster  * places (esp size-related)
     66  1.1  oster  *
     67  1.1  oster  * Revision 1.24  1996/06/07  21:33:04  jimz
     68  1.1  oster  * begin using consistent types for sector numbers,
     69  1.1  oster  * stripe numbers, row+col numbers, recon unit numbers
     70  1.1  oster  *
     71  1.1  oster  * Revision 1.23  1996/06/03  23:28:26  jimz
     72  1.1  oster  * more bugfixes
     73  1.1  oster  * check in tree to sync for IPDS runs with current bugfixes
     74  1.1  oster  * there still may be a problem with threads in the script test
     75  1.1  oster  * getting I/Os stuck- not trivially reproducible (runs ~50 times
     76  1.1  oster  * in a row without getting stuck)
     77  1.1  oster  *
     78  1.1  oster  * Revision 1.22  1996/06/02  17:31:48  jimz
     79  1.1  oster  * Moved a lot of global stuff into array structure, where it belongs.
     80  1.1  oster  * Fixed up paritylogging, pss modules in this manner. Some general
     81  1.1  oster  * code cleanup. Removed lots of dead code, some dead files.
     82  1.1  oster  *
     83  1.1  oster  * Revision 1.21  1996/05/30  23:22:16  jimz
     84  1.1  oster  * bugfixes of serialization, timing problems
     85  1.1  oster  * more cleanup
     86  1.1  oster  *
     87  1.1  oster  * Revision 1.20  1996/05/30  11:29:41  jimz
     88  1.1  oster  * Numerous bug fixes. Stripe lock release code disagreed with the taking code
     89  1.1  oster  * about when stripes should be locked (I made it consistent: no parity, no lock)
     90  1.1  oster  * There was a lot of extra serialization of I/Os which I've removed- a lot of
     91  1.1  oster  * it was to calculate values for the cache code, which is no longer with us.
     92  1.1  oster  * More types, function, macro cleanup. Added code to properly quiesce the array
     93  1.1  oster  * on shutdown. Made a lot of stuff array-specific which was (bogusly) general
     94  1.1  oster  * before. Fixed memory allocation, freeing bugs.
     95  1.1  oster  *
     96  1.1  oster  * Revision 1.19  1996/05/27  18:56:37  jimz
     97  1.1  oster  * more code cleanup
     98  1.1  oster  * better typing
     99  1.1  oster  * compiles in all 3 environments
    100  1.1  oster  *
    101  1.1  oster  * Revision 1.18  1996/05/24  22:17:04  jimz
    102  1.1  oster  * continue code + namespace cleanup
    103  1.1  oster  * typed a bunch of flags
    104  1.1  oster  *
    105  1.1  oster  * Revision 1.17  1996/05/24  01:59:45  jimz
    106  1.1  oster  * another checkpoint in code cleanup for release
    107  1.1  oster  * time to sync kernel tree
    108  1.1  oster  *
    109  1.1  oster  * Revision 1.16  1996/05/23  21:46:35  jimz
    110  1.1  oster  * checkpoint in code cleanup (release prep)
    111  1.1  oster  * lots of types, function names have been fixed
    112  1.1  oster  *
    113  1.1  oster  * Revision 1.15  1996/05/23  00:33:23  jimz
    114  1.1  oster  * code cleanup: move all debug decls to rf_options.c, all extern
    115  1.1  oster  * debug decls to rf_options.h, all debug vars preceded by rf_
    116  1.1  oster  *
    117  1.1  oster  * Revision 1.14  1996/05/18  19:51:34  jimz
    118  1.1  oster  * major code cleanup- fix syntax, make some types consistent,
    119  1.1  oster  * add prototypes, clean out dead code, et cetera
    120  1.1  oster  *
    121  1.1  oster  * Revision 1.13  1996/05/02  14:57:43  jimz
    122  1.1  oster  * initialize sectorMask
    123  1.1  oster  *
    124  1.1  oster  * Revision 1.12  1995/12/01  15:57:04  root
    125  1.1  oster  * added copyright info
    126  1.1  oster  *
    127  1.1  oster  */
    128  1.1  oster 
    129  1.1  oster #include "rf_types.h"
    130  1.1  oster #include "rf_raid.h"
    131  1.1  oster #include "rf_alloclist.h"
    132  1.1  oster #include "rf_utils.h"
    133  1.1  oster #include "rf_configure.h"
    134  1.1  oster #include "rf_general.h"
    135  1.1  oster #if !defined(__NetBSD__)
    136  1.1  oster #include "rf_camlayer.h"
    137  1.1  oster #endif
    138  1.1  oster #include "rf_options.h"
    139  1.1  oster #include "rf_sys.h"
    140  1.1  oster 
    141  1.1  oster #if defined(__NetBSD__) && defined(_KERNEL)
    142  1.1  oster #include <sys/types.h>
    143  1.1  oster #include <sys/param.h>
    144  1.1  oster #include <sys/systm.h>
    145  1.1  oster #include <sys/proc.h>
    146  1.1  oster #include <sys/ioctl.h>
    147  1.1  oster #include <sys/fcntl.h>
    148  1.1  oster #include <sys/vnode.h>
    149  1.1  oster 
    150  1.1  oster int raidlookup __P((char *, struct proc *p, struct vnode **));
    151  1.1  oster #endif
    152  1.1  oster 
    153  1.1  oster #ifdef SIMULATE
    154  1.1  oster static char disk_db_file_name[120], disk_type_name[120];
    155  1.1  oster static double init_offset;
    156  1.1  oster #endif /* SIMULATE  */
    157  1.1  oster 
    158  1.1  oster #define DPRINTF6(a,b,c,d,e,f) if (rf_diskDebug) printf(a,b,c,d,e,f)
    159  1.1  oster #define DPRINTF7(a,b,c,d,e,f,g) if (rf_diskDebug) printf(a,b,c,d,e,f,g)
    160  1.1  oster 
    161  1.1  oster #include "rf_ccmn.h"
    162  1.1  oster 
    163  1.1  oster /****************************************************************************************
    164  1.1  oster  *
    165  1.1  oster  * initialize the disks comprising the array
    166  1.1  oster  *
    167  1.1  oster  * We want the spare disks to have regular row,col numbers so that we can easily
    168  1.1  oster  * substitue a spare for a failed disk.  But, the driver code assumes throughout
    169  1.1  oster  * that the array contains numRow by numCol _non-spare_ disks, so it's not clear
    170  1.1  oster  * how to fit in the spares.  This is an unfortunate holdover from raidSim.  The
    171  1.1  oster  * quick and dirty fix is to make row zero bigger than the rest, and put all the
    172  1.1  oster  * spares in it.  This probably needs to get changed eventually.
    173  1.1  oster  *
    174  1.1  oster  ***************************************************************************************/
    175  1.1  oster int rf_ConfigureDisks(
    176  1.1  oster   RF_ShutdownList_t  **listp,
    177  1.1  oster   RF_Raid_t           *raidPtr,
    178  1.1  oster   RF_Config_t         *cfgPtr)
    179  1.1  oster {
    180  1.1  oster   RF_RaidDisk_t **disks;
    181  1.1  oster   RF_SectorCount_t min_numblks = (RF_SectorCount_t)0x7FFFFFFFFFFFLL;
    182  1.1  oster   RF_RowCol_t r, c;
    183  1.1  oster   int bs, ret;
    184  1.1  oster   unsigned i, count, foundone=0, numFailuresThisRow;
    185  1.1  oster   RF_DiskOp_t *rdcap_op = NULL, *tur_op = NULL;
    186  1.1  oster   int num_rows_done,num_cols_done;
    187  1.1  oster 
    188  1.1  oster #if defined(__NetBSD__) && defined(_KERNEL)
    189  1.1  oster 	struct proc *proc = 0;
    190  1.1  oster #endif
    191  1.1  oster #ifndef SIMULATE
    192  1.1  oster #ifndef __NetBSD__
    193  1.1  oster   ret = rf_SCSI_AllocReadCapacity(&rdcap_op);
    194  1.1  oster   if (ret)
    195  1.1  oster     goto fail;
    196  1.1  oster   ret = rf_SCSI_AllocTUR(&tur_op);
    197  1.1  oster   if (ret)
    198  1.1  oster     goto fail;
    199  1.1  oster #endif /* !__NetBSD__ */
    200  1.1  oster #endif /* !SIMULATE */
    201  1.1  oster 
    202  1.1  oster   num_rows_done = 0;
    203  1.1  oster   num_cols_done = 0;
    204  1.1  oster 
    205  1.1  oster 
    206  1.1  oster   RF_CallocAndAdd(disks, raidPtr->numRow, sizeof(RF_RaidDisk_t *), (RF_RaidDisk_t **), raidPtr->cleanupList);
    207  1.1  oster   if (disks == NULL) {
    208  1.1  oster     ret = ENOMEM;
    209  1.1  oster     goto fail;
    210  1.1  oster   }
    211  1.1  oster   raidPtr->Disks = disks;
    212  1.1  oster 
    213  1.1  oster #if defined(__NetBSD__) && defined(_KERNEL)
    214  1.1  oster 
    215  1.1  oster   proc = raidPtr->proc; /* Blah XXX */
    216  1.1  oster 
    217  1.1  oster   /* get space for the device-specific stuff... */
    218  1.1  oster   RF_CallocAndAdd(raidPtr->raid_cinfo, raidPtr->numRow,
    219  1.1  oster 		  sizeof(struct raidcinfo *), (struct raidcinfo **),
    220  1.1  oster 		  raidPtr->cleanupList);
    221  1.1  oster   if (raidPtr->raid_cinfo == NULL) {
    222  1.1  oster 	  ret = ENOMEM;
    223  1.1  oster 	  goto fail;
    224  1.1  oster   }
    225  1.1  oster #endif
    226  1.1  oster 
    227  1.1  oster   for (r=0; r<raidPtr->numRow; r++) {
    228  1.1  oster     numFailuresThisRow = 0;
    229  1.1  oster     RF_CallocAndAdd(disks[r], raidPtr->numCol + ((r==0) ? raidPtr->numSpare : 0), sizeof(RF_RaidDisk_t), (RF_RaidDisk_t *), raidPtr->cleanupList);
    230  1.1  oster     if (disks[r] == NULL) {
    231  1.1  oster       ret = ENOMEM;
    232  1.1  oster       goto fail;
    233  1.1  oster     }
    234  1.1  oster 
    235  1.1  oster     /* get more space for device specific stuff.. */
    236  1.1  oster     RF_CallocAndAdd(raidPtr->raid_cinfo[r],
    237  1.1  oster 		    raidPtr->numCol + ((r==0) ? raidPtr->numSpare : 0),
    238  1.1  oster 		    sizeof(struct raidcinfo), (struct raidcinfo *),
    239  1.1  oster 		    raidPtr->cleanupList);
    240  1.1  oster     if (raidPtr->raid_cinfo[r] == NULL) {
    241  1.1  oster       ret = ENOMEM;
    242  1.1  oster       goto fail;
    243  1.1  oster     }
    244  1.1  oster 
    245  1.1  oster 
    246  1.1  oster     for (c=0; c<raidPtr->numCol; c++) {
    247  1.1  oster       ret = rf_ConfigureDisk(raidPtr,&cfgPtr->devnames[r][c][0],
    248  1.1  oster 			     &disks[r][c], rdcap_op, tur_op,
    249  1.1  oster 			     cfgPtr->devs[r][c],r,c);
    250  1.1  oster       if (ret)
    251  1.1  oster         goto fail;
    252  1.1  oster       if (disks[r][c].status != rf_ds_optimal) {
    253  1.1  oster         numFailuresThisRow++;
    254  1.1  oster       }
    255  1.1  oster       else {
    256  1.1  oster         if (disks[r][c].numBlocks < min_numblks)
    257  1.1  oster           min_numblks = disks[r][c].numBlocks;
    258  1.1  oster         DPRINTF7("Disk at row %d col %d: dev %s numBlocks %ld blockSize %d (%ld MB)\n",
    259  1.1  oster           r,c,disks[r][c].devname,
    260  1.1  oster 		 (long int) disks[r][c].numBlocks,
    261  1.1  oster 		 disks[r][c].blockSize,
    262  1.1  oster 		 (long int) disks[r][c].numBlocks * disks[r][c].blockSize / 1024 / 1024);
    263  1.1  oster       }
    264  1.1  oster       num_cols_done++;
    265  1.1  oster     }
    266  1.1  oster     /* XXX fix for n-fault tolerant */
    267  1.1  oster     if (numFailuresThisRow > 0)
    268  1.1  oster       raidPtr->status[r] = rf_rs_degraded;
    269  1.1  oster     num_rows_done++;
    270  1.1  oster   }
    271  1.1  oster #ifndef SIMULATE
    272  1.1  oster #if defined(__NetBSD__) && defined(_KERNEL)
    273  1.1  oster   /* we do nothing */
    274  1.1  oster #else
    275  1.1  oster   rf_SCSI_FreeDiskOp(rdcap_op, 1); rdcap_op = NULL;
    276  1.1  oster   rf_SCSI_FreeDiskOp(tur_op, 0);   tur_op   = NULL;
    277  1.1  oster #endif
    278  1.1  oster #endif /* !SIMULATE */
    279  1.1  oster   /* all disks must be the same size & have the same block size, bs must be a power of 2 */
    280  1.1  oster   bs = 0;
    281  1.1  oster   for (foundone=r=0; !foundone && r<raidPtr->numRow; r++) {
    282  1.1  oster     for (c=0; !foundone && c<raidPtr->numCol; c++) {
    283  1.1  oster       if (disks[r][c].status == rf_ds_optimal) {
    284  1.1  oster         bs = disks[r][c].blockSize;
    285  1.1  oster         foundone = 1;
    286  1.1  oster       }
    287  1.1  oster     }
    288  1.1  oster   }
    289  1.1  oster   if (!foundone) {
    290  1.1  oster     RF_ERRORMSG("RAIDFRAME: Did not find any live disks in the array.\n");
    291  1.1  oster     ret = EINVAL;
    292  1.1  oster     goto fail;
    293  1.1  oster   }
    294  1.1  oster   for (count=0,i=1; i; i<<=1) if (bs & i)
    295  1.1  oster     count++;
    296  1.1  oster   if (count != 1) {
    297  1.1  oster     RF_ERRORMSG1("Error: block size on disks (%d) must be a power of 2\n",bs);
    298  1.1  oster     ret = EINVAL;
    299  1.1  oster     goto fail;
    300  1.1  oster   }
    301  1.1  oster   for (r=0; r<raidPtr->numRow; r++) {
    302  1.1  oster     for (c=0; c<raidPtr->numCol; c++) {
    303  1.1  oster       if (disks[r][c].status == rf_ds_optimal) {
    304  1.1  oster 	if (disks[r][c].blockSize != bs) {
    305  1.1  oster 	  RF_ERRORMSG2("Error: block size of disk at r %d c %d different from disk at r 0 c 0\n",r,c);
    306  1.1  oster 	  ret = EINVAL;
    307  1.1  oster 	  goto fail;
    308  1.1  oster 	}
    309  1.1  oster 	if (disks[r][c].numBlocks != min_numblks) {
    310  1.1  oster 	  RF_ERRORMSG3("WARNING: truncating disk at r %d c %d to %d blocks\n",
    311  1.1  oster 		       r,c,(int) min_numblks);
    312  1.1  oster 	  disks[r][c].numBlocks = min_numblks;
    313  1.1  oster 	}
    314  1.1  oster       }
    315  1.1  oster     }
    316  1.1  oster   }
    317  1.1  oster 
    318  1.1  oster   raidPtr->sectorsPerDisk = min_numblks;
    319  1.1  oster   raidPtr->logBytesPerSector = ffs(bs) - 1;
    320  1.1  oster   raidPtr->bytesPerSector = bs;
    321  1.1  oster   raidPtr->sectorMask = bs-1;
    322  1.1  oster   return(0);
    323  1.1  oster 
    324  1.1  oster fail:
    325  1.1  oster 
    326  1.1  oster #ifndef SIMULATE
    327  1.1  oster #if defined(__NetBSD__) && defined(_KERNEL)
    328  1.1  oster 
    329  1.1  oster   for(r=0;r<raidPtr->numRow;r++) {
    330  1.1  oster 	  for(c=0;c<raidPtr->numCol;c++) {
    331  1.1  oster 		  /* Cleanup.. */
    332  1.1  oster #ifdef DEBUG
    333  1.1  oster 		  printf("Cleaning up row: %d col: %d\n",r,c);
    334  1.1  oster #endif
    335  1.1  oster 		  if (raidPtr->raid_cinfo[r][c].ci_vp) {
    336  1.1  oster 			  (void)vn_close(raidPtr->raid_cinfo[r][c].ci_vp,
    337  1.1  oster 					 FREAD|FWRITE, proc->p_ucred, proc);
    338  1.1  oster 		  }
    339  1.1  oster 	  }
    340  1.1  oster   }
    341  1.1  oster   /* Space allocated for raid_vpp will get cleaned up at some other point */
    342  1.1  oster   /* XXX Need more #ifdefs in the above... */
    343  1.1  oster 
    344  1.1  oster #else
    345  1.1  oster 
    346  1.1  oster   if (rdcap_op) rf_SCSI_FreeDiskOp(rdcap_op, 1);
    347  1.1  oster   if (tur_op)   rf_SCSI_FreeDiskOp(tur_op, 0);
    348  1.1  oster 
    349  1.1  oster #endif
    350  1.1  oster #endif /* !SIMULATE */
    351  1.1  oster   return(ret);
    352  1.1  oster }
    353  1.1  oster 
    354  1.1  oster 
    355  1.1  oster /****************************************************************************************
    356  1.1  oster  * set up the data structures describing the spare disks in the array
    357  1.1  oster  * recall from the above comment that the spare disk descriptors are stored
    358  1.1  oster  * in row zero, which is specially expanded to hold them.
    359  1.1  oster  ***************************************************************************************/
    360  1.1  oster int rf_ConfigureSpareDisks(
    361  1.1  oster   RF_ShutdownList_t  **listp,
    362  1.1  oster   RF_Raid_t           *raidPtr,
    363  1.1  oster   RF_Config_t         *cfgPtr)
    364  1.1  oster {
    365  1.1  oster   char buf[256];
    366  1.1  oster   int i, ret;
    367  1.1  oster   RF_DiskOp_t *rdcap_op = NULL, *tur_op = NULL;
    368  1.1  oster   unsigned bs;
    369  1.1  oster   RF_RaidDisk_t *disks;
    370  1.1  oster   int num_spares_done;
    371  1.1  oster 
    372  1.1  oster #if defined(__NetBSD__) && defined(_KERNEL)
    373  1.1  oster 	struct proc *proc;
    374  1.1  oster #endif
    375  1.1  oster 
    376  1.1  oster #ifndef SIMULATE
    377  1.1  oster #ifndef __NetBSD__
    378  1.1  oster   ret = rf_SCSI_AllocReadCapacity(&rdcap_op);
    379  1.1  oster   if (ret)
    380  1.1  oster     goto fail;
    381  1.1  oster   ret = rf_SCSI_AllocTUR(&tur_op);
    382  1.1  oster   if (ret)
    383  1.1  oster     goto fail;
    384  1.1  oster #endif /* !__NetBSD__ */
    385  1.1  oster #endif /* !SIMULATE */
    386  1.1  oster 
    387  1.1  oster   num_spares_done = 0;
    388  1.1  oster 
    389  1.1  oster #if defined(__NetBSD__) && defined(_KERNEL)
    390  1.1  oster   proc = raidPtr->proc;
    391  1.1  oster   /* The space for the spares should have already been
    392  1.1  oster      allocated by ConfigureDisks() */
    393  1.1  oster #endif
    394  1.1  oster 
    395  1.1  oster   disks = &raidPtr->Disks[0][raidPtr->numCol];
    396  1.1  oster   for (i=0; i<raidPtr->numSpare; i++) {
    397  1.1  oster     ret = rf_ConfigureDisk(raidPtr,&cfgPtr->spare_names[i][0],
    398  1.1  oster 			   &disks[i], rdcap_op, tur_op,
    399  1.1  oster 			   cfgPtr->spare_devs[i],0,raidPtr->numCol+i);
    400  1.1  oster     if (ret)
    401  1.1  oster       goto fail;
    402  1.1  oster     if (disks[i].status != rf_ds_optimal) {
    403  1.1  oster       RF_ERRORMSG1("Warning: spare disk %s failed TUR\n",buf);
    404  1.1  oster     } else {
    405  1.1  oster       disks[i].status = rf_ds_spare;      /* change status to spare */
    406  1.1  oster       DPRINTF6("Spare Disk %d: dev %s numBlocks %ld blockSize %d (%ld MB)\n",i,
    407  1.1  oster 	       disks[i].devname,
    408  1.1  oster 	       (long int) disks[i].numBlocks,disks[i].blockSize,
    409  1.1  oster 	       (long int) disks[i].numBlocks * disks[i].blockSize / 1024 / 1024);
    410  1.1  oster     }
    411  1.1  oster     num_spares_done++;
    412  1.1  oster   }
    413  1.1  oster #ifndef SIMULATE
    414  1.1  oster #if defined(__NetBSD__) && (_KERNEL)
    415  1.1  oster 
    416  1.1  oster #else
    417  1.1  oster   rf_SCSI_FreeDiskOp(rdcap_op, 1); rdcap_op = NULL;
    418  1.1  oster   rf_SCSI_FreeDiskOp(tur_op, 0);   tur_op   = NULL;
    419  1.1  oster #endif
    420  1.1  oster #endif /* !SIMULATE */
    421  1.1  oster 
    422  1.1  oster   /* check sizes and block sizes on spare disks */
    423  1.1  oster   bs = 1 << raidPtr->logBytesPerSector;
    424  1.1  oster   for (i=0; i<raidPtr->numSpare; i++) {
    425  1.1  oster     if (disks[i].blockSize != bs) {
    426  1.1  oster       RF_ERRORMSG3("Block size of %d on spare disk %s is not the same as on other disks (%d)\n",disks[i].blockSize, disks[i].devname, bs);
    427  1.1  oster       ret = EINVAL;
    428  1.1  oster       goto fail;
    429  1.1  oster     }
    430  1.1  oster     if (disks[i].numBlocks < raidPtr->sectorsPerDisk) {
    431  1.1  oster 	    RF_ERRORMSG3("Spare disk %s (%d blocks) is too small to serve as a spare (need %ld blocks)\n",
    432  1.1  oster 		disks[i].devname, disks[i].blockSize, (long int)raidPtr->sectorsPerDisk);
    433  1.1  oster       ret = EINVAL;
    434  1.1  oster       goto fail;
    435  1.1  oster     } else if (disks[i].numBlocks > raidPtr->sectorsPerDisk) {
    436  1.1  oster 	    RF_ERRORMSG2("Warning: truncating spare disk %s to %ld blocks\n",disks[i].devname, (long int) raidPtr->sectorsPerDisk);
    437  1.1  oster 
    438  1.1  oster       disks[i].numBlocks = raidPtr->sectorsPerDisk;
    439  1.1  oster     }
    440  1.1  oster   }
    441  1.1  oster 
    442  1.1  oster   return(0);
    443  1.1  oster 
    444  1.1  oster fail:
    445  1.1  oster #ifndef SIMULATE
    446  1.1  oster #if defined(__NetBSD__) && defined(_KERNEL)
    447  1.1  oster 
    448  1.1  oster   for(i=0;i<raidPtr->numSpare;i++) {
    449  1.1  oster 	  /* Cleanup.. */
    450  1.1  oster #ifdef DEBUG
    451  1.1  oster 	  printf("Cleaning up spare: %d\n",i);
    452  1.1  oster #endif
    453  1.1  oster 	  if (raidPtr->raid_cinfo[0][raidPtr->numCol+i].ci_vp) {
    454  1.1  oster 		  (void)vn_close(raidPtr->raid_cinfo[0][raidPtr->numCol+i].ci_vp,
    455  1.1  oster 				 FREAD|FWRITE, proc->p_ucred, proc);
    456  1.1  oster 	  }
    457  1.1  oster   }
    458  1.1  oster 
    459  1.1  oster #else
    460  1.1  oster 
    461  1.1  oster   if (rdcap_op) rf_SCSI_FreeDiskOp(rdcap_op, 1);
    462  1.1  oster   if (tur_op)   rf_SCSI_FreeDiskOp(tur_op, 0);
    463  1.1  oster 
    464  1.1  oster #endif
    465  1.1  oster 
    466  1.1  oster #endif /* !SIMULATE */
    467  1.1  oster   return(ret);
    468  1.1  oster }
    469  1.1  oster 
    470  1.1  oster 
    471  1.1  oster 
    472  1.1  oster /* configure a single disk in the array */
    473  1.1  oster int rf_ConfigureDisk(raidPtr, buf, diskPtr, rdcap_op, tur_op, dev, row, col)
    474  1.1  oster   RF_Raid_t      *raidPtr;  /* We need this down here too!! GO */
    475  1.1  oster   char           *buf;
    476  1.1  oster   RF_RaidDisk_t  *diskPtr;
    477  1.1  oster   RF_DiskOp_t    *rdcap_op;
    478  1.1  oster   RF_DiskOp_t    *tur_op;
    479  1.1  oster   dev_t           dev;      /* device number used only in kernel */
    480  1.1  oster   RF_RowCol_t     row;
    481  1.1  oster   RF_RowCol_t     col;
    482  1.1  oster {
    483  1.1  oster   char *p;
    484  1.1  oster #ifdef SIMULATE
    485  1.1  oster   double	init_offset;
    486  1.1  oster #else /* SIMULATE  */
    487  1.1  oster #if defined(__NetBSD__) && defined(_KERNEL)
    488  1.1  oster   int retcode;
    489  1.1  oster #else
    490  1.1  oster   int busid, targid, lun, retcode;
    491  1.1  oster #endif
    492  1.1  oster #endif /* SIMULATE  */
    493  1.1  oster 
    494  1.1  oster #if defined(__NetBSD__) && defined(_KERNEL)
    495  1.1  oster 	struct partinfo dpart;
    496  1.1  oster 	struct vnode *vp;
    497  1.1  oster 	struct vattr va;
    498  1.1  oster 	struct proc *proc;
    499  1.1  oster 	int error;
    500  1.1  oster #endif
    501  1.1  oster 
    502  1.1  oster retcode = 0;
    503  1.1  oster   p = rf_find_non_white(buf);
    504  1.1  oster   if (p[strlen(p)-1] == '\n') {
    505  1.1  oster     /* strip off the newline */
    506  1.1  oster     p[strlen(p)-1] = '\0';
    507  1.1  oster   }
    508  1.1  oster   (void) strcpy(diskPtr->devname, p);
    509  1.1  oster 
    510  1.1  oster #ifdef SIMULATE
    511  1.1  oster 
    512  1.1  oster   init_offset = 0.0;
    513  1.1  oster   rf_InitDisk(&diskPtr->diskState, disk_db_file_name,diskPtr->devname,0,0,init_offset,row,col);
    514  1.1  oster   rf_GeometryDoReadCapacity(&diskPtr->diskState, &diskPtr->numBlocks, &diskPtr->blockSize);
    515  1.1  oster   diskPtr->numBlocks = diskPtr->numBlocks * rf_sizePercentage / 100;
    516  1.1  oster 
    517  1.1  oster   /* we allow the user to specify that only a fraction of the disks should be used
    518  1.1  oster    * this is just for debug:  it speeds up the parity scan
    519  1.1  oster    */
    520  1.1  oster 
    521  1.1  oster #else /* SIMULATE */
    522  1.1  oster #ifndef __NetBSD__
    523  1.1  oster   /* get bus, target, lun */
    524  1.1  oster   retcode = rf_extract_ids(p, &busid, &targid, &lun);
    525  1.1  oster   if (retcode)
    526  1.1  oster     return(retcode);
    527  1.1  oster 
    528  1.1  oster   /* required in kernel, nop at user level */
    529  1.1  oster   retcode = rf_SCSI_OpenUnit(dev);
    530  1.1  oster   if (retcode)
    531  1.1  oster     return(retcode);
    532  1.1  oster 
    533  1.1  oster   diskPtr->dev = dev;
    534  1.1  oster   if (rf_SCSI_DoTUR(tur_op, (u_char)busid, (u_char)targid, (u_char)lun, dev)) {
    535  1.1  oster     RF_ERRORMSG1("Disk %s failed TUR.  Marked as dead.\n",diskPtr->devname);
    536  1.1  oster     diskPtr->status = rf_ds_failed;
    537  1.1  oster   } else {
    538  1.1  oster     diskPtr->status = rf_ds_optimal;
    539  1.1  oster     retcode = rf_SCSI_DoReadCapacity(raidPtr,rdcap_op, busid, targid, lun, dev,
    540  1.1  oster       &diskPtr->numBlocks, &diskPtr->blockSize, diskPtr->devname);
    541  1.1  oster     if (retcode)
    542  1.1  oster       return(retcode);
    543  1.1  oster 
    544  1.1  oster     /* we allow the user to specify that only a fraction of the disks should be used
    545  1.1  oster      * this is just for debug:  it speeds up the parity scan
    546  1.1  oster      */
    547  1.1  oster     diskPtr->numBlocks = diskPtr->numBlocks * rf_sizePercentage / 100;
    548  1.1  oster   }
    549  1.1  oster #endif
    550  1.1  oster #if defined(__NetBSD__) && defined(_KERNEL)
    551  1.1  oster 
    552  1.1  oster   proc = raidPtr->proc;  /* XXX Yes, this is not nice.. */
    553  1.1  oster 
    554  1.1  oster   /* Let's start by claiming the component is fine and well... */
    555  1.1  oster   /* XXX not the case if the disk is toast.. */
    556  1.1  oster   diskPtr->status = rf_ds_optimal;
    557  1.1  oster 
    558  1.1  oster 
    559  1.1  oster   raidPtr->raid_cinfo[row][col].ci_vp = NULL;
    560  1.1  oster   raidPtr->raid_cinfo[row][col].ci_dev = NULL;
    561  1.1  oster 
    562  1.1  oster   error = raidlookup(diskPtr->devname, proc, &vp);
    563  1.1  oster   if (error) {
    564  1.1  oster 	  printf("raidlookup on device: %s failed!\n",diskPtr->devname);
    565  1.1  oster 	  if (error == ENXIO) {
    566  1.1  oster 		  /* XXX the component isn't there... must be dead :-( */
    567  1.1  oster 		  diskPtr->status = rf_ds_failed;
    568  1.1  oster 	  } else {
    569  1.1  oster 		  return(error);
    570  1.1  oster 	  }
    571  1.1  oster   }
    572  1.1  oster 
    573  1.1  oster   if (diskPtr->status == rf_ds_optimal) {
    574  1.1  oster 
    575  1.1  oster 	  if ((error = VOP_GETATTR(vp, &va, proc->p_ucred, proc)) != 0) {
    576  1.1  oster 		  return(error);
    577  1.1  oster 	  }
    578  1.1  oster 
    579  1.1  oster 	  error = VOP_IOCTL(vp, DIOCGPART, (caddr_t)&dpart,
    580  1.1  oster 			    FREAD, proc->p_ucred, proc);
    581  1.1  oster 	  if (error) {
    582  1.1  oster 		  return(error);
    583  1.1  oster 	  }
    584  1.1  oster 
    585  1.1  oster 
    586  1.1  oster 	  diskPtr->blockSize = dpart.disklab->d_secsize;
    587  1.1  oster 
    588  1.1  oster 	  diskPtr->numBlocks = dpart.part->p_size - rf_protectedSectors;
    589  1.1  oster 
    590  1.1  oster 	  raidPtr->raid_cinfo[row][col].ci_vp = vp;
    591  1.1  oster 	  raidPtr->raid_cinfo[row][col].ci_dev = va.va_rdev;
    592  1.1  oster 
    593  1.1  oster #if 0
    594  1.1  oster 	  diskPtr->dev = dev;
    595  1.1  oster #endif
    596  1.1  oster 
    597  1.1  oster 	  diskPtr->dev = va.va_rdev; /* XXX or the above? */
    598  1.1  oster 
    599  1.1  oster 	  /* we allow the user to specify that only a fraction of the disks should be used
    600  1.1  oster 	   * this is just for debug:  it speeds up the parity scan
    601  1.1  oster 	   */
    602  1.1  oster 	  diskPtr->numBlocks = diskPtr->numBlocks * rf_sizePercentage / 100;
    603  1.1  oster 
    604  1.1  oster   }
    605  1.1  oster 
    606  1.1  oster #endif /* !__NetBSD__ */
    607  1.1  oster #endif /* SIMULATE */
    608  1.1  oster 
    609  1.1  oster   return(0);
    610  1.1  oster }
    611  1.1  oster 
    612  1.1  oster #ifdef SIMULATE
    613  1.1  oster 
    614  1.1  oster void rf_default_disk_names()
    615  1.1  oster {
    616  1.1  oster     sprintf(disk_db_file_name,"disk.db");
    617  1.1  oster     sprintf(disk_type_name,"HP2247");
    618  1.1  oster }
    619  1.1  oster 
    620  1.1  oster void rf_set_disk_db_name(s)
    621  1.1  oster  char  *s;
    622  1.1  oster {
    623  1.1  oster     strcpy(disk_db_file_name,s);
    624  1.1  oster }
    625  1.1  oster 
    626  1.1  oster void rf_set_disk_type_name(s)
    627  1.1  oster  char  *s;
    628  1.1  oster {
    629  1.1  oster     strcpy(disk_type_name,s);
    630  1.1  oster }
    631  1.1  oster 
    632  1.1  oster #endif /* SIMULATE */
    633